diff --git a/.changeset/flat-snails-send.md b/.changeset/flat-snails-send.md new file mode 100644 index 00000000000..f2e95093b26 --- /dev/null +++ b/.changeset/flat-snails-send.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#changed: add workflowKey to StandardCapabilities keystore diff --git a/core/capabilities/integration_tests/framework/don.go b/core/capabilities/integration_tests/framework/don.go index 19d65a60309..36b7bda5475 100644 --- a/core/capabilities/integration_tests/framework/don.go +++ b/core/capabilities/integration_tests/framework/don.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-protos/cre/go/values" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" "github.com/smartcontractkit/chainlink-evm/pkg/assets" @@ -111,11 +112,12 @@ func (c DonContext) WaitForWorkflowRegistryMetadata(t *testing.T, workflowName s type capabilityNode struct { *cltest.TestApplication - registry *capabilities.Registry - key ethkey.KeyV2 - KeyBundle ocr2key.KeyBundle - peer peerIDAndOCRSigner - start func() + registry *capabilities.Registry + key ethkey.KeyV2 + KeyBundle ocr2key.KeyBundle + peer peerIDAndOCRSigner + workflowKey *workflowkey.Key + start func() } type DON struct { @@ -190,6 +192,14 @@ func NewDON(ctx context.Context, t *testing.T, lggr logger.Logger, donConfig Don } }, donContext.syncerFetcherFunc, donContext.computeFetcherFactory) require.NoError(t, node.KeyStore.P2P().Add(ctx, donConfig.p2pKeys[i])) + workflowKeys, err := node.KeyStore.Workflow().GetAll() + require.NoError(t, err) + + // Workflow nodes should only have at most 1 workflow key. + require.LessOrEqual(t, len(workflowKeys), 1) + if len(workflowKeys) == 1 { + cn.workflowKey = &workflowKeys[0] + } require.NoError(t, node.Start(testutils.Context(t))) cn.TestApplication = node } @@ -260,6 +270,17 @@ func (d *DON) GetPeerIDsAndOCRSigners() []peerIDAndOCRSigner { return peers } +func (d *DON) GetWorkflowPublicKeys() []*[32]byte { + keys := make([]*[32]byte, 0, len(d.nodes)) + for _, node := range d.nodes { + if node.workflowKey != nil { + pubKey := node.workflowKey.PublicKey() + keys = append(keys, &pubKey) + } + } + return keys +} + func (d *DON) Start(ctx context.Context) error { for _, triggerFactory := range d.triggerFactories { for _, node := range d.nodes { diff --git a/core/services/standardcapabilities/delegate.go b/core/services/standardcapabilities/delegate.go index 3661bc0e5cf..84ed6111ff1 100644 --- a/core/services/standardcapabilities/delegate.go +++ b/core/services/standardcapabilities/delegate.go @@ -2,6 +2,7 @@ package standardcapabilities import ( "context" + "crypto" "fmt" "github.com/google/uuid" @@ -118,22 +119,29 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser kvStore := job.NewKVStore(spec.ID, d.ds) - var keystore core.Keystore - if d.ks.P2P() != nil && d.externalPeerWrapper != nil { - key, err := d.ks.P2P().GetOrFirst(p2pkey.PeerID(d.externalPeerWrapper.GetPeer().ID())) + // Enable signing and decryption for the capability, if available. + var ks core.Keystore + var decrypter core.Decrypter + var signer crypto.Signer + if d.ks.Workflow() != nil { + workflowKeys, err := d.ks.Workflow().GetAll() if err != nil { - return nil, fmt.Errorf("external peer wrapper does not pertain to a valid P2P key %x: %w", d.externalPeerWrapper.GetPeer().ID(), err) + return nil, fmt.Errorf("failed to get workflow keys: %w", err) } - keystore, err = core.NewSingleAccountSigner(&core.P2PAccountKey, key) - if err != nil { - return nil, fmt.Errorf("failed to create single account signer for P2P key: %w", err) + if len(workflowKeys) > 0 { + decrypter = &workflowKeys[0] } - } else { - var err error - keystore, err = core.NewSingleAccountSigner(nil, nil) + } + if d.ks.P2P() != nil && d.externalPeerWrapper != nil { + p2pKey, err := d.ks.P2P().GetOrFirst(p2pkey.PeerID(d.externalPeerWrapper.GetPeer().ID())) if err != nil { - return nil, fmt.Errorf("failed to create empty single account signer: %w", err) + return nil, fmt.Errorf("external peer wrapper does not pertain to a valid P2P key %x: %w", d.externalPeerWrapper.GetPeer().ID(), err) } + signer = p2pKey + } + ks, err := core.NewSignerDecrypter(core.StandardCapabilityAccount, signer, decrypter) + if err != nil { + return nil, fmt.Errorf("failed to create signer decrypter: %w", err) } telemetryService := generic.NewTelemetryAdapter(d.monitoringEndpointGen) @@ -293,7 +301,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser } standardCapability := NewStandardCapabilities(log, spec.StandardCapabilitiesSpec, d.cfg, telemetryService, kvStore, d.registry, errorLog, - pr, relayerSet, oracleFactory, connector, keystore) + pr, relayerSet, oracleFactory, connector, ks) return []job.ServiceCtx{standardCapability}, nil }