Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3f5ac43
[CRE] [1/5] Gateway handler for confidential relay
nadahalli Mar 23, 2026
ac120be
Fix exhaustive switch lint and tidy integration-tests modules
nadahalli Mar 23, 2026
7d8d2aa
Fix goimports formatting in gateway_job.go
nadahalli Mar 23, 2026
24fc4c0
Use ServiceName constants and add RequestTimeoutSec to relay handler
nadahalli Mar 23, 2026
974346f
Add comment explaining requestTimeoutSec - 1 in relay handler
nadahalli Mar 24, 2026
c6ff920
Use fmt.Errorf instead of errors.New with string concatenation
nadahalli Mar 24, 2026
5cd788f
Improve F+1 quorum comment in relay aggregator
nadahalli Mar 25, 2026
481675e
Move requestTimeoutSec - 1 to call site for relay handler
nadahalli Mar 25, 2026
dbe318d
Extract deleteActiveRequest from sendResponse
nadahalli Mar 26, 2026
043ec1d
Rename sendResponse to sendResponseAndCleanup, fix cleanup-on-error bug
nadahalli Mar 26, 2026
1bf76d5
Handle errQuorumUnobtainable explicitly in aggregation switch
nadahalli Mar 26, 2026
4edeaf4
Merge errorResponse into sendErrorResponseAndCleanup
nadahalli Mar 30, 2026
60a30f4
Move error sanitization into sendResponseAndCleanup
nadahalli Mar 30, 2026
64dacce
Inline send+cleanup into sendResponseAndCleanup and sendSuccessRespon…
nadahalli Mar 30, 2026
c3d18de
Unify sendResponseAndCleanup to handle both success and error paths
nadahalli Mar 30, 2026
4e968c5
Simplify `sendResponseAndCleanup`.
pavel-raykov Mar 30, 2026
78a2b67
Fix exhaustive lint: restore missing switch cases in recordMetrics an…
nadahalli Mar 31, 2026
71b884c
Suppress exhaustive switch warning.
pavel-raykov Mar 31, 2026
981c2c0
fan out relay requests to don nodes concurrently
nadahalli Apr 1, 2026
ebbee31
Clean up confidential relay concurrency test helper
nadahalli Apr 1, 2026
2828547
Remove redundant loop variable copy in relay fanout
nadahalli Apr 1, 2026
2c01583
Use atomic counter for relay node send errors
nadahalli Apr 2, 2026
40fb483
use cre settings for relay gateway rate limits
nadahalli Apr 2, 2026
7d1d54f
Fail fast when relay quorum becomes impossible
nadahalli Apr 2, 2026
2c460ea
Run gomodtidy to fix CI module drift
nadahalli Apr 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/scripts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ 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.20260331163339-a3c0d217e843
github.com/smartcontractkit/chainlink-common v0.11.2-0.20260402120824-48154c0c65a6
github.com/smartcontractkit/chainlink-common/keystore v1.0.2
github.com/smartcontractkit/chainlink-data-streams v0.1.13
github.com/smartcontractkit/chainlink-deployments-framework v0.86.3
Expand Down
4 changes: 2 additions & 2 deletions core/scripts/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 9 additions & 5 deletions core/services/gateway/handler_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,20 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities"
v2 "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities/v2"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/confidentialrelay"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/vault"
"github.com/smartcontractkit/chainlink/v2/core/services/gateway/network"
workflowsyncerv2 "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer/v2"
)

const (
FunctionsHandlerType HandlerType = "functions"
DummyHandlerType HandlerType = "dummy"
WebAPICapabilitiesType HandlerType = "web-api-capabilities" // Handler for v0.1 HTTP capabilities for DAG workflows
HTTPCapabilityType HandlerType = "http-capabilities" // Handler for v1.0 HTTP capabilities for NoDAG workflows
VaultHandlerType HandlerType = "vault"
FunctionsHandlerType HandlerType = "functions"
DummyHandlerType HandlerType = "dummy"
WebAPICapabilitiesType HandlerType = "web-api-capabilities" // Handler for v0.1 HTTP capabilities for DAG workflows
HTTPCapabilityType HandlerType = "http-capabilities" // Handler for v1.0 HTTP capabilities for NoDAG workflows
VaultHandlerType HandlerType = "vault"
ConfidentialRelayHandlerType HandlerType = "confidential-compute-relay"
)

type handlerFactory struct {
Expand Down Expand Up @@ -87,6 +89,8 @@ func (hf *handlerFactory) NewHandler(
case VaultHandlerType:
requestAuthorizer := vaultcap.NewRequestAuthorizer(hf.lggr, hf.workflowRegistrySyncer)
return vault.NewHandler(handlerConfig, donConfig, don, hf.capabilitiesRegistry, requestAuthorizer, hf.lggr, clockwork.NewRealClock(), hf.lf)
case ConfidentialRelayHandlerType:
return confidentialrelay.NewHandler(handlerConfig, donConfig, don, hf.lggr, clockwork.NewRealClock(), hf.lf)
default:
return nil, fmt.Errorf("unsupported handler type %s", handlerType)
}
Expand Down
56 changes: 56 additions & 0 deletions core/services/gateway/handlers/confidentialrelay/aggregator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package confidentialrelay

import (
"encoding/json"
"errors"
"fmt"

jsonrpc "github.com/smartcontractkit/chainlink-common/pkg/jsonrpc2"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
)

var (
errInsufficientResponsesForQuorum = errors.New("insufficient valid responses to reach quorum")
errQuorumUnobtainable = errors.New("quorum unobtainable")
)

type aggregator struct{}

func (a *aggregator) Aggregate(resps map[string]jsonrpc.Response[json.RawMessage], donF int, donMembersCount int, l logger.Logger) (*jsonrpc.Response[json.RawMessage], error) {
// F+1 (QuorumFPlusOne) is sufficient because each relay node calls the
// target DON (Vault or capability) through CRE's standard capability
// dispatch, which includes DON-level consensus. Every honest relay node
// receives the same consensus-aggregated response and performs deterministic
// translation, producing byte-identical outputs. F+1 matching responses
// therefore guarantees at least one honest node vouched for the result.
requiredQuorum := donF + 1

if len(resps) < requiredQuorum {
return nil, errInsufficientResponsesForQuorum
}

shaToCount := map[string]int{}
maxShaToCount := 0
for _, r := range resps {
sha, err := r.Digest()
if err != nil {
l.Errorw("failed to compute digest of response during quorum validation, skipping...", "error", err)
continue
}
shaToCount[sha]++
if shaToCount[sha] > maxShaToCount {
maxShaToCount = shaToCount[sha]
}
if shaToCount[sha] >= requiredQuorum {
return &r, nil
}
}

remainingResponses := donMembersCount - len(resps)
if maxShaToCount+remainingResponses < requiredQuorum {
l.Warnw("quorum unattainable for request", "requiredQuorum", requiredQuorum, "remainingResponses", remainingResponses, "maxShaToCount", maxShaToCount)
return nil, fmt.Errorf("%w: requiredQuorum=%d, maxShaToCount=%d, remainingResponses=%d", errQuorumUnobtainable, requiredQuorum, maxShaToCount, remainingResponses)
}

return nil, errInsufficientResponsesForQuorum
}
Loading
Loading