diff --git a/core/capabilities/compute/test/fetch/cmd/testdata/output.wasm.br b/core/capabilities/compute/test/fetch/cmd/testdata/output.wasm.br index 5050a7f3587..da251d838f9 100644 Binary files a/core/capabilities/compute/test/fetch/cmd/testdata/output.wasm.br and b/core/capabilities/compute/test/fetch/cmd/testdata/output.wasm.br differ diff --git a/core/capabilities/compute/test/simple/cmd/testdata/output.wasm.br b/core/capabilities/compute/test/simple/cmd/testdata/output.wasm.br index 1ac1a0f4667..3f8dbd3db0f 100644 Binary files a/core/capabilities/compute/test/simple/cmd/testdata/output.wasm.br and b/core/capabilities/compute/test/simple/cmd/testdata/output.wasm.br differ diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 711632da375..8a331e95f12 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -47,7 +47,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.104 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260618155522-3600f66e26cd - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d github.com/smartcontractkit/chainlink-common/keystore v1.2.0 github.com/smartcontractkit/chainlink-data-streams v0.1.15-0.20260522094612-5f9f748bd87a github.com/smartcontractkit/chainlink-deployments-framework v0.111.1-0.20260612191326-e31c0ae4cd54 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index b51f0e50b3a..38770bb7778 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1580,8 +1580,8 @@ github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260511195239-0f6e1b177fc7/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094 h1:uMn1w/n95p+pSxK6hYNqji/sDaab8D0Cxuph9qUkM2g= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094/go.mod h1:3XQmy2zQHrmufebP7dM+x595+gghxzyIKxK9wv91Rh8= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 h1:ywWOEZYL4DhVwf/TQ5jXsGlx6CzERsYbqd6ov3OS1sc= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d h1:7zOCnNtsys5uR9LUzskQ5Q+/CdynTGMYjF7sLrduRfk= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= github.com/smartcontractkit/chainlink-common/keystore v1.2.0 h1:1BH/b14CkGjArfzznlioQpIJiynECWVT48JUP9E277U= github.com/smartcontractkit/chainlink-common/keystore v1.2.0/go.mod h1:9R/74vN+bJ5PbkOyM/pUy/AeAZaRwYb/k4XPeXcbDio= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 74168bdd70e..b5f244feae1 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -676,6 +676,7 @@ func NewApplication(ctx context.Context, opts ApplicationOpts) (Application, err atomicSettings, creServices.OCRConfigService, cfg.Capabilities().Local(), + creServices.WorkflowRegistrySyncer, ) delegates[job.StandardCapabilities] = stdcapDelegate if creServices.SetDelegatesDeps != nil { diff --git a/core/services/standardcapabilities/delegate.go b/core/services/standardcapabilities/delegate.go index 63a37c1bcef..1f2355cb0a7 100644 --- a/core/services/standardcapabilities/delegate.go +++ b/core/services/standardcapabilities/delegate.go @@ -3,8 +3,10 @@ package standardcapabilities import ( "context" "crypto" + "encoding/json" "fmt" "strconv" + "strings" "github.com/google/uuid" "github.com/pelletier/go-toml" @@ -38,6 +40,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities/conversions" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" + syncerV2 "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer/v2" "github.com/smartcontractkit/chainlink/v2/plugins" ) @@ -66,6 +69,7 @@ type Delegate struct { creSettings core.SettingsBroadcaster ocrConfigService capregconfig.OCRConfigService localCfg coreconfig.LocalCapabilities + workflowRegistrySyncer syncerV2.WorkflowRegistrySyncer initErr error isNewlyCreatedJob bool @@ -98,6 +102,7 @@ func NewDelegate( creSettings core.SettingsBroadcaster, ocrConfigService capregconfig.OCRConfigService, localCfg coreconfig.LocalCapabilities, + workflowRegistrySyncer syncerV2.WorkflowRegistrySyncer, opts ...func(*gateway.RoundRobinSelector), ) *Delegate { initErr := registerOptionalMockStreamsTrigger(logger, localCfg, registry) @@ -125,6 +130,7 @@ func NewDelegate( creSettings: creSettings, ocrConfigService: ocrConfigService, localCfg: localCfg, + workflowRegistrySyncer: workflowRegistrySyncer, initErr: initErr, selectorOpts: opts, } @@ -146,6 +152,12 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser command := spec.StandardCapabilitiesSpec.Command configJSON := spec.StandardCapabilitiesSpec.Config + if d.workflowRegistrySyncer != nil { + if tenantID, ok := parseTenantID(configJSON); ok { + d.workflowRegistrySyncer.SetTenantID(tenantID) + d.logger.Infow("Configured tenant ID from capability job spec", "tenantID", tenantID, "command", command) + } + } if d.localCfg != nil { capabilityID := conversions.GetCapabilityIDFromCommand(command, configJSON) @@ -168,6 +180,25 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser return d.NewServices(ctx, command, configJSON, spec.ID, spec.Name.ValueOrZero(), spec.ExternalJobID, spec.StandardCapabilitiesSpec.OracleFactory, 0) } +// parseTenantID extracts tenantID from the consensus capability job spec config. It ignores all other fields so it does not +// interfere with the capability plugin's own use of the config. The second return value is false when tenantID is +// absent, zero, or the config cannot be parsed. +func parseTenantID(configJSON string) (uint64, bool) { + if strings.TrimSpace(configJSON) == "" { + return 0, false + } + var c struct { + TenantID uint64 `json:"tenantID"` + } + if err := json.Unmarshal([]byte(configJSON), &c); err != nil { + return 0, false + } + if c.TenantID == 0 { + return 0, false + } + return c.TenantID, true +} + // NewServices builds the per-job services for a Standard Capabilities LOOP. // // capabilityDonID is the on-chain DON ID this plugin process is being spawned diff --git a/core/services/standardcapabilities/tenant_id_test.go b/core/services/standardcapabilities/tenant_id_test.go new file mode 100644 index 00000000000..903c945ae91 --- /dev/null +++ b/core/services/standardcapabilities/tenant_id_test.go @@ -0,0 +1,34 @@ +package standardcapabilities + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_parseTenantID(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + config string + want uint64 + wantOK bool + }{ + {name: "empty config", config: "", want: 0, wantOK: false}, + {name: "no tenantID", config: `{"schedule":"1s"}`, want: 0, wantOK: false}, + {name: "zero tenantID", config: `{"tenantID":0}`, want: 0, wantOK: false}, + {name: "tenantID set", config: `{"tenantID":1}`, want: 1, wantOK: true}, + {name: "tenantID with other fields", config: `{"foo":"bar","tenantID":42}`, want: 42, wantOK: true}, + {name: "invalid json", config: `{not json`, want: 0, wantOK: false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + got, ok := parseTenantID(tt.config) + assert.Equal(t, tt.wantOK, ok) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/core/services/workflows/cmd/cre/examples/legacy/data_feeds/testdata/output.wasm.br b/core/services/workflows/cmd/cre/examples/legacy/data_feeds/testdata/output.wasm.br index 63b2675a9b0..8634c75807c 100644 Binary files a/core/services/workflows/cmd/cre/examples/legacy/data_feeds/testdata/output.wasm.br and b/core/services/workflows/cmd/cre/examples/legacy/data_feeds/testdata/output.wasm.br differ diff --git a/core/services/workflows/syncer/v2/handler.go b/core/services/workflows/syncer/v2/handler.go index 55284f71ed0..f233933bc21 100644 --- a/core/services/workflows/syncer/v2/handler.go +++ b/core/services/workflows/syncer/v2/handler.go @@ -7,7 +7,10 @@ import ( "fmt" "io" "maps" + "strconv" + "strings" "sync" + "sync/atomic" "time" "go.opentelemetry.io/otel" @@ -89,7 +92,11 @@ type eventHandler struct { workflowDonSubscriber capabilities.DonSubscriber billingClient metering.BillingClient orgResolver orgresolver.OrgResolver - secretsFetcher v2.SecretsFetcher + // tenantID is the tenant numeric id for the CRE environment. It is sourced from a + // job spec (see SetTenantID, wired from the consensus OCR2 plugin) and may be + // updated at runtime, so access is atomic. Zero falls back to defaultTenantID. + tenantID atomic.Uint64 + secretsFetcher v2.SecretsFetcher // localSecretOverrides is keyed by owner address; values are secret id -> secret value localSecretOverrides map[string]map[string]string @@ -180,6 +187,21 @@ func WithOrgResolver(orgResolver orgresolver.OrgResolver) func(*eventHandler) { } } +// WithTenantID sets the tenant numeric id for the CRE environment. A zero value +// falls back to defaultTenantID. +func WithTenantID(tenantID uint64) func(*eventHandler) { + return func(e *eventHandler) { + e.tenantID.Store(tenantID) + } +} + +// SetTenantID updates the tenant numeric id for the CRE environment. It is safe for +// concurrent use and is called at runtime when the owning job spec (consensus OCR2 +// plugin) is applied. +func (h *eventHandler) SetTenantID(tenantID uint64) { + h.tenantID.Store(tenantID) +} + // WithDebugMode enables OTel tracing when debugMode is true. // When disabled (default), a noop tracer is used for zero overhead. // The debugMode is also propagated to workflow engines created by this handler. @@ -640,6 +662,24 @@ func (h *eventHandler) createWorkflowSpec(ctx context.Context, payload WorkflowR } ctx = contexts.WithCRE(ctx, contexts.CRE{Org: orgID, Owner: owner, Workflow: wfID}) + // Defense-in-depth against centralized workflow source owner spoofing: + // on-chain sources enforce ownership via msg.sender, but centralized (off-chain) + // sources accept an owner claim without any owner-signed proof. For centralized + // sources, verify that the claimed owner is the address deterministically derived + // from the organization ID that the Linking Service maps it to. A mismatch means + // the registry is asserting an owner it cannot prove ownership of (e.g. an on-chain + // EOA), so we log a critical error and reject the workflow (fail-closed). + if isCentralizedWorkflowSource(payload.Source) { + if gateErr := h.engineLimiters.CentralizedWorkflowOwnerVerificationEnabled.AllowErr(ctx); gateErr == nil { + if verr := h.verifyCentralizedOwnerOrgMapping(payload.Source, owner, orgID); verr != nil { + return nil, verr + } + } else if !errors.Is(gateErr, limits.ErrorNotAllowed{}) { + h.lggr.Warnw("failed to evaluate limit CentralizedWorkflowOwnerVerificationEnabled", "error", gateErr) + return nil, gateErr + } + } + // With Workflow Registry contract v2 the BinaryURL and ConfigURL are expected to be identifiers that put through the Storage Service. decodedBinary, config, err := h.workflowArtifactsStore.FetchWorkflowArtifacts(ctx, wfID, payload.BinaryURL, payload.ConfigURL) if err != nil { @@ -670,6 +710,87 @@ func (h *eventHandler) createWorkflowSpec(ctx context.Context, payload WorkflowR return entry, nil } +// defaultTenantID is the fallback tenant numeric id for the CRE environment when none +// is configured on the job spec. It matches defaultJWTAuthJobSpecTenantID in +// core/capabilities/vault and cre-platform-graphql's account service. +const defaultTenantID uint64 = 1 + +// ErrCentralizedOwnerOrgMismatch is returned when a workflow owner claimed by a +// centralized (off-chain) source does not match the owner deterministically derived +// from its Linking Service organization ID. The workflow is rejected: admitting it +// would let a centralized registry impersonate an owner (e.g. an on-chain EOA) and +// exfiltrate that owner's Vault secrets. +var ErrCentralizedOwnerOrgMismatch = errors.New("centralized workflow owner does not match owner derived from its organization ID") + +// tenantIDOrDefault returns the tenant id for the CRE environment, falling back to +// defaultTenantID when the job spec does not configure one. +func (h *eventHandler) tenantIDOrDefault() uint64 { + if v := h.tenantID.Load(); v != 0 { + return v + } + return defaultTenantID +} + +// isCentralizedWorkflowSource reports whether workflow metadata originated from a +// centralized / off-chain source (the gRPC workflow registry or a local file source), +// as opposed to the on-chain workflow registry contract (source prefix "contract:"). +// On-chain ownership is enforced by msg.sender; off-chain sources accept an owner +// claim without on-chain proof and therefore require independent owner<->orgID +// verification before the workflow is admitted. +func isCentralizedWorkflowSource(source string) bool { + return strings.HasPrefix(source, "grpc:") || strings.HasPrefix(source, "file:") +} + +// verifyCentralizedOwnerOrgMapping checks that a workflow owner claimed by a +// centralized source is consistent with the organization the Linking Service maps it +// to. Legitimate centralized CRE workflow owners are deterministically derived from +// (tenantID, orgID) via workflows.GenerateWorkflowOwnerAddress. This mirrors the +// derivation in core/capabilities/vault/workflow_owner_derivation.go +// (DeriveJWTAuthorizedVaultWorkflowOwner) and cre-platform-graphql +// account_service.GetCreOrganizationInfo, which is also the source of truth the Vault +// DON authorizes secret access against. A mismatch means the centralized registry is +// asserting an owner it cannot prove ownership of (for example an on-chain EOA), +// which indicates data corruption or a malicious registry attempting to hijack +// another owner's identity and secrets. +// +// On a mismatch it logs a critical error and returns ErrCentralizedOwnerOrgMismatch +// so the caller rejects the workflow (fail-closed). If the orgID cannot be resolved +// or the derivation fails, verification is skipped (returns nil) rather than blocking +// legitimate workflows on a transient Linking Service outage. +func (h *eventHandler) verifyCentralizedOwnerOrgMapping(source, ownerHex, orgID string) error { + if orgID == "" { + // Without an orgID we cannot derive the expected owner; the resolution failure + // was already logged by fetchOrganizationID. + h.lggr.Warnw("skipping centralized workflow owner/orgID verification: no organization ID resolved", + "source", source, "workflowOwner", ownerHex) + return nil + } + + tenantID := h.tenantIDOrDefault() + derived, err := pkgworkflows.GenerateWorkflowOwnerAddress(strconv.FormatUint(tenantID, 10), orgID) + if err != nil { + h.lggr.Errorw("failed to derive expected workflow owner for centralized source", + "source", source, "workflowOwner", ownerHex, "organizationID", orgID, "error", err) + return nil + } + derivedHex := hex.EncodeToString(derived) + + claimedOwner := strings.ToLower(strings.TrimPrefix(strings.TrimSpace(ownerHex), "0x")) + if strings.ToLower(derivedHex) != claimedOwner { + logger.Sugared(h.lggr).Criticalw( + "centralized workflow owner does not match owner derived from its organization ID: possible data corruption or malicious workflow registry", + "source", source, + "claimedWorkflowOwner", ownerHex, + "organizationID", orgID, + "derivedWorkflowOwner", derivedHex, + "tenantID", tenantID, + ) + return fmt.Errorf("%w: source=%s claimedOwner=%s organizationID=%s derivedOwner=%s", + ErrCentralizedOwnerOrgMismatch, source, ownerHex, orgID, derivedHex) + } + return nil +} + // fetchOrganizationID fetches the organization ID for the given workflow owner using the OrgResolver func (h *eventHandler) fetchOrganizationID(ctx context.Context, workflowOwner string) (string, error) { if h.orgResolver == nil { diff --git a/core/services/workflows/syncer/v2/handler_owner_org_verification_test.go b/core/services/workflows/syncer/v2/handler_owner_org_verification_test.go new file mode 100644 index 00000000000..4c9c8413450 --- /dev/null +++ b/core/services/workflows/syncer/v2/handler_owner_org_verification_test.go @@ -0,0 +1,113 @@ +package v2 + +import ( + "encoding/hex" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" +) + +func Test_isCentralizedWorkflowSource(t *testing.T) { + t.Parallel() + + assert.True(t, isCentralizedWorkflowSource("grpc:my-source:v1")) + assert.True(t, isCentralizedWorkflowSource("file:my-source:v1")) + assert.False(t, isCentralizedWorkflowSource("contract:1:0xabc")) + assert.False(t, isCentralizedWorkflowSource("")) +} + +// deriveOwnerHex returns the hex-encoded (no 0x prefix) workflow owner address that +// the centralized owner/org verification expects for the given org ID. +func deriveOwnerHex(t *testing.T, orgID string) string { + t.Helper() + derived, err := pkgworkflows.GenerateWorkflowOwnerAddress(strconv.FormatUint(defaultTenantID, 10), orgID) + require.NoError(t, err) + return hex.EncodeToString(derived) +} + +const criticalMismatchMsg = "centralized workflow owner does not match owner derived from its organization ID: possible data corruption or malicious workflow registry" + +func Test_verifyCentralizedOwnerOrgMapping(t *testing.T) { + t.Parallel() + + const orgID = "org-123" + matchingOwner := deriveOwnerHex(t, orgID) + + t.Run("matching owner passes and does not log critical", func(t *testing.T) { + t.Parallel() + lggr, logs := logger.TestObserved(t, zapcore.DebugLevel) + h := &eventHandler{lggr: lggr} + + err := h.verifyCentralizedOwnerOrgMapping("grpc:my-source:v1", matchingOwner, orgID) + + require.NoError(t, err) + assert.Empty(t, logs.FilterMessage(criticalMismatchMsg).All()) + }) + + t.Run("matching owner is case-insensitive and 0x tolerant", func(t *testing.T) { + t.Parallel() + lggr, logs := logger.TestObserved(t, zapcore.DebugLevel) + h := &eventHandler{lggr: lggr} + + err := h.verifyCentralizedOwnerOrgMapping("grpc:my-source:v1", "0x"+matchingOwner, orgID) + + require.NoError(t, err) + assert.Empty(t, logs.FilterMessage(criticalMismatchMsg).All()) + }) + + t.Run("mismatched owner logs critical and rejects (spoofed on-chain owner)", func(t *testing.T) { + t.Parallel() + lggr, logs := logger.TestObserved(t, zapcore.DebugLevel) + h := &eventHandler{lggr: lggr} + + // An attacker-claimed on-chain EOA that is not derived from orgID. + victimEOA := "1234567890123456789012345678901234567890" + err := h.verifyCentralizedOwnerOrgMapping("grpc:malicious-source:v1", victimEOA, orgID) + + require.Error(t, err) + require.ErrorIs(t, err, ErrCentralizedOwnerOrgMismatch) + + entries := logs.FilterMessage(criticalMismatchMsg).All() + require.Len(t, entries, 1) + // Critical is a remapping of DPanic, but falls back to Error ('[crit]' prefix) + // on loggers that don't support it; accept either. + assert.GreaterOrEqual(t, entries[0].Level, zapcore.ErrorLevel) + }) + + t.Run("empty orgID skips verification (no error, no critical)", func(t *testing.T) { + t.Parallel() + lggr, logs := logger.TestObserved(t, zapcore.DebugLevel) + h := &eventHandler{lggr: lggr} + + err := h.verifyCentralizedOwnerOrgMapping("grpc:my-source:v1", matchingOwner, "") + + require.NoError(t, err) + assert.Empty(t, logs.FilterMessage(criticalMismatchMsg).All()) + }) + + t.Run("configured tenantID is used for derivation", func(t *testing.T) { + t.Parallel() + lggr, logs := logger.TestObserved(t, zapcore.DebugLevel) + + const tenantID uint64 = 42 + h := &eventHandler{lggr: lggr} + h.SetTenantID(tenantID) + + derived, err := pkgworkflows.GenerateWorkflowOwnerAddress(strconv.FormatUint(tenantID, 10), orgID) + require.NoError(t, err) + ownerForTenant42 := hex.EncodeToString(derived) + + // The default-tenant owner must be rejected under tenant 42... + require.Error(t, h.verifyCentralizedOwnerOrgMapping("grpc:my-source:v1", matchingOwner, orgID)) + // ...while the tenant-42-derived owner passes. + require.NoError(t, h.verifyCentralizedOwnerOrgMapping("grpc:my-source:v1", ownerForTenant42, orgID)) + + assert.Len(t, logs.FilterMessage(criticalMismatchMsg).All(), 1) + }) +} diff --git a/core/services/workflows/syncer/v2/helpers.go b/core/services/workflows/syncer/v2/helpers.go index e8be21d6d7f..d6c5b519dad 100644 --- a/core/services/workflows/syncer/v2/helpers.go +++ b/core/services/workflows/syncer/v2/helpers.go @@ -78,6 +78,8 @@ func (m *testEvtHandler) EmitActivationAbandoned(context.Context, Event, eventsv return nil } +func (m *testEvtHandler) SetTenantID(uint64) {} + func (m *testEvtHandler) ClearEvents() { m.mux.Lock() defer m.mux.Unlock() diff --git a/core/services/workflows/syncer/v2/mocks/workflow_registry_syncer.go b/core/services/workflows/syncer/v2/mocks/workflow_registry_syncer.go index 1dddb1f4882..58cefc8ae44 100644 --- a/core/services/workflows/syncer/v2/mocks/workflow_registry_syncer.go +++ b/core/services/workflows/syncer/v2/mocks/workflow_registry_syncer.go @@ -253,6 +253,39 @@ func (_c *WorkflowRegistrySyncer_Ready_Call) RunAndReturn(run func() error) *Wor return _c } +// SetTenantID provides a mock function with given fields: tenantID +func (_m *WorkflowRegistrySyncer) SetTenantID(tenantID uint64) { + _m.Called(tenantID) +} + +// WorkflowRegistrySyncer_SetTenantID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetTenantID' +type WorkflowRegistrySyncer_SetTenantID_Call struct { + *mock.Call +} + +// SetTenantID is a helper method to define mock.On call +// - tenantID uint64 +func (_e *WorkflowRegistrySyncer_Expecter) SetTenantID(tenantID interface{}) *WorkflowRegistrySyncer_SetTenantID_Call { + return &WorkflowRegistrySyncer_SetTenantID_Call{Call: _e.mock.On("SetTenantID", tenantID)} +} + +func (_c *WorkflowRegistrySyncer_SetTenantID_Call) Run(run func(tenantID uint64)) *WorkflowRegistrySyncer_SetTenantID_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(uint64)) + }) + return _c +} + +func (_c *WorkflowRegistrySyncer_SetTenantID_Call) Return() *WorkflowRegistrySyncer_SetTenantID_Call { + _c.Call.Return() + return _c +} + +func (_c *WorkflowRegistrySyncer_SetTenantID_Call) RunAndReturn(run func(uint64)) *WorkflowRegistrySyncer_SetTenantID_Call { + _c.Run(run) + return _c +} + // Start provides a mock function with given fields: _a0 func (_m *WorkflowRegistrySyncer) Start(_a0 context.Context) error { ret := _m.Called(_a0) diff --git a/core/services/workflows/syncer/v2/workflow_registry.go b/core/services/workflows/syncer/v2/workflow_registry.go index deb591b6f8c..94d5b9383f8 100644 --- a/core/services/workflows/syncer/v2/workflow_registry.go +++ b/core/services/workflows/syncer/v2/workflow_registry.go @@ -58,6 +58,10 @@ type WorkflowRegistrySyncer interface { // GetAllowlistedRequests returns the latest list of allowlisted requests. This list is fetched periodically // from the workflow registry contract. GetAllowlistedRequests(ctx context.Context) []workflow_registry_wrapper_v2.WorkflowRegistryOwnerAllowlistedRequest + + // SetTenantID sets the tenant numeric id for the CRE environment. It is sourced + // from a job spec (the consensus OCR2 plugin config) and may be set at runtime. + SetTenantID(tenantID uint64) } // workflowRegistry is the implementation of the WorkflowRegistrySyncer interface. @@ -137,6 +141,7 @@ type evtHandler interface { Handle(ctx context.Context, event Event) error EmitActivationAbandoned(ctx context.Context, event Event, reason eventsv2.ActivationAbandonReason, activationErr error, retryCount int32) error + SetTenantID(tenantID uint64) } type donNotifier interface { @@ -485,6 +490,11 @@ func (w *workflowRegistry) abandonActivation( } } +// SetTenantID forwards the tenant id for the CRE environment to the event handler. +func (w *workflowRegistry) SetTenantID(tenantID uint64) { + w.handler.SetTenantID(tenantID) +} + // toLocalHead converts a chainlink-common Head to our local Head struct func toLocalHead(head *types.Head) Head { return Head{ diff --git a/core/services/workflows/test/break/cmd/testdata/output.wasm.br b/core/services/workflows/test/break/cmd/testdata/output.wasm.br index c1b69ad152e..62e4a30cea2 100644 Binary files a/core/services/workflows/test/break/cmd/testdata/output.wasm.br and b/core/services/workflows/test/break/cmd/testdata/output.wasm.br differ diff --git a/core/services/workflows/test/wasm/legacy/cmd/testdata/output.wasm.br b/core/services/workflows/test/wasm/legacy/cmd/testdata/output.wasm.br index d9687b07d61..d2c089adc7d 100644 Binary files a/core/services/workflows/test/wasm/legacy/cmd/testdata/output.wasm.br and b/core/services/workflows/test/wasm/legacy/cmd/testdata/output.wasm.br differ diff --git a/core/services/workflows/test/zerotimeout/cmd/testdata/output.wasm.br b/core/services/workflows/test/zerotimeout/cmd/testdata/output.wasm.br index c7a02c90a38..115ce37d95f 100644 Binary files a/core/services/workflows/test/zerotimeout/cmd/testdata/output.wasm.br and b/core/services/workflows/test/zerotimeout/cmd/testdata/output.wasm.br differ diff --git a/core/services/workflows/v2/config.go b/core/services/workflows/v2/config.go index e5e88fe377b..17177cf8adf 100644 --- a/core/services/workflows/v2/config.go +++ b/core/services/workflows/v2/config.go @@ -116,9 +116,10 @@ type EngineLimiters struct { UserMetricLabelsPerMetric limits.BoundLimiter[int] UserMetricLabelValueLength limits.BoundLimiter[int] - ExecutionTimestampsEnabled limits.GateLimiter - ConfidentialWorkflowsEnabled limits.GateLimiter - DONTimeRequestTimeout limits.TimeLimiter + ExecutionTimestampsEnabled limits.GateLimiter + ConfidentialWorkflowsEnabled limits.GateLimiter + CentralizedWorkflowOwnerVerificationEnabled limits.GateLimiter + DONTimeRequestTimeout limits.TimeLimiter } // NewLimiters returns a new set of EngineLimiters based on the default configuration, and optionally modified by cfgFn. @@ -270,6 +271,10 @@ func (l *EngineLimiters) init(lf limits.Factory, cfgFn func(*cresettings.Workflo if err != nil { return } + l.CentralizedWorkflowOwnerVerificationEnabled, err = limits.MakeGateLimiter(lf, cresettings.Default.CentralizedWorkflowOwnerVerificationEnabled) + if err != nil { + return + } l.DONTimeRequestTimeout, err = lf.MakeTimeLimiter(cfg.DONTime.RequestTimeout) if err != nil { return @@ -313,6 +318,7 @@ func (l *EngineLimiters) EvictWorkflow(workflowID string) error { l.SecretsCalls, l.ExecutionTimestampsEnabled, l.ConfidentialWorkflowsEnabled, + l.CentralizedWorkflowOwnerVerificationEnabled, l.DONTimeRequestTimeout, } var errs error @@ -356,6 +362,7 @@ func (l *EngineLimiters) Close() error { l.SecretsCalls, l.ExecutionTimestampsEnabled, l.ConfidentialWorkflowsEnabled, + l.CentralizedWorkflowOwnerVerificationEnabled, l.DONTimeRequestTimeout, ) } diff --git a/deployment/go.mod b/deployment/go.mod index 77286d5ddba..11e729932a2 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -46,7 +46,7 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260511195239-0f6e1b177fc7 github.com/smartcontractkit/chainlink-ccip/deployment v0.0.0-20260618155522-3600f66e26cd - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d github.com/smartcontractkit/chainlink-common/keystore v1.2.0 github.com/smartcontractkit/chainlink-data-streams v0.1.15-0.20260522094612-5f9f748bd87a github.com/smartcontractkit/chainlink-deployments-framework v0.111.1-0.20260612191326-e31c0ae4cd54 diff --git a/deployment/go.sum b/deployment/go.sum index aaa375dedf4..d1a6c909348 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1383,8 +1383,8 @@ github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094 h github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094/go.mod h1:3XQmy2zQHrmufebP7dM+x595+gghxzyIKxK9wv91Rh8= github.com/smartcontractkit/chainlink-ccv/deployment v0.0.2-0.20260616151800-9a3a31c4e194 h1:QxZkbKtQyPtVLYP4eMwc+VbXY7M5ve1deSiLZ2pOA+Y= github.com/smartcontractkit/chainlink-ccv/deployment v0.0.2-0.20260616151800-9a3a31c4e194/go.mod h1:bNMFRxwWdgVFdSsFZRmsUUPoBUncU3RM765K99svIKM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 h1:ywWOEZYL4DhVwf/TQ5jXsGlx6CzERsYbqd6ov3OS1sc= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d h1:7zOCnNtsys5uR9LUzskQ5Q+/CdynTGMYjF7sLrduRfk= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= github.com/smartcontractkit/chainlink-common/keystore v1.2.0 h1:1BH/b14CkGjArfzznlioQpIJiynECWVT48JUP9E277U= github.com/smartcontractkit/chainlink-common/keystore v1.2.0/go.mod h1:9R/74vN+bJ5PbkOyM/pUy/AeAZaRwYb/k4XPeXcbDio= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= diff --git a/go.mod b/go.mod index 3014ddb9f4d..d1808e9f74a 100644 --- a/go.mod +++ b/go.mod @@ -85,7 +85,7 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d github.com/smartcontractkit/chainlink-common/keystore v1.2.0 github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 github.com/smartcontractkit/chainlink-data-streams v0.1.15-0.20260522094612-5f9f748bd87a diff --git a/go.sum b/go.sum index bfab02b97a6..6313bdba5e0 100644 --- a/go.sum +++ b/go.sum @@ -1162,8 +1162,8 @@ github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094 h1:uMn1w/n95p+pSxK6hYNqji/sDaab8D0Cxuph9qUkM2g= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094/go.mod h1:3XQmy2zQHrmufebP7dM+x595+gghxzyIKxK9wv91Rh8= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 h1:ywWOEZYL4DhVwf/TQ5jXsGlx6CzERsYbqd6ov3OS1sc= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d h1:7zOCnNtsys5uR9LUzskQ5Q+/CdynTGMYjF7sLrduRfk= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= github.com/smartcontractkit/chainlink-common/keystore v1.2.0 h1:1BH/b14CkGjArfzznlioQpIJiynECWVT48JUP9E277U= github.com/smartcontractkit/chainlink-common/keystore v1.2.0/go.mod h1:9R/74vN+bJ5PbkOyM/pUy/AeAZaRwYb/k4XPeXcbDio= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 76a9572a0aa..ad16b959d1f 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -33,7 +33,7 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260618155522-3600f66e26cd github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260506144252-c100eabfda74 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260511195239-0f6e1b177fc7 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d github.com/smartcontractkit/chainlink-common/keystore v1.2.0 github.com/smartcontractkit/chainlink-deployments-framework v0.111.1-0.20260612191326-e31c0ae4cd54 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260623170329-4577ef4ba0ae diff --git a/integration-tests/go.sum b/integration-tests/go.sum index c31786746d0..6abb1b7fbae 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1370,8 +1370,8 @@ github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094 h github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094/go.mod h1:3XQmy2zQHrmufebP7dM+x595+gghxzyIKxK9wv91Rh8= github.com/smartcontractkit/chainlink-ccv/deployment v0.0.2-0.20260616151800-9a3a31c4e194 h1:QxZkbKtQyPtVLYP4eMwc+VbXY7M5ve1deSiLZ2pOA+Y= github.com/smartcontractkit/chainlink-ccv/deployment v0.0.2-0.20260616151800-9a3a31c4e194/go.mod h1:bNMFRxwWdgVFdSsFZRmsUUPoBUncU3RM765K99svIKM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 h1:ywWOEZYL4DhVwf/TQ5jXsGlx6CzERsYbqd6ov3OS1sc= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d h1:7zOCnNtsys5uR9LUzskQ5Q+/CdynTGMYjF7sLrduRfk= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= github.com/smartcontractkit/chainlink-common/keystore v1.2.0 h1:1BH/b14CkGjArfzznlioQpIJiynECWVT48JUP9E277U= github.com/smartcontractkit/chainlink-common/keystore v1.2.0/go.mod h1:9R/74vN+bJ5PbkOyM/pUy/AeAZaRwYb/k4XPeXcbDio= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index c9a99dbcf5c..9fc251edad0 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -24,7 +24,7 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/evm v0.0.0-20260618155522-3600f66e26cd github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260506144252-c100eabfda74 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260511195239-0f6e1b177fc7 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d github.com/smartcontractkit/chainlink-deployments-framework v0.111.1-0.20260612191326-e31c0ae4cd54 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260623170329-4577ef4ba0ae github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.6-0.20260630120514-36abe27604df diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index ea64ea73bf2..153c3186ac7 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1632,8 +1632,8 @@ github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094 h github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094/go.mod h1:3XQmy2zQHrmufebP7dM+x595+gghxzyIKxK9wv91Rh8= github.com/smartcontractkit/chainlink-ccv/deployment v0.0.2-0.20260616151800-9a3a31c4e194 h1:QxZkbKtQyPtVLYP4eMwc+VbXY7M5ve1deSiLZ2pOA+Y= github.com/smartcontractkit/chainlink-ccv/deployment v0.0.2-0.20260616151800-9a3a31c4e194/go.mod h1:bNMFRxwWdgVFdSsFZRmsUUPoBUncU3RM765K99svIKM= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 h1:ywWOEZYL4DhVwf/TQ5jXsGlx6CzERsYbqd6ov3OS1sc= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d h1:7zOCnNtsys5uR9LUzskQ5Q+/CdynTGMYjF7sLrduRfk= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= github.com/smartcontractkit/chainlink-common/keystore v1.2.0 h1:1BH/b14CkGjArfzznlioQpIJiynECWVT48JUP9E277U= github.com/smartcontractkit/chainlink-common/keystore v1.2.0/go.mod h1:9R/74vN+bJ5PbkOyM/pUy/AeAZaRwYb/k4XPeXcbDio= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index e1e8dfb3fd2..b3754a3ebfb 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -37,7 +37,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.104 github.com/smartcontractkit/chainlink-aptos v0.0.0-20260609211101-71d38bd6a0a9 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d github.com/smartcontractkit/chainlink-common/keystore v1.2.0 github.com/smartcontractkit/chainlink-deployments-framework v0.111.1-0.20260612191326-e31c0ae4cd54 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260623170329-4577ef4ba0ae diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index 430939337f4..0f8f6ce4e15 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1545,8 +1545,8 @@ github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260511195239-0f6e1b177fc7/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094 h1:uMn1w/n95p+pSxK6hYNqji/sDaab8D0Cxuph9qUkM2g= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094/go.mod h1:3XQmy2zQHrmufebP7dM+x595+gghxzyIKxK9wv91Rh8= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 h1:ywWOEZYL4DhVwf/TQ5jXsGlx6CzERsYbqd6ov3OS1sc= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d h1:7zOCnNtsys5uR9LUzskQ5Q+/CdynTGMYjF7sLrduRfk= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= github.com/smartcontractkit/chainlink-common/keystore v1.2.0 h1:1BH/b14CkGjArfzznlioQpIJiynECWVT48JUP9E277U= github.com/smartcontractkit/chainlink-common/keystore v1.2.0/go.mod h1:9R/74vN+bJ5PbkOyM/pUy/AeAZaRwYb/k4XPeXcbDio= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index f576eb686de..7ff96571766 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -62,7 +62,7 @@ require ( github.com/rs/zerolog v1.35.1 github.com/smartcontractkit/chain-selectors v1.0.104 github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20260415165642-49f23e4d76cc - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d github.com/smartcontractkit/chainlink-common/keystore v1.2.0 github.com/smartcontractkit/chainlink-deployments-framework v0.111.1-0.20260612191326-e31c0ae4cd54 github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index f177e4c8e41..8a7d3ead675 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1559,8 +1559,8 @@ github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260 github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260511195239-0f6e1b177fc7/go.mod h1:67YbnoglYD61Pz/jTVCgav9wFq7S35OU8UyQSvPllRw= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094 h1:uMn1w/n95p+pSxK6hYNqji/sDaab8D0Cxuph9qUkM2g= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260706093831-dad26b360094/go.mod h1:3XQmy2zQHrmufebP7dM+x595+gghxzyIKxK9wv91Rh8= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0 h1:ywWOEZYL4DhVwf/TQ5jXsGlx6CzERsYbqd6ov3OS1sc= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260701091216-9264d4444ce0/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d h1:7zOCnNtsys5uR9LUzskQ5Q+/CdynTGMYjF7sLrduRfk= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260706164853-7fb6f76d132d/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= github.com/smartcontractkit/chainlink-common/keystore v1.2.0 h1:1BH/b14CkGjArfzznlioQpIJiynECWVT48JUP9E277U= github.com/smartcontractkit/chainlink-common/keystore v1.2.0/go.mod h1:9R/74vN+bJ5PbkOyM/pUy/AeAZaRwYb/k4XPeXcbDio= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w=