-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support ION DID Reconstruction & Long Form DID resolution #389
Conversation
Codecov Report
@@ Coverage Diff @@
## main #389 +/- ##
==========================================
+ Coverage 57.18% 57.34% +0.15%
==========================================
Files 65 67 +2
Lines 7016 7250 +234
==========================================
+ Hits 4012 4157 +145
- Misses 2290 2362 +72
- Partials 714 731 +17
|
did/ion/did.go
Outdated
@@ -85,3 +108,216 @@ func LongToShortFormDID(longFormDID string) (string, error) { | |||
} | |||
return shortFormDID, nil | |||
} | |||
|
|||
// PatchesToDIDDocument applies a list of sidetree state patches in order resulting in a DID Document. | |||
func PatchesToDIDDocument(shortFormDID, longFormDID string, patches []any) (*did.Document, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I strongly discourage the use of any
unless there is a strong reason to do so. Can you clarify why it's preferable to have patches be []any
?
An alternative is to define an interface that all patches implement.
type Patch interface{
isPatch()
}
func (a AddServicesAction) isPatch() { }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will switch to interface
did/ion/did.go
Outdated
switch knownPatch.(type) { | ||
case AddServicesAction: | ||
addServicePatch := knownPatch.(AddServicesAction) | ||
doc.Services = append(doc.Services, addServicePatch.Services...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you do this, then you don't need to re-cast within each case
. You can use typedPatch
switch knownPatch.(type) { | |
case AddServicesAction: | |
addServicePatch := knownPatch.(AddServicesAction) | |
doc.Services = append(doc.Services, addServicePatch.Services...) | |
switch typedPatch := knownPatch.(type) { | |
case AddServicesAction: | |
doc.Services = append(doc.Services, typedPatch.Services...) |
did/ion/did.go
Outdated
|
||
// tryCastPatch attempts to cast a patch to a known patch type | ||
func tryCastPatch(patch any) (any, error) { | ||
switch patch.(type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above.
Mixing map[string]any
and typed structs leads to too much freedom and code that is harder to maintain. Can this API be structured so we can have devs avoid shooting themselves in the foot?
did/ion/did.go
Outdated
removed := false | ||
for i, key := range doc.VerificationMethod { | ||
if key.ID == id { | ||
doc.VerificationMethod = append(doc.VerificationMethod[:i], doc.VerificationMethod[i+1:]...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a lot of copying around within this function. Is this OK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a way to remove an element in an array should be fine
did/ion/did.go
Outdated
doc.AssertionMethod = append(doc.AssertionMethod[:j], doc.AssertionMethod[j+1:]...) | ||
} | ||
} | ||
for j, auth := range doc.Authentication { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be KeyAgreement
?
did/ion/did.go
Outdated
doc.KeyAgreement = append(doc.KeyAgreement[:j], doc.KeyAgreement[j+1:]...) | ||
} | ||
} | ||
for j, auth := range doc.Authentication { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CapabilityInvocation
?
did/ion/did.go
Outdated
doc.CapabilityInvocation = append(doc.CapabilityInvocation[:j], doc.CapabilityInvocation[j+1:]...) | ||
} | ||
} | ||
for j, auth := range doc.Authentication { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CapabilityDelegation
?
did/ion/did.go
Outdated
|
||
// TODO(gabe): in the future handle the case where the value is not a simple ID | ||
// remove from all other key lists | ||
for j, auth := range doc.Authentication { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to un-nest this for loop and the following ones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
did/ion/did_test.go
Outdated
doc, err := PatchesToDIDDocument("did:ion:test", "", []any{struct{ Bad string }{Bad: "bad"}}) | ||
assert.Empty(tt, doc) | ||
assert.Error(tt, err) | ||
assert.Contains(tt, err.Error(), "unknown patch type") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and elsewhere
assert.Contains(tt, err.Error(), "unknown patch type") | |
assert.ErrorContains(tt, err, "unknown patch type") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
did/ion/did.go
Outdated
doc.AssertionMethod = append(doc.AssertionMethod[:j], doc.AssertionMethod[j+1:]...) | ||
} | ||
} | ||
for j, auth := range doc.Authentication { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is repeated. Is it intentional?
If not, should there be a test for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
did/ion/did.go
Outdated
doc.Authentication = append(doc.Authentication[:j], doc.Authentication[j+1:]...) | ||
} | ||
} | ||
for j, auth := range doc.CapabilityInvocation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for j, auth := range doc.CapabilityInvocation { | |
for j, ci := range doc.CapabilityInvocation { |
did/ion/did.go
Outdated
doc.CapabilityInvocation = append(doc.CapabilityInvocation[:j], doc.CapabilityInvocation[j+1:]...) | ||
} | ||
} | ||
for j, auth := range doc.CapabilityDelegation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for j, auth := range doc.CapabilityDelegation { | |
for j, cd := range doc.CapabilityDelegation { |
// ResolutionOption https://www.w3.org/TR/did-spec-registries/#did-resolution-options | ||
type ResolutionOption any | ||
// Option https://www.w3.org/TR/did-spec-registries/#did-resolution-options | ||
type Option any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having any
makes me sad :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can fix this when we implement any options
#331
if !ok { | ||
return fmt.Errorf("patch has no action") | ||
} | ||
currPatchBytes, err := json.Marshal(currPatch) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is a way to use json.RawMessage to avoid the whole unmarshal -> marshal -> unmarshal round tripping, but I've never done it. If you're feeling brave :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm you're right but I am not feeling brave
did/ion/did.go
Outdated
|
||
// TODO(gabe): in the future handle the case where the value is not a simple ID | ||
// remove from all other key lists | ||
for j, auth := range doc.Authentication { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also unnest this and the following for loops?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how? this needs to be nested as far as I can tell
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i have no idea what I was talking about... ignore please.
Co-authored-by: Andres Uribe <[email protected]>
Co-authored-by: Andres Uribe <[email protected]>
#349
adds the ability to reconstruct any ION DID's state from a set of patches