github.com/hyperledger/aries-framework-go@v0.3.2/pkg/client/connection/client.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package connection 8 9 import ( 10 "fmt" 11 12 "github.com/google/uuid" 13 14 "github.com/hyperledger/aries-framework-go/pkg/common/log" 15 "github.com/hyperledger/aries-framework-go/pkg/common/model" 16 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/middleware" 17 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/peerdid" 18 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" 19 "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" 20 "github.com/hyperledger/aries-framework-go/pkg/kms" 21 "github.com/hyperledger/aries-framework-go/pkg/store/connection" 22 didstore "github.com/hyperledger/aries-framework-go/pkg/store/did" 23 "github.com/hyperledger/aries-framework-go/spi/storage" 24 ) 25 26 var logger = log.New("aries-framework/pkg/client/connection") 27 28 type provider interface { 29 VDRegistry() vdr.Registry 30 DIDRotator() *middleware.DIDCommMessageMiddleware 31 StorageProvider() storage.Provider 32 ProtocolStateStorageProvider() storage.Provider 33 DIDConnectionStore() didstore.ConnectionStore 34 KMS() kms.KeyManager 35 KeyType() kms.KeyType 36 KeyAgreementType() kms.KeyType 37 } 38 39 // Client is a connection management SDK client. 40 type Client struct { 41 didRotator *middleware.DIDCommMessageMiddleware 42 connectionRecorder *connection.Recorder 43 didMap didstore.ConnectionStore 44 vdr vdr.Registry 45 peerDIDCreator *peerdid.Creator 46 } 47 48 // New creates connection Client. 49 func New(prov provider) (*Client, error) { 50 connRec, err := connection.NewRecorder(prov) 51 if err != nil { 52 return nil, err 53 } 54 55 return &Client{ 56 didRotator: prov.DIDRotator(), 57 connectionRecorder: connRec, 58 vdr: prov.VDRegistry(), 59 didMap: prov.DIDConnectionStore(), 60 peerDIDCreator: peerdid.New(prov), 61 }, nil 62 } 63 64 // RotateDID rotates the DID of the given connection to the given new DID, using the signing KID for the key in the old 65 // DID doc to sign the DID rotation. 66 func (c *Client) RotateDID(connectionID, signingKID string, opts ...RotateDIDOption) (string, error) { 67 options := rotateDIDOpts{} 68 69 for _, opt := range opts { 70 opt(&options) 71 } 72 73 if options.createPeerDID { 74 newDoc, err := c.peerDIDCreator.CreatePeerDIDV2() 75 if err != nil { 76 return "", fmt.Errorf("creating peer DID: %w", err) 77 } 78 79 options.newDID = newDoc.ID 80 } 81 82 return options.newDID, c.didRotator.RotateConnectionDID(connectionID, signingKID, options.newDID) 83 } 84 85 // CreateConnectionV2 creates a DIDComm V2 connection with the given DID. 86 //nolint:funlen 87 func (c *Client) CreateConnectionV2(myDID, theirDID string, opts ...CreateConnectionOption) (string, error) { 88 theirDocRes, err := c.vdr.Resolve(theirDID) 89 if err != nil { 90 return "", fmt.Errorf("resolving their DID: %w", err) 91 } 92 93 theirDoc := theirDocRes.DIDDocument 94 95 err = c.didMap.SaveDIDFromDoc(theirDoc) 96 if err != nil { 97 return "", fmt.Errorf("failed to save theirDID to the did.ConnectionStore: %w", err) 98 } 99 100 err = c.didMap.SaveDIDByResolving(myDID) 101 if err != nil { 102 return "", fmt.Errorf("failed to save myDID to the did.ConnectionStore: %w", err) 103 } 104 105 destination, err := service.CreateDestination(theirDoc) 106 if err != nil { 107 return "", fmt.Errorf("failed to create destination: %w", err) 108 } 109 110 connID := uuid.New().String() 111 112 uri, err := destination.ServiceEndpoint.URI() 113 if err != nil { 114 logger.Debugf("create destination from serviceEndpoint.URI() failed: %w, using value: %s", err, uri) 115 } 116 117 accept, err := destination.ServiceEndpoint.Accept() 118 if err != nil { 119 logger.Debugf("create destination from serviceEndpoint.Accept() failed: %w, using value %v", err, accept) 120 } 121 122 routingKeys, err := destination.ServiceEndpoint.RoutingKeys() 123 if err != nil { 124 logger.Debugf("create destination from serviceEndpoint.RoutingKeys() failed: %w, using value %v", err, routingKeys) 125 } 126 127 connRec := connection.Record{ 128 ConnectionID: connID, 129 State: connection.StateNameCompleted, 130 TheirDID: theirDID, 131 MyDID: myDID, 132 ServiceEndPoint: model.NewDIDCommV2Endpoint([]model.DIDCommV2Endpoint{{ 133 URI: uri, 134 Accept: accept, 135 RoutingKeys: routingKeys, 136 }}), 137 RecipientKeys: destination.RecipientKeys, 138 Namespace: connection.MyNSPrefix, 139 DIDCommVersion: service.V2, 140 } 141 142 for _, opt := range opts { 143 opt(&connRec) 144 } 145 146 err = c.connectionRecorder.SaveConnectionRecord(&connRec) 147 if err != nil { 148 return "", err 149 } 150 151 return connID, nil 152 } 153 154 // SetConnectionToDIDCommV2 sets that a connection is using didcomm v2, and associated versions of protocols. 155 func (c *Client) SetConnectionToDIDCommV2(connID string) error { 156 connRec, err := c.connectionRecorder.GetConnectionRecord(connID) 157 if err != nil { 158 return fmt.Errorf("failed to get connection: %w", err) 159 } 160 161 connRec.DIDCommVersion = service.V2 162 163 err = c.connectionRecorder.SaveConnectionRecord(connRec) 164 if err != nil { 165 return fmt.Errorf("failed to save updated connection: %w", err) 166 } 167 168 return nil 169 } 170 171 type rotateDIDOpts struct { 172 createPeerDID bool 173 newDID string 174 } 175 176 // RotateDIDOption options for Client.RotateDID. 177 type RotateDIDOption func(opts *rotateDIDOpts) 178 179 // WithNewDID option for rotating a DID, with the given DID for the new DID. 180 func WithNewDID(newDID string) RotateDIDOption { 181 return func(opts *rotateDIDOpts) { 182 opts.newDID = newDID 183 } 184 } 185 186 // ByCreatingPeerDID option for rotating a DID to a peer DID, by creating a fresh peer DID. 187 func ByCreatingPeerDID() RotateDIDOption { 188 return func(opts *rotateDIDOpts) { 189 opts.createPeerDID = true 190 } 191 } 192 193 // CreateConnectionOption options for Client.CreateConnectionV2. 194 type CreateConnectionOption func(record *connection.Record) 195 196 // WithTheirLabel option. 197 func WithTheirLabel(l string) CreateConnectionOption { 198 return func(record *connection.Record) { 199 record.TheirLabel = l 200 } 201 }