Skip to content

Commit

Permalink
feat: updated to support abstract specs (#141)
Browse files Browse the repository at this point in the history
* updated to support abstract specs

* updated model specs for resolution and metadata

* adjust not error

* small twaeks to teh data model for resolution

* change resolution error to a pointer

* updated to comment around validation

* Update did/model.go

Co-authored-by: Gabe <gcohen@squareup.com>
  • Loading branch information
andorsk and Gabe authored Aug 15, 2022
1 parent 4ad8843 commit 7327f20
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 33 deletions.
6 changes: 4 additions & 2 deletions did/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ func ParseDID(did DID, prefix string) (string, error) {
return split[1], nil
}

type Resolver interface {
Resolve(d DID) (*DIDDocument, error)
type ResolutionOptions interface{}

type DIDResolver interface {
Resolve(d DID, opts ResolutionOptions) (*DIDDocument, *DIDResolutionMetadata, *DIDDocumentMetadata, error)
}
30 changes: 30 additions & 0 deletions did/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,36 @@ const (
EcdsaSecp256k1VerificationKey2019 cryptosuite.LDKeyType = "EcdsaSecp256k1VerificationKey2019"
)

// https://www.w3.org/TR/did-core/#did-document-metadata
type DIDDocumentMetadata struct {
Created string `json:"created,omitempty" validate:"datetime"`
Updated string `json:"updated,omitempty" validate:"datetime"`
Deactivated bool `json:"deactivated"`
NextUpdate string `json:"nextUpdate,omitempty"`
VersionID string `json:"versionId,omitempty"`
NextVersionID string `json:"nextVersionId,omitempty"`
EquivalentID string `json:"equivalentId,omitempty"`
CanonicalID string `json:"canonicalId,omitempty"`
}

func (s *DIDDocumentMetadata) IsValid() bool {
return util.NewValidator().Struct(s) == nil
}

// https://www.w3.org/TR/did-core/#did-resolution-metadata
type ResolutionError struct {
Code string `json:"code"`
InvalidDID bool `json:"invalidDid"`
NotFound bool `json:"notFound"`
RepresentationNotSupported bool `json:"representationNotSupported"`
}

// https://www.w3.org/TR/did-core/#did-resolution-metadata
type DIDResolutionMetadata struct {
contentType string
error *ResolutionError
}

// DIDDocument is a representation of the did core specification https://www.w3.org/TR/did-core
// TODO(gabe) enforce validation of DID syntax https://www.w3.org/TR/did-core/#did-syntax
type DIDDocument struct {
Expand Down
51 changes: 26 additions & 25 deletions did/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type (
PurposeType string
)

var availablePeerMethods = map[string]Resolver{
var availablePeerMethods = map[string]DIDResolver{
"0": PeerMethod0{},
"1": PeerMethod1{},
"2": PeerMethod2{},
Expand Down Expand Up @@ -188,29 +188,29 @@ func (d DIDPeer) IsValidPurpose(p PurposeType) bool {
//
// This allows PeerMethod0 to implement the DID Resolver
// interface and be used to expand the did into the DID Document.
func (m PeerMethod0) Resolve(did DID) (*DIDDocument, error) {
func (m PeerMethod0) Resolve(did DID, opts ResolutionOptions) (*DIDDocument, *DIDResolutionMetadata, *DIDDocumentMetadata, error) {

d, ok := did.(DIDPeer)
if !ok {
return nil, errors.Wrap(util.CastingError, "did:peer")
return nil, nil, nil, errors.Wrap(util.CastingError, "did:peer")
}

v, err := d.Parse()
if err != nil {
return nil, err
return nil, nil, nil, err
}

pubKey, keyType, err := decodeEncodedKey(v)
if err != nil {
return nil, err
return nil, nil, nil, err
}

keyReference := Hash + v
id := string(d)

verificationMethod, err := constructVerificationMethod(id, keyReference, pubKey, keyType)
if err != nil {
return nil, err
return nil, nil, nil, err
}

verificationMethodSet := []VerificationMethodSet{
Expand All @@ -225,16 +225,16 @@ func (m PeerMethod0) Resolve(did DID) (*DIDDocument, error) {
AssertionMethod: verificationMethodSet,
KeyAgreement: verificationMethodSet,
CapabilityDelegation: verificationMethodSet,
}, nil
}, nil, nil, nil
}

func (m PeerMethod1) Resolve(d DID) (*DIDDocument, error) {
func (m PeerMethod1) Resolve(d DID, opts ResolutionOptions) (*DIDDocument, *DIDResolutionMetadata, *DIDDocumentMetadata, error) {
d, ok := d.(DIDPeer)
if !ok {
return nil, errors.Wrap(util.CastingError, "did:peer")
return nil, nil, nil, errors.Wrap(util.CastingError, "did:peer")
}

return nil, util.NotImplementedError
return nil, nil, nil, util.NotImplementedError

}

Expand All @@ -258,22 +258,22 @@ func (d DIDPeer) buildVerificationMethod(data, did string) (*VerificationMethod,
// Split the DID string into element.
// Extract element purpose and decode each key or service.
// Insert each key or service into the document according to the designated pu
func (m PeerMethod2) Resolve(did DID) (*DIDDocument, error) {
func (m PeerMethod2) Resolve(did DID, opts ResolutionOptions) (*DIDDocument, *DIDResolutionMetadata, *DIDDocumentMetadata, error) {

d, ok := did.(DIDPeer)

if !ok {
return nil, errors.Wrap(util.CastingError, "did:peer")
return nil, nil, nil, errors.Wrap(util.CastingError, "did:peer")
}

parsed, err := d.Parse()
if err != nil {
return nil, err
return nil, nil, nil, err
}

entries := strings.Split(parsed, ".")
if len(entries) == 0 {
return nil, errors.New("no entries found")
return nil, nil, nil, errors.New("no entries found")
}

doc := NewDIDDocument()
Expand All @@ -292,39 +292,39 @@ func (m PeerMethod2) Resolve(did DID) (*DIDDocument, error) {
case PeerPurposeCapabilityServiceCode:
service, err := d.decodeServiceBlock("." + entry)
if err != nil {
return nil, err
return nil, nil, nil, err
}
service.ID = string(d) + "#didcommmessaging-0"
doc.Services = append(doc.Services, *service)
case PeerPurposeEncryptionCode:
vm, err := d.buildVerificationMethod(entry[1:], string(d))
if err != nil {
return nil, errors.Wrap(err, "failed to build encryption code")
return nil, nil, nil, errors.Wrap(err, "failed to build encryption code")
}
doc.KeyAgreement = append(doc.KeyAgreement, *vm)
case PeerPurposeVerificationCode:
vm, err := d.buildVerificationMethod(entry[1:], string(d))
if err != nil {
return nil, errors.Wrap(err, "failed to build verification code")
return nil, nil, nil, errors.Wrap(err, "failed to build verification code")
}
doc.Authentication = append(doc.Authentication, *vm)
case PeerPurposeCapabilityInvocationCode:
vm, err := d.buildVerificationMethod(entry[1:], string(d))
if err != nil {
return nil, errors.Wrap(err, "failed to build capabilities invocation code")
return nil, nil, nil, errors.Wrap(err, "failed to build capabilities invocation code")
}
doc.CapabilityInvocation = append(doc.CapabilityInvocation, *vm)
case PeerPurposeCapabilityDelegationCode:
vm, err := d.buildVerificationMethod(entry[1:], string(d))
if err != nil {
return nil, errors.Wrap(err, "failed to build capability delegation code")
return nil, nil, nil, errors.Wrap(err, "failed to build capability delegation code")
}
doc.CapabilityDelegation = append(doc.CapabilityDelegation, *vm)
default:
return nil, errors.Wrap(util.UnsupportedError, string(entry[0]))
return nil, nil, nil, errors.Wrap(util.UnsupportedError, string(entry[0]))
}
}
return doc, nil
return doc, nil, nil, nil
}

// If numalgo == 2, the generation mode is similar to Method 0 (and therefore
Expand Down Expand Up @@ -510,7 +510,7 @@ func (d DIDPeer) GetMethodID() (string, error) {
}

// id:peer:<method>
func (d DIDPeer) GetMethod() (Resolver, error) {
func (d DIDPeer) GetMethod() (DIDResolver, error) {

m := string(d[9])

Expand All @@ -530,12 +530,13 @@ func (d DIDPeer) GetMethod() (Resolver, error) {
return nil, errors.New(fmt.Sprintf("%s method not supported", m))
}

func (d DIDPeer) Resolve() (*DIDDocument, error) {
func (d DIDPeer) Resolve() (*DIDDocument, *DIDResolutionMetadata, *DIDDocumentMetadata, error) {
m, err := d.GetMethod()
if err != nil {
return nil, err
return nil, nil, nil, err
}
return m.Resolve(d)
did, rm, dm, err := m.Resolve(d, nil)
return did, rm, dm, err
}

func (d DIDPeer) ToString() string {
Expand Down
10 changes: 4 additions & 6 deletions did/peer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestPeerMethod0(t *testing.T) {
did, err := m0.Generate(kt, pubKey)
assert.NoError(t, err)

doc, err := m0.Resolve(*did)
doc, _, _, err := m0.Resolve(*did, nil)
assert.NoError(t, err)
testDoc := makeSamplePeerDIDDocument1()

Expand Down Expand Up @@ -128,7 +128,7 @@ func getSampleDIDDocumentMethod0() *DIDDocument {

func TestPeerResolveMethod0(t *testing.T) {
did := DIDPeer("did:peer:0z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH")
didDoc, err := PeerMethod0{}.Resolve(did)
didDoc, _, _, err := PeerMethod0{}.Resolve(did, nil)
assert.NoError(t, err)
gtestDoc := getSampleDIDDocumentMethod0()
assert.Equal(t, gtestDoc.Context, didDoc.Context)
Expand All @@ -153,10 +153,8 @@ func TestPeerResolveMethod2(t *testing.T) {
testDoc := makeSamplePeerDIDDocument()
did := DIDPeer(testDoc.ID)

doc, err := did.Resolve()
if err != nil {
t.Fatal(err)
}
doc, _, _, err := did.Resolve()
assert.NoError(t, err)

assert.Equal(t, testDoc.Context, doc.Context)
assert.Equal(t, testDoc.ID, doc.ID)
Expand Down

0 comments on commit 7327f20

Please sign in to comment.