This repository has been archived by the owner on Mar 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 162
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #938 from Moopli/725
feat: Protocols can use DIDs to identify the agents they communicate with
- Loading branch information
Showing
42 changed files
with
1,107 additions
and
337 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package didconnection | ||
|
||
import ( | ||
"errors" | ||
|
||
diddoc "github.com/hyperledger/aries-framework-go/pkg/doc/did" | ||
) | ||
|
||
// Store stores DIDs indexed by public key, so agents can find the DID associated with a given key. | ||
type Store interface { | ||
// SaveDID saves a DID indexed by the given public keys to the Store | ||
SaveDID(did string, keys ...string) error | ||
// GetDID gets the DID stored under the given key | ||
GetDID(key string) (string, error) | ||
// SaveDIDByResolving resolves a DID using the VDR then saves the map from keys -> did | ||
SaveDIDByResolving(did string, keys ...string) error | ||
// SaveDIDFromDoc saves a map from keys -> did for a did doc | ||
SaveDIDFromDoc(doc *diddoc.Doc) error | ||
} | ||
|
||
// ErrNotFound signals that the entry for the given DID and key is not present in the store. | ||
var ErrNotFound = errors.New("did not found under given key") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package didconnection | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
|
||
diddoc "github.com/hyperledger/aries-framework-go/pkg/doc/did" | ||
"github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdri" | ||
"github.com/hyperledger/aries-framework-go/pkg/storage" | ||
) | ||
|
||
// ConnectionStore stores DIDs indexed by key | ||
type ConnectionStore struct { | ||
store storage.Store | ||
vdr vdri.Registry | ||
} | ||
|
||
type didRecord struct { | ||
DID string `json:"did,omitempty"` | ||
} | ||
|
||
type provider interface { | ||
StorageProvider() storage.Provider | ||
VDRIRegistry() vdri.Registry | ||
} | ||
|
||
// New returns a new did lookup Store | ||
func New(ctx provider) (*ConnectionStore, error) { | ||
store, err := ctx.StorageProvider().OpenStore("didconnection") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &ConnectionStore{store: store, vdr: ctx.VDRIRegistry()}, nil | ||
} | ||
|
||
// saveDID saves a DID, indexed using the given public key | ||
func (c *ConnectionStore) saveDID(did, key string) error { | ||
data := didRecord{ | ||
DID: did, | ||
} | ||
|
||
bytes, err := json.Marshal(data) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return c.store.Put(key, bytes) | ||
} | ||
|
||
// SaveDID saves a DID, indexed using the given public keys | ||
func (c *ConnectionStore) SaveDID(did string, keys ...string) error { | ||
for _, key := range keys { | ||
err := c.saveDID(did, key) | ||
if err != nil { | ||
return fmt.Errorf("saving DID in did map: %w", err) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// SaveDIDFromDoc saves a map from a did doc's keys to the did | ||
func (c *ConnectionStore) SaveDIDFromDoc(doc *diddoc.Doc) error { | ||
var keys []string | ||
for i := range doc.PublicKey { | ||
keys = append(keys, string(doc.PublicKey[i].Value)) | ||
} | ||
|
||
return c.SaveDID(doc.ID, keys...) | ||
} | ||
|
||
// SaveDIDByResolving resolves a DID using the VDR then saves the map from keys -> did | ||
// keys: fallback keys in case the DID can't be resolved | ||
func (c *ConnectionStore) SaveDIDByResolving(did string, keys ...string) error { | ||
doc, err := c.vdr.Resolve(did) | ||
if errors.Is(err, vdri.ErrNotFound) { | ||
return c.SaveDID(did, keys...) | ||
} else if err != nil { | ||
return err | ||
} | ||
|
||
return c.SaveDIDFromDoc(doc) | ||
} | ||
|
||
// GetDID gets the DID stored under the given key | ||
func (c *ConnectionStore) GetDID(key string) (string, error) { | ||
bytes, err := c.store.Get(key) | ||
if errors.Is(err, storage.ErrDataNotFound) { | ||
return "", ErrNotFound | ||
} else if err != nil { | ||
return "", err | ||
} | ||
|
||
var record didRecord | ||
|
||
err = json.Unmarshal(bytes, &record) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return record.DID, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package didconnection | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
vdriapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdri" | ||
mockdiddoc "github.com/hyperledger/aries-framework-go/pkg/internal/mock/diddoc" | ||
mockstorage "github.com/hyperledger/aries-framework-go/pkg/internal/mock/storage" | ||
mockvdri "github.com/hyperledger/aries-framework-go/pkg/internal/mock/vdri" | ||
"github.com/hyperledger/aries-framework-go/pkg/storage" | ||
) | ||
|
||
type ctx struct { | ||
store storage.Provider | ||
vdr vdriapi.Registry | ||
} | ||
|
||
func (c *ctx) StorageProvider() storage.Provider { | ||
return c.store | ||
} | ||
|
||
func (c *ctx) VDRIRegistry() vdriapi.Registry { | ||
return c.vdr | ||
} | ||
|
||
func TestBaseConnectionStore(t *testing.T) { | ||
prov := ctx{ | ||
store: mockstorage.NewMockStoreProvider(), | ||
vdr: &mockvdri.MockVDRIRegistry{ | ||
CreateValue: mockdiddoc.GetMockDIDDoc(), | ||
ResolveValue: mockdiddoc.GetMockDIDDoc(), | ||
}, | ||
} | ||
|
||
t.Run("New", func(t *testing.T) { | ||
_, err := New(&prov) | ||
require.NoError(t, err) | ||
|
||
_, err = New(&ctx{ | ||
store: &mockstorage.MockStoreProvider{ | ||
ErrOpenStoreHandle: fmt.Errorf("store error"), | ||
}, | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "store error") | ||
}) | ||
|
||
t.Run("SaveDID error", func(t *testing.T) { | ||
cs, err := New(&ctx{ | ||
store: &mockstorage.MockStoreProvider{ | ||
Store: &mockstorage.MockStore{ | ||
Store: map[string][]byte{}, | ||
ErrPut: fmt.Errorf("put error"), | ||
}, | ||
}, | ||
vdr: &mockvdri.MockVDRIRegistry{ | ||
CreateValue: mockdiddoc.GetMockDIDDoc(), | ||
ResolveValue: mockdiddoc.GetMockDIDDoc(), | ||
}, | ||
}) | ||
require.NoError(t, err) | ||
|
||
err = cs.SaveDID("did", "key") | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "put error") | ||
}) | ||
|
||
t.Run("SaveDID + GetDID", func(t *testing.T) { | ||
connStore, err := New(&prov) | ||
require.NoError(t, err) | ||
|
||
err = connStore.SaveDID("did:abcde", "abcde") | ||
require.NoError(t, err) | ||
|
||
didVal, err := connStore.GetDID("abcde") | ||
require.NoError(t, err) | ||
require.Equal(t, "did:abcde", didVal) | ||
|
||
wrong, err := connStore.GetDID("fhtagn") | ||
require.EqualError(t, err, ErrNotFound.Error()) | ||
require.Equal(t, "", wrong) | ||
|
||
err = connStore.store.Put("bad-data", []byte("aaooga")) | ||
require.NoError(t, err) | ||
|
||
_, err = connStore.GetDID("bad-data") | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "invalid character") | ||
}) | ||
|
||
t.Run("SaveDIDFromDoc", func(t *testing.T) { | ||
connStore, err := New(&prov) | ||
require.NoError(t, err) | ||
|
||
err = connStore.SaveDIDFromDoc(mockdiddoc.GetMockDIDDoc()) | ||
require.NoError(t, err) | ||
}) | ||
|
||
t.Run("SaveDIDByResolving success", func(t *testing.T) { | ||
cs, err := New(&prov) | ||
require.NoError(t, err) | ||
|
||
err = cs.SaveDIDByResolving(mockdiddoc.GetMockDIDDoc().ID) | ||
require.NoError(t, err) | ||
}) | ||
|
||
t.Run("SaveDIDByResolving error", func(t *testing.T) { | ||
prov := ctx{ | ||
store: mockstorage.NewMockStoreProvider(), | ||
vdr: &mockvdri.MockVDRIRegistry{ResolveErr: fmt.Errorf("resolve error")}, | ||
} | ||
|
||
cs, err := New(&prov) | ||
require.NoError(t, err) | ||
|
||
err = cs.SaveDIDByResolving("did") | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "resolve error") | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.