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  }