allinbits / cosmos-cash

Cosmos Cash
https://docs.cosmos-cash.app.beta.starport.cloud/
Apache License 2.0
36 stars 12 forks source link

DID Method versioning #341

Open jandrieu opened 2 years ago

jandrieu commented 2 years ago

Is there any approach to versioning in the proposed did:cosmos syntax?

For the did:earth method, and hopefully a cosmos-cash compatible did:cosmos method, we anticipate at least two known versions, and can easily see the need for other versions moving forward.

In the near term, did:earth version 0 is going to rely on a manual process of grabbing the chain.json files from the cosmos chain registry repo. This will let us get a working spec operational even before we have the on-chain name server that has been discussed. For version 1, we anticipate the first step would be to interactively query the chain registry to get the verifiable reference to a chain.json file (stored somewhere, including github, or IPFS, or wherever).

Since this adjustment would mean that extant did:earth and did:cosmos implementations could be out of sync--old code using version 0 while everyone else is using version 1--we anticipate using a version identifier to allow a smooth transition from an initial approach to a later approach.

This also allows future flexibility with inevitable future versions where, e.g., the schema in the chain.json changes or other features are added or deprecated. Having the version directly in the did itself would allow a time period in which overlapping versions can simultaneously be supported, as older versions are gradually end-of-lifed through a traditional deprecation process.

Has there been any thinking on versioning in this DID module?

Our expectation would be something like did:cosmos:ixo:nft:1:abc123 where the :1: is the version identifier.

Any thoughts on how to approach this?

PaddyMc commented 2 years ago

hmmm, I think the version id we are using for this implementation is the tx hash, from which we can get the block height, so each block is a new version of the chain. And the block that the did was created on is the version.

I think that the version discrepancies would be mitigated by running state migrations on each of the dids in the store, so the version would be updated on chain upgrade. This would happen when "Breaking Changes" are pushed to the node. So it would actually be pretty difficult to have different versions of the data structure in the state at the same time without having different data stores :thinking:

I would look into proto versioning as these will represent the version of the did module.

Hope that helps, and sorry for the delay, we'll be archiving this repo soon :bow:

jandrieu commented 2 years ago

@PaddyMc

Hope that helps, and sorry for the delay, we'll be archiving this repo soon Hope that helps, and sorry for the delay, we'll be archiving this repo soon

Is there another repo where we should be asking these questions?

jandrieu commented 2 years ago

@PaddyMc

hmmm, I think the version id we are using for this implementation is the tx hash, from which we can get the block height, so each block is a new version of the chain. And the block that the did was created on is the version.

You mean the syntax of the cosmos-cash DID is did:cosmos:ixo:nft:<tx hash>:abc123?

I think for uses in the wild, such as a long-lived VC issued with a subject ID of a did:cosmos DID, you still need somewhere that the resolving party can look up the tx hash to get a definitive statement about which protocol version is in play. Whatever that mechanism is, it cannot change if you want backwards compatibility. The reader of the DID, who needs to resolve it, will need to be able to consistently map any tx hash to the correct resolution operation. Any time you have two services interacting, each of whom are expecting the DID to use one resolution approach or another, those two services need to both agree on the protocol in play. For example, if a Holder is signing a Verifiable Presentation (VP) with the DID Document reachable by the on-chain registry mechanism, and the Verifier is verifying that the subject of that VC signed the VP by resolving the DID Document using the repo registry mechanism, it will be easy for that verification to fail. Somewhere, they need to map the DID to a resolution operation.

For a concrete example, version 0 of did:earth will use the chain registry as a repo with a simple rule for mapping the chainspace ("ixo" in the example) to a chain.json file in that repo, call this did:earth:ixo:nft:txHash1:abc123. Version 1 will leverage some on-chain name server to do that same lookup, call this did:earth:ixo:nft:txHash2:abc123

As the recipient of a VC with did:earth:ixo:nft:txHash1:abc123 as subject, how do I look up the correct way to find the definitive server for resolution? How does the txHash get interpreted to clarify which process is definitive? Even if we require them to connect to the Hub to get the blockheight for that txHash, we still also need a way for to map that blockheight to a version. Any app, built for an older version, needs to realize that a given DID is not to be resolved the old way, but rather some way new way it may not even understand. Because the DID itself will exist externally to the chain, and over long periods of time, it is almost certainly a requirement that the DID encodes its own version to support resolution-breaking changes. Apps that don't understand a newer version can prompt the user with a resolvable error. Apps that mistakenly continue to use the old version for new version DIDs will break.

The tx hash also doesn't seem to work with off-chain identifier construction, since there is no tx hash at that point. I realize many folks don't seem to care about off-chain creation, but it is an improvement with orders of magnitude greater scalability. There should be no need to publish or register un-updated DIDs anywhere. All you actually need is to publish updates to the DID Document, should they occur. This means that for short lived DIDs you may never see them on-chain at all. Only those that have updates to their documents need to be on chain. Which means only updates have to pay transaction fees. This is a game changer on cost-structure and scalability.

This was an innovation that came from the uPort team at consensus with did:ethr. This approach has been adopted by Veres One, slated for the next BTCR, and seen in did:key, did:peer, and did:pkh (and likely in many other methods I'm not familiar with).

IMNSHO, DID methods that do not support off-chain creation will be displaced by those that do. The benefit from enabling off-chain creation far outweighs the overhead of ensuring your unique identifier is capable of generating a deterministic minimal DID document. Generally, this is accomplished by making that unique id a form of a public key, like did:key. Then the on-chain records are searched every time for updates, but if none are found that minimal version is the authoritative one. For several orders of magnitude improvement in cost and scale, it is worth the effort.

PaddyMc commented 2 years ago

Great thoughts, I think you have a great understanding of how DIDs should be used in the wild, always happy to read your comments.

So the did method id here follows this structure:

did:cosmos:net:cash:<id or module>:<contract or extended-id>

Versioning is handled by the DID metadata e.g

https://www.w3.org/TR/did-spec-registries/#versionid

So an example did looks like this when it goes through the resolution process:

{
  "didDocument": {
    "context": [
      "https://www.w3.org/ns/did/v1"
    ],
    "id": "did:cosmos:net:cosmoscash-testnet:900d82bc-2bfe-45a7-ab22-a8d11773568e",
    "controller": [
      "did:cosmos:key:cosmos1sl48sj2jjed7enrv3lzzplr9wc2f5js5tzjph8"
    ],
    "verificationMethod": [
      {
        "controller": "did:cosmos:net:cosmoscash-testnet:900d82bc-2bfe-45a7-ab22-a8d11773568e",
        "id": "did:cosmos:net:cosmoscash-testnet:900d82bc-2bfe-45a7-ab22-a8d11773568e#cosmos1x5hrv0hngmg8gls5cft7nphqs83njj25pwxpt0",
        "publicKeyMultibase": "0248a5178d7a90ec187b3c3d533a4385db905f6fcdaac5026859ca5ef7b0b1c3b5",
        "type": "EcdsaSecp256k1VerificationKey2019"
      }
    ],
    "authentication": [
      "did:cosmos:net:cosmoscash-testnet:900d82bc-2bfe-45a7-ab22-a8d11773568e#cosmos1x5hrv0hngmg8gls5cft7nphqs83njj25pwxpt0"
    ]
  },
  "didMetadata": {
    "versionId": "9f7c547dc852af60c9da1fd514e1497d407b6a3d8ae3e52b626d536519dc8f4c",
    "created": "2021-08-23T08:24:26.972761898Z",
    "updated": "2021-08-24T15:54:40.902858856Z",
    "deactivated": false
  }
}

In this implementation, which is what was needed to solve the cosmos-cash use-case, we have the metadata in the chain state, but in our newest version of the module we have removed it in favor of the resolver computing the metadata and version id on the fly.

We have native support for did:key on cosmos-cash and we use did:peer for our private did SSI stuff, and I believe a mixture of multiple VDRs and resolvers is needed to realize the semantic web. :bow:

PaddyMc commented 2 years ago

Hope that helps, and sorry for the delay, we'll be archiving this repo soon

Is there another repo where we should be asking these questions?

I'll respond here to you until we have another forum to discuss these topics :smile:

Feel free to ping me on Discord as well :bow: