PLC Threat-modeling & Auditability

I’ve been meaning to break in my leaflet for awhile but haven’t gotten to it! Thanks to Phil ( @ bad-example.com ) for voicing some concerns about the current work that we’re doing on PLC to support mirroring. It gave me a good reason to write up my thoughts on the technical improvements we have planned for PLC & to invite feedback/discussion from folks that are interested.

First some background: DID PLC is a self-authenticating DID which is strongly-consistent, recoverable, and allows for key rotation. Each identity is made up of a series of signed operations that each reference the preceding operation in a chain back to the genesis operation. Any observer can verify the chain of operations in order to verify the current state of the identity.

PLC operations are stored in a directory (currently run at plc.directory) which is a centralized service that validates operations, stores them, and serves those operations as well as computed views of the identities derived from the operations. The trust model for the directory is fairly limited as it is unable to modify identities without a signed operation on their behalf.

The directory cannot fake a valid operation, however the directory may reject a valid operation or remove a previously accepted operation. In other words, the directory must be trusted with “maintaining the set of accepted valid operations”.

One design goal of PLC is that applications should have a clear answer about the current state of an identity. If two applications reach out to the same directory, they should always receive the same answer. This sort of strong consistency requires either a single writer or a consensus mechanism. PLC currently achieves this through a centralized single writer.

Let’s first look at alternative consensus mechanisms and then look at checks and balances if we maintain PLC as a single writer.

In terms of consensus, we have two options: an open or closed set of participants. An open set of participants requires some sort of sybil-resistant BFT consensus mechanism a la blockchains: Proof of Work, Proof of Stake, etc. This in turn requires some sort of incentive mechanism (usually a digital currency) that encourages reliable participation. To me, this is just a non-starter. I really don’t think PLC should have a cryptocurrency, and I really don’t want the UX hits of operating off a blockchain (paying for transactions, awaiting block confirmations, etc).

The other type of consensus is to have a closed set of participants that use some consensus protocol like Paxos in order to decide on the current state of the directory. Of course this just moves the governance problem from “which operations are included in the directory” to “which organizations are included in consensus”. The world has sophisticated governance and legal structures for handling exactly this type of multi-stakeholder decision making, and my opinion is that those structures are better suited to the job than Paxos. In other words: a single organization governed by a multi-stakeholder board ( which is what we’re pursuing btw ).

Okay but even a multi-stakeholder, independently-governed PLC can go bad. So what does the network do in that case? My opinion is to solve this in the way that we commonly solve it in AT: provide credible exit. That is, if you have reason to believe that a directory is not acting in good faith, then you have the ability to use another directory. You’ll notice that all of the reference client SDKs for PLC allow you to swap out the URL of the directory that you’re talking to.

Applications or communities may run their own directories. In nearly all cases those directories will directly mirror plc.directory. If plc.directory chooses to exclude an operation that other directories deem valid then they can opt to include the operation and even gossip it around to other directories while continuing to mirror the operations coming out of plc.directory.

Currently we’re working on a feature to make mirroring of PLC easier . This occurs over a streaming websocket and involves assigning a monotonic sequence number to each operation in the directory. This is a step toward our longer goal which is the introduction of Transparency Logs (tlogs) to PLC (see Sunlight for more on that). Tlogs require strong ordering of operations within a directory.

The concern of giving operations a sequence number and tlogs more broadly is that this may complicate a multi-authority future. If an alternative directory accepts an operation that plc.directory does not, then those two directories may be required to maintain different sequence numbers for all operations going forward. In any case, they will never have the same root hash for their tlog. If that sounds uneasy or messy, it’s because it is.

My opinion is that we should own up to the messiness of this. We shouldn’t consider either the sequence numbers of operations or the root hash of a tlog to be a “global” value or something that divergent directories must reach consensus on. Rather these should be thought of as mechanisms that allow for auditing a particular directory. As discussed earlier, the responsibility of a directory is to decide “which operations are included in the directory”. Sequence numbers and tlogs allow observers to audit exactly how a given directory answers that question.

This does not mean that a multi-authority future is not messy (and hopefully it never happens!). But in that future, the most important thing to resolve that messiness will be to understand exactly where two directories diverge from one another.

As I mentioned, I’m looking forward to hearing any feedback/concerns around this ahead of rolling out the websocket export API !