Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 7 additions & 4 deletions core/capabilities/remote/executable/hasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"strings"
"time"

"google.golang.org/protobuf/types/known/anypb"

Expand Down Expand Up @@ -64,9 +65,10 @@ func (r *simpleHasher) Hash(msg *types.MessageBody) ([32]byte, error) {
return [32]byte{}, fmt.Errorf("failed to unmarshal capability request: %w", err)
}

// Exclude SpendLimits from RequestMetadata to ensure identical requests
// with different SpendLimits produce the same hash
// Exclude per-node-divergent metadata fields to ensure identical requests
// with different values produce the same hash
req.Metadata.SpendLimits = nil
req.Metadata.ExecutionTimestamp = time.Time{}

reqBytes, err := pb.MarshalCapabilityRequest(req)
if err != nil {
Expand All @@ -92,9 +94,10 @@ func (r *writeReportExcludeSignaturesHasher) Hash(msg *types.MessageBody) ([32]b
return [32]byte{}, errors.New("capability request payload is nil")
}

// Exclude SpendLimits from RequestMetadata to ensure identical requests
// with different SpendLimits produce the same hash
// Exclude per-node-divergent metadata fields to ensure identical requests
// with different values produce the same hash
req.Metadata.SpendLimits = nil
req.Metadata.ExecutionTimestamp = time.Time{}
family, familyErr := getWriteReportFamily(msg)
if familyErr != nil {
return [32]byte{}, familyErr
Expand Down
47 changes: 47 additions & 0 deletions core/capabilities/remote/executable/hasher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package executable

import (
"testing"
"time"

"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/anypb"
Expand Down Expand Up @@ -106,6 +107,31 @@ func TestSimpleHasher_ExcludesSpendLimits(t *testing.T) {
require.NotEqual(t, hash1, hash3) // different data should produce different hash
}

func TestSimpleHasher_ExcludesExecutionTimestamp(t *testing.T) {
ts1 := time.Date(2025, 6, 15, 12, 0, 0, 0, time.UTC)
ts2 := time.Date(2025, 7, 20, 8, 30, 0, 0, time.UTC)
req1 := getRequestWithMetadata(t, []byte("testdata"), capabilities.RequestMetadata{
WorkflowID: "wf1", WorkflowExecutionID: "exec1", ExecutionTimestamp: ts1,
})
req2 := getRequestWithMetadata(t, []byte("testdata"), capabilities.RequestMetadata{
WorkflowID: "wf1", WorkflowExecutionID: "exec1", ExecutionTimestamp: ts2,
})
req3 := getRequestWithMetadata(t, []byte("otherdata"), capabilities.RequestMetadata{
WorkflowID: "wf1", WorkflowExecutionID: "exec1", ExecutionTimestamp: ts1,
})

hasher := NewSimpleHasher()
hash1, err := hasher.Hash(req1)
require.NoError(t, err)
hash2, err := hasher.Hash(req2)
require.NoError(t, err)
hash3, err := hasher.Hash(req3)
require.NoError(t, err)

require.Equal(t, hash1, hash2) // same data, different ExecutionTimestamp should produce same hash
require.NotEqual(t, hash1, hash3) // different data should produce different hash
}

func TestWriteReportExcludeSignaturesHasher_ExcludesSpendLimits(t *testing.T) {
// Create two requests with identical payloads but different SpendLimits
req1 := getWriteReportRequestWithSpendLimits(t, []byte("testdata"), [][]byte{[]byte("sig1"), []byte("sig2")}, []capabilities.SpendLimit{
Expand Down Expand Up @@ -161,6 +187,27 @@ func getRequest(t *testing.T, data []byte, sigs [][]byte) *types.MessageBody {
}
}

func getRequestWithMetadata(t *testing.T, data []byte, md capabilities.RequestMetadata) *types.MessageBody {
report := &sdk.ReportResponse{
RawReport: data,
Sigs: []*sdk.AttributedSignature{},
}
wrReq := &evmcappb.WriteReportRequest{
Report: report,
}
wrAny, err := anypb.New(wrReq)
require.NoError(t, err)
capReq := capabilities.CapabilityRequest{
Payload: wrAny,
Metadata: md,
}
capReqBytes, err := pb.MarshalCapabilityRequest(capReq)
require.NoError(t, err)
return &types.MessageBody{
Payload: capReqBytes,
}
}

func getRequestWithSpendLimits(t *testing.T, data []byte, spendLimits []capabilities.SpendLimit) *types.MessageBody {
report := &sdk.ReportResponse{
RawReport: data,
Expand Down
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.20260326163134-c8e0d77df421
github.com/smartcontractkit/chainlink-common v0.11.2-0.20260327152052-032e58514a84
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.

2 changes: 1 addition & 1 deletion core/services/workflows/v2/capability_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ func (c *ExecutionHelper) callCapability(ctx context.Context, request *sdkpb.Cap
DecodedWorkflowName: c.cfg.WorkflowName.String(),
SpendLimits: spendLimits,
WorkflowTag: c.cfg.WorkflowTag,
// TODO(CRE-2087): Propagate execution timestamp to capability calls (including remote)
ExecutionTimestamp: c.ExecutionTimestamp,
},
Config: values.EmptyMap(),
}
Expand Down
2 changes: 1 addition & 1 deletion deployment/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ 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 v0.11.2-0.20260327152052-032e58514a84
github.com/smartcontractkit/chainlink-common/keystore v1.0.2
github.com/smartcontractkit/chainlink-deployments-framework v0.86.3
github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260326181417-f2272e4b4aa6
Expand Down
4 changes: 2 additions & 2 deletions deployment/go.sum

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

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ 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 v0.11.2-0.20260327152052-032e58514a84
github.com/smartcontractkit/chainlink-common/keystore v1.0.2
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10
github.com/smartcontractkit/chainlink-data-streams v0.1.13
Expand Down
4 changes: 2 additions & 2 deletions go.sum

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

2 changes: 1 addition & 1 deletion integration-tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,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.20260327152052-032e58514a84
github.com/smartcontractkit/chainlink-common/keystore v1.0.2
github.com/smartcontractkit/chainlink-deployments-framework v0.86.3
github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260326181417-f2272e4b4aa6
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/go.sum

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

2 changes: 1 addition & 1 deletion integration-tests/load/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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.20260327152052-032e58514a84
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
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/load/go.sum

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

2 changes: 1 addition & 1 deletion system-tests/lib/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ 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 v0.11.2-0.20260327152052-032e58514a84
github.com/smartcontractkit/chainlink-common/keystore v1.0.2
github.com/smartcontractkit/chainlink-deployments-framework v0.86.3
github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260326181417-f2272e4b4aa6
Expand Down
4 changes: 2 additions & 2 deletions system-tests/lib/go.sum

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

2 changes: 1 addition & 1 deletion system-tests/tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ 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 v0.11.2-0.20260327152052-032e58514a84
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 system-tests/tests/go.sum

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

Loading