diff --git a/core/capabilities/launcher.go b/core/capabilities/launcher.go index 32bda8c9e08..ee578ce0c0a 100644 --- a/core/capabilities/launcher.go +++ b/core/capabilities/launcher.go @@ -490,7 +490,7 @@ func (w *launcher) addRemoteCapability(ctx context.Context, cid string, capabili methodConfig := capabilityConfig.CapabilityMethodConfig if methodConfig != nil { // v2 capability - handle via CombinedClient - errAdd := w.addRemoteCapabilityV2(ctx, capability.ID, methodConfig, myDON, remoteDON) + errAdd := w.addRemoteCapabilityV2(ctx, capability.ID, methodConfig, myDON, remoteDON, localRegistry) if errAdd != nil { return fmt.Errorf("failed to add remote v2 capability %s: %w", capability.ID, errAdd) } @@ -581,7 +581,7 @@ func (w *launcher) addRemoteCapability(ctx context.Context, cid string, capabili w.cachedShims.executableClients[shimKey] = execCap } // V1 capabilities read transmission schedule from every request - if errCfg := execCap.SetConfig(info, myDON.DON, defaultTargetRequestTimeout, nil); errCfg != nil { + if errCfg := execCap.SetConfig(info, myDON.DON, defaultTargetRequestTimeout, nil, nil); errCfg != nil { return nil, fmt.Errorf("failed to set trigger config: %w", errCfg) } return execCap.(capabilityService), nil @@ -607,7 +607,7 @@ func (w *launcher) addRemoteCapability(ctx context.Context, cid string, capabili w.cachedShims.executableClients[shimKey] = execCap } // V1 capabilities read transmission schedule from every request - if errCfg := execCap.SetConfig(info, myDON.DON, defaultTargetRequestTimeout, nil); errCfg != nil { + if errCfg := execCap.SetConfig(info, myDON.DON, defaultTargetRequestTimeout, nil, nil); errCfg != nil { return nil, fmt.Errorf("failed to set trigger config: %w", errCfg) } return execCap.(capabilityService), nil @@ -914,7 +914,7 @@ func signersFor(don registrysyncer.DON, localRegistry *registrysyncer.LocalRegis } // Add a V2 capability with multiple methods, using CombinedClient. -func (w *launcher) addRemoteCapabilityV2(ctx context.Context, capID string, methodConfig map[string]capabilities.CapabilityMethodConfig, myDON registrysyncer.DON, remoteDON registrysyncer.DON) error { +func (w *launcher) addRemoteCapabilityV2(ctx context.Context, capID string, methodConfig map[string]capabilities.CapabilityMethodConfig, myDON registrysyncer.DON, remoteDON registrysyncer.DON, localRegistry *registrysyncer.LocalRegistry) error { info, err := capabilities.NewRemoteCapabilityInfo( capID, capabilities.CapabilityTypeCombined, @@ -969,7 +969,12 @@ func (w *launcher) addRemoteCapabilityV2(ctx context.Context, capID string, meth Schedule: transmission.EnumToString(config.RemoteExecutableConfig.TransmissionSchedule), DeltaStage: config.RemoteExecutableConfig.DeltaStage, } - err := client.SetConfig(info, myDON.DON, config.RemoteExecutableConfig.RequestTimeout, transmissionConfig) + + signers, err := signersFor(remoteDON, localRegistry) + if err != nil { + return fmt.Errorf("failed to get signers for executable client: %w", err) + } + err = client.SetConfig(info, myDON.DON, config.RemoteExecutableConfig.RequestTimeout, transmissionConfig, signers) if err != nil { w.lggr.Errorw("failed to update client config", "capID", capID, "method", method, "error", err) continue diff --git a/core/capabilities/remote/executable/client.go b/core/capabilities/remote/executable/client.go index fe664aa6988..96abdc76eb3 100644 --- a/core/capabilities/remote/executable/client.go +++ b/core/capabilities/remote/executable/client.go @@ -46,12 +46,14 @@ type dynamicConfig struct { requestTimeout time.Duration // Has to be set only for V2 capabilities. V1 capabilities read transmission schedule from every request. transmissionConfig *transmission.TransmissionConfig + // Has to be set only for V2 capabilities using OCR. + signers [][]byte } type Client interface { commoncap.ExecutableCapability Receive(ctx context.Context, msg *types.MessageBody) - SetConfig(remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, requestTimeout time.Duration, transmissionConfig *transmission.TransmissionConfig) error + SetConfig(remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, requestTimeout time.Duration, transmissionConfig *transmission.TransmissionConfig, signers [][]byte) error } var _ Client = &client{} @@ -78,7 +80,7 @@ func NewClient(capabilityID string, capMethodName string, dispatcher types.Dispa // SetConfig sets the remote capability configuration dynamically // TransmissionConfig has to be set only for V2 capabilities. V1 capabilities read transmission schedule from every request. -func (c *client) SetConfig(remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, requestTimeout time.Duration, transmissionConfig *transmission.TransmissionConfig) error { +func (c *client) SetConfig(remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, requestTimeout time.Duration, transmissionConfig *transmission.TransmissionConfig, signers [][]byte) error { if remoteCapabilityInfo.ID == "" || remoteCapabilityInfo.ID != c.capabilityID { return fmt.Errorf("capability info provided does not match the client's capabilityID: %s != %s", remoteCapabilityInfo.ID, c.capabilityID) } @@ -98,6 +100,7 @@ func (c *client) SetConfig(remoteCapabilityInfo commoncap.CapabilityInfo, localD localDONInfo: localDonInfo, requestTimeout: requestTimeout, transmissionConfig: transmissionConfig, + signers: signers, }) c.lggr.Infow("SetConfig", "remoteDONName", remoteCapabilityInfo.DON.Name, "remoteDONID", remoteCapabilityInfo.DON.ID, "requestTimeout", requestTimeout, "transmissionConfig", transmissionConfig) return nil @@ -234,7 +237,7 @@ func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest } req, err := request.NewClientExecuteRequest(ctx, c.lggr, capReq, cfg.remoteCapabilityInfo, cfg.localDONInfo, c.dispatcher, - cfg.requestTimeout, cfg.transmissionConfig, c.capMethodName) + cfg.requestTimeout, cfg.transmissionConfig, c.capMethodName, cfg.signers) if err != nil { return commoncap.CapabilityResponse{}, fmt.Errorf("failed to create client request: %w", err) } diff --git a/core/capabilities/remote/executable/client_test.go b/core/capabilities/remote/executable/client_test.go index 93c463f59c1..4d82eb85e57 100644 --- a/core/capabilities/remote/executable/client_test.go +++ b/core/capabilities/remote/executable/client_test.go @@ -243,7 +243,7 @@ func testClient(t *testing.T, numWorkflowPeers int, workflowNodeResponseTimeout for i := range numWorkflowPeers { workflowPeerDispatcher := broker.NewDispatcherForNode(workflowPeers[i]) caller := executable.NewClient(capInfo.ID, "", workflowPeerDispatcher, lggr) - err := caller.SetConfig(capInfo, workflowDonInfo, workflowNodeResponseTimeout, nil) + err := caller.SetConfig(capInfo, workflowDonInfo, workflowNodeResponseTimeout, nil, nil) require.NoError(t, err) servicetest.Run(t, caller) broker.RegisterReceiverNode(workflowPeers[i], caller) @@ -403,7 +403,7 @@ func TestClient_SetConfig(t *testing.T) { DeltaStage: 10 * time.Millisecond, } - err := client.SetConfig(validCapInfo, validDonInfo, validTimeout, transmissionConfig) + err := client.SetConfig(validCapInfo, validDonInfo, validTimeout, transmissionConfig, nil) require.NoError(t, err) // Verify config was set @@ -418,7 +418,7 @@ func TestClient_SetConfig(t *testing.T) { CapabilityType: commoncap.CapabilityTypeAction, } - err := client.SetConfig(invalidCapInfo, validDonInfo, validTimeout, nil) + err := client.SetConfig(invalidCapInfo, validDonInfo, validTimeout, nil, nil) require.Error(t, err) assert.Contains(t, err.Error(), "capability info provided does not match the client's capabilityID") assert.Contains(t, err.Error(), "different_capability@1.0.0 != test_capability@1.0.0") @@ -431,7 +431,7 @@ func TestClient_SetConfig(t *testing.T) { F: 0, } - err := client.SetConfig(validCapInfo, invalidDonInfo, validTimeout, nil) + err := client.SetConfig(validCapInfo, invalidDonInfo, validTimeout, nil, nil) require.Error(t, err) assert.Contains(t, err.Error(), "empty localDonInfo provided") }) @@ -439,7 +439,7 @@ func TestClient_SetConfig(t *testing.T) { t.Run("successful config update", func(t *testing.T) { // Set initial config initialTimeout := 10 * time.Second - err := client.SetConfig(validCapInfo, validDonInfo, initialTimeout, nil) + err := client.SetConfig(validCapInfo, validDonInfo, initialTimeout, nil, nil) require.NoError(t, err) // Replace with new config @@ -450,7 +450,7 @@ func TestClient_SetConfig(t *testing.T) { F: 1, } - err = client.SetConfig(validCapInfo, newDonInfo, newTimeout, nil) + err = client.SetConfig(validCapInfo, newDonInfo, newTimeout, nil, nil) require.NoError(t, err) // Verify the config was completely replaced @@ -494,7 +494,7 @@ func TestClient_SetConfig_StartClose(t *testing.T) { }) t.Run("start succeeds after config set", func(t *testing.T) { - require.NoError(t, client.SetConfig(validCapInfo, validDonInfo, validTimeout, nil)) + require.NoError(t, client.SetConfig(validCapInfo, validDonInfo, validTimeout, nil, nil)) require.NoError(t, client.Start(ctx)) require.NoError(t, client.Close()) }) @@ -504,12 +504,12 @@ func TestClient_SetConfig_StartClose(t *testing.T) { freshClient := executable.NewClient(capabilityID, "execute", dispatcher, lggr) // Set initial config and start - require.NoError(t, freshClient.SetConfig(validCapInfo, validDonInfo, validTimeout, nil)) + require.NoError(t, freshClient.SetConfig(validCapInfo, validDonInfo, validTimeout, nil, nil)) require.NoError(t, freshClient.Start(ctx)) // Update config while running validCapInfo.Description = "new description" - require.NoError(t, freshClient.SetConfig(validCapInfo, validDonInfo, validTimeout, nil)) + require.NoError(t, freshClient.SetConfig(validCapInfo, validDonInfo, validTimeout, nil, nil)) // Verify config was updated info, err := freshClient.Info(ctx) diff --git a/core/capabilities/remote/executable/endtoend_test.go b/core/capabilities/remote/executable/endtoend_test.go index 996c0ca4657..2917df3124b 100644 --- a/core/capabilities/remote/executable/endtoend_test.go +++ b/core/capabilities/remote/executable/endtoend_test.go @@ -309,7 +309,7 @@ func testRemoteExecutableCapability(ctx context.Context, t *testing.T, underlyin for i := range numWorkflowPeers { workflowPeerDispatcher := broker.NewDispatcherForNode(workflowPeers[i]) workflowNode := executable.NewClient(capInfo.ID, "", workflowPeerDispatcher, lggr) - err := workflowNode.SetConfig(capInfo, workflowDonInfo, workflowNodeTimeout, nil) + err := workflowNode.SetConfig(capInfo, workflowDonInfo, workflowNodeTimeout, nil, nil) require.NoError(t, err) servicetest.Run(t, workflowNode) broker.RegisterReceiverNode(workflowPeers[i], workflowNode) diff --git a/core/capabilities/remote/executable/request/client_request.go b/core/capabilities/remote/executable/request/client_request.go index a771be2ad7c..e78bf39b08c 100644 --- a/core/capabilities/remote/executable/request/client_request.go +++ b/core/capabilities/remote/executable/request/client_request.go @@ -14,6 +14,7 @@ import ( ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ocr2key" "github.com/smartcontractkit/chainlink-common/pkg/beholder" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" caperrors "github.com/smartcontractkit/chainlink-common/pkg/capabilities/errors" @@ -60,19 +61,23 @@ type clientResponse struct { } type ClientRequest struct { - id string - cancelFn context.CancelFunc - responseCh chan clientResponse - createdAt time.Time - responseIDCount map[[32]byte]int - meteringResponses map[[32]byte][]commoncap.MeteringNodeDetail - errorCount map[string]int - totalErrorCount int - responseReceived map[p2ptypes.PeerID]bool - lggr logger.Logger - - requiredIdenticalResponses int - remoteNodeCount int + id string + cancelFn context.CancelFunc + responseCh chan clientResponse + createdAt time.Time + responseIDCount map[[32]byte]int + meteringResponses map[[32]byte][]commoncap.MeteringNodeDetail + errorCount map[string]int + totalErrorCount int + payloadNotAvailableCount int + responseReceived map[p2ptypes.PeerID]bool + lggr logger.Logger + signers [][]byte + workflowExecutionID string + referenceID string + + requiredResponseConfirmations int + remoteNodeCount int requestTimeout time.Duration @@ -85,6 +90,7 @@ type ClientRequest struct { func NewClientExecuteRequest(ctx context.Context, lggr logger.Logger, req commoncap.CapabilityRequest, remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, dispatcher types.Dispatcher, requestTimeout time.Duration, transmissionConfig *transmission.TransmissionConfig, capMethodName string, + signers [][]byte, ) (*ClientRequest, error) { rawRequest, err := proto.MarshalOptions{Deterministic: true}.Marshal(pb.CapabilityRequestToProto(req)) if err != nil { @@ -114,7 +120,7 @@ func NewClientExecuteRequest(ctx context.Context, lggr logger.Logger, req common } lggr = logger.With(lggr, "requestId", requestID) // cap ID and method name included in the parent logger - return newClientRequest(ctx, lggr, requestID, remoteCapabilityInfo, localDonInfo, dispatcher, requestTimeout, tc, types.MethodExecute, rawRequest, workflowExecutionID, req.Metadata.ReferenceID, capMethodName) + return newClientRequest(ctx, lggr, requestID, remoteCapabilityInfo, localDonInfo, dispatcher, requestTimeout, tc, types.MethodExecute, rawRequest, workflowExecutionID, req.Metadata.ReferenceID, capMethodName, signers) } var defaultDelayMargin = 10 * time.Second @@ -122,6 +128,7 @@ var defaultDelayMargin = 10 * time.Second func newClientRequest(ctx context.Context, lggr logger.Logger, requestID string, remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, dispatcher types.Dispatcher, requestTimeout time.Duration, tc transmission.TransmissionConfig, methodType string, rawRequest []byte, workflowExecutionID string, stepRef string, capMethodName string, + signers [][]byte, ) (*ClientRequest, error) { remoteCapabilityDonInfo := remoteCapabilityInfo.DON if remoteCapabilityDonInfo == nil { @@ -214,19 +221,22 @@ func newClientRequest(ctx context.Context, lggr logger.Logger, requestID string, } return &ClientRequest{ - id: requestID, - cancelFn: cancelFn, - createdAt: time.Now(), - requestTimeout: requestTimeout, - requiredIdenticalResponses: int(remoteCapabilityDonInfo.F + 1), - remoteNodeCount: len(remoteCapabilityDonInfo.Members), - responseIDCount: make(map[[32]byte]int), - meteringResponses: make(map[[32]byte][]commoncap.MeteringNodeDetail), - errorCount: make(map[string]int), - responseReceived: responseReceived, - responseCh: make(chan clientResponse, 1), - wg: &wg, - lggr: lggr, + id: requestID, + cancelFn: cancelFn, + createdAt: time.Now(), + requestTimeout: requestTimeout, + requiredResponseConfirmations: int(remoteCapabilityDonInfo.F + 1), + remoteNodeCount: len(remoteCapabilityDonInfo.Members), + responseIDCount: make(map[[32]byte]int), + meteringResponses: make(map[[32]byte][]commoncap.MeteringNodeDetail), + errorCount: make(map[string]int), + responseReceived: responseReceived, + responseCh: make(chan clientResponse, 1), + wg: &wg, + lggr: lggr, + signers: signers, + workflowExecutionID: workflowExecutionID, + referenceID: stepRef, }, nil } @@ -328,29 +338,32 @@ func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) err c.responseReceived[sender] = true if msg.Error == types.Error_OK { + resp, err := pb.UnmarshalCapabilityResponse(msg.Payload) + if err != nil { + return fmt.Errorf("failed to unmarshal capability response: %w", err) + } + // metering reports per node are aggregated into a single array of values. for any single node message, the // metering values are extracted from the CapabilityResponse, added to an array, and the CapabilityResponse // is marshalled without the metering value to get the hash. each node could have a different metering value // which would result in different hashes. removing the metering detail allows for direct comparison of results. - responseID, metadata, err := c.getMessageHashAndMetadata(msg) + responseID, err := c.getMessageHash(resp) if err != nil { return fmt.Errorf("failed to get message hash: %w", err) } - lggr := logger.With(c.lggr, "responseID", hex.EncodeToString(responseID[:]), "requiredCount", c.requiredIdenticalResponses, "peer", sender) + lggr := logger.With(c.lggr, "responseID", hex.EncodeToString(responseID[:]), "requiredCount", c.requiredResponseConfirmations, "peer", sender) nodeReports, exists := c.meteringResponses[responseID] if !exists { nodeReports = make([]commoncap.MeteringNodeDetail, 0) } - if len(metadata.Metering) == 1 { - rpt := metadata.Metering[0] - rpt.Peer2PeerID = sender.String() - - nodeReports = append(nodeReports, rpt) + rpt, err := commoncap.ExtractMeteringFromMetadata(sender, resp.Metadata) + if err != nil { + lggr.Warnw("invalid metering detail", "err", err) } else { - lggr.Warnw("node metering detail did not contain exactly 1 record", "records", len(metadata.Metering)) + nodeReports = append(nodeReports, rpt) } c.responseIDCount[responseID]++ @@ -360,7 +373,7 @@ func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) err lggr.Warnw("received multiple unique responses for the same request", "count for responseID", len(c.responseIDCount)) } - if c.responseIDCount[responseID] == c.requiredIdenticalResponses { + if c.responseIDCount[responseID] == c.requiredResponseConfirmations || c.hasValidAttestation(resp) { payload, err := c.encodePayloadWithMetadata(msg, commoncap.ResponseMetadata{Metering: nodeReports}) if err != nil { return fmt.Errorf("failed to encode payload with metadata: %w", err) @@ -370,6 +383,16 @@ func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) err } } else { c.lggr.Debugw("received error from peer", "error", msg.Error, "errorMsg", msg.ErrorMsg, "peer", sender) + if commoncap.ErrResponsePayloadNotAvailable.Is(errors.New(msg.ErrorMsg)) { + c.payloadNotAvailableCount++ + if c.payloadNotAvailableCount == c.remoteNodeCount-c.requiredResponseConfirmations+1 { + // return an error to indicate unexpected state, but do not send an error as we might still receive a response with valid attestation. + return fmt.Errorf("unexpected state: received %d payload not available responses, while max allowed is %d. This means a bug in the code, please investigate", + c.payloadNotAvailableCount, c.remoteNodeCount-c.requiredResponseConfirmations) + } + return nil + } + c.errorCount[msg.ErrorMsg]++ c.totalErrorCount++ @@ -377,9 +400,9 @@ func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) err c.lggr.Warnw("received multiple different errors for the same request", "numDifferentErrors", len(c.errorCount)) } - if c.errorCount[msg.ErrorMsg] == c.requiredIdenticalResponses { + if c.errorCount[msg.ErrorMsg] == c.requiredResponseConfirmations { c.sendResponse(clientResponse{Err: newRemoteCapabilityExecuteError(msg.Error, msg.ErrorMsg)}) - } else if c.totalErrorCount == c.remoteNodeCount-c.requiredIdenticalResponses+1 { + } else if c.totalErrorCount == c.remoteNodeCount-c.requiredResponseConfirmations+1 { c.sendResponse(clientResponse{Err: newRemoteCapabilityExecuteErrorWithMessage( fmt.Sprintf("received %d errors, last error %s : %s", c.totalErrorCount, msg.Error, msg.ErrorMsg), msg.ErrorMsg, @@ -389,6 +412,59 @@ func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) err return nil } +func (c *ClientRequest) hasValidAttestation(resp commoncap.CapabilityResponse) bool { + if resp.OCRAttestation == nil { + return false + } + + err := c.verifyAttestation(resp) + if err != nil { + c.lggr.Errorw("Attestation is present, but not valid. This is most likely a bug and requires investigation - falling back to identical responses verification", "error", err) + return false + } + + return true +} + +func (c *ClientRequest) verifyAttestation(resp commoncap.CapabilityResponse) error { + attestation := resp.OCRAttestation + if attestation == nil { + return errors.New("attestation is missing") + } + + if len(attestation.Sigs) < c.requiredResponseConfirmations { + return fmt.Errorf("not enough signatures: got %d, need at least %d", len(attestation.Sigs), c.requiredResponseConfirmations) + } + + if len(c.signers) < c.requiredResponseConfirmations { + return fmt.Errorf("number of configured OCR signers is less than required confirmations: got %d, need at least %d", len(c.signers), c.requiredResponseConfirmations) + } + + reportData, err := commoncap.ResponseToReportData(c.workflowExecutionID, c.referenceID, resp.Payload.Value, resp.Metadata) + if err != nil { + return fmt.Errorf("failed to convert response to report data: %w", err) + } + sigData := ocr2key.ReportToSigData3(attestation.ConfigDigest, attestation.SequenceNumber, reportData[:]) + signed := make([]bool, len(c.signers)) + for _, sig := range attestation.Sigs { + if int(sig.Signer) >= len(c.signers) { + return fmt.Errorf("invalid signer index: %d", sig.Signer) + } + + if signed[sig.Signer] { + return fmt.Errorf("duplicate signature from signer index: %d", sig.Signer) + } + + if !ocr2key.EvmVerifyBlob(c.signers[sig.Signer], sigData, sig.Signature) { + return fmt.Errorf("invalid signature from signer index: %d", sig.Signer) + } + + signed[sig.Signer] = true + } + + return nil +} + func (c *ClientRequest) sendResponse(response clientResponse) { c.responseCh <- response close(c.responseCh) @@ -400,23 +476,17 @@ func (c *ClientRequest) sendResponse(response clientResponse) { c.lggr.Debugw("received OK response") } -func (c *ClientRequest) getMessageHashAndMetadata(msg *types.MessageBody) ([32]byte, commoncap.ResponseMetadata, error) { - var metadata commoncap.ResponseMetadata - - resp, err := pb.UnmarshalCapabilityResponse(msg.Payload) - if err != nil { - return [32]byte{}, metadata, err - } - - metadata = resp.Metadata - resp.Metadata = commoncap.ResponseMetadata{} - - payload, err := pb.MarshalCapabilityResponse(resp) +func (c *ClientRequest) getMessageHash(msg commoncap.CapabilityResponse) ([32]byte, error) { + // clear metadata to ensure it doesn't affect the hash, as different nodes might have different metadata (e.g. different metering values) + // since msg is passed as value, this won't affect the original message + msg.Metadata = commoncap.ResponseMetadata{} + msg.OCRAttestation = nil + payload, err := pb.MarshalCapabilityResponse(msg) if err != nil { - return [32]byte{}, metadata, err + return [32]byte{}, err } - return sha256.Sum256(payload), metadata, nil + return sha256.Sum256(payload), nil } func (c *ClientRequest) encodePayloadWithMetadata(msg *types.MessageBody, metadata commoncap.ResponseMetadata) ([]byte, error) { diff --git a/core/capabilities/remote/executable/request/client_request_internal_test.go b/core/capabilities/remote/executable/request/client_request_internal_test.go new file mode 100644 index 00000000000..2193bc3fa50 --- /dev/null +++ b/core/capabilities/remote/executable/request/client_request_internal_test.go @@ -0,0 +1,191 @@ +package request + +import ( + "crypto/rand" + "testing" + + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" + + "github.com/smartcontractkit/chainlink-common/keystore/corekeys" + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ocr2key" + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-protos/cre/go/values" +) + +func Test_ClientRequest_VerifyAttestation(t *testing.T) { + const workflowExecutionID = "95ef5e32deb99a10ee6804bc4af13855687559d7ff6552ac6dbb2ce0abbadeed" + const referenceID = "step1" + spendUnit, spendValue := "testunit", "42" + + val, err := values.NewMap(map[string]any{"response": "attested"}) + require.NoError(t, err) + valueProto := values.ProtoMap(val) + valueBytes, err := proto.Marshal(valueProto) + require.NoError(t, err) + + configDigest := ocrtypes.ConfigDigest{1, 2, 3, 4, 5} + seqNr := uint64(100) + + kb1, err := ocr2key.New(corekeys.EVM) + require.NoError(t, err) + kb2, err := ocr2key.New(corekeys.EVM) + require.NoError(t, err) + + validResp := commoncap.CapabilityResponse{ + Metadata: commoncap.ResponseMetadata{ + Metering: []commoncap.MeteringNodeDetail{ + {SpendUnit: spendUnit, SpendValue: spendValue}, + }, + }, + Payload: &anypb.Any{TypeUrl: "type.googleapis.com/values.v1.Map", Value: valueBytes}, + } + + reportData, err := commoncap.ResponseToReportData(workflowExecutionID, referenceID, valueBytes, validResp.Metadata) + require.NoError(t, err) + + sig1, err := kb1.Sign3(configDigest, seqNr, reportData[:]) + require.NoError(t, err) + sig2, err := kb2.Sign3(configDigest, seqNr, reportData[:]) + require.NoError(t, err) + + signers := [][]byte{kb1.PublicKey(), kb2.PublicKey()} + + validResp.OCRAttestation = &commoncap.OCRAttestation{ + ConfigDigest: configDigest, + SequenceNumber: seqNr, + Sigs: []commoncap.AttributedSignature{ + {Signer: 0, Signature: sig1}, + {Signer: 1, Signature: sig2}, + }, + } + + c := &ClientRequest{ + lggr: logger.Test(t), + signers: signers, + workflowExecutionID: workflowExecutionID, + referenceID: referenceID, + requiredResponseConfirmations: 2, + } + + t.Run("not enough signers returns error", func(t *testing.T) { + cBad := &ClientRequest{ + workflowExecutionID: workflowExecutionID, + referenceID: referenceID, + lggr: logger.Test(t), + requiredResponseConfirmations: 2, + } + err := cBad.verifyAttestation(validResp) + require.Error(t, err) + require.Contains(t, err.Error(), "number of configured OCR signers is less than required confirmations: got 0, need at least 2") + }) + + t.Run("not enough signatures returns error", func(t *testing.T) { + respFewSigs := commoncap.CapabilityResponse{ + Metadata: commoncap.ResponseMetadata{ + Metering: []commoncap.MeteringNodeDetail{{SpendUnit: spendUnit, SpendValue: spendValue}}, + }, + Payload: &anypb.Any{TypeUrl: "type.googleapis.com/values.v1.Map", Value: valueBytes}, + OCRAttestation: &commoncap.OCRAttestation{ + ConfigDigest: configDigest, + SequenceNumber: seqNr, + Sigs: []commoncap.AttributedSignature{{Signer: 0, Signature: sig1}}, + }, + } + err := c.verifyAttestation(respFewSigs) + require.Error(t, err) + require.Contains(t, err.Error(), "not enough signatures") + }) + + t.Run("invalid signer index returns error", func(t *testing.T) { + respBadSigner := commoncap.CapabilityResponse{ + Metadata: commoncap.ResponseMetadata{ + Metering: []commoncap.MeteringNodeDetail{{SpendUnit: spendUnit, SpendValue: spendValue}}, + }, + Payload: &anypb.Any{TypeUrl: "type.googleapis.com/values.v1.Map", Value: valueBytes}, + OCRAttestation: &commoncap.OCRAttestation{ + ConfigDigest: configDigest, + SequenceNumber: seqNr, + Sigs: []commoncap.AttributedSignature{ + {Signer: 0, Signature: sig1}, + {Signer: 99, Signature: sig2}, + }, + }, + } + err := c.verifyAttestation(respBadSigner) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid signer index") + }) + + t.Run("duplicate signature returns error", func(t *testing.T) { + respDupSig := commoncap.CapabilityResponse{ + Metadata: commoncap.ResponseMetadata{ + Metering: []commoncap.MeteringNodeDetail{{SpendUnit: spendUnit, SpendValue: spendValue}}, + }, + Payload: &anypb.Any{TypeUrl: "type.googleapis.com/values.v1.Map", Value: valueBytes}, + OCRAttestation: &commoncap.OCRAttestation{ + ConfigDigest: configDigest, + SequenceNumber: seqNr, + Sigs: []commoncap.AttributedSignature{ + {Signer: 0, Signature: sig1}, + {Signer: 0, Signature: sig1}, + }, + }, + } + err := c.verifyAttestation(respDupSig) + require.Error(t, err) + require.Contains(t, err.Error(), "duplicate signature") + }) + + t.Run("invalid signature returns error", func(t *testing.T) { + badSig := make([]byte, 65) + _, err := rand.Read(badSig) + require.NoError(t, err) + respBadSig := commoncap.CapabilityResponse{ + Metadata: commoncap.ResponseMetadata{ + Metering: []commoncap.MeteringNodeDetail{{SpendUnit: spendUnit, SpendValue: spendValue}}, + }, + Payload: &anypb.Any{TypeUrl: "type.googleapis.com/values.v1.Map", Value: valueBytes}, + OCRAttestation: &commoncap.OCRAttestation{ + ConfigDigest: configDigest, + SequenceNumber: seqNr, + Sigs: []commoncap.AttributedSignature{ + {Signer: 0, Signature: sig1}, + {Signer: 1, Signature: badSig}, + }, + }, + } + err = c.verifyAttestation(respBadSig) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid signature") + }) + + t.Run("wrong payload bytes produces invalid signature", func(t *testing.T) { + wrongBytes := []byte("tampered") + respWrongPayload := commoncap.CapabilityResponse{ + Metadata: commoncap.ResponseMetadata{ + Metering: []commoncap.MeteringNodeDetail{{SpendUnit: spendUnit, SpendValue: spendValue}}, + }, + Payload: &anypb.Any{TypeUrl: "x", Value: wrongBytes}, + OCRAttestation: &commoncap.OCRAttestation{ + ConfigDigest: configDigest, + SequenceNumber: seqNr, + Sigs: []commoncap.AttributedSignature{ + {Signer: 0, Signature: sig1}, + {Signer: 1, Signature: sig2}, + }, + }, + } + err := c.verifyAttestation(respWrongPayload) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid signature") + }) + + t.Run("valid attestation succeeds", func(t *testing.T) { + err := c.verifyAttestation(validResp) + require.NoError(t, err) + }) +} diff --git a/core/capabilities/remote/executable/request/client_request_test.go b/core/capabilities/remote/executable/request/client_request_test.go index d35f8c11082..e9c25255938 100644 --- a/core/capabilities/remote/executable/request/client_request_test.go +++ b/core/capabilities/remote/executable/request/client_request_test.go @@ -8,15 +8,20 @@ import ( "testing" "time" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + "google.golang.org/protobuf/types/known/anypb" + "github.com/smartcontractkit/chainlink-common/keystore/corekeys" + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ocr2key" "github.com/smartcontractkit/chainlink-common/pkg/beholder/beholdertest" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" caperrors "github.com/smartcontractkit/chainlink-common/pkg/capabilities/errors" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-protos/cre/go/values" + pbvalues "github.com/smartcontractkit/chainlink-protos/cre/go/values/pb" "github.com/smartcontractkit/chainlink-protos/workflows/go/events" "google.golang.org/protobuf/proto" @@ -84,7 +89,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute, nil, "") + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", nil) defer req.Cancel(errors.New("test end")) require.NoError(t, err) @@ -135,7 +140,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute, nil, "") + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", nil) require.NoError(t, err) defer req.Cancel(errors.New("test end")) @@ -169,7 +174,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute, nil, "") + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", nil) require.NoError(t, err) defer req.Cancel(errors.New("test end")) @@ -200,7 +205,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute, nil, "") + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", nil) require.NoError(t, err) defer req.Cancel(errors.New("test end")) @@ -244,7 +249,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute, nil, "") + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", nil) require.NoError(t, err) defer req.Cancel(errors.New("test end")) @@ -290,7 +295,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute, nil, "") + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", nil) require.NoError(t, err) defer req.Cancel(errors.New("test end")) @@ -351,7 +356,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute, nil, "") + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", nil) require.NoError(t, err) defer req.Cancel(errors.New("test end")) @@ -383,6 +388,236 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { assert.Equal(t, resp, values.NewString("response1")) }) + t.Run("Execute Request With Valid Attestation", func(t *testing.T) { + const F = 1 + const N = 3*F + 1 + capabilityPeers, capDonInfo, capInfo := capabilityDon(t, N, F) + + configDigest := ocrtypes.ConfigDigest{1, 2, 3, 4, 5} + kb1, err := ocr2key.New(corekeys.EVM) + require.NoError(t, err) + kb2, err := ocr2key.New(corekeys.EVM) + require.NoError(t, err) + + seqNr := uint64(100) + + payload, err := values.NewMap(map[string]int{ + "number": 42, + }) + require.NoError(t, err) + payloadAsAny, err := anypb.New(values.Proto(payload)) + require.NoError(t, err) + + spendUnit, spendValue := "testunit", "42" + capResponse := commoncap.CapabilityResponse{ + Metadata: commoncap.ResponseMetadata{ + Metering: []commoncap.MeteringNodeDetail{ + {SpendUnit: spendUnit, SpendValue: spendValue}, + }, + }, + Payload: payloadAsAny, + } + + reportData, err := commoncap.ResponseToReportData(capabilityRequest.Metadata.WorkflowExecutionID, capabilityRequest.Metadata.ReferenceID, payloadAsAny.Value, capResponse.Metadata) + require.NoError(t, err) + + sig1, err := kb1.Sign3(configDigest, seqNr, reportData[:]) + require.NoError(t, err) + sig2, err := kb2.Sign3(configDigest, seqNr, reportData[:]) + require.NoError(t, err) + + capResponse.OCRAttestation = &commoncap.OCRAttestation{ + ConfigDigest: configDigest, + SequenceNumber: seqNr, + Sigs: []commoncap.AttributedSignature{ + {Signer: 0, Signature: sig1}, + {Signer: 1, Signature: sig2}, + }, + } + + rawResponseWithAttestation, err := pb.MarshalCapabilityResponse(capResponse) + require.NoError(t, err) + + ocrSigners := [][]byte{kb1.PublicKey(), kb2.PublicKey()} + + assertValidResponse := func(t *testing.T, result []byte) { + capResponse, err := pb.UnmarshalCapabilityResponse(result) + require.NoError(t, err) + + var pbValue pbvalues.Value + require.NoError(t, capResponse.Payload.UnmarshalTo(&pbValue)) + receivedValue, err := values.FromProto(&pbValue) + require.NoError(t, err) + + var receivedMap map[string]int + require.NoError(t, receivedValue.UnwrapTo(&receivedMap)) + + assert.Equal(t, 42, receivedMap["number"]) + require.GreaterOrEqual(t, len(capResponse.Metadata.Metering), 1) + require.Equal(t, spendUnit, capResponse.Metadata.Metering[0].SpendUnit) + require.Equal(t, spendValue, capResponse.Metadata.Metering[0].SpendValue) + } + + t.Run("succeeds on first peer with valid attestation", func(t *testing.T) { + ctx := t.Context() + + dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} + req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", ocrSigners) + require.NoError(t, err) + defer req.Cancel(errors.New("test end")) + + for range N { + <-dispatcher.msgs + } + + assert.Empty(t, dispatcher.msgs) + + msg := &types.MessageBody{ + CapabilityId: capInfo.ID, + CapabilityDonId: capDonInfo.ID, + CallerDonId: workflowDonInfo.ID, + Method: types.MethodExecute, + Payload: rawResponseWithAttestation, + MessageId: []byte("messageID"), + } + msg.Sender = capabilityPeers[0][:] + err = req.OnMessage(ctx, msg) + require.NoError(t, err) + + response := <-req.ResponseChan() + assertValidResponse(t, response.Result) + }) + t.Run("attestation is not valid, but we fallback to identical responses", func(t *testing.T) { + ctx := t.Context() + + dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} + req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", ocrSigners) + require.NoError(t, err) + defer req.Cancel(errors.New("test end")) + + for range N { + <-dispatcher.msgs + } + + assert.Empty(t, dispatcher.msgs) + + for i := range F + 1 { + respInvalidAtt := commoncap.CapabilityResponse{ + Metadata: commoncap.ResponseMetadata{ + Metering: []commoncap.MeteringNodeDetail{ + {SpendUnit: spendUnit, SpendValue: spendValue}, + }, + }, + OCRAttestation: &commoncap.OCRAttestation{ + ConfigDigest: configDigest, + // make the sequence number invalid + SequenceNumber: seqNr + uint64(i) + 1, // #nosec G115 -- i is non-negative and within uint64 range + Sigs: []commoncap.AttributedSignature{ + {Signer: 0, Signature: sig1}, + {Signer: 1, Signature: sig2}, + }, + }, + Payload: payloadAsAny, + } + + rawRespInvalidAtt, err := pb.MarshalCapabilityResponse(respInvalidAtt) + require.NoError(t, err) + + msg := &types.MessageBody{ + CapabilityId: capInfo.ID, + CapabilityDonId: capDonInfo.ID, + CallerDonId: workflowDonInfo.ID, + Method: types.MethodExecute, + Payload: rawRespInvalidAtt, + MessageId: []byte("messageID"), + } + msg.Sender = capabilityPeers[i][:] + err = req.OnMessage(ctx, msg) + require.NoError(t, err) + } + + response := <-req.ResponseChan() + assertValidResponse(t, response.Result) + }) + + t.Run("2F peers return ErrResponsePayloadNotAvailable then success", func(t *testing.T) { + ctx := t.Context() + dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} + req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", ocrSigners) + require.NoError(t, err) + defer req.Cancel(errors.New("test end")) + + for range N { + <-dispatcher.msgs + } + + assert.Empty(t, dispatcher.msgs) + + for i := range 2 * F { + msgNA := &types.MessageBody{ + CapabilityId: capInfo.ID, + CapabilityDonId: capDonInfo.ID, + CallerDonId: workflowDonInfo.ID, + Method: types.MethodExecute, + MessageId: []byte("messageID"), + Error: types.Error_INTERNAL_ERROR, + ErrorMsg: commoncap.ErrResponsePayloadNotAvailable.Error(), + } + msgNA.Sender = capabilityPeers[i][:] + require.NoError(t, req.OnMessage(ctx, msgNA)) + } + + msgOK := &types.MessageBody{ + CapabilityId: capInfo.ID, + CapabilityDonId: capDonInfo.ID, + CallerDonId: workflowDonInfo.ID, + Method: types.MethodExecute, + Payload: rawResponseWithAttestation, + MessageId: []byte("messageID"), + } + msgOK.Sender = capabilityPeers[2*F][:] + require.NoError(t, req.OnMessage(ctx, msgOK)) + + response := <-req.ResponseChan() + assertValidResponse(t, response.Result) + }) + + t.Run("2F+1 peers return ErrResponsePayloadNotAvailable", func(t *testing.T) { + ctx := t.Context() + dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} + req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", ocrSigners) + require.NoError(t, err) + defer req.Cancel(errors.New("test end")) + + for range N { + <-dispatcher.msgs + } + + assert.Empty(t, dispatcher.msgs) + + noPayloadMsg := types.MessageBody{ + CapabilityId: capInfo.ID, + CapabilityDonId: capDonInfo.ID, + CallerDonId: workflowDonInfo.ID, + Method: types.MethodExecute, + MessageId: []byte("messageID"), + Error: types.Error_INTERNAL_ERROR, + ErrorMsg: commoncap.ErrResponsePayloadNotAvailable.Error(), + } + + for i := range 2 * F { + noPayloadMsg.Sender = capabilityPeers[i][:] + require.NoError(t, req.OnMessage(ctx, &noPayloadMsg)) + } + + noPayloadMsg.Sender = capabilityPeers[2*F][:] + require.Error(t, req.OnMessage(ctx, &noPayloadMsg)) + }) + }) t.Run("Executes full schedule", func(t *testing.T) { beholderTester := beholdertest.NewObserver(t) @@ -410,6 +645,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { 10*time.Minute, nil, "", + nil, ) require.NoError(t, err) defer req.Cancel(errors.New("test end")) @@ -529,6 +765,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { 10*time.Minute, nil, "", + nil, ) require.NoError(t, err) defer req.Cancel(errors.New("test end")) @@ -621,7 +858,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} req, err := request.NewClientExecuteRequest(ctx, logger.Test(t), capabilityRequest, capInfo, - workflowDonInfo, dispatcher, 10*time.Minute, nil, "") + workflowDonInfo, dispatcher, 10*time.Minute, nil, "", nil) require.NoError(t, err) defer req.Cancel(errors.New("test end")) @@ -686,6 +923,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { DeltaStage: 1000 * time.Millisecond, }, "", + nil, ) require.NoError(t, err) defer req.Cancel(errors.New("test end")) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index bb9d7fac716..516b5bd0a16 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -45,8 +45,8 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.97 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260317185256-d5f7db87ae70 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 - github.com/smartcontractkit/chainlink-common/keystore v1.0.2 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 + github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 github.com/smartcontractkit/chainlink-data-streams v0.1.13 github.com/smartcontractkit/chainlink-deployments-framework v0.86.3 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260326181417-f2272e4b4aa6 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 97c3f8d91d7..7421a6bc785 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1634,10 +1634,10 @@ github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7 github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7db87ae70/go.mod h1:P0/tjeeIIxfsBupk5MneRjq5uI9mj+ZQpMpYnFla6WM= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2 h1:5HdH/A6yn8INZAltYDLb7UkUi5IKemhJzJkDW4Bgxyg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2/go.mod h1:wDHq2E0KwUWG0lQ9f5frW1a7CKVW17MJLPuvKmtSRDg= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 h1:nh92CD2TZTtziEWu2reMDgEx1Zu0TGTkQcjQ3IE5bYM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2 h1:AWisx4JT3QV8tcgh6J5NCrex+wAgTYpWyHsyNPSXzsQ= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2/go.mod h1:rSkIHdomyak3YnUtXLenl6poIq8q0V3UZPiiyYqPdGA= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 h1:BAk0hlY3niOthWTOaF1mPyDdR17CNyARYKBeD9pF9uM= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 h1:5VDCWCwm0TFHJqK2gbs0ZeSIWFF4rDmHQBbJvvO87o4= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47/go.mod h1:vIX8ZkBosdvvVRJkxJV4qQjFXbRyDz/D2V/DJAv0lu8= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4 h1:NOUsjsMzNecbjiPWUQGlRSRAutEvCFrqqyETDJeh5q4= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4/go.mod h1:Zpvul9sTcZNAZOVzt5vBl1XZGNvQebFpnpn3/KOQvOQ= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340 h1:PsjEI+5jZIz9AS4eOsLS5VpSWJINf38clXV3wryPyMk= diff --git a/deployment/go.mod b/deployment/go.mod index 1c9d573e7f4..743b2f446d3 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -44,8 +44,8 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260224214816-cb23ec38649f github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260310183131-8d0f0e383288 github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317175207-e9ff89561326 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 - github.com/smartcontractkit/chainlink-common/keystore v1.0.2 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 + github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 github.com/smartcontractkit/chainlink-deployments-framework v0.86.3 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260326181417-f2272e4b4aa6 github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260107191744-4b93f62cffe3 diff --git a/deployment/go.sum b/deployment/go.sum index 195a9933489..6eea5bd873b 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1387,10 +1387,10 @@ github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317175207-e9ff github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317175207-e9ff89561326/go.mod h1:P0/tjeeIIxfsBupk5MneRjq5uI9mj+ZQpMpYnFla6WM= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2 h1:5HdH/A6yn8INZAltYDLb7UkUi5IKemhJzJkDW4Bgxyg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2/go.mod h1:wDHq2E0KwUWG0lQ9f5frW1a7CKVW17MJLPuvKmtSRDg= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 h1:nh92CD2TZTtziEWu2reMDgEx1Zu0TGTkQcjQ3IE5bYM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2 h1:AWisx4JT3QV8tcgh6J5NCrex+wAgTYpWyHsyNPSXzsQ= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2/go.mod h1:rSkIHdomyak3YnUtXLenl6poIq8q0V3UZPiiyYqPdGA= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 h1:BAk0hlY3niOthWTOaF1mPyDdR17CNyARYKBeD9pF9uM= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 h1:5VDCWCwm0TFHJqK2gbs0ZeSIWFF4rDmHQBbJvvO87o4= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47/go.mod h1:vIX8ZkBosdvvVRJkxJV4qQjFXbRyDz/D2V/DJAv0lu8= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340 h1:PsjEI+5jZIz9AS4eOsLS5VpSWJINf38clXV3wryPyMk= diff --git a/go.mod b/go.mod index c5f44b12223..4ee67651562 100644 --- a/go.mod +++ b/go.mod @@ -85,8 +85,8 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260224214816-cb23ec38649f github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250912190424-fd2e35d7deb5 github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 - github.com/smartcontractkit/chainlink-common/keystore v1.0.2 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 + github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 github.com/smartcontractkit/chainlink-data-streams v0.1.13 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260326181417-f2272e4b4aa6 diff --git a/go.sum b/go.sum index e0ae18005fa..bc9a3ed1881 100644 --- a/go.sum +++ b/go.sum @@ -1235,10 +1235,10 @@ github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250912190424-fd2e35d7deb5/go.mod h1:xtZNi6pOKdC3sLvokDvXOhgHzT+cyBqH/gWwvxTxqrg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2 h1:5HdH/A6yn8INZAltYDLb7UkUi5IKemhJzJkDW4Bgxyg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2/go.mod h1:wDHq2E0KwUWG0lQ9f5frW1a7CKVW17MJLPuvKmtSRDg= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 h1:nh92CD2TZTtziEWu2reMDgEx1Zu0TGTkQcjQ3IE5bYM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2 h1:AWisx4JT3QV8tcgh6J5NCrex+wAgTYpWyHsyNPSXzsQ= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2/go.mod h1:rSkIHdomyak3YnUtXLenl6poIq8q0V3UZPiiyYqPdGA= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 h1:BAk0hlY3niOthWTOaF1mPyDdR17CNyARYKBeD9pF9uM= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 h1:5VDCWCwm0TFHJqK2gbs0ZeSIWFF4rDmHQBbJvvO87o4= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47/go.mod h1:vIX8ZkBosdvvVRJkxJV4qQjFXbRyDz/D2V/DJAv0lu8= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340 h1:PsjEI+5jZIz9AS4eOsLS5VpSWJINf38clXV3wryPyMk= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 1d550a92e54..b3fa1b08dfb 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -38,8 +38,8 @@ require ( github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260317185256-d5f7db87ae70 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260310183131-8d0f0e383288 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260310183131-8d0f0e383288 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 - github.com/smartcontractkit/chainlink-common/keystore v1.0.2 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 + github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 github.com/smartcontractkit/chainlink-deployments-framework v0.86.3 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260326181417-f2272e4b4aa6 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260119171452-39c98c3b33cd diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 6e126ef7ed2..ae39690276f 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1374,10 +1374,10 @@ github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7 github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7db87ae70/go.mod h1:P0/tjeeIIxfsBupk5MneRjq5uI9mj+ZQpMpYnFla6WM= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2 h1:5HdH/A6yn8INZAltYDLb7UkUi5IKemhJzJkDW4Bgxyg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2/go.mod h1:wDHq2E0KwUWG0lQ9f5frW1a7CKVW17MJLPuvKmtSRDg= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 h1:nh92CD2TZTtziEWu2reMDgEx1Zu0TGTkQcjQ3IE5bYM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2 h1:AWisx4JT3QV8tcgh6J5NCrex+wAgTYpWyHsyNPSXzsQ= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2/go.mod h1:rSkIHdomyak3YnUtXLenl6poIq8q0V3UZPiiyYqPdGA= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 h1:BAk0hlY3niOthWTOaF1mPyDdR17CNyARYKBeD9pF9uM= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 h1:5VDCWCwm0TFHJqK2gbs0ZeSIWFF4rDmHQBbJvvO87o4= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47/go.mod h1:vIX8ZkBosdvvVRJkxJV4qQjFXbRyDz/D2V/DJAv0lu8= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340 h1:PsjEI+5jZIz9AS4eOsLS5VpSWJINf38clXV3wryPyMk= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 3f8c8cc6b8e..b44718f5e6a 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -27,7 +27,7 @@ require ( github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260317185256-d5f7db87ae70 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260310183131-8d0f0e383288 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260310183131-8d0f0e383288 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 github.com/smartcontractkit/chainlink-deployments-framework v0.86.3 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260326181417-f2272e4b4aa6 github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.3 @@ -473,7 +473,7 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/evm/deployment v0.0.0-20260317185256-d5f7db87ae70 // indirect github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7db87ae70 // indirect github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2 // indirect - github.com/smartcontractkit/chainlink-common/keystore v1.0.2 // indirect + github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 // indirect github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.13 // indirect github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260107191744-4b93f62cffe3 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index eb564e5975f..7d8e3d6cf2a 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1588,10 +1588,10 @@ github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7 github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7db87ae70/go.mod h1:P0/tjeeIIxfsBupk5MneRjq5uI9mj+ZQpMpYnFla6WM= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2 h1:5HdH/A6yn8INZAltYDLb7UkUi5IKemhJzJkDW4Bgxyg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2/go.mod h1:wDHq2E0KwUWG0lQ9f5frW1a7CKVW17MJLPuvKmtSRDg= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 h1:nh92CD2TZTtziEWu2reMDgEx1Zu0TGTkQcjQ3IE5bYM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2 h1:AWisx4JT3QV8tcgh6J5NCrex+wAgTYpWyHsyNPSXzsQ= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2/go.mod h1:rSkIHdomyak3YnUtXLenl6poIq8q0V3UZPiiyYqPdGA= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 h1:BAk0hlY3niOthWTOaF1mPyDdR17CNyARYKBeD9pF9uM= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 h1:5VDCWCwm0TFHJqK2gbs0ZeSIWFF4rDmHQBbJvvO87o4= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47/go.mod h1:vIX8ZkBosdvvVRJkxJV4qQjFXbRyDz/D2V/DJAv0lu8= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340 h1:PsjEI+5jZIz9AS4eOsLS5VpSWJINf38clXV3wryPyMk= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index b122b79ca02..d876a88e137 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -32,8 +32,8 @@ require ( github.com/sethvargo/go-retry v0.3.0 github.com/smartcontractkit/chain-selectors v1.0.97 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260310183131-8d0f0e383288 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 - github.com/smartcontractkit/chainlink-common/keystore v1.0.2 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 + github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 github.com/smartcontractkit/chainlink-deployments-framework v0.86.3 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260326181417-f2272e4b4aa6 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260119171452-39c98c3b33cd diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index 05aaa3292e5..4c0b94d4723 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1601,10 +1601,10 @@ github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7 github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7db87ae70/go.mod h1:P0/tjeeIIxfsBupk5MneRjq5uI9mj+ZQpMpYnFla6WM= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2 h1:5HdH/A6yn8INZAltYDLb7UkUi5IKemhJzJkDW4Bgxyg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2/go.mod h1:wDHq2E0KwUWG0lQ9f5frW1a7CKVW17MJLPuvKmtSRDg= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 h1:nh92CD2TZTtziEWu2reMDgEx1Zu0TGTkQcjQ3IE5bYM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2 h1:AWisx4JT3QV8tcgh6J5NCrex+wAgTYpWyHsyNPSXzsQ= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2/go.mod h1:rSkIHdomyak3YnUtXLenl6poIq8q0V3UZPiiyYqPdGA= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 h1:BAk0hlY3niOthWTOaF1mPyDdR17CNyARYKBeD9pF9uM= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 h1:5VDCWCwm0TFHJqK2gbs0ZeSIWFF4rDmHQBbJvvO87o4= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47/go.mod h1:vIX8ZkBosdvvVRJkxJV4qQjFXbRyDz/D2V/DJAv0lu8= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340 h1:PsjEI+5jZIz9AS4eOsLS5VpSWJINf38clXV3wryPyMk= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index d5766e73fad..44a038774c6 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -56,8 +56,8 @@ require ( github.com/rs/zerolog v1.34.0 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.97 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 - github.com/smartcontractkit/chainlink-common/keystore v1.0.2 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 + github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 github.com/smartcontractkit/chainlink-data-streams v0.1.13 github.com/smartcontractkit/chainlink-deployments-framework v0.86.3 github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260107191744-4b93f62cffe3 diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index 87696ed1917..d2875b5695b 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1785,10 +1785,10 @@ github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7 github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260317185256-d5f7db87ae70/go.mod h1:P0/tjeeIIxfsBupk5MneRjq5uI9mj+ZQpMpYnFla6WM= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2 h1:5HdH/A6yn8INZAltYDLb7UkUi5IKemhJzJkDW4Bgxyg= github.com/smartcontractkit/chainlink-ccv v0.0.0-20260324000441-d4cfddc9f7d2/go.mod h1:wDHq2E0KwUWG0lQ9f5frW1a7CKVW17MJLPuvKmtSRDg= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421 h1:nh92CD2TZTtziEWu2reMDgEx1Zu0TGTkQcjQ3IE5bYM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260326163134-c8e0d77df421/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2 h1:AWisx4JT3QV8tcgh6J5NCrex+wAgTYpWyHsyNPSXzsQ= -github.com/smartcontractkit/chainlink-common/keystore v1.0.2/go.mod h1:rSkIHdomyak3YnUtXLenl6poIq8q0V3UZPiiyYqPdGA= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47 h1:BAk0hlY3niOthWTOaF1mPyDdR17CNyARYKBeD9pF9uM= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327162949-a95884b8ab47/go.mod h1:6tlxlsiWypGdpaZI+Kz5gFm53gCAcU/pTU3PR9CiFB8= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47 h1:5VDCWCwm0TFHJqK2gbs0ZeSIWFF4rDmHQBbJvvO87o4= +github.com/smartcontractkit/chainlink-common/keystore v1.0.3-0.20260327162949-a95884b8ab47/go.mod h1:vIX8ZkBosdvvVRJkxJV4qQjFXbRyDz/D2V/DJAv0lu8= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4 h1:NOUsjsMzNecbjiPWUQGlRSRAutEvCFrqqyETDJeh5q4= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20251211140724-319861e514c4/go.mod h1:Zpvul9sTcZNAZOVzt5vBl1XZGNvQebFpnpn3/KOQvOQ= github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20251215152504-b1e41f508340 h1:PsjEI+5jZIz9AS4eOsLS5VpSWJINf38clXV3wryPyMk=