[CRE] [5/5] Wire confidential workflow execution into CRE#21642
[CRE] [5/5] Wire confidential workflow execution into CRE#21642nadahalli wants to merge 18 commits intotejaswi/cw-2-relay-handlerfrom
Conversation
|
👋 nadahalli, thanks for creating this pull request! To help reviewers, please consider creating future PRs as drafts first. This allows you to self-review and make any final changes before notifying the team. Once you're ready, you can mark it as "Ready for review" to request feedback. Thanks! |
CORA - Analysis SkippedReason: The number of code owners (4) is less than the minimum required (5) and/or the number of CODEOWNERS entries with changed files (8) is less than the minimum required (2). |
|
✅ No conflicts with other open PRs targeting |
There was a problem hiding this comment.
Pull request overview
Risk Rating: HIGH
Wires confidential workflow execution into CRE end-to-end (registry attributes → syncer routing → confidential module execution → gateway relay plumbing), with accompanying config, DB migration, and system-test helpers/plugins.
Changes:
- Add confidential workflow execution support via
WorkflowSpec.Attributes, confidential engine routing, andConfidentialModule. - Introduce gateway + relay DON plumbing (new gateway handler type + CRE subservice) and related config.
- Extend system tests to register workflows with attributes and provide a confidential relay feature/plugin.
Targeted areas for scrupulous human review:
- DB migration for
workflow_specs_v2.attributesand the ORM upsert path. - Filesystem fetcher path validation changes (security boundary check).
- Confidential relay request/attestation verification flow and error handling (gateway handler + relay handler).
Recommended reviewers (per CODEOWNERS):
@smartcontractkit/keystone(core/services/workflows, core/capabilities, deployment/cre)@smartcontractkit/capabilities-team(core/capabilities)@smartcontractkit/operations-platform(deployment/cre)
Reviewed changes
Copilot reviewed 40 out of 45 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| system-tests/tests/test-helpers/t_helpers.go | Updates workflow artifact creation/registration, adds attributes + confidential deploy helper; currently removes helpers still used elsewhere. |
| system-tests/tests/go.mod | Bumps deps to support confidential workflow/attestation work. |
| system-tests/tests/go.sum | go.sum updates for system-tests/tests module. |
| system-tests/lib/go.mod | Bumps deps to support confidential workflow/attestation work. |
| system-tests/lib/go.sum | go.sum updates for system-tests/lib module. |
| system-tests/lib/cre/workflow/workflow.go | Extends workflow registration to include attributes. |
| system-tests/lib/cre/types.go | Adds ConfidentialRelayCapability flag. |
| system-tests/lib/cre/features/confidential_relay/confidential_relay.go | New system-test feature plugin wiring confidential relay handler + node TOML overrides. |
| core/store/migrate/migrations/0295_add_workflow_attributes_column.sql | Adds attributes column to workflow_specs_v2 (migration default needs fix). |
| core/services/job/models.go | Adds WorkflowSpec.Attributes DB field. |
| core/services/workflows/artifacts/v2/orm.go | Persists attributes in workflow spec upsert. |
| core/services/workflows/syncer/v2/handler.go | Routes confidential workflows to confidential engine creation path. |
| core/services/workflows/syncer/v2/handler_test.go | Adds tests for confidential vs non-confidential routing + malformed attributes. |
| core/services/workflows/v2/confidential_module.go | New module delegating execution to confidential-workflows capability. |
| core/services/workflows/v2/confidential_module_test.go | Unit tests for attribute parsing, hashing, and module execution request/response handling. |
| core/services/workflows/v2/engine.go | Adjusts execution timestamp handling and tracing attributes. |
| core/services/workflows/v2/capability_executor.go | Changes execution timestamp representation in helper. |
| core/services/workflows/syncer/v2/fetcher.go | Adapts file fetcher to support HTTP(S) URLs for confidential workflows (path boundary check needs hardening). |
| core/services/workflows/syncer/fetcher.go | Same fetcher change for non-v2 path (path boundary check needs hardening). |
| core/services/gateway/handlers/confidentialrelay/handler.go | New gateway handler implementing confidential relay fanout/quorum aggregation and callbacks. |
| core/services/gateway/handlers/confidentialrelay/handler_test.go | Tests for the new gateway handler behavior (quorum, rate limiting, timeouts, etc.). |
| core/services/gateway/handlers/confidentialrelay/aggregator.go | Aggregator implementing F+1 quorum by response digest. |
| core/services/gateway/handler_factory.go | Registers the new confidential-compute-relay handler type. |
| deployment/cre/jobs/pkg/gateway_job.go | Adds gateway job wiring for confidential-compute-relay handler type and service name mapping. |
| core/capabilities/confidentialrelay/service.go | New CRE subservice wrapper that starts the confidential relay handler when enabled. |
| core/capabilities/confidentialrelay/handler.go | New relay DON gateway-connector handler: attestation validation + proxy to vault/capabilities. |
| core/capabilities/confidentialrelay/handler_test.go | Unit tests for relay DON handler request processing and lifecycle. |
| core/services/cre/cre.go | Starts confidential relay service when CRE config enables it. |
| core/config/cre_config.go | Adds CREConfidentialRelay interface to config surface. |
| core/services/chainlink/config_cre.go | Implements ConfidentialRelay() config adapter for CRE config. |
| core/config/toml/types.go | Adds TOML config struct for CRE.ConfidentialRelay and merge logic. |
| core/services/standardcapabilities/conversions/conversions.go | Adds “mock” mapping for capability ID/command conversions. |
| core/capabilities/launcher.go | Logger type changes + single-DON capability serving fix + cross-DON capability discovery for capability DONs. |
| core/capabilities/launcher_test.go | Adds regression test for single-DON capability serving + adjusts mock expectations. |
| core/services/workflows/models.go | Adds a field on step struct (supports workflow execution changes). |
| core/services/workflows/metering/metering.go | Logger interface change + reduces trace logging to a single debug log. |
| core/services/workflows/syncer/engine_registry_test.go | Minor test tweak (adds const). |
| core/scripts/cre/environment/environment/workflow.go | Updates workflow registration call to pass attributes argument. |
| go.mod | Bumps deps (cbor + chainlink-common + teeattestation + nitrite). |
| go.sum | go.sum updates for root module. |
| deployment/go.mod | Bumps deps for deployment module (chainlink-common/protos, cbor, teeattestation, nitrite). |
| deployment/go.sum | go.sum updates for deployment module. |
| core/scripts/go.mod | Bumps deps for scripts module (chainlink-common/protos, teeattestation, nitrite). |
| core/scripts/go.sum | go.sum updates for scripts module. |
| .changeset/confidential-workflow-execution.md | Adds changelog entry for confidential workflow execution feature. |
Comments suppressed due to low confidence (2)
core/services/workflows/syncer/v2/fetcher.go:231
- The path containment check uses
strings.HasPrefix(fullPath, basePath), which is not a safe filesystem boundary check (e.g., basePath/tmp/basewill match/tmp/base2/...). Usefilepath.Rel(reject any rel path starting with..) or ensurefullPathis cleaned/absolute and compare againstbasePath+string(os.PathSeparator).
if !strings.HasPrefix(fullPath, basePath) {
return nil, fmt.Errorf("request URL %s is not within the basePath %s", fullPath, basePath)
}
core/services/workflows/syncer/fetcher.go:197
- The path containment check uses
strings.HasPrefix(fullPath, basePath), which is not a safe filesystem boundary check (e.g., basePath/tmp/basewill match/tmp/base2/...). Usefilepath.Rel(reject any rel path starting with..) or ensurefullPathis cleaned/absolute and compare againstbasePath+string(os.PathSeparator).
if !strings.HasPrefix(fullPath, basePath) {
return nil, fmt.Errorf("request URL %s is not within the basePath %s", fullPath, basePath)
}
| @@ -0,0 +1,5 @@ | |||
| -- +goose Up | |||
| ALTER TABLE workflow_specs_v2 ADD COLUMN attributes bytea DEFAULT ''; | |||
There was a problem hiding this comment.
This migration sets a bytea column default to a text literal (DEFAULT ''), which will fail on Postgres with a type mismatch. Use an explicit bytea default (e.g., ''::bytea or '\x'::bytea) or make the column nullable with no default and handle empty attributes in application code.
| require.IsType(t, &evm.Blockchain{}, blockchains[0], "expected EVM blockchain type") | ||
| deleteErr := creworkflow.DeleteWithContract(t.Context(), blockchains[0].(*evm.Blockchain).SethClient, workflowRegistryAddress, version, uniqueWorkflowName) |
There was a problem hiding this comment.
deleteWorkflows indexes blockchains[0] without checking length; if the environment has zero blockchains this will panic before the type assertion. Add a length check (and ideally pick the registry chain explicitly rather than assuming index 0).
| // CompileAndDeployConfidentialWorkflow compiles a workflow WASM binary, copies it to Docker | ||
| // containers, and registers it with confidential attributes on the workflow registry. | ||
| func CompileAndDeployConfidentialWorkflow[T WorkflowConfig](t *testing.T, | ||
| testEnv *ttypes.TestEnvironment, testLogger zerolog.Logger, workflowName string, | ||
| workflowConfig *T, workflowFileLocation string, attributes []byte, | ||
| ) string { |
There was a problem hiding this comment.
UniqueWorkflowName and ParallelEnabled were removed from this helper, but they are still referenced by multiple system tests (e.g., system-tests/tests/smoke/cre/cre_suite_test.go, system-tests/tests/regression/cre/cre_regression_suite_test.go). This will break compilation for the system-tests module unless the call sites are updated or these helpers are reintroduced.
f652007 to
571766f
Compare
|
81fce03 to
898b32b
Compare
| @@ -0,0 +1,484 @@ | |||
| package confidentialrelay | |||
There was a problem hiding this comment.
isn't this file from a prior PR?
There was a problem hiding this comment.
Seems like this PR has not perfectly caught the rest of the chain.
There was a problem hiding this comment.
Fixed. Rebuilt PR from scratch using the clean PR 1-4 branches. All core-test drift removed.
| trustedPCRs: trustedPCRs, | ||
| caRootsPEM: caRootsPEM, |
There was a problem hiding this comment.
again, don't really think either of these need to be constructor-level params so long as we have the capRegistry param.
There was a problem hiding this comment.
Done. Updated NewService to pull config from capabilities registry. cre.go now calls NewService(wrapper, capRegistry, lggr) with no trustedPCRs/caRootsPEM params.
core/capabilities/launcher.go
Outdated
| type launcher struct { | ||
| services.StateMachine | ||
| lggr logger.SugaredLogger | ||
| lggr logger.Logger |
There was a problem hiding this comment.
Probably don't want to mess with this, here or anywhere else below.
There was a problem hiding this comment.
Fixed. Removed logger type changes and allWorkflowDONs fix (redundant with LocalOnly). Only the addRemoteCapabilities fix for capability DONs remains (PR #21640).
core/capabilities/launcher.go
Outdated
| if w.don2donSharedPeer != nil { | ||
| donPairs := w.donPairsToUpdate(w.myPeerID, localRegistry) | ||
| err := w.don2donSharedPeer.UpdateConnectionsByDONs(ctx, donPairs, w.p2pStreamConfig) | ||
| err := w.don2donSharedPeer.UpdateConnectionsByDONs(ctx, donPairs, defaultStreamConfig) |
| balance *balanceStore | ||
| client BillingClient | ||
| lggr logger.SugaredLogger | ||
| lggr logger.Logger |
| func TestEngineRegistry(t *testing.T) { | ||
| var srv services.Service = &fakeService{} | ||
|
|
||
| const id1 = "foo" |
| *Engine | ||
| WorkflowExecutionID string | ||
| ExecutionTimestamp time.Time | ||
| ExecutionTimestamp int64 |
There was a problem hiding this comment.
not sure this should be touched
| creCtx := contexts.CREValue(ctx) | ||
| // Tracer is no-op if DebugMode is false | ||
| ctx, span := e.tracer.Start(ctx, "workflow_execution", | ||
| trace.WithAttributes( | ||
| attribute.String("workflow_name", e.cfg.WorkflowName.String()), | ||
| attribute.String("version", "v2"), | ||
| attribute.String("org_id", creCtx.Org), | ||
| attribute.String("owner_id", creCtx.Owner), | ||
| attribute.String("workflow_id", creCtx.Workflow), |
There was a problem hiding this comment.
why is any of this changing?
| } | ||
| e.metrics.IncrementExecutionIDLegacyCounter(ctx) | ||
| } | ||
| trace.SpanFromContext(ctx).SetAttributes(attribute.String("execution_id", executionID)) |
There was a problem hiding this comment.
don't think any bit of this file should change
core/services/workflows/models.go
Outdated
| workflows.Vertex | ||
| capability capabilities.ExecutableCapability | ||
| info capabilities.CapabilityInfo | ||
| config *values.Map |
There was a problem hiding this comment.
concerning to see a change like this. Why do we need this added to the step struct?
There was a problem hiding this comment.
Removed. This was core-test drift, not part of the confidential workflow changes.
The enclave needs an authenticated URL to download WASM binaries from the CRE storage service. BinaryURLResolver resolves the raw on-chain URL into a presigned/ephemeral URL per execution. Nil-safe: falls back to the raw URL when no resolver is set. PR 5/5 (#21642) wires this to the storage service retriever.
The enclave needs an authenticated URL to download WASM binaries from the CRE storage service. BinaryURLResolver resolves the raw on-chain URL into a presigned/ephemeral URL per execution. Nil-safe: falls back to the raw URL when no resolver is set. PR 5/5 (#21642) wires this to the storage service retriever.
16e4fc9 to
5cfc03f
Compare
The enclave needs an authenticated URL to download WASM binaries from the CRE storage service. BinaryURLResolver resolves the raw on-chain URL into a presigned/ephemeral URL per execution. Nil-safe: falls back to the raw URL when no resolver is set. PR 5/5 (#21642) wires this to the storage service retriever.
5cfc03f to
cd40794
Compare
The enclave needs an authenticated URL to download WASM binaries from the CRE storage service. BinaryURLResolver resolves the raw on-chain URL into a presigned/ephemeral URL per execution. Nil-safe: falls back to the raw URL when no resolver is set. PR 5/5 (#21642) wires this to the storage service retriever.
The enclave needs an authenticated URL to download WASM binaries from the CRE storage service. BinaryURLResolver resolves the raw on-chain URL into a presigned/ephemeral URL per execution. Nil-safe: falls back to the raw URL when no resolver is set. PR 5/5 (#21642) wires this to the storage service retriever.
|
cb65a31 to
00a16e6
Compare
Wires PRs 1-4 together: - cre.go: start confidential relay service when gateway connector exists - system tests: ConfidentialRelay feature plugin, workflow registration with attributes, CompileAndDeployConfidentialWorkflow helper This branch includes code from PRs 1-4 for compilation. As those merge into develop, rebasing this branch will shrink the diff to just the wiring and system test changes. Part of #21635
The enclave needs an authenticated URL to download WASM binaries from the CRE storage service. BinaryURLResolver resolves the raw on-chain URL into a presigned/ephemeral URL per execution. Nil-safe: falls back to the raw URL when no resolver is set. PR 5/5 (#21642) wires this to the storage service retriever.
…CC plugin ref - chainlink-common v0.11.2-0.20260330123353-c1870a5eff52 (teeattestation merged into root) - Pavel review fixes: sendResponseAndCleanup, error sanitization, requestTimeoutSec - CC plugin ref updated to 526a251
…d constructErrorResponse
(cherry picked from commit 7b4af73) (cherry picked from commit 9a721064b9ca7d070231a0031b33d1db82b16eef)
The enclave needs an authenticated URL to download WASM binaries from the CRE storage service. BinaryURLResolver resolves the raw on-chain URL into a presigned/ephemeral URL per execution. Nil-safe: falls back to the raw URL when no resolver is set. PR 5/5 (#21642) wires this to the storage service retriever.
0603953 to
b22f1da
Compare



Context
Part of #21635 (confidential workflow execution). [5/5] in the series.
Final wiring PR.
What this does
Wires PRs 1-4 together:
cre.go: starts confidential relay service when config is enabledmodels.go: Attributes field on WorkflowSpecwith attributes, CompileAndDeployConfidentialWorkflow helper
This branch includes code from PRs 1-4 for compilation. As those merge
into develop, rebasing this branch will shrink the diff to just the
wiring and system test changes.
Dependencies
Depends on #21638, #21639, #21640, #21641 (PRs 1-4). Merge those first.