In Sidetree-based DID Methods, there are two forms of ID strings for the same identifier:
Long-Form ID: Base64_Initial_DID_Doc
Short-Form ID: SHA256_Hash_Of_Base64_Initial_DID_Doc
The use case for this is that in more robustly decentralized systems, commitment is delayed by consensus, which can take 30 seconds, or even minutes. That said, there is still a desire to immediately use an ID, which is what the Long-Form ID above allows. By passing the Long-Form ID to an RP or Issuer, the system can resolve the ID to its latest state (assuming it is registered and can be found by its Short-Form equivalent), or, if it has not yet been registered/broadcast, it can resolve via return of the initial DID Document that comprises the ID string.
Presently the DID spec seems to prohibit Methods from supporting multiple ID string forms of the same DID with the language found in the Binding of Identity section:
Proving control of a DID, i.e., the binding between the DID and the DID Document that describes it, requires a two step process:
1. Resolving the DID to a DID Document according to its DID method specification.
2. Verifying that the id property of the resulting DID Document matches the DID that was resolved.
We would like to support the notion of both forms being equivalents, given the Long-Form hashes to the Short-Form, making them provably synonymous. Was the DID spec written with this in mind, or is this something new to consider?
The section on equivalence, appears to describe similar functionality.
If it were not for the language mentioned above, defining equivalence within a DID Method would be up to the method implementer it would seem.
The Long-Form ID has similarities to did:key or other self certifying methods such as did:ethr, given a Long-Form ID, it should be possible to verify a JSON-LD Signature attributed to it, because the identifier contains key material.
To summarize again, it might be desirable for some DID Methods to support multiple DIDs that resolve to the same DID Document, where that document always contains a Short-Form ID.
@OR13 You are exactly right, that is the reason we included Equivalence in the Future Work session. @csuwildcat's use case is indeed a good example of when equivalence assertions are needed, however it is actually one of the easier ones since:
The reason we put Equivalence in the Future Work section is that it can be considerably harder to prove equivalence across DIDs from different methods where there is no direct algorithmic proof.
I personally favor tackling at least intra-method equivalence in the DID spec. I could also support defining at least one straightforward method of achieving inter-method equivalence. But I would not make it a top priority.
So it seems the key question is: If you resolve did:ex:1234, could you get back a DID Document with an id that is different from did:ex:1234? Right now the spec doesn't allow that, and I feel it would be problematic from a URI/RDF perspective.
Instead, my feeling was that the DID Document would include an equivalence statement, or redirect statement, that points to the new DID.. E.g. if you resolve did:ex:<long-form>, you would get:
{
"@context": "https://w3id.org/did/v1",
"id": "did:ex:<long-form>",
"redirect": "did:ex:<short-form>",
.. services and public keys ..
}
Semantically, there's a slight difference between stating "equivalence" and "redirect". The former would be a bit like an owl:sameAs statement in RDF, whereas the latter would be a bit like an HTTP 303 code. Mastodon has a property as:movedTo for redirecting to a new account.
The above would instruct a client to use did:ex:<short-form> from now on.
Also see https://github.com/w3c-ccg/did-resolution/issues/36.
Given the veracity of a DID Document is determined by the process/proofing done within the DID Method itself, why is there a need to pose this as a redirect? Redirect sounds more like a pointer to something distinctly different, not the exact same ID. Can we at least call this something besides redirect, given the IDs in Sidetree-based DID Methods, for example, are exact equivalents that represent the exact same ID in the system. I like equivalent or alias, personally.
Markus and I talked a bit, and he made a good point: this ask is dealing with a unidirectional relationship between variations of the same ID. Markus mentioned that XDI had a canonical value that expressed this sort of relationship - would folks here be open to adding a canonical property that, if present, indicates a unidirectional pointer to the canonical form of the ID the resolving party should use going forward?
Markus mentioned that XDI had a
canonicalvalue that expressed this sort of relationship
Quick correction.. What I said was that XRDS (not XDI) had a <EquivID> and a <CanonicalID> element. The latter was unidirectional, and you could have only one of it. In XDI, very similar constructs exist, they are called $is and $ref.
After talking with several folks, there may be a better way to address the needs of methods that have a period of delay between generation of a DID and the finalization of the DID on whatever ledger/chain, etc., their network uses:
The proposal is to create a new Generic DID Parameter: init, and a DID Resolution metadata field: published. These two items would include the following specification language and directives:
init - Value(s) a DID Method and its resolver code may utilize to process DIDs that are in an 'unpublished' state, not yet anchored/propagated in the underlying trust system a Method uses.published - Boolean applied by the DID Method's resolving code indicating whether or not the DID that was resolved has been anchored in the underlying trust system. When this metadata field is returned true from the resolving code, the party performing the resolution MAY choose to discard the init parameter from any held references to the DID in question.If there are no objections, I intend to fork the current spec and create a PR for the addition of the init Matrix Parameter to the Generic DID Parameter list. Please respond with any feedback about this direction before the next WG meeting to ensure we fully consider all points of view.
This probably requires some review from the wider WG, but in general I think this could be a useful feature that makes sense across multiple DID methods. So let's start a PR to try and get some more feedback.
There was a discussion about a similar approach for did:git at IIW. I like the language for init. I don't fully understand the other side published or how a method resolve interface is able to respond to matrix parameters generally.
@OR13 the published metadata field is something the DID Method's resolving code would be aware of and include when it resolves a DID. This resolution metadata field would always be populated by methods that seek to employ it, and would be present regardless of whether or not the init Matrix Parameter was included on the DID being resolved. Just think of published as a generic indicator that all Methods can use for signalling the anchored/not anchored state of a DID, irrespective of this particular utilization of that indication.
Can we consider renaming init to initial-values or initial-state as init typically means "initialize" or "initialization" in the programming world?
@thehenrytsai of the two you mentioned, I like initial-values.
I wonder if init could be generalized to specify a DID document that is returned not only until the DID is anchored/propagated, but also if for some other reason the DID cannot be resolved. The parameter could be called fallback or default instead of init. But I guess the behavior I am describing is a bit different than what you have in mind.
I don't fully understand the other side
publishedor how a method resolve interface is able to respond to matrix parameters generally.
+1 I don't understand that either. It's confusing the say a matrix parameter is "returned". Perhaps what you really want here is resolver metadata, or a DID document extension?
I wonder if
initcould be generalized to specify a DID document that is returned not only until the DID is anchored/propagated, but also if for some other reason the DID cannot be resolved. The parameter could be calledfallbackordefaultinstead ofinit. But I guess the behavior I am describing is a bit different than what you have in mind.
I don't think you can use this in a 'fallback' sense, because the initial values present in the parameter may describe a state that is only secure and valid during the unpublished/propagated phase. This means that making it a fallback would be insecure for any DID that had changes made to it since, because it would wrongly indicate that the resolving party could rely on the initial values, which may, for example, include keys that have since been removed.
I don't fully understand the other side
publishedor how a method resolve interface is able to respond to matrix parameters generally.+1 I don't understand that either. It's confusing the say a matrix parameter is "returned". Perhaps what you really want here is resolver metadata, or a DID document extension?
Sorry that I mixed this up - what I meant is that published is a field in the resolved metadata, which the DID Method's resolving code would return (because obviously it is the thing aware of whether a DID has been published/anchored).
@peacekeeper whats the relationship between the did resolution spec:
https://w3c-ccg.github.io/did-resolution/
And this working group again?
It seems like the addition of a generic matrix parameter would be very much in scope for this group, but a method specific one, wouldn't need any changes.
I'm very much in favor of standardizing the process of providing initial data to a resolver, and I think it would be nice if it were generic, but if method specific resolvers are making the decision of when to use the resolution meta data to forward related info, it feels like maybe the initial-values is a method specific matrix param.
Seems like we could do:
A. Generic matrix param + DID Document Extension
B. Method Specific Matrix Param + Resolver Meta Data
A seems definitely in this working group, I'm not sure about B, but it seems like its potentially less difficult to accomplish.
@OR13 right now the DID spec (identifier syntax and DID document data model and format) is being developed by the DID WG, whereas the DID Resolution spec (resolving and dereferencing) is a work item of the CCG. This is under active discussion right now, since we often find that topics in both groups are closely related. Matrix parameters are one such topic, and there are others as well.
I do think this proposal would be a generic matrix parameter rather than method-specific. Generic doesn't mean that all methods have to support it. It just means that it should have the same semantics across those methods that DO support it.
+1 I do think this proposal would be a generic matrix parameter rather than method-specific.
Yes, I agree with you Markus, this is a generic parameter, because it would
have the same general meaning/intent across all methods that use it, and
there are many methods that have the same need - this is, imo, what defines
a generic parameter.
On Fri, Oct 18, 2019, 2:00 PM Markus Sabadello notifications@github.com
wrote:
@OR13 https://github.com/OR13 right now the DID spec (identifier syntax
and DID document data model and format) is being developed by the DID WG,
whereas the DID Resolution spec (resolving and dereferencing) is a work
item of the CCG. This is under active discussion right now, since we often
find that topic in both groups are closely related. Matrix parameters are
one such topic, and there are others as well.I do think this proposal would be a generic matrix parameter rather than
method-specific. Generic doesn't mean that all methods have to support it.
It just means that it should have the same semantics across those methods
that DO support it.—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
https://github.com/w3c/did-spec/issues/70?email_source=notifications&email_token=AABAFSVE2DNBSM3WD5WSA3TQPIPXVA5CNFSM4JATH4U2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEBV6Z4Q#issuecomment-543943922,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AABAFSV3C7J55HRR3AK2OIDQPIPXVANCNFSM4JATH4UQ
.
+1 also that this request would be part of the DID resolution protocol. Also, it seems like the default param would be published if not specified. If ledgers and chains that use a more decentralized protocol that requires propagation, then initial-values can be used.
Initial values in sidetree spec:
https://github.com/decentralized-identity/sidetree/blob/ae54238411245a55edeeda992e3dbcc6af1ffbc4/docs/protocol.md#unpublished-did-resolution
did:sidetree:<unique-portion>;initial-values=<encoded-original-did-document>
wouldn't this lead to a race condition and/or eclipse attack if I trick the validating party into thinking that there are init values when it isn't a new DID doc?
@jonnycrunch I don't believe such an attack is possible, because the resolution process starts with a DID being resolved against the underlying global trust system (e.g. the blockchain to which the Method anchors in), which, if any updates are present, returns the current DID Document. The initial-values parameter is only utilized by the Method if the identifier is not published in the underlying global trust system. If absolute segregation of the resolving node is the issue, that's something that would block the retrieval of any updates for any DID, regardless of Method (and would affect any blockchain or ledger node at the lower level), so I don't think this is an issueinitial-values introduces.
Yeah, but there will likely be a delay in the resolution process as not all DIDs will be cached by a resolving service, so I could fool the validator into believing this is a new initial value for the DID, before they have a chance to fully resolve and validate it doesn't already exist. Really pushes the trust framework to the resolution process.
@jonnycrunch I am not sure how what your saying is possible, given the intent is that the initial values are unique and inextricably linked to a given DID. There's also no race condition between publication and use of initial-values, given first publication would literally be the same result as what initial-values is intended to produce.
Really pushes the trust framework to the resolution process.
I also want to ask for clarity on this, given I am under the impression that 'clarity' on the present state of a DID's DID Document is implicitly reliant on the process of resolving DID to incorporate any changes/deltas since its genesis state. What I am not seeing here is how initial-values introduces race conditions anywhere, given the trust assumption remains resolution of the DID against the target trust system.
This issue was discussed in a meeting.
Concrete example: did:sidetree:exKwW0HjS5y4zBtJ7vYDwglYhtckdO15JDt1j5F5Q0A;initial-values=ewogICAgICAiQGNvbnRleHQiOiAiaHR0cHM6Ly93M2lkLm9yZy9kaWQvdjEiLAogICAgICAicHVibGljS2V5IjogWwogICAgICAgIHsKICAgICAgICAgICAgImlkIjogIiNrZXkxIiwKICAgICAgICAgICAgInR5cGUiOiAiU2VjcDI1NmsxVmVyaWZpY2F0aW9uS2V5MjAxOCIsCiAgICAgICAgICAgICJwdWJsaWNLZXlIZXgiOiAiMDM0ZWUwZjY3MGZjOTZiYjc1ZThiODljMDY4YTE2NjUwMDdhNDFjOTg1MTNkNmE5MTFiNjEzN2UyZDE2ZjFkMzAwIgogICAgICAgIH0KICAgICAgXQogICAgfQ
The base64url encoded initial-values property is the initial did document without the id property, because sidetree calculates the id property from the initial-values payload.
Semantically, the intention is the following:
If did:sidetree:exKwW0HjS5y4zBtJ7vYDwglYhtckdO15JDt1j5F5Q0A, does not exist on a ledger, use did:sidetree:exKwW0HjS5y4zBtJ7vYDwglYhtckdO15JDt1j5F5Q0A;initial-values=ewogICAgICAiQGNvbnRleHQiOiAiaHR0cHM6Ly93M2lkLm9yZy9kaWQvdjEiLAogICAgICAicHVibGljS2V5IjogWwogICAgICAgIHsKICAgICAgICAgICAgImlkIjogIiNrZXkxIiwKICAgICAgICAgICAgInR5cGUiOiAiU2VjcDI1NmsxVmVyaWZpY2F0aW9uS2V5MjAxOCIsCiAgICAgICAgICAgICJwdWJsaWNLZXlIZXgiOiAiMDM0ZWUwZjY3MGZjOTZiYjc1ZThiODljMDY4YTE2NjUwMDdhNDFjOTg1MTNkNmE5MTFiNjEzN2UyZDE2ZjFkMzAwIgogICAgICAgIH0KICAgICAgXQogICAgfQ which always yields a DID Document (because of the way the DID Method resolution handles initial-values).
Both identify the subject, one is an identifier for something that might not exist, the other is an identifier to something that always exists.
Here's my (hopefully) simple challenge to any folks reading this thread who may not yet fully grok this issue:
If you are working with a robustly decentralized DID Method that features highly-secure global resolution (the ability to resolve a DID against a hardened global oracle, e.g. a blockchain), anyone who happens to come across your DID immediately after it is created won't be able to resolve it. Why you ask? Simple: because it isn't propagated across the underlying ledger yet (e.g. Bitcoin, which takes ~10 minutes to do so), meaning, obviously, the DID/Doc will not be resolvable. For shame, such are the throes of space, time, and consensus!
_pause for tears_
Whatever are we to do?!? If only such a Method's resolver code could determine the DID is not yet anchored/propagated, and use some hard-bound values you passed with the DID to successfully resolve it. Magic you say? No sir, all we need is a way to pass (in the case of Sidetree-based methods) the base64 encoded initial DID Document state, and just like that, you can instantly use your DID regardless of anchoring/propagation state! If the DID is already anchored/propagated, or becomes anchored/propagated at a later date, no worries, the resolver code will find whatever the current state is an simply disregard the initial DID Document passed with the DID. How do we make this possible? Well, I'm not sure what you have in mind, but this Issue and matching PR provide one way to do exactly that. My challenge to you is to find me another way, that is, if you continue to disagree about how we did it here after this articulation of the problem statement. The only unacceptable response to this challenge is to tell me I don't need this, because I absolutely do, and will die on this hill endlessly, Edge of Tomorrow-style.
My vote would be to support for method-specific matrix parameters. As a proposal for this, if your DID method is named sidetree any matrix parameter of the form sidetree-* would only be meaningful to the sidetree resolver. This gives DID methods a generic way to add functionality like initial-values without needing the support of the entire community. Rendering @OR13's example as:
did:sidetree:exKwW0HjS5y4zBtJ7vYDwglYhtckdO15JDt1j5F5Q0A;sidetree-initial-values=ewogICAgICAiQGNvbnRleHQiOiAiaHR0cHM6Ly93M2lkLm9yZy9kaWQvdjEiLAogICAgICAicHVibGljS2V5IjogWwogICAgICAgIHsKICAgICAgICAgICAgImlkIjogIiNrZXkxIiwKICAgICAgICAgICAgInR5cGUiOiAiU2VjcDI1NmsxVmVyaWZpY2F0aW9uS2V5MjAxOCIsCiAgICAgICAgICAgICJwdWJsaWNLZXlIZXgiOiAiMDM0ZWUwZjY3MGZjOTZiYjc1ZThiODljMDY4YTE2NjUwMDdhNDFjOTg1MTNkNmE5MTFiNjEzN2UyZDE2ZjFkMzAwIgogICAgICAgIH0KICAgICAgXQogICAgfQ
Method-specific ideas that gain widespread use across many methods could then be proposed as part of the base standard.
https://www.w3.org/TR/did-core/#method-specific-did-parameter-names
I think it would be did:ion:exKwW0HjS5y4zBtJ7vYDwglYhtckdO15JDt1j5F5Q0A;ion:initial-values=ewogICAgICAiQGNvbnRleHQiOiAiaHR0cHM6Ly93M2lkLm9yZy9kaWQvdjEiLAogICAgICAicHVibGljS2V5IjogWwogICAgICAgIHsKICAgICAgICAgICAgImlkIjogIiNrZXkxIiwKICAgICAgICAgICAgInR5cGUiOiAiU2VjcDI1NmsxVmVyaWZpY2F0aW9uS2V5MjAxOCIsCiAgICAgICAgICAgICJwdWJsaWNLZXlIZXgiOiAiMDM0ZWUwZjY3MGZjOTZiYjc1ZThiODljMDY4YTE2NjUwMDdhNDFjOTg1MTNkNmE5MTFiNjEzN2UyZDE2ZjFkMzAwIgogICAgICAgIH0KICAgICAgXQogICAgfQ
This is always an option, but it would probably be more helpful if we can define support for this in a generic way.
I don't understand why we'd want to force every Method based on a
decentralized blockchain to invent their own variant of the exact
same thing to cover this basic need. With the same goal and handling rules
across multiple Methods, initial-values seems like the very definition of
what a generic parameter would be.
On Tue, Dec 3, 2019, 10:31 AM Orie Steele notifications@github.com wrote:
https://www.w3.org/TR/did-core/#method-specific-did-parameter-names
I think it would be
did:ion:exKwW0HjS5y4zBtJ7vYDwglYhtckdO15JDt1j5F5Q0A;ion:initial-values=ewogICAgICAiQGNvbnRleHQiOiAiaHR0cHM6Ly93M2lkLm9yZy9kaWQvdjEiLAogICAgICAicHVibGljS2V5IjogWwogICAgICAgIHsKICAgICAgICAgICAgImlkIjogIiNrZXkxIiwKICAgICAgICAgICAgInR5cGUiOiAiU2VjcDI1NmsxVmVyaWZpY2F0aW9uS2V5MjAxOCIsCiAgICAgICAgICAgICJwdWJsaWNLZXlIZXgiOiAiMDM0ZWUwZjY3MGZjOTZiYjc1ZThiODljMDY4YTE2NjUwMDdhNDFjOTg1MTNkNmE5MTFiNjEzN2UyZDE2ZjFkMzAwIgogICAgICAgIH0KICAgICAgXQogICAgfQThis is always an option, but it would probably be more helpful if we can
define support for this in a generic way.—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
https://github.com/w3c/did-core/issues/70?email_source=notifications&email_token=AABAFSTHDM3ZPDALHL5VZX3QW2QXXA5CNFSM4JATH4U2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEF2LO6Y#issuecomment-561297275,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AABAFSWR7CGC7CBFRTXRGW3QW2QXXANCNFSM4JATH4UQ
.
My sense was also that this should be a generic parameter, since it feels plausible that it could be used for other methods as well (e.g. btcr).
Thanks for pointing out that section, @OR13
Regarding @csuwildcat's comment:
I don't understand why we'd want to force every Method based on a
decentralized blockchain to invent their own variant of the exact
same thing to cover this basic need.
I don't feel strongly about using generic vs. method-specific for this, but it feels to me like a method-specific parameter for two reasons:
btcr even do this?)initial-value= is inherently method-specific and not generic.@cboscolo serious question, because I don't know the answer: are generic matrix params required to have the exact same value signature across Methods, or just the same intent and rules for use? If the latter, then this would still be a generic, if the former, I would agree with you on technical/spec grounds.
I don't know the answer to this, @peacekeeper?
But, I suspect not. Thus supporting keeping it generic. Here's the txt from the DID spec:
Some generic DID parameter names (e.g., for service selection) are completely independent of any specific DID method and MUST always function the same way for all DIDs. Others (e.g., for versioning) MAY be supported by certain DID methods, but MUST operate uniformly across those DID methods that do support them.
I've tended to prefer NOT encouraging did-method specific matrix parameters. Specifically what I'm thinking about is the burden on implementers of DID resolution and the Cambrian explosion it could cause.
As someone working on implementing DID Resolution, I am taking careful consideration before choosing a did-method that defines it's own matrix parameters. This is primarily because the implementation burden on both the resolver and the clients that are making calls to the library are far more complex when having to consider method specific matrix parameters. I'd much rather encourage that they be defined and used by all DID methods.
As a disclaimer, I'm not encouraging DID-core should ban method specific matrix parameters, but if a method specific matrix parameter is required by a did-method, I'm likely to question implementing that did method all together in the resolver.
I agree with @kdenhartog, whenever possible we should avoid method specific definitions. Sidetree DIDs are likely to represent a family of DID Methods, I'd be in favor of defining this such that this would solve this problem for all eventually consistent ledger anchored decentralized identifiers, and have sidetree dids (ion, elem, etc) just be the first user of this generic matrix param.
I too agree that method-specific parameters (MSP) should be avoided whenever there's another easier solution. However not all MSP affect resolution or dereferencing. If the MSP is simply something that's passed on, it should not be a concern of the resolver code.
BTW, this thread brings up another DID feature that is not yet on our list, but which I'm now seeing several communities needed: DID method types. This is the ability for one DID method to re-use the code defined for another DID method, just in a different DID method namespace (meaning it has a different governance authority and/or target DID registry).
This would enable a whole family of DID methods to reuse the same resolution code while having different DID method names.
@talltree can you provide an example where we'd want to implement an MSP without having to resolve it? In my mind, that's like passing a variable around in code that I never initialized. Put another way that's like putting in a json document
{
did:example:1234567890;unresolvableMSP=1 :
}
If the value can never be de-referenced (and therefor I don't need to implement resolver code), what would I need the identifier for in the first place?
As for your second point:
BTW, this thread brings up another DID feature that is not yet on our list, but which I'm now seeing several communities needed: DID method types. This is the ability for one DID method to re-use
the code defined for another DID method, just in a different DID method namespace (meaning it
has a different governance authority and/or target DID registry).
I suspect this discussion may curtail into it's own separate discussion. We may need to open a separate issue to discuss this topic.
In short though, I was of the understanding method type works as follows:
did:<method>:{<method-type>:method-specific-identifier} where the method-type falls under the namespacing ABNF of the method. In this case what this means is that method indicates the process by which the identifier is de-referenced to the did document, and the method-type falls under the scope of the authority of the method.
I've seen some of this functionality supported via the universal registrar e.g. did:sov:danube:968zF324uXTLGzWpFqcTYg. Of note, some did methods are doing this via namespacing like is done in the sov example, while things like sidetree have opted for their own namespacing authority. From an implementation standpoint, this makes sense how our identifiers ended up this way because the sovrin method is reusing the indy-sdk, but connecting to different pools, where as with sidetree, there's two separate implementations that couple the network to anchor transactions with the implementation which led to the implementer's to opt for did:ion and did:elem rather than did:sidetree:ion and did:sidetree:elem. Note, it doesn't have to be done this way but as it stands this is what's implemented - element is a separate codebase which doesn't depend on the sidetree protocol library.
It would be more accurate to say did:elem does not depend on did:ion codebase, we both depend on the sidetree spec... which is not a codebase, but a protocol definition, the fact that a typescript library exists for implementing that spec (in the same repo), and that ion uses it and element does not is what you are getting at... This is similar to how many different implementations exist for HTTP servers, with varying degrees of support for HTTP spec features, and some amount of shared components (like use of the http module in a node js example).
I would not be opposed to taking a nested prefixing approach for sidetree, but thats a separate issue.
I create a new issue to continue this method-type discussion.
https://github.com/w3c/did-core/issues/152
To keep this discussion focusses on instant DID use.
@cboscolo Thanks, I should have done that myself.
Can we make this did method specific and solve it as method implementers? The chances of getting this into core seem less and less by the day.
So, several methods have an instant approach that is also rotatable and revocable. It is doable. Although it might be challenging.
I am strongly against having to wait on this for strong consensus... or matrix parameters... we should make it a did method specific matrix parameter, and move on... sidetree methods will support it, when other methods realize they want it, they can implement method specific support as needed. we don't need strong consensus to make progress here.
@OR13 Forging consensus is why we are here.
If not every method needs it, why does it need to be a generic method matrix parameter?
I must express my extreme frustration with folks who dismissively replied to discussion about this with "Design a better Method", in relation to some DID Methods affected by public chain transaction delays. This has nothing to do with having a better method, it is squarely an issue any time a Method based on a public chain seeks to allow a full, well-populated DID Document at inception, and also allow that DID to be instantly resolvable. The person who made that dismissive comment then proceeded to bring up DID methods that do not allow for this feature.
@OR13 if there is any chance Matrix params don't make it in, and some folks just can't grok the issue, what if we just created some pseudo-reserve URL param that won't collide and do it that way? When even more folks run into this, and I _promise_ more in the community will, perhaps the best way forward is to allow reality to teach a harsher lesson than I can apply via frustrated explanations on this thread.
I would focus on driving consensus around matrix parameters being included, use this as a method specific example to support that position. It helps in 2 ways:
@OR13 Forging consensus is why we are here.
@jandrieu I completely agree, the consensus appears to be that generic matrix parameters that not everyone will use, are not really generic, and while method specific matrix parameters might make the resolvers job harder, they would not pollute the did core spec with things that are not relevant to most did methods.
We don't need to wait for strong consensus if the problem is best solved with a method specific matrix parameter AND we have strong consensus on matrix parameters are going to remain around... we should focus on getting strong consensus on matrix parameters first... every other issue we discuss related to them should be tabled until we know that matrix parameters are in or out... including this one :)
I would really advise against using a special reserved query parameter for this, for the same reason why I am also arguing against using query parameters for service endpoint selection: The DID Core spec should not "step on" URI query parameters, instead their meaning should be left application- or service-specific. Just like the HTTP spec doesn't define any concrete paths or query parameters.
E.g. if you did this (which I think is what some people would propose):
did:ex:1234/mypath?_did_service=hub&_did_initial_values=0000&myquery=abc
Then the _did_service and _did_initial_values would have meaning for the DID resolver, whereas /mypath and &myquery=abc would have meaning for the selected service. This is very confusing and mixes different concerns.
Matrix parameters are a way to separate this in a clean way (DID resolution parameters defined by the DID Core spec or extension registry, vs. standard URI paths and queries defined by applications, services, etc.).
Whether or not a generic or method-specific matrix parameter should be used here is a secondary question, I can see arguments for both.
@OR13 or @csuwildcat - the crucial piece of the puzzle I'm missing, with regards to either query or matrix params for instant resolution is -- how are you binding these together, cryptographically? I didn't quite understand it from glancing at the sidetree spec, probably I missed it.
@OR13 or @csuwildcat - the crucial piece of the puzzle I'm missing, with regards to either query or matrix params for instant resolution is -- how are you binding these together, cryptographically? I didn't quite understand it from glancing at the sidetree spec, probably I missed it.
Yes, absolutely - the identifier portion of a Sidetree-based DID string is cryptographically bound to those initial values, such that it is self-validating. If you have the initial values, you can validate they are correct simply by comparing them to the DID identifier string.
All methods that have a publishing delay, for any reason, that follow the self-validating convention would be able to become instantly usable without waiting if we had some generic parameter like initial-values. I simply have no way to attach those verbose, cryptographically linked values in a way that allows us to feed it to a Resolver, thus the need for this param. If the Method's resolver detects the DID with this param is not published, it can reproduce the right DID Document by doing cryptographic validation of the initial values vs the identifier string, and spit you back out the Doc.
To use Sidetree methods as an example, their DID identifier strings are made up of the following:
did:ion: RECOVERY_PUB_KEY : INITIAL_STATE_HASH : COMMITTMENT_HASH
If you were to change any of those identifier values, you would be dealing with a different DID, thus when you tack on the initial state values via a matrix param, as follows:
did:ion: RECOVERY_PUB_KEY : INITIAL_STATE_HASH : COMMITTMENT_HASH:initial-values:INITIAL_STATE_DATA
^ This way you have cryptographic certainty that the person who controls the keys/values bound to to that particular DID identifier string is the controller. If someone were to tack on a different initial-values payload that didn't match the identifier string's INTIAL_STATE_HASH, you would immediately know it is invalid.
If not every method needs it, why does it need to be a generic method matrix parameter?
Yeah, this is a tough one, because we know multiple methods do need it, and I would bet dollars to doughnuts more future methods that have nothing to do with how Sidetree works will face the same general constraints imposed by underlying ledger systems, for which this is a generic solution that allows instant use of their DIDs regardless of what your specific DID Method's initial-values are. The fundamental question then becomes: does a generic matrix parameter literally need to be so generic that all methods must/will likely use them, or is it ok to create generic matrix parameters that some subset of all known DID Methods use in the same generic way? I would argue the latter is more sane, because hardly any parameters are truly so universal that all methods can/must/will support them. <-- @peacekeeper, what do you think?
Even without the time delay concern, this is useful for leaving the did off ledger until an update is necessary. In other words, this makes creating a DID free initially. This is why I believe most methods will want to use it.
fwiw, this concept is also useful for btcr. We just haven't dug into this yet.
or is it ok to create generic matrix parameters that some subset of all known DID Methods use in the same generic way
I agree with this. Some generic parameters work with all DID methods (e.g. the service one which operates on the DID document - every DID method has DID documents!). Other generic parameters are only supported by some DID methods, but if they are supported, then they have the same meaning across those methods.
Besides initial-values, another example is version-id and version-time: Not all DID methods support the lookup of previous versions of a DID document, but if they do, then the meaning of the parameters is consistent.
@kdenhartog
this makes creating a DID free initially
Only if you're assuming that everybody who wants to resolve the did will know the initial state information which may not be the case.
@kdenhartog
this makes creating a DID free initially
Only if you're assuming that everybody who wants to resolve the did will know the initial state information which may not be the case.
I am not sure what you mean - initial-values IS the initial state information, which you would be handing anyone you would like to resolve the DID. For this reason, I don't see anything inaccurate about what Kyle wrote.
If you assume that people can only know about or want to resolve a DID if the DID controller handed them the DID (with the initial state information) then yes the statement is accurate.
For Sidetree, this assumption makes sense because how else is anyone supposed to guess a DID, however this may not be the case for all DID methods. Some don't cryptographically tie the unique suffix with the initial state information.
For example if you use did:github:, I can know your DID by knowing your Github name. If you use did:ethr I can know your DID by knowing your Ethereum address.
Hence my point: Using initial-values makes creating a DID free initially, only if the people who would want to resolve the DID know directly or indirectly the initial state information from the DID controller.
@gjgd
If you assume that people can only know about or want to resolve a DID if the DID controller handed them the DID (with the initial state information) then yes the statement is accurate.
Yes, this is what this mechanism is for.
For Sidetree, this assumption makes sense because how else is anyone supposed to guess a DID, however this may not be the case for all DID methods. Some don't cryptographically tie the unique suffix with the initial state information.
Yes, other Methods may not be able to provide this useful feature, due to limitations inherent to them.
For example if you use
did:github, I can know your DID by knowing your Github name.
Yes, GitHub is a centralized database, so it can be updated very quickly, and delete your account, screw up your data, or do any number of negative things very quickly as well. With a mechanism like this, Sidetree and other methods that are capable of this generic concept are able to provide secure, immediate resolvability of newly created DIDs (and potentially even 'anchored + 1' states) in a robustly decentralized way, all without the downsides of a centralized Method, like Github DIDs.
If you use
did:ethrI can know your DID by knowing your Ethereum address.
Yes, methods like did:ethr and did:key sort of do this (obviously you can resolve a key from something that directly attaches a key), but not in a way the supports the same features this adds. Ironically, it looks like did:ethr could actually enhance their method using this matrix parameter mechanism as well.
Regarding your last two points, did:github and did:ethr were taken as examples of did methods that don't cryptographically tie their did unique suffix to the initial state. Obviously I'm not comparing them to Sidetree from a security perspective, nor am I starting an argument about centralized VS decentralized ledgers...
I do remain concerned about the point made earlier:
Even without the time delay concern, this is useful for leaving the did off ledger until an update is necessary. In other words, this makes creating a DID free initially. This is why I believe most methods will want to use it.
IMO Initial-values is a useful feature than solves an important business problem when there is a propagation delay concern, but should not be an excuse to do away with ledgers until an update is necessary for mainly two reasons:
That being said, I'm in favor of initial-values being a generic method matrix parameter, even if it won't be pertinent for every did methods. There is a lot of did documents values that are defined in the did-core spec but that not every did methods will use, I think that's fine.
That does however brings the question: Do we need a standard way to verify that the did corresponds to the initial-values parameter, or can that be method specific?
Given the discussing occurring in #159 I'd suggest we put this discussion on hold until a decision is made there.
@csuwildcat and I came up with an approach that may enable his use case without requiring an extra labeled parameter. I'd like to float that idea here to see how others feel about it.
The specific idea is to separate the method-specific identifier into components for which only the first element is considered the unique identifier for the entity. The latter components are optional and their meaning method specific.
For convenience sake, I'm assuming a colon is a suitable separator. This would require an adjustment to the ABNF, but that an implementation detail we can figure out later.
For example,
did:ex:abc:123
Would refer to the entity identified by did:ex:abc, with the initial state of 123 (assuming the method treats the additional component as an initial state). Any credentials issued to the entity would be free to use the "short form" of did:ex:abc, since that uniquely defines the identifier.
I believe this relaxation of the meaning of a method-specific id would give DID method creators a flexible, optional means for including the initial state of a DID Document in the DID URL itself, without the need for labeled parameters, matrix or otherwise.
Another way to think about this pattern is that the DID URL basically says
did:ex:id:data
In the case of side-tree that id part is deterministically derived from that data so if the registry-based lookup returns no result, the data part can be verified against the id and treated as the DID Document itself. This makes the DID-URL sort of a data: style URL carrying its content with it (where that content is the initial state of the DID Document).
In short, each DID method would be free to specify an initial subset of the method-specific identifier as an entity ID, usable for all references to that entity, while using the balance of the method-specific identifier for additional information, such as initial state. Or the DID method could simply define this extra part is not used.
My initial recommend is that only that the id part have consistent semantics across methods. The meaning of the data part, IMO, could be method specific, and as such always optional. Although, standardizing its use for "initial state" may prove useful.
@peacekeeper @msporny @talltree Does this relaxation of the method-specific identifier violate any deeply held notions of what a DID means?
@jandrieu I still think the A+ is to see if we can get some sort of param agreement that we can utilize for this. Also, I thought about it and it's going to be hard to make assumptions about DID colon-separated segments, because there's a broad range of uses. For example: we just agreed to add did:method:test:ID_SUFFIX as the way to note the difference between test/prod network IDs in a family of methods folks are developing, which means any other path assumptions may be fraught for this or similar segment uses by other groups. Params are my first choice, with anything else being less-than. I'm happy to wait on this and just proceed with the param discussion.
@peacekeeper @msporny @talltree Does this relaxation of the method-specific identifier violate any deeply held notions of what a DID means?
This is essentially the approach taken by the Hashlink spec (content_id:content_meta), except that in this case, you're prepending a global identifier and placing the content identifier after it (global_id:content_id:content_meta).
Raises the question why you couldn't just use a hashlink here, as hashlinks enable you to encode the data in the content_meta if you so desired.
In any case, feels like a workable solution for those that want initial_params with the caveats that @csuwildcat mentions above.
This approach does seem problematic for DID methods already using did:method:test:id and did:method:method-specific-thing:id. These should not be understood to be the DIDs did:method:test and did:method:method-specific-thing, respectively.
@dlongley Right. That's an issue. And if we allow the method to independently set which part of the method-specific id, then we don't have interoperability.
If that's not a reasonable solution, then, to @csuwildcat's dismay, I'll have to say I still don't find a compelling reason to put the meta-data in the URL itself. If the DID-URL recipient has a short time preference for resolution, then there is guaranteed to be a matching short-time-preference communication channel through which they received that URL. The initial state can easily be published through the same channel. For example, by wrapping it in a JSON payload:
{
did: "did:ex:abc",
initialState: "WHATEVER YOU WANT"
}
Just like VCs didn't depend on the eventual realization of DIDs, nor did they require specific crypto suites, there's no need, IMO, to put an initial state in the URL when the use cases that need such a feature can achieve it through the same communication channel already in place. In short, we are conflating meta-data that is useful but communicable through other means with the data required to use a DID at all. This feels like an optimization parameter one might send to a resolver rather than a requirement for the DID to work at all.
To wit: if the DID is going to be presented in a long-time-preference medium (blog post, business card, billboard, video credits, etc.), then there is no advantage to initial state. The initial state is useful when and only when there is a relatively short period of time between DID registration and DID resolution. That short time period implies that there is a communication channel, which could easily afford @csuwildcat his needed initial state without the burden of parameters (matrix or otherwise).
I disagree with @jandrieu's last statement of apparent certainty about this use case, the needs that motivate it, or the issues with sending strings required for resolution via random, non-standard communications channels/payloads. I only needed to say that so folks would not walk away thinking Joe's comments accurately reflect the technical needs and implications of this use case, or the view of most folks involved in these developments. That out of the way, I don't feel this Issue should be the place where we continue to discuss this need; I would suggest instead that we all focus on settling the issue of including a parameter mechanism (which the bulk of the community seems to be in favor of), given it would solve this Issue without any further discussion of this particular usage.
There are features which some of us need, which are fulfilled via DID Parameters.
Regardless of the mechanism for delivering these parameters, some of them will be used at resolution time.
DIDComm, Sidetree, DIDPeer, and this proposal for did:key all take this approach:
https://github.com/w3c-ccg/did-method-key/issues/5
Since the specifics of DID Method Implementation are outside of this WG, we cannot create statements in the core spec, about what a Method can and cannot do with a did parameter... we know that they will be available to the method at the time of resolution, and we know we are not in control of defining the specific process of resolution in for example: did:ion, did:elem, did:peer, or did:key...
How a method handles what comes after the method... is the methods business... and people are already relying on this behavior today:
https://github.com/decentralized-identity/ethr-did-resolver/blob/develop/doc/did-method-spec.md
I think this issue has become about things that are none actionable, and is blocked... entirely... by the matrix parameter discussion, and agreement that method implementers are free to define how a method is implemented.
I suggest we close this issue, have the discussion regarding DID parameters, and acknowledge that any handling of DID Params that is method specific, is outside of the control of this WG, and cannot be blocked by this wg, so long as the format of the parameters complies with the did core spec.
As the one who opened this issue, I don't see any further need to discuss it at this level, given the eventual mechanism it would rely on is far more general. Furthermore, as Orie notes, this is not something the WG or its members should dictate to Method implementers, so once we have a solution for the variant of parameters DIDs can use to pass resolution-related values of any kind, it will naturally satisfy this need.
Reopening, as the direction/mechanics of parameters cannot fulfill the need.
This issue is related to #431 and will be resolved once that issue is resolved. This issue needs a special topic call. This is a high priority issue before CR as it could affect normative sections of the specification.
This will be resolved once PR #431 is merged in.
PR #431 has been merged via PR #473; closing.
Most helpful comment
fwiw, this concept is also useful for btcr. We just haven't dug into this yet.