From 1df09bcc50a52890964a5e168fbaa53072fd02d4 Mon Sep 17 00:00:00 2001 From: "sudesh.shetty" Date: Tue, 17 Aug 2021 15:33:33 -0400 Subject: [PATCH] fix: integration issues in wallet DIDcomm interfaces - Part of #2433 Signed-off-by: sudesh.shetty --- pkg/client/vcwallet/client.go | 6 +- pkg/client/vcwallet/client_test.go | 42 ++++-- pkg/controller/command/vcwallet/command.go | 17 ++- .../command/vcwallet/command_test.go | 72 ++++++---- pkg/controller/command/vcwallet/models.go | 30 +++- pkg/controller/rest/vcwallet/operation.go | 2 + .../rest/vcwallet/operation_test.go | 53 ++++--- .../middleware/presentproof/middlewares.go | 42 +++--- .../protocol/didexchange/mock_didexchange.go | 10 ++ pkg/wallet/options.go | 39 ++++- pkg/wallet/wallet.go | 63 ++++++--- pkg/wallet/wallet_test.go | 109 ++++++++++---- .../test/didexchange/didexchange_e2e.js | 4 +- .../test/introduce/introduce.js | 4 +- test/bdd/features/ld_e2e_controller.feature | 2 +- test/bdd/features/ld_e2e_sdk.feature | 2 +- test/bdd/fixtures/agent-rest/.env | 2 +- .../fixtures/agent-rest/docker-compose.yml | 14 +- .../presentation_multiple_attachments.json | 96 ++++++++++--- ...est_presentation_multiple_attachments.json | 133 +----------------- 20 files changed, 441 insertions(+), 301 deletions(-) diff --git a/pkg/client/vcwallet/client.go b/pkg/client/vcwallet/client.go index 221518cf7b..88ec726163 100644 --- a/pkg/client/vcwallet/client.go +++ b/pkg/client/vcwallet/client.go @@ -47,6 +47,8 @@ type didCommProvider interface { ServiceEndpoint() string ProtocolStateStorageProvider() storage.Provider Service(id string) (interface{}, error) + KeyType() kms.KeyType + KeyAgreementType() kms.KeyType } // walletAuth is auth function which returns wallet unlock token. @@ -405,11 +407,11 @@ func (c *Client) ProposePresentation(invitation *outofband.Invitation, options . // - error if operation fails. // // TODO: wait for acknowledgement option to be added. -func (c *Client) PresentProof(thID string, presentation *verifiable.Presentation) error { +func (c *Client) PresentProof(thID string, presentProofFrom wallet.PresentProofFrom) error { auth, err := c.auth() if err != nil { return err } - return c.wallet.PresentProof(auth, thID, presentation) + return c.wallet.PresentProof(auth, thID, presentProofFrom) } diff --git a/pkg/client/vcwallet/client_test.go b/pkg/client/vcwallet/client_test.go index b5604a4b18..1eb53c7932 100644 --- a/pkg/client/vcwallet/client_test.go +++ b/pkg/client/vcwallet/client_test.go @@ -23,6 +23,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" + "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator" outofbandSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofband" presentproofSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/presentproof" "github.com/hyperledger/aries-framework-go/pkg/doc/did" @@ -34,6 +35,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/kms" cryptomock "github.com/hyperledger/aries-framework-go/pkg/mock/crypto" mockdidexchange "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/didexchange" + mockmediator "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator" mockoutofband "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/outofband" mockpresentproof "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/presentproof" mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider" @@ -1551,6 +1553,10 @@ func TestClient_Connect(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -1561,8 +1567,7 @@ func TestClient_Connect(t *testing.T) { return nil }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc vcWallet, err := New(sampleUser, mockctx) require.NoError(t, err) @@ -1578,13 +1583,12 @@ func TestClient_Connect(t *testing.T) { }) t.Run("test did connect failure", func(t *testing.T) { - oobSvc := &mockoutofband.MockOobService{ + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { return fmt.Errorf(sampleClientErr) }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc vcWallet, err := New(sampleUser, mockctx) require.NoError(t, err) @@ -1618,6 +1622,11 @@ func TestClient_ProposePresentation(t *testing.T) { err := CreateProfile(sampleUser, mockctx, wallet.WithPassphrase(samplePassPhrase)) require.NoError(t, err) + const ( + myDID = "did:mydid:123" + theirDID = "did:theirdid:123" + ) + t.Run("test propose presentation success", func(t *testing.T) { sampleConnID := uuid.New().String() @@ -1625,6 +1634,10 @@ func TestClient_ProposePresentation(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -1635,6 +1648,7 @@ func TestClient_ProposePresentation(t *testing.T) { return nil }, } + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc thID := uuid.New().String() @@ -1646,6 +1660,8 @@ func TestClient_ProposePresentation(t *testing.T) { Msg: service.NewDIDCommMsgMap(&presentproofSvc.RequestPresentation{ Comment: "mock msg", }), + MyDID: myDID, + TheirDID: theirDID, }, }, nil }, @@ -1653,8 +1669,6 @@ func TestClient_ProposePresentation(t *testing.T) { return thID, nil }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc mockctx.ServiceMap[presentproofSvc.Name] = ppSvc store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) @@ -1662,8 +1676,8 @@ func TestClient_ProposePresentation(t *testing.T) { record := &connection.Record{ ConnectionID: sampleConnID, - MyDID: "did:mydid", - TheirDID: "did:theirDID", + MyDID: myDID, + TheirDID: theirDID, } recordBytes, err := json.Marshal(record) require.NoError(t, err) @@ -1730,7 +1744,7 @@ func TestClient_PresentProof(t *testing.T) { require.NoError(t, err) defer vcWallet.Close() - err = vcWallet.PresentProof(uuid.New().String(), &verifiable.Presentation{}) + err = vcWallet.PresentProof(uuid.New().String(), wallet.FromPresentation(&verifiable.Presentation{})) require.NoError(t, err) }) @@ -1739,7 +1753,7 @@ func TestClient_PresentProof(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, vcWallet) - err = vcWallet.PresentProof(uuid.New().String(), &verifiable.Presentation{}) + err = vcWallet.PresentProof(uuid.New().String(), wallet.FromPresentation(&verifiable.Presentation{})) require.True(t, errors.Is(err, ErrWalletLocked)) }) } @@ -1751,8 +1765,10 @@ func newMockProvider(t *testing.T) *mockprovider.Provider { require.NoError(t, err) serviceMap := map[string]interface{}{ - presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, - outofbandSvc.Name: &mockoutofband.MockOobService{}, + presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, + outofbandSvc.Name: &mockoutofband.MockOobService{}, + didexchange.DIDExchange: &mockdidexchange.MockDIDExchangeSvc{}, + mediator.Coordination: &mockmediator.MockMediatorSvc{}, } return &mockprovider.Provider{ diff --git a/pkg/controller/command/vcwallet/command.go b/pkg/controller/command/vcwallet/command.go index 93180b2fac..7385547350 100644 --- a/pkg/controller/command/vcwallet/command.go +++ b/pkg/controller/command/vcwallet/command.go @@ -180,6 +180,8 @@ type didCommProvider interface { ServiceEndpoint() string ProtocolStateStorageProvider() storage.Provider Service(id string) (interface{}, error) + KeyType() kms.KeyType + KeyAgreementType() kms.KeyType } // Command contains operations provided by verifiable credential wallet controller. @@ -735,8 +737,8 @@ func (o *Command) Connect(rw io.Writer, req io.Reader) command.Error { connectionID, err := vcWallet.Connect(request.Auth, request.Invitation, wallet.WithConnectTimeout(request.Timeout), wallet.WithReuseDID(request.ReuseConnection), - wallet.WithReuseAnyConnection(), wallet.WithMyLabel(request.MyLabel), - wallet.WithRouterConnections(request.RouterConnections)) + wallet.WithReuseAnyConnection(request.ReuseAnyConnection), wallet.WithMyLabel(request.MyLabel), + wallet.WithRouterConnections(request.RouterConnections...)) if err != nil { logutil.LogInfo(logger, CommandName, ConnectMethod, err.Error()) @@ -777,7 +779,12 @@ func (o *Command) ProposePresentation(rw io.Writer, req io.Reader) command.Error } msg, err := vcWallet.ProposePresentation(request.Auth, request.Invitation, - wallet.WithFromDID(request.FromDID), wallet.WithPresentProofTimeout(request.Timeout)) + wallet.WithFromDID(request.FromDID), wallet.WithPresentProofTimeout(request.Timeout), + wallet.WithConnectOptions(wallet.WithConnectTimeout(request.ConnectionOpts.Timeout), + wallet.WithReuseDID(request.ConnectionOpts.ReuseConnection), + wallet.WithReuseAnyConnection(request.ConnectionOpts.ReuseAnyConnection), + wallet.WithMyLabel(request.ConnectionOpts.MyLabel), + wallet.WithRouterConnections(request.ConnectionOpts.RouterConnections...))) if err != nil { logutil.LogInfo(logger, CommandName, ProposePresentationMethod, err.Error()) @@ -792,7 +799,7 @@ func (o *Command) ProposePresentation(rw io.Writer, req io.Reader) command.Error return nil } -// PresentProof sends message present proof message from wallet to relying party. +// PresentProof sends present proof message from wallet to relying party. // // Currently Supporting // [0454-present-proof-v2](https://github.com/hyperledger/aries-rfcs/tree/master/features/0454-present-proof-v2) @@ -814,7 +821,7 @@ func (o *Command) PresentProof(rw io.Writer, req io.Reader) command.Error { return command.NewExecuteError(PresentProofErrorCode, err) } - err = vcWallet.PresentProof(request.Auth, request.ThreadID, request.Presentation) + err = vcWallet.PresentProof(request.Auth, request.ThreadID, wallet.FromRawPresentation(request.Presentation)) if err != nil { logutil.LogInfo(logger, CommandName, PresentProofMethod, err.Error()) diff --git a/pkg/controller/command/vcwallet/command_test.go b/pkg/controller/command/vcwallet/command_test.go index 48dea5da04..8d6d6ef678 100644 --- a/pkg/controller/command/vcwallet/command_test.go +++ b/pkg/controller/command/vcwallet/command_test.go @@ -22,10 +22,10 @@ import ( outofbandClient "github.com/hyperledger/aries-framework-go/pkg/client/outofband" "github.com/hyperledger/aries-framework-go/pkg/controller/command" - "github.com/hyperledger/aries-framework-go/pkg/controller/command/outofband" "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" + "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator" outofbandSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofband" presentproofSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/presentproof" "github.com/hyperledger/aries-framework-go/pkg/doc/did" @@ -34,6 +34,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil" "github.com/hyperledger/aries-framework-go/pkg/kms" mockdidexchange "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/didexchange" + mockmediator "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator" mockoutofband "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/outofband" mockpresentproof "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/presentproof" mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider" @@ -1851,6 +1852,10 @@ func TestCommand_Connect(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -1861,16 +1866,15 @@ func TestCommand_Connect(t *testing.T) { return nil }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc cmd := New(mockctx, &Config{}) request := &ConnectRequest{ WalletAuth: WalletAuth{UserID: sampleDIDCommUser, Auth: token}, - AcceptInvitationArgs: outofband.AcceptInvitationArgs{ - Invitation: &outofbandClient.Invitation{}, - MyLabel: "sample-label", + Invitation: &outofbandClient.Invitation{}, + ConnectOpts: ConnectOpts{ + MyLabel: "sample-label", }, } @@ -1890,16 +1894,15 @@ func TestCommand_Connect(t *testing.T) { return "", fmt.Errorf(sampleCommandError) }, } - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc cmd := New(mockctx, &Config{}) request := &ConnectRequest{ WalletAuth: WalletAuth{UserID: sampleDIDCommUser, Auth: token}, - AcceptInvitationArgs: outofband.AcceptInvitationArgs{ - Invitation: &outofbandClient.Invitation{}, - MyLabel: "sample-label", + Invitation: &outofbandClient.Invitation{}, + ConnectOpts: ConnectOpts{ + MyLabel: "sample-label", }, } @@ -1928,9 +1931,9 @@ func TestCommand_Connect(t *testing.T) { request := &ConnectRequest{ WalletAuth: WalletAuth{UserID: sampleUserID, Auth: sampleFakeTkn}, - AcceptInvitationArgs: outofband.AcceptInvitationArgs{ - Invitation: &outofbandClient.Invitation{}, - MyLabel: "sample-label", + Invitation: &outofbandClient.Invitation{}, + ConnectOpts: ConnectOpts{ + MyLabel: "sample-label", }, } @@ -1960,12 +1963,22 @@ func TestCommand_ProposePresentation(t *testing.T) { defer lock() + const ( + myDID = "did:mydid:123" + theirDID = "did:theirdid:123" + ) + t.Run("successfully send propose presentation", func(t *testing.T) { sampleConnID := uuid.New().String() + oobSvc := &mockoutofband.MockOobService{ AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -1976,6 +1989,7 @@ func TestCommand_ProposePresentation(t *testing.T) { return nil }, } + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc thID := uuid.New().String() ppSvc := &mockpresentproof.MockPresentProofSvc{ @@ -1986,6 +2000,8 @@ func TestCommand_ProposePresentation(t *testing.T) { Msg: service.NewDIDCommMsgMap(&presentproofSvc.RequestPresentation{ Comment: "mock msg", }), + MyDID: myDID, + TheirDID: theirDID, }, }, nil }, @@ -1993,8 +2009,6 @@ func TestCommand_ProposePresentation(t *testing.T) { return thID, nil }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc mockctx.ServiceMap[presentproofSvc.Name] = ppSvc store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) @@ -2002,8 +2016,8 @@ func TestCommand_ProposePresentation(t *testing.T) { record := &connection.Record{ ConnectionID: sampleConnID, - MyDID: "did:mydid", - TheirDID: "did:theirDID", + MyDID: myDID, + TheirDID: theirDID, } recordBytes, err := json.Marshal(record) require.NoError(t, err) @@ -2039,9 +2053,9 @@ func TestCommand_ProposePresentation(t *testing.T) { request := &ConnectRequest{ WalletAuth: WalletAuth{UserID: sampleDIDCommUser, Auth: token}, - AcceptInvitationArgs: outofband.AcceptInvitationArgs{ - Invitation: &outofbandClient.Invitation{}, - MyLabel: "sample-label", + Invitation: &outofbandClient.Invitation{}, + ConnectOpts: ConnectOpts{ + MyLabel: "sample-label", }, } @@ -2070,9 +2084,9 @@ func TestCommand_ProposePresentation(t *testing.T) { request := &ConnectRequest{ WalletAuth: WalletAuth{UserID: sampleUserID, Auth: sampleFakeTkn}, - AcceptInvitationArgs: outofband.AcceptInvitationArgs{ - Invitation: &outofbandClient.Invitation{}, - MyLabel: "sample-label", + Invitation: &outofbandClient.Invitation{}, + ConnectOpts: ConnectOpts{ + MyLabel: "sample-label", }, } @@ -2108,7 +2122,7 @@ func TestCommand_PresentProof(t *testing.T) { request := &PresentProofRequest{ WalletAuth: WalletAuth{UserID: sampleDIDCommUser, Auth: token}, ThreadID: uuid.New().String(), - Presentation: &verifiable.Presentation{}, + Presentation: json.RawMessage{}, } var b bytes.Buffer @@ -2130,7 +2144,7 @@ func TestCommand_PresentProof(t *testing.T) { request := &PresentProofRequest{ WalletAuth: WalletAuth{UserID: sampleDIDCommUser, Auth: token}, ThreadID: uuid.New().String(), - Presentation: &verifiable.Presentation{}, + Presentation: json.RawMessage{}, } var b bytes.Buffer @@ -2156,7 +2170,7 @@ func TestCommand_PresentProof(t *testing.T) { request := &PresentProofRequest{ WalletAuth: WalletAuth{UserID: sampleUserID, Auth: token}, ThreadID: uuid.New().String(), - Presentation: &verifiable.Presentation{}, + Presentation: json.RawMessage{}, } var b bytes.Buffer @@ -2236,8 +2250,10 @@ func newMockProvider(t *testing.T) *mockprovider.Provider { require.NoError(t, err) serviceMap := map[string]interface{}{ - presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, - outofbandSvc.Name: &mockoutofband.MockOobService{}, + presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, + outofbandSvc.Name: &mockoutofband.MockOobService{}, + didexchange.DIDExchange: &mockdidexchange.MockDIDExchangeSvc{}, + mediator.Coordination: &mockmediator.MockMediatorSvc{}, } return &mockprovider.Provider{ diff --git a/pkg/controller/command/vcwallet/models.go b/pkg/controller/command/vcwallet/models.go index 7bb82e859f..e4eb820bd6 100644 --- a/pkg/controller/command/vcwallet/models.go +++ b/pkg/controller/command/vcwallet/models.go @@ -11,7 +11,6 @@ import ( "time" "github.com/hyperledger/aries-framework-go/pkg/client/outofband" - outofbandCmd "github.com/hyperledger/aries-framework-go/pkg/controller/command/outofband" "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" "github.com/hyperledger/aries-framework-go/pkg/kms" @@ -314,9 +313,27 @@ type CreateKeyPairResponse struct { type ConnectRequest struct { WalletAuth - outofbandCmd.AcceptInvitationArgs + // out-of-band invitation to establish connection. + Invitation *outofband.Invitation `json:"invitation"` + + ConnectOpts +} + +// ConnectOpts is option for accepting out-of-band invitation and to perform DID exchange. +type ConnectOpts struct { + // Label to be shared with the other agent during the subsequent DID exchange. + MyLabel string `json:"myLabel,omitempty"` - // Timeout (in milliseconds) waiting for connection status to be completed + // router connections to be used to establish connection. + RouterConnections []string `json:"routerConnections,omitempty"` + + // DID to be used when reusing a connection. + ReuseConnection string `json:"reuseConnection,omitempty"` + + // To use any recognized DID in the services array for a reusable connection. + ReuseAnyConnection bool `json:"reuseAnyConnection,omitempty"` + + // Timeout (in milliseconds) waiting for connection status to be completed. Timeout time.Duration `json:"timeout,omitempty"` } @@ -336,8 +353,11 @@ type ProposePresentationRequest struct { // Optional From DID option to customize sender DID. FromDID string `json:"from,omitempty"` - // Timeout (in milliseconds) waiting for connection status to be completed + // Timeout (in milliseconds) waiting for operation to be completed. Timeout time.Duration `json:"timeout,omitempty"` + + // Options for accepting out-of-band invitation and to perform DID exchange (for DIDComm V1). + ConnectionOpts ConnectOpts `json:"connectOptions,omitempty"` } // ProposePresentationResponse is response model from wallet propose presentation operation. @@ -355,5 +375,5 @@ type PresentProofRequest struct { ThreadID string `json:"threadID,omitempty"` // presentation to be sent as part of present proof message. - Presentation *verifiable.Presentation `json:"presentation,omitempty"` + Presentation json.RawMessage `json:"presentation,omitempty"` } diff --git a/pkg/controller/rest/vcwallet/operation.go b/pkg/controller/rest/vcwallet/operation.go index 2af35636fb..5db359ac28 100644 --- a/pkg/controller/rest/vcwallet/operation.go +++ b/pkg/controller/rest/vcwallet/operation.go @@ -66,6 +66,8 @@ type didCommProvider interface { ServiceEndpoint() string ProtocolStateStorageProvider() storage.Provider Service(id string) (interface{}, error) + KeyType() kms.KeyType + KeyAgreementType() kms.KeyType } // Operation contains REST operations provided by verifiable credential wallet. diff --git a/pkg/controller/rest/vcwallet/operation_test.go b/pkg/controller/rest/vcwallet/operation_test.go index a74272055e..50f4e3ef2c 100644 --- a/pkg/controller/rest/vcwallet/operation_test.go +++ b/pkg/controller/rest/vcwallet/operation_test.go @@ -22,11 +22,11 @@ import ( "github.com/stretchr/testify/require" outofbandClient "github.com/hyperledger/aries-framework-go/pkg/client/outofband" - "github.com/hyperledger/aries-framework-go/pkg/controller/command/outofband" "github.com/hyperledger/aries-framework-go/pkg/controller/command/vcwallet" "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" + "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator" outofbandSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofband" presentproofSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/presentproof" "github.com/hyperledger/aries-framework-go/pkg/doc/did" @@ -35,6 +35,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil" "github.com/hyperledger/aries-framework-go/pkg/kms" mockdidexchange "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/didexchange" + mockmediator "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator" mockoutofband "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/outofband" mockpresentproof "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/presentproof" mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider" @@ -1410,6 +1411,10 @@ func TestOperation_Connect(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -1420,14 +1425,13 @@ func TestOperation_Connect(t *testing.T) { return nil }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc request := &vcwallet.ConnectRequest{ WalletAuth: vcwallet.WalletAuth{UserID: sampleDIDCommUser, Auth: token}, - AcceptInvitationArgs: outofband.AcceptInvitationArgs{ - Invitation: &outofbandClient.Invitation{}, - MyLabel: "sample-label", + Invitation: &outofbandClient.Invitation{}, + ConnectOpts: vcwallet.ConnectOpts{ + MyLabel: "sample-label", }, } @@ -1446,19 +1450,18 @@ func TestOperation_Connect(t *testing.T) { }) t.Run("wallet connect operation failure", func(t *testing.T) { - oobSvc := &mockoutofband.MockOobService{ + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { return fmt.Errorf(sampleCommandError) }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc request := &vcwallet.ConnectRequest{ WalletAuth: vcwallet.WalletAuth{UserID: sampleDIDCommUser, Auth: token}, - AcceptInvitationArgs: outofband.AcceptInvitationArgs{ - Invitation: &outofbandClient.Invitation{}, - MyLabel: "sample-label", + Invitation: &outofbandClient.Invitation{}, + ConnectOpts: vcwallet.ConnectOpts{ + MyLabel: "sample-label", }, } @@ -1489,12 +1492,21 @@ func TestOperation_ProposePresentation(t *testing.T) { defer lock() + const ( + myDID = "did:mydid:123" + theirDID = "did:theirdid:123" + ) + t.Run("wallet propose presentation success", func(t *testing.T) { sampleConnID := uuid.New().String() oobSvc := &mockoutofband.MockOobService{ AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -1505,6 +1517,7 @@ func TestOperation_ProposePresentation(t *testing.T) { return nil }, } + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc thID := uuid.New().String() ppSvc := &mockpresentproof.MockPresentProofSvc{ @@ -1515,6 +1528,8 @@ func TestOperation_ProposePresentation(t *testing.T) { Msg: service.NewDIDCommMsgMap(&presentproofSvc.RequestPresentation{ Comment: "mock msg", }), + MyDID: myDID, + TheirDID: theirDID, }, }, nil }, @@ -1531,8 +1546,8 @@ func TestOperation_ProposePresentation(t *testing.T) { record := &connection.Record{ ConnectionID: sampleConnID, - MyDID: "did:mydid", - TheirDID: "did:theirDID", + MyDID: myDID, + TheirDID: theirDID, } recordBytes, err := json.Marshal(record) require.NoError(t, err) @@ -1602,7 +1617,7 @@ func TestOperation_PresentProof(t *testing.T) { request := &vcwallet.PresentProofRequest{ WalletAuth: vcwallet.WalletAuth{UserID: sampleDIDCommUser, Auth: token}, ThreadID: uuid.New().String(), - Presentation: &verifiable.Presentation{}, + Presentation: json.RawMessage{}, } rq := httptest.NewRequest(http.MethodPost, PresentProofPath, getReader(t, request)) @@ -1625,7 +1640,7 @@ func TestOperation_PresentProof(t *testing.T) { request := &vcwallet.PresentProofRequest{ WalletAuth: vcwallet.WalletAuth{UserID: sampleDIDCommUser, Auth: token}, ThreadID: uuid.New().String(), - Presentation: &verifiable.Presentation{}, + Presentation: json.RawMessage{}, } rq := httptest.NewRequest(http.MethodPost, PresentProofPath, getReader(t, request)) @@ -1695,8 +1710,10 @@ func newMockProvider(t *testing.T) *mockprovider.Provider { require.NoError(t, err) serviceMap := map[string]interface{}{ - presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, - outofbandSvc.Name: &mockoutofband.MockOobService{}, + presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, + outofbandSvc.Name: &mockoutofband.MockOobService{}, + didexchange.DIDExchange: &mockdidexchange.MockDIDExchangeSvc{}, + mediator.Coordination: &mockmediator.MockMediatorSvc{}, } return &mockprovider.Provider{ diff --git a/pkg/didcomm/protocol/middleware/presentproof/middlewares.go b/pkg/didcomm/protocol/middleware/presentproof/middlewares.go index b9cb236b95..0f2c4e6119 100644 --- a/pkg/didcomm/protocol/middleware/presentproof/middlewares.go +++ b/pkg/didcomm/protocol/middleware/presentproof/middlewares.go @@ -164,7 +164,7 @@ func AddBBSProofFn(p Provider) func(presentation *verifiable.Presentation) error // PresentationDefinition the helper function for the present proof protocol that creates VP based on credentials that // were provided in the attachments according to the requested presentation definition. -func PresentationDefinition(p Provider, opts ...OptPD) presentproof.Middleware { // nolint: funlen,gocyclo +func PresentationDefinition(p Provider, opts ...OptPD) presentproof.Middleware { // nolint: funlen,gocyclo,gocognit vdr := p.VDRegistry() documentLoader := p.JSONLDDocumentLoader() @@ -208,28 +208,30 @@ func PresentationDefinition(p Provider, opts ...OptPD) presentproof.Middleware { return fmt.Errorf("parse credentials: %w", err) } - presentation, err := payload.PresentationDefinition.CreateVP(credentials, documentLoader, - verifiable.WithPublicKeyFetcher(verifiable.NewVDRKeyResolver(vdr).PublicKeyFetcher()), - verifiable.WithJSONLDDocumentLoader(documentLoader)) - if err != nil { - return fmt.Errorf("create VP: %w", err) - } + if len(credentials) > 0 { + presentation, err := payload.PresentationDefinition.CreateVP(credentials, documentLoader, + verifiable.WithPublicKeyFetcher(verifiable.NewVDRKeyResolver(vdr).PublicKeyFetcher()), + verifiable.WithJSONLDDocumentLoader(documentLoader)) + if err != nil { + return fmt.Errorf("create VP: %w", err) + } - singFn := metadata.GetAddProofFn() - if singFn == nil { - singFn = options.addProof - } + singFn := metadata.GetAddProofFn() + if singFn == nil { + singFn = options.addProof + } - err = singFn(presentation) - if err != nil { - return fmt.Errorf("add proof: %w", err) - } + err = singFn(presentation) + if err != nil { + return fmt.Errorf("add proof: %w", err) + } - metadata.Presentation().PresentationsAttach = []decorator.Attachment{{ - ID: uuid.New().String(), - MimeType: mimeTypeApplicationLdJSON, - Data: decorator.AttachmentData{JSON: presentation}, - }} + metadata.Presentation().PresentationsAttach = []decorator.Attachment{{ + ID: uuid.New().String(), + MimeType: mimeTypeApplicationLdJSON, + Data: decorator.AttachmentData{JSON: presentation}, + }} + } return next.Handle(metadata) }) diff --git a/pkg/mock/didcomm/protocol/didexchange/mock_didexchange.go b/pkg/mock/didcomm/protocol/didexchange/mock_didexchange.go index c0645b1531..7fa185aea8 100644 --- a/pkg/mock/didcomm/protocol/didexchange/mock_didexchange.go +++ b/pkg/mock/didcomm/protocol/didexchange/mock_didexchange.go @@ -34,7 +34,9 @@ type MockDIDExchangeSvc struct { AcceptFunc func(string) bool RegisterActionEventErr error UnregisterActionEventErr error + RegisterMsgEventHandle func(chan<- service.StateMsg) error RegisterMsgEventErr error + UnregisterMsgEventHandle func(chan<- service.StateMsg) error UnregisterMsgEventErr error AcceptError error ImplicitInvitationErr error @@ -103,6 +105,10 @@ func (m *MockDIDExchangeSvc) RegisterMsgEvent(ch chan<- service.StateMsg) error return m.RegisterMsgEventErr } + if m.RegisterMsgEventHandle != nil { + return m.RegisterMsgEventHandle(ch) + } + return nil } @@ -112,6 +118,10 @@ func (m *MockDIDExchangeSvc) UnregisterMsgEvent(ch chan<- service.StateMsg) erro return m.UnregisterMsgEventErr } + if m.UnregisterMsgEventHandle != nil { + return m.UnregisterMsgEventHandle(ch) + } + return nil } diff --git a/pkg/wallet/options.go b/pkg/wallet/options.go index b97a9b313a..56884bff87 100644 --- a/pkg/wallet/options.go +++ b/pkg/wallet/options.go @@ -315,9 +315,9 @@ func WithMyLabel(label string) ConnectOptions { } // WithReuseAnyConnection option to use any recognized DID in the services array for a reusable connection. -func WithReuseAnyConnection() ConnectOptions { +func WithReuseAnyConnection(reuse bool) ConnectOptions { return func(opts *connectOpts) { - opts.ReuseAny = true + opts.ReuseAny = reuse } } @@ -361,6 +361,8 @@ func getOobMessageOptions(opts *connectOpts) []outofband.MessageOption { type proposePresOpts struct { // optional from DID option to customize message sender DID. from string + // connect options. + connectOpts []ConnectOptions // timeout duration to wait for request presentation response from relying party. timeout time.Duration } @@ -375,9 +377,42 @@ func WithFromDID(from string) ProposePresentationOption { } } +// WithConnectOptions for customizing options for accepting invitation. +func WithConnectOptions(options ...ConnectOptions) ProposePresentationOption { + return func(opts *proposePresOpts) { + opts.connectOpts = options + } +} + // WithPresentProofTimeout to provide timeout duration to wait for request presentation response from relying party. func WithPresentProofTimeout(timeout time.Duration) ProposePresentationOption { return func(opts *proposePresOpts) { opts.timeout = timeout } } + +// presentProofOpts contains options to send present proof from wallet. +type presentProofOpts struct { + // presenting proof from raw credential. + rawPresentation json.RawMessage + // presenting proof verifiable presentation instance. + // this option takes precedence when provided with other options. + presentation *verifiable.Presentation +} + +// PresentProofFrom is option to send present proof from wallet. +type PresentProofFrom func(opts *presentProofOpts) + +// FromPresentation for sending aries verifiable presentation. +func FromPresentation(presentation *verifiable.Presentation) PresentProofFrom { + return func(opts *presentProofOpts) { + opts.presentation = presentation + } +} + +// FromRawPresentation for sending raw JSON as presentation. +func FromRawPresentation(raw json.RawMessage) PresentProofFrom { + return func(opts *presentProofOpts) { + opts.rawPresentation = raw + } +} diff --git a/pkg/wallet/wallet.go b/pkg/wallet/wallet.go index 43097d9646..00dae2376f 100644 --- a/pkg/wallet/wallet.go +++ b/pkg/wallet/wallet.go @@ -17,13 +17,14 @@ import ( "github.com/google/uuid" "github.com/piprate/json-gold/ld" + "github.com/hyperledger/aries-framework-go/pkg/client/didexchange" "github.com/hyperledger/aries-framework-go/pkg/client/outofband" "github.com/hyperledger/aries-framework-go/pkg/client/presentproof" "github.com/hyperledger/aries-framework-go/pkg/common/log" "github.com/hyperledger/aries-framework-go/pkg/crypto" "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" - "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" + didexchangeSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" presentproofSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/presentproof" "github.com/hyperledger/aries-framework-go/pkg/doc/did" "github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld" @@ -92,6 +93,8 @@ type didCommProvider interface { ServiceEndpoint() string ProtocolStateStorageProvider() storage.Provider Service(id string) (interface{}, error) + KeyType() kms.KeyType + KeyAgreementType() kms.KeyType } type provable interface { @@ -127,6 +130,9 @@ type Wallet struct { // out of band client oobClient *outofband.Client + // did-exchange client + didexchangeClient *didexchange.Client + // connection lookup connectionLookup *connection.Lookup } @@ -161,6 +167,11 @@ func New(userID string, ctx provider) (*Wallet, error) { return nil, fmt.Errorf("failed to initialize connection lookup: %w", err) } + didexchangeClient, err := didexchange.New(ctx) + if err != nil { + return nil, fmt.Errorf("failed to initialize didexchange client: %w", err) + } + return &Wallet{ userID: userID, profile: profile, @@ -171,6 +182,7 @@ func New(userID string, ctx provider) (*Wallet, error) { jsonldDocumentLoader: ctx.JSONLDDocumentLoader(), presentProofClient: presentProofClient, oobClient: oobClient, + didexchangeClient: didexchangeClient, connectionLookup: connectionLookup, }, nil } @@ -611,13 +623,13 @@ func (c *Wallet) CreateKeyPair(authToken string, keyType kms.KeyType) (*KeyPair, func (c *Wallet) Connect(authToken string, invitation *outofband.Invitation, options ...ConnectOptions) (string, error) { //nolint: lll statusCh := make(chan service.StateMsg, msgEventBufferSize) - err := c.oobClient.RegisterMsgEvent(statusCh) + err := c.didexchangeClient.RegisterMsgEvent(statusCh) if err != nil { return "", fmt.Errorf("failed to register msg event : %w", err) } defer func() { - e := c.oobClient.UnregisterMsgEvent(statusCh) + e := c.didexchangeClient.UnregisterMsgEvent(statusCh) if e != nil { logger.Warnf("Failed to unregister msg event for connect: %w", e) } @@ -664,7 +676,12 @@ func (c *Wallet) Connect(authToken string, invitation *outofband.Invitation, opt // - error if operation fails. // func (c *Wallet) ProposePresentation(authToken string, invitation *outofband.Invitation, options ...ProposePresentationOption) (*service.DIDCommMsgMap, error) { //nolint: lll - connID, err := c.Connect(authToken, invitation) + opts := &proposePresOpts{} + for _, opt := range options { + opt(opts) + } + + connID, err := c.Connect(authToken, invitation, opts.connectOpts...) if err != nil { return nil, fmt.Errorf("failed to perform did connection : %w", err) } @@ -674,9 +691,9 @@ func (c *Wallet) ProposePresentation(authToken string, invitation *outofband.Inv return nil, fmt.Errorf("failed to lookup connection for propose presentation : %w", err) } - opts := preparePresentProofOpts(connRecord, options...) + opts = preparePresentProofOpts(connRecord, opts) - thID, err := c.presentProofClient.SendProposePresentation(&presentproof.ProposePresentation{}, connRecord.MyDID, + _, err = c.presentProofClient.SendProposePresentation(&presentproof.ProposePresentation{}, connRecord.MyDID, opts.from) if err != nil { return nil, fmt.Errorf("failed to propose presentation from wallet: %w", err) @@ -685,7 +702,7 @@ func (c *Wallet) ProposePresentation(authToken string, invitation *outofband.Inv ctx, cancel := context.WithTimeout(context.Background(), opts.timeout) defer cancel() - return c.waitForRequestPresentation(ctx, thID) + return c.waitForRequestPresentation(ctx, connRecord) } // PresentProof sends message present proof message from wallet to relying party. @@ -696,13 +713,23 @@ func (c *Wallet) ProposePresentation(authToken string, invitation *outofband.Inv // Args: // - authToken: authorization for performing operation. // - thID: thread ID (action ID) of request presentation. -// - presentation: presentation to be sent. +// - presentProofFrom: presentation to be sent. // // Returns: // - error if operation fails. // // TODO: wait for acknowledgement option to be added. -func (c *Wallet) PresentProof(authToken, thID string, presentation *verifiable.Presentation) error { +func (c *Wallet) PresentProof(authToken, thID string, presentProofFrom PresentProofFrom) error { + presFrom := &presentProofOpts{} + presentProofFrom(presFrom) + + var presentation interface{} + if presFrom.presentation != nil { + presentation = presFrom.presentation + } else { + presentation = presFrom.rawPresentation + } + return c.presentProofClient.AcceptRequestPresentation(thID, &presentproof.Presentation{ Type: presentproofSvc.PresentationMsgType, PresentationsAttach: []decorator.Attachment{{ @@ -936,7 +963,8 @@ func (c *Wallet) validateVerificationMethod(didDoc *did.Doc, opts *ProofOptions, return fmt.Errorf("unable to find '%s' for given verification method", supportedRelationships[relationship]) } -func (c *Wallet) waitForRequestPresentation(ctx context.Context, piid string) (*service.DIDCommMsgMap, error) { +// currently correlating response action by connection due to limitation in current present proof V1 implementation. +func (c *Wallet) waitForRequestPresentation(ctx context.Context, record *connection.Record) (*service.DIDCommMsgMap, error) { //nolint: lll done := make(chan *service.DIDCommMsgMap) go func() { @@ -948,7 +976,7 @@ func (c *Wallet) waitForRequestPresentation(ctx context.Context, piid string) (* if len(actions) > 0 { for _, action := range actions { - if action.PIID == piid { + if action.MyDID == record.MyDID && action.TheirDID == record.TheirDID { done <- &action.Msg return } @@ -977,14 +1005,14 @@ func waitForConnect(ctx context.Context, didStateMsgs chan service.StateMsg, con go func() { for msg := range didStateMsgs { - if msg.Type != service.PostState || msg.StateID != didexchange.StateIDCompleted { + if msg.Type != service.PostState || msg.StateID != didexchangeSvc.StateIDCompleted { continue } - var event didexchange.Event + var event didexchangeSvc.Event switch p := msg.Properties.(type) { - case didexchange.Event: + case didexchangeSvc.Event: event = p default: logger.Warnf("failed to cast didexchange event properties") @@ -1046,12 +1074,7 @@ func updateProfile(auth string, profile *profile) error { return nil } -func preparePresentProofOpts(connRecord *connection.Record, options ...ProposePresentationOption) *proposePresOpts { - opts := &proposePresOpts{} - for _, opt := range options { - opt(opts) - } - +func preparePresentProofOpts(connRecord *connection.Record, opts *proposePresOpts) *proposePresOpts { if opts.from == "" { opts.from = connRecord.TheirDID } diff --git a/pkg/wallet/wallet_test.go b/pkg/wallet/wallet_test.go index 710ea88db3..809db64cd4 100644 --- a/pkg/wallet/wallet_test.go +++ b/pkg/wallet/wallet_test.go @@ -28,6 +28,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange" + "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator" outofbandSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/outofband" presentproofSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/presentproof" "github.com/hyperledger/aries-framework-go/pkg/doc/did" @@ -40,6 +41,7 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/kms/webkms" cryptomock "github.com/hyperledger/aries-framework-go/pkg/mock/crypto" mockdidexchange "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/didexchange" + mockmediator "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator" mockoutofband "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/outofband" mockpresentproof "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/presentproof" mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms" @@ -589,6 +591,19 @@ func TestNew(t *testing.T) { require.Contains(t, err.Error(), "failed to initialize out-of-band client") }) + t.Run("test get wallet failure - oob client initialize error", func(t *testing.T) { + mockctx := newMockProvider(t) + delete(mockctx.ServiceMap, didexchange.DIDExchange) + + err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase)) + require.NoError(t, err) + + wallet, err := New(sampleUserID, mockctx) + require.Error(t, err) + require.Empty(t, wallet) + require.Contains(t, err.Error(), "failed to initialize didexchange client") + }) + t.Run("test get wallet failure - connection lookup initialize error", func(t *testing.T) { mockctx := newMockProvider(t) mockStoreProvider := mockstorage.NewMockStoreProvider() @@ -2509,6 +2524,10 @@ func TestWallet_Connect(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -2519,8 +2538,7 @@ func TestWallet_Connect(t *testing.T) { return nil }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc wallet, err := New(sampleDIDCommUser, mockctx) require.NoError(t, err) @@ -2564,13 +2582,12 @@ func TestWallet_Connect(t *testing.T) { }) t.Run("test did connect failure - register event failure", func(t *testing.T) { - oobSvc := &mockoutofband.MockOobService{ + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { return fmt.Errorf(sampleWalletErr) }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc wallet, err := New(sampleDIDCommUser, mockctx) require.NoError(t, err) @@ -2591,6 +2608,7 @@ func TestWallet_Connect(t *testing.T) { t.Run("test did connect failure - state not completed", func(t *testing.T) { mockctx.ServiceMap[outofbandSvc.Name] = &mockoutofband.MockOobService{} + mockctx.ServiceMap[didexchange.DIDExchange] = &mockdidexchange.MockDIDExchangeSvc{} wallet, err := New(sampleDIDCommUser, mockctx) require.NoError(t, err) @@ -2615,6 +2633,10 @@ func TestWallet_Connect(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PreState, @@ -2638,8 +2660,7 @@ func TestWallet_Connect(t *testing.T) { return fmt.Errorf(sampleWalletErr) }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc wallet, err := New(sampleDIDCommUser, mockctx) require.NoError(t, err) @@ -2661,7 +2682,7 @@ func TestWallet_Connect(t *testing.T) { WithConnectTimeout(10 * time.Second), WithRouterConnections("sample-conn"), WithMyLabel("sample-label"), - WithReuseAnyConnection(), + WithReuseAnyConnection(true), WithReuseDID("sample-did"), } @@ -2686,6 +2707,11 @@ func TestWallet_ProposePresentation(t *testing.T) { err := CreateProfile(sampleDIDCommUser, mockctx, WithPassphrase(samplePassPhrase)) require.NoError(t, err) + const ( + myDID = "did:mydid:123" + theirDID = "did:theirdid:123" + ) + t.Run("test propose presentation success", func(t *testing.T) { sampleConnID := uuid.New().String() @@ -2693,6 +2719,10 @@ func TestWallet_ProposePresentation(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -2703,6 +2733,7 @@ func TestWallet_ProposePresentation(t *testing.T) { return nil }, } + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc thID := uuid.New().String() @@ -2714,6 +2745,8 @@ func TestWallet_ProposePresentation(t *testing.T) { Msg: service.NewDIDCommMsgMap(&presentproofSvc.RequestPresentation{ Comment: "mock msg", }), + MyDID: myDID, + TheirDID: theirDID, }, }, nil }, @@ -2730,8 +2763,8 @@ func TestWallet_ProposePresentation(t *testing.T) { record := &connection.Record{ ConnectionID: sampleConnID, - MyDID: "did:mydid", - TheirDID: "did:theirDID", + MyDID: myDID, + TheirDID: theirDID, } recordBytes, err := json.Marshal(record) require.NoError(t, err) @@ -2747,19 +2780,19 @@ func TestWallet_ProposePresentation(t *testing.T) { defer wallet.Close() - msg, err := wallet.ProposePresentation(token, &outofband.Invitation{}) + msg, err := wallet.ProposePresentation(token, &outofband.Invitation{}, + WithConnectOptions(WithConnectTimeout(1*time.Millisecond))) require.NoError(t, err) require.NotEmpty(t, msg) }) t.Run("test propose presentation failure - did connect failure", func(t *testing.T) { - oobSvc := &mockoutofband.MockOobService{ + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { return fmt.Errorf(sampleWalletErr) }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc wallet, err := New(sampleDIDCommUser, mockctx) require.NoError(t, err) @@ -2785,6 +2818,10 @@ func TestWallet_ProposePresentation(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -2795,8 +2832,7 @@ func TestWallet_ProposePresentation(t *testing.T) { return nil }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc wallet, err := New(sampleDIDCommUser, mockctx) require.NoError(t, err) @@ -2821,6 +2857,10 @@ func TestWallet_ProposePresentation(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -2831,14 +2871,13 @@ func TestWallet_ProposePresentation(t *testing.T) { return nil }, } + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc ppSvc := &mockpresentproof.MockPresentProofSvc{ HandleFunc: func(service.DIDCommMsg) (string, error) { return "", fmt.Errorf(sampleWalletErr) }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc mockctx.ServiceMap[presentproofSvc.Name] = ppSvc store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) @@ -2846,8 +2885,8 @@ func TestWallet_ProposePresentation(t *testing.T) { record := &connection.Record{ ConnectionID: sampleConnID, - MyDID: "did:mydid", - TheirDID: "did:theirDID", + MyDID: myDID, + TheirDID: theirDID, } recordBytes, err := json.Marshal(record) require.NoError(t, err) @@ -2877,6 +2916,10 @@ func TestWallet_ProposePresentation(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -2887,14 +2930,13 @@ func TestWallet_ProposePresentation(t *testing.T) { return nil }, } + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc ppSvc := &mockpresentproof.MockPresentProofSvc{ HandleFunc: func(service.DIDCommMsg) (string, error) { return uuid.New().String(), nil }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc mockctx.ServiceMap[presentproofSvc.Name] = ppSvc store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) @@ -2902,8 +2944,8 @@ func TestWallet_ProposePresentation(t *testing.T) { record := &connection.Record{ ConnectionID: sampleConnID, - MyDID: "did:mydid", - TheirDID: "did:theirDID", + MyDID: myDID, + TheirDID: theirDID, } recordBytes, err := json.Marshal(record) require.NoError(t, err) @@ -2932,6 +2974,10 @@ func TestWallet_ProposePresentation(t *testing.T) { AcceptInvitationHandle: func(*outofbandSvc.Invitation, outofbandSvc.Options) (string, error) { return sampleConnID, nil }, + } + mockctx.ServiceMap[outofbandSvc.Name] = oobSvc + + didexSvc := &mockdidexchange.MockDIDExchangeSvc{ RegisterMsgEventHandle: func(ch chan<- service.StateMsg) error { ch <- service.StateMsg{ Type: service.PostState, @@ -2942,6 +2988,7 @@ func TestWallet_ProposePresentation(t *testing.T) { return nil }, } + mockctx.ServiceMap[didexchange.DIDExchange] = didexSvc ppSvc := &mockpresentproof.MockPresentProofSvc{ HandleFunc: func(service.DIDCommMsg) (string, error) { @@ -2951,8 +2998,6 @@ func TestWallet_ProposePresentation(t *testing.T) { return nil, fmt.Errorf(sampleWalletErr) }, } - - mockctx.ServiceMap[outofbandSvc.Name] = oobSvc mockctx.ServiceMap[presentproofSvc.Name] = ppSvc store, err := mockctx.StorageProvider().OpenStore(connection.Namespace) @@ -2960,7 +3005,7 @@ func TestWallet_ProposePresentation(t *testing.T) { record := &connection.Record{ ConnectionID: sampleConnID, - TheirDID: "did:theirDID", + TheirDID: theirDID, } recordBytes, err := json.Marshal(record) require.NoError(t, err) @@ -3001,7 +3046,7 @@ func TestWallet_PresentProof(t *testing.T) { defer wallet.Close() - err = wallet.PresentProof(token, uuid.New().String(), &verifiable.Presentation{}) + err = wallet.PresentProof(token, uuid.New().String(), FromPresentation(&verifiable.Presentation{})) require.NoError(t, err) }) @@ -3024,7 +3069,7 @@ func TestWallet_PresentProof(t *testing.T) { defer wallet.Close() - err = wallet.PresentProof(token, uuid.New().String(), &verifiable.Presentation{}) + err = wallet.PresentProof(token, uuid.New().String(), FromRawPresentation([]byte("{}"))) require.Error(t, err) require.Contains(t, err.Error(), sampleWalletErr) }) @@ -3037,8 +3082,10 @@ func newMockProvider(t *testing.T) *mockprovider.Provider { require.NoError(t, err) serviceMap := map[string]interface{}{ - presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, - outofbandSvc.Name: &mockoutofband.MockOobService{}, + presentproofSvc.Name: &mockpresentproof.MockPresentProofSvc{}, + outofbandSvc.Name: &mockoutofband.MockOobService{}, + didexchange.DIDExchange: &mockdidexchange.MockDIDExchangeSvc{}, + mediator.Coordination: &mockmediator.MockMediatorSvc{}, } return &mockprovider.Provider{ diff --git a/test/aries-js-worker/test/didexchange/didexchange_e2e.js b/test/aries-js-worker/test/didexchange/didexchange_e2e.js index 8093d2b2e0..a29531075a 100644 --- a/test/aries-js-worker/test/didexchange/didexchange_e2e.js +++ b/test/aries-js-worker/test/didexchange/didexchange_e2e.js @@ -133,8 +133,8 @@ export const didExchangeClient = class { await this.agent2.mediator.unregister({"connectionID": this.agent2RouterConnection}) } - await this.agent1.destroy() - await this.agent2.destroy() + this.agent1 ? await this.agent1.destroy() : '' + this.agent2 ? await this.agent2.destroy() : '' } static async createInvitationFromRouter(endpoint) { diff --git a/test/aries-js-worker/test/introduce/introduce.js b/test/aries-js-worker/test/introduce/introduce.js index 83c104edf0..c2b4463b26 100644 --- a/test/aries-js-worker/test/introduce/introduce.js +++ b/test/aries-js-worker/test/introduce/introduce.js @@ -64,7 +64,9 @@ async function proposalWithRequest(mode) { }) after(async () => { - await destroy() + if (destroy) { + await destroy() + } }) let alice_bob, alice_carol; diff --git a/test/bdd/features/ld_e2e_controller.feature b/test/bdd/features/ld_e2e_controller.feature index 1f41820a50..b76fdf9fa9 100644 --- a/test/bdd/features/ld_e2e_controller.feature +++ b/test/bdd/features/ld_e2e_controller.feature @@ -12,5 +12,5 @@ Feature: JSON-LD operations using controller API Scenario: Controller API for remote JSON-LD context provider Given "Alice" agent is running on "localhost" port "8081" with controller "https://localhost:8082" - When "Alice" adds a new remote provider with endpoint "https://file-server.example.com/vaccination-context.json" through controller + When "Alice" adds a new remote provider with endpoint "https://file-server.example.com:9099/vaccination-context.json" through controller Then vaccination context from the provider is available to the agent instance diff --git a/test/bdd/features/ld_e2e_sdk.feature b/test/bdd/features/ld_e2e_sdk.feature index c54f898715..808b25481f 100644 --- a/test/bdd/features/ld_e2e_sdk.feature +++ b/test/bdd/features/ld_e2e_sdk.feature @@ -11,5 +11,5 @@ Feature: JSON-LD operations using SDK client Scenario: Using SDK client for operations with remote JSON-LD context provider Given "Bob" agent is running on "localhost" port "random" with "http" as the transport provider - When "Bob" adds a new remote provider with endpoint "https://localhost:443/citizenship-context.json" using client + When "Bob" adds a new remote provider with endpoint "https://localhost:9099/citizenship-context.json" using client Then "https://w3id.org/citizenship/v1" context from the provider is in agent's JSON-LD context store diff --git a/test/bdd/fixtures/agent-rest/.env b/test/bdd/fixtures/agent-rest/.env index 042e3c72d8..c3d7b7575a 100644 --- a/test/bdd/fixtures/agent-rest/.env +++ b/test/bdd/fixtures/agent-rest/.env @@ -111,4 +111,4 @@ KMS_REST_IMAGE=ghcr.io/trustbloc/kms KMS_REST_TAG=0.1.6 # Remote JSON-LD context provider configuration -CONTEXT_PROVIDER_URL=https://file-server.example.com/agent-startup-contexts.json +CONTEXT_PROVIDER_URL=https://file-server.example.com:9099/agent-startup-contexts.json diff --git a/test/bdd/fixtures/agent-rest/docker-compose.yml b/test/bdd/fixtures/agent-rest/docker-compose.yml index 4c123196ee..d6459f81c8 100644 --- a/test/bdd/fixtures/agent-rest/docker-compose.yml +++ b/test/bdd/fixtures/agent-rest/docker-compose.yml @@ -32,6 +32,8 @@ services: command: /bin/sh -c "cp /etc/tls/* /usr/local/share/ca-certificates/;update-ca-certificates; aries-agent-rest start" networks: - bdd_net + depends_on: + - file-server.example.com erin.agent.example.com: container_name: erin.aries.example.com @@ -58,6 +60,8 @@ services: command: /bin/sh -c "cp /etc/tls/* /usr/local/share/ca-certificates/;update-ca-certificates; aries-agent-rest start" networks: - bdd_net + depends_on: + - file-server.example.com bob.agent.example.com: container_name: bob.aries.example.com @@ -85,6 +89,8 @@ services: command: /bin/sh -c "cp /etc/tls/* /usr/local/share/ca-certificates/;update-ca-certificates; aries-agent-rest start" networks: - bdd_net + depends_on: + - file-server.example.com alice.webhook.example.com: container_name: ${ALICE_WEBHOOK_CONTAINER_NAME} @@ -139,6 +145,8 @@ services: command: /bin/sh -c "cp /etc/tls/* /usr/local/share/ca-certificates/;update-ca-certificates; aries-agent-rest start" networks: - bdd_net + depends_on: + - file-server.example.com carl.webhook.example.com: container_name: ${CARL_WEBHOOK_CONTAINER_NAME} @@ -210,6 +218,8 @@ services: command: /bin/sh -c "cp /etc/tls/* /usr/local/share/ca-certificates/;update-ca-certificates; aries-agent-rest start" networks: - bdd_net + depends_on: + - file-server.example.com dave.webhook.example.com: container_name: ${DAVE_WEBHOOK_CONTAINER_NAME} @@ -314,12 +324,12 @@ services: container_name: file-server.example.com image: halverneus/static-file-server:latest environment: - - PORT=443 + - PORT=9099 - FOLDER=/data - TLS_CERT=/etc/tls/ec-pubCert.pem - TLS_KEY=/etc/tls/ec-key.pem ports: - - "443:443" + - "9099:9099" volumes: - ./data:/data - ../keys/tls:/etc/tls diff --git a/test/bdd/pkg/presentproof/testdata/presentation_multiple_attachments.json b/test/bdd/pkg/presentproof/testdata/presentation_multiple_attachments.json index 2e83928df0..aafc8d5363 100644 --- a/test/bdd/pkg/presentproof/testdata/presentation_multiple_attachments.json +++ b/test/bdd/pkg/presentproof/testdata/presentation_multiple_attachments.json @@ -3,52 +3,106 @@ "presentations~attach":[ { "lastmod_time":"0001-01-01T00:00:00Z", + "mime-type":"application/ld+json", "data":{ "json":{ - "@context":[ + "@context": [ "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1", "https://w3id.org/security/bbs/v1" ], - "first_name":"Jesse", - "id":"a5f67880-f5ec-431c-814a-ab6245a6f4eb", - "issuer":"", - "type":"VerifiableCredential" + "credentialSchema": [], + "credentialSubject": { + "degree": { + "type": "BachelorDegree", + "university": "MIT" + }, + "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", + "name": "Jayden Doe", + "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1" + }, + "expirationDate": "2020-01-01T19:23:24Z", + "id": "http://example.edu/credentials/1872", + "issuanceDate": "2010-01-01T19:23:24Z", + "issuer": { + "id": "did:example:76e12ec712ebc6f1c221ebfeb1f", + "name": "Example University" + }, + "referenceNumber": 83294847, + "type": [ + "VerifiableCredential", + "UniversityDegreeCredential" + ] } } }, { "lastmod_time":"0001-01-01T00:00:00Z", + "mime-type":"application/ld+json", "data":{ "json":{ - "@context":[ + "@context": [ "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1", "https://w3id.org/security/bbs/v1" ], - "age":2, - "credentialSubject":"fa7ec857-4b25-4d35-9785-0d8d9a6ba960", - "first_name":"Jesse", - "id":"17394f9d-4e12-4500-801c-f849d3269530", - "issuer":"fa7ec857-4b25-4d35-9785-0d8d9a6ba960", - "last_name":"Travis", - "type":"VerifiableCredential" + "credentialSchema": [], + "credentialSubject": { + "degree": { + "type": "BachelorDegree", + "university": "MIT" + }, + "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", + "name": "Jayden Doe", + "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1" + }, + "expirationDate": "2020-01-01T19:23:24Z", + "id": "http://example.edu/credentials/1872", + "issuanceDate": "2010-01-01T19:23:24Z", + "issuer": { + "id": "did:example:76e12ec712ebc6f1c221ebfeb1f", + "name": "Example University" + }, + "referenceNumber": 83294847, + "type": [ + "VerifiableCredential", + "UniversityDegreeCredential" + ] } } }, { "lastmod_time":"0001-01-01T00:00:00Z", + "mime-type":"application/ld+json", "data":{ "json":{ - "@context":[ + "@context": [ "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1", "https://w3id.org/security/bbs/v1" ], - "age":17, - "credentialSubject":"5dd636b7-3fb7-4977-930a-f6cdab3b7eb4", - "first_name":"Jesse", - "id":"a2ece1da-84d5-428c-879c-21740af14c0a", - "issuer":"5dd636b7-3fb7-4977-930a-f6cdab3b7eb4", - "last_name":"Travis", - "type":"VerifiableCredential" + "credentialSchema": [], + "credentialSubject": { + "degree": { + "type": "BachelorDegree", + "university": "MIT" + }, + "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", + "name": "Jayden Doe", + "spouse": "did:example:c276e12ec21ebfeb1f712ebc6f1" + }, + "expirationDate": "2020-01-01T19:23:24Z", + "id": "http://example.edu/credentials/1872", + "issuanceDate": "2010-01-01T19:23:24Z", + "issuer": { + "id": "did:example:76e12ec712ebc6f1c221ebfeb1f", + "name": "Example University" + }, + "referenceNumber": 83294847, + "type": [ + "VerifiableCredential", + "UniversityDegreeCredential" + ] } } } diff --git a/test/bdd/pkg/presentproof/testdata/request_presentation_multiple_attachments.json b/test/bdd/pkg/presentproof/testdata/request_presentation_multiple_attachments.json index 1b28894580..4800e4e48c 100644 --- a/test/bdd/pkg/presentproof/testdata/request_presentation_multiple_attachments.json +++ b/test/bdd/pkg/presentproof/testdata/request_presentation_multiple_attachments.json @@ -14,134 +14,11 @@ "data":{ "json":{ "presentation_definition":{ - "id":"63328f06-9bb1-4430-8cdb-9d00e688c2fa", - "submission_requirements":[ - { - "rule":"all", - "from":"A" - }, - { - "rule":"pick", - "count":1, - "from_nested":[ - { - "rule":"all", - "from":"teenager" - }, - { - "rule":"all", - "from":"child" - }, - { - "rule":"pick", - "min":2, - "from":"adult" - } - ] - } - ], - "input_descriptors":[ - { - "id":"74ef1ffa-cbf6-40c9-a44a-f87f2b9918e1", - "group":[ - "A" - ], - "schema":[ - { - "uri": "https://www.w3.org/2018/credentials/examples/v1" - } - ], - "constraints":{ - "subject_is_issuer":"required", - "fields":[ - { - "path":[ - "$.first_name", - "$.last_name" - ] - } - ] - } - }, - { - "id":"1747bea7-c346-45af-a1f3-531fa54f193f", - "group":[ - "child" - ], - "schema":[ - { - "uri":"https://www.w3.org/2018/credentials/examples/v1" - } - ], - "constraints":{ - "subject_is_issuer":"required", - "fields":[ - { - "path":[ - "$.age" - ], - "filter":{ - "type":"integer", - "minimum":3, - "maximum":12 - } - } - ] - } - }, - { - "id":"6eef6813-1b03-4fa6-9e69-0416dc496ed7", - "group":[ - "teenager" - ], - "schema":[ - { - "uri": "https://www.w3.org/2018/credentials/examples/v1" - } - ], - "constraints":{ - "subject_is_issuer":"required", - "fields":[ - { - "path":[ - "$.age" - ], - "filter":{ - "type":"integer", - "minimum":13, - "maximum":17 - } - } - ] - } - }, - { - "id":"3b3aec3d-7e55-46f6-80ba-9745552d3453", - "group":[ - "adult" - ], - "schema":[ - { - "uri": "https://www.w3.org/2018/credentials/examples/v1" - } - ], - "constraints":{ - "subject_is_issuer":"required", - "fields":[ - { - "path":[ - "$.age" - ], - "filter":{ - "type":"integer", - "minimum":18, - "maximum":23 - } - } - ] - } - } - ] + "id": "22c77155-edf2-4ec5-8d44-b393b4e4fa38", + "input_descriptors": [{ + "id": "20b073bb-cede-4912-9e9d-334e5702077b", + "schema": [{"uri": "https://www.w3.org/2018/credentials#VerifiableCredential"}] + }] } } }