From 865c82f884faae50ad5c496678641290624ed5ab Mon Sep 17 00:00:00 2001 From: amit-momin Date: Fri, 29 May 2026 17:58:21 -0500 Subject: [PATCH 1/4] Updated hardcoded f+1 identical response aggregation to be configurable --- libs/chainconsensus/oracle/error_mode.go | 14 +- libs/chainconsensus/oracle/error_mode_test.go | 69 +++++++- libs/chainconsensus/oracle/mode.go | 8 +- libs/chainconsensus/oracle/mode_test.go | 66 ++++++++ .../chainconsensus/oracle/reporting_plugin.go | 32 ++-- .../oracle/reporting_plugin_factory.go | 17 +- .../oracle/reporting_plugin_test.go | 156 ++++++++++++++++++ 7 files changed, 335 insertions(+), 27 deletions(-) create mode 100644 libs/chainconsensus/oracle/mode_test.go diff --git a/libs/chainconsensus/oracle/error_mode.go b/libs/chainconsensus/oracle/error_mode.go index e3d0df038..9a6fa9935 100644 --- a/libs/chainconsensus/oracle/error_mode.go +++ b/libs/chainconsensus/oracle/error_mode.go @@ -12,11 +12,11 @@ var errInsufficientErrorOb = fmt.Errorf("insufficient number of errors") // modeForError returns a slice of common errors for a given request when: // 1. The total number of observations is at least (N+F)/2+1, and -// 2. The number of observed errors is at least F+1. -// If no single error was observed by at least F+1 nodes, it returns a slice -// of the most frequently observed errors whose combined observation count equals F+1. +// 2. The number of observed errors is at least minMatching. +// If no single error was observed by at least minMatching nodes, it returns a slice +// of the most frequently observed errors whose combined observation count equals minMatching. // The returned int is the count of the most frequently observed error(s) (not necessarily identical). -func modeForError(N, F int, requestID string, aos []attributedObservation) ([][]byte, int, error) { +func modeForError(N, F, minMatching int, requestID string, aos []attributedObservation) ([][]byte, int, error) { type keyT [sha256.Size]byte counters := make(map[keyT]*counter[[]byte]) var totalNum int @@ -82,13 +82,13 @@ func modeForError(N, F int, requestID string, aos []attributedObservation) ([][] for _, c := range sortedCounters { result = append(result, c.value) count += c.count - if count >= F+1 { + if count >= minMatching { break } } - if count < F+1 { - return nil, count, fmt.Errorf("%w: expected %d, got %d", errInsufficientErrorOb, F+1, count) + if count < minMatching { + return nil, count, fmt.Errorf("%w: expected %d, got %d", errInsufficientErrorOb, minMatching, count) } return result, count, nil diff --git a/libs/chainconsensus/oracle/error_mode_test.go b/libs/chainconsensus/oracle/error_mode_test.go index 9f2986a7a..b5cccfd2d 100644 --- a/libs/chainconsensus/oracle/error_mode_test.go +++ b/libs/chainconsensus/oracle/error_mode_test.go @@ -101,7 +101,7 @@ func TestErrorMode(t *testing.T) { Observation: strToObservation(ob), } } - rawActualErrors, actualCount, err := modeForError(N, tc.F, requestID, aos) + rawActualErrors, actualCount, err := modeForError(N, tc.F, tc.F+1, requestID, aos) if tc.ExpectedError != "" { require.ErrorContains(t, err, tc.ExpectedError) } else { @@ -153,3 +153,70 @@ func TestErrorMode(t *testing.T) { runTest(t, newObservation) }) } + +func TestErrorMode_TwoFPlusOneThreshold(t *testing.T) { + // N=7, F=2: with minMatching=5 (2F+1), we need 5 matching errors to succeed. + const requestID = "req-2f1" + N, F := 7, 2 + minMatching := 2*F + 1 // 5 + + makeAos := func(errors []string) []attributedObservation { + aos := make([]attributedObservation, len(errors)) + for i, e := range errors { + aos[i] = attributedObservation{ + //nolint:gosec + Observer: commontypes.OracleID(i), + Observation: &types.Observation{ + Observations: map[string]*types.RequestObservation{ + requestID: {Observation: &types.RequestObservation_Error{Error: []byte(e)}}, + }, + }, + } + } + return aos + } + + t.Run("succeeds when 5 of 7 report same error", func(t *testing.T) { + errors := []string{"err", "err", "err", "err", "err", "other", "other"} + result, err := modeForError(N, F, minMatching, requestID, makeAos(errors)) + require.NoError(t, err) + require.Equal(t, []string{"err"}, func() []string { + s := make([]string, len(result)) + for i, b := range result { + s[i] = string(b) + } + return s + }()) + }) + + t.Run("fails when combined error observations don't reach minMatching", func(t *testing.T) { + // Only 4 error observations total (3 distinct errors), non-errors fill the remaining 3 slots + allObs := make([]attributedObservation, N) + errPayloads := []string{"err-a", "err-b", "err-a", "err-c"} + for i, e := range errPayloads { + allObs[i] = attributedObservation{ + //nolint:gosec + Observer: commontypes.OracleID(i), + Observation: &types.Observation{ + Observations: map[string]*types.RequestObservation{ + requestID: {Observation: &types.RequestObservation_Error{Error: []byte(e)}}, + }, + }, + } + } + // remaining 3 are non-error (EventuallyConsistent) — count toward totalNum but not error count + for i := len(errPayloads); i < N; i++ { + allObs[i] = attributedObservation{ + //nolint:gosec + Observer: commontypes.OracleID(i), + Observation: &types.Observation{ + Observations: map[string]*types.RequestObservation{ + requestID: {Observation: &types.RequestObservation_EventuallyConsistent{EventuallyConsistent: []byte("value")}}, + }, + }, + } + } + _, err := modeForError(N, F, minMatching, requestID, allObs) + require.ErrorContains(t, err, "insufficient number of errors") + }) +} diff --git a/libs/chainconsensus/oracle/mode.go b/libs/chainconsensus/oracle/mode.go index 90ec33431..897a04c01 100644 --- a/libs/chainconsensus/oracle/mode.go +++ b/libs/chainconsensus/oracle/mode.go @@ -20,10 +20,10 @@ type observation[keyT comparable, valueT any] struct { } // mode - returns most frequent value and its support count, if total number of observations is at least (N+F)/2+1 and -// number of values with identical keys is at least F+1. Returns error, otherwise. +// number of values with identical keys is at least minMatching. Returns error, otherwise. // If multiple values have identical number of observations, prefers value reported by oracle with the lowest oracleID. // The returned int is the count of nodes that observed the winning value (i.e. the number of identical responses). -func mode[keyT comparable, valueT any](N, F int, observations iter.Seq2[commontypes.OracleID, *observation[keyT, valueT]]) (valueT, int, error) { +func mode[keyT comparable, valueT any](N, F, minMatching int, observations iter.Seq2[commontypes.OracleID, *observation[keyT, valueT]]) (valueT, int, error) { counters := make(map[keyT]*counter[valueT]) var totalNum int for nodeID, nodeObservation := range observations { @@ -66,9 +66,9 @@ func mode[keyT comparable, valueT any](N, F int, observations iter.Seq2[commonty return zero, 0, errors.New("unexpected state: highestCounter is nil") } - if highestCounter.count < F+1 { + if highestCounter.count < minMatching { var zero valueT - return zero, highestCounter.count, fmt.Errorf("insufficient number of identical observations: expected %d, got %d", F+1, highestCounter.count) + return zero, highestCounter.count, fmt.Errorf("insufficient number of identical observations: expected %d, got %d", minMatching, highestCounter.count) } return highestCounter.value, highestCounter.count, nil diff --git a/libs/chainconsensus/oracle/mode_test.go b/libs/chainconsensus/oracle/mode_test.go new file mode 100644 index 000000000..4526cd564 --- /dev/null +++ b/libs/chainconsensus/oracle/mode_test.go @@ -0,0 +1,66 @@ +package oracle + +import ( + "iter" + "testing" + + "github.com/smartcontractkit/libocr/commontypes" + "github.com/stretchr/testify/require" +) + +// stringObs returns an iterator over the given values, attributed to sequential oracle IDs. +// An empty string produces a nil observation (counts toward total but not toward any key). +func stringObs(values ...string) iter.Seq2[commontypes.OracleID, *observation[string, string]] { + return func(yield func(commontypes.OracleID, *observation[string, string]) bool) { + for i, v := range values { + //nolint:gosec + id := commontypes.OracleID(i) + if v == "" { + if !yield(id, nil) { + return + } + continue + } + if !yield(id, &observation[string, string]{Key: v, Value: v}) { + return + } + } + } +} + +func TestMode_DefaultFPlusOne(t *testing.T) { + // N=7, F=2 → byzQuorumSize=5, default minMatching=F+1=3 + N, F := 7, 2 + got, err := mode[string, string](N, F, F+1, stringObs("a", "a", "a", "b", "b", "c", "")) + require.NoError(t, err) + require.Equal(t, "a", got) +} + +func TestMode_DefaultFPlusOne_InsufficientMatching(t *testing.T) { + // N=7, F=2 → byzQuorumSize=5; default minMatching=F+1=3 + N, F := 7, 2 + _, err := mode[string, string](N, F, F+1, stringObs("a", "a", "b", "b", "c", "c", "d")) + require.ErrorContains(t, err, "insufficient number of identical observations: expected 3, got 2") +} + +func TestMode_TwoFPlusOne(t *testing.T) { + // N=7, F=2 → minMatching=5; 5 agree on "a" + N, F := 7, 2 + got, err := mode[string, string](N, F, 2*F+1, stringObs("a", "a", "a", "a", "a", "b", "c")) + require.NoError(t, err) + require.Equal(t, "a", got) +} + +func TestMode_TwoFPlusOne_InsufficientMatching(t *testing.T) { + // N=7, F=2 → minMatching=5; only 4 agree on "a" → fail + N, F := 7, 2 + _, err := mode[string, string](N, F, 2*F+1, stringObs("a", "a", "a", "a", "b", "b", "c")) + require.ErrorContains(t, err, "insufficient number of identical observations: expected 5, got 4") +} + +func TestMode_InsufficientTotalObservations(t *testing.T) { + // N=7, F=2 → byzQuorumSize=5; only 4 provided → fail before matching check + N, F := 7, 2 + _, err := mode[string, string](N, F, F+1, stringObs("a", "a", "a", "a")) + require.ErrorContains(t, err, "insufficient number of observations: expected 5, got 4") +} diff --git a/libs/chainconsensus/oracle/reporting_plugin.go b/libs/chainconsensus/oracle/reporting_plugin.go index 094c7c9c6..13d5e7b1d 100644 --- a/libs/chainconsensus/oracle/reporting_plugin.go +++ b/libs/chainconsensus/oracle/reporting_plugin.go @@ -37,10 +37,21 @@ var _ ocr3types.ReportingPlugin[[]byte] = (*reportingPlugin)(nil) type Config struct { ocr3types.ReportingPluginConfig - MaxBatchSize int // max number of requests that this node will try to process in a single round - MaxObservationLength int // max length of observation in bytes + MaxBatchSize int // max number of requests that this node will try to process in a single round + MaxObservationLength int // max length of observation in bytes MaxReportLengthBytes int // max length of report in bytes MaxReportCount int // max number of reports in a single round + MinResponsesToAggregate int // minimum responses to aggregate to accept a read value; 0 means use F+1 +} + +// matchingThreshold returns the minimum number of nodes that must report identical +// observations for a read value to be accepted. When MinIdenticalObservations is +// zero the default of F+1 is used. +func (c Config) matchingThreshold() int { + if c.MinResponsesToAggregate > 0 { + return c.MinResponsesToAggregate + } + return c.F + 1 } type reportingPlugin struct { @@ -453,7 +464,7 @@ func (rp *reportingPlugin) agreeOnObservationType(requestID string, aos []attrib } } - value, _, err := mode[ctypes.ObservationType, ctypes.ObservationType](rp.config.N, rp.config.F, iterator) + value, _, err := mode[ctypes.ObservationType, ctypes.ObservationType](rp.config.N, rp.config.F, rp.config.matchingThreshold(), iterator) return value, err } @@ -519,18 +530,19 @@ func (rp *reportingPlugin) agreeOnAggregationMethod(requestID string, aos []attr } } - value, _, err := mode[string, string](rp.config.N, rp.config.F, iterator) + value, _, err := mode[string, string](rp.config.N, rp.config.F, rp.config.matchingThreshold(), iterator) return value, err } func (rp *reportingPlugin) agreeOnMissingRequestIDs(aos []attributedObservation) ([]string, error) { counter := make(map[string]int) var result []string + minMatching := rp.config.matchingThreshold() for _, ob := range aos { // MissingRequestIDs are guaranteed to be unique per observation by ValidateObservation for _, missingRequestID := range ob.Observation.MissingRequestIDs { counter[missingRequestID]++ - if counter[missingRequestID] == rp.config.F+1 { + if counter[missingRequestID] == minMatching { result = append(result, missingRequestID) } } @@ -565,7 +577,7 @@ func (rp *reportingPlugin) agreeOnEventuallyConsistentValue(requestID string, ao } } - return mode[[32]byte, []byte](rp.config.N, rp.config.F, iterator) + return mode[[32]byte, []byte](rp.config.N, rp.config.F, rp.config.matchingThreshold(), iterator) } func (rp *reportingPlugin) agreeOnHashableValue(requestID string, aos []attributedObservation) ([]byte, int, error) { @@ -602,7 +614,7 @@ func (rp *reportingPlugin) agreeOnHashableValue(requestID string, aos []attribut } } - return mode[[32]byte, []byte](rp.config.N, rp.config.F, iterator) + return mode[[32]byte, []byte](rp.config.N, rp.config.F, rp.config.matchingThreshold(), iterator) } func medianUInt64(heights []uint64) float64 { @@ -687,7 +699,7 @@ func (rp *reportingPlugin) agreeOnVolatileValue(requestID string, aos []attribut var best *volatileOutcomeCandidate for _, candidate := range candidates { - if candidate.supporters < rp.config.F+1 { + if candidate.supporters < rp.config.matchingThreshold() { continue } if best == nil || isVolatileCandidateABetter(&candidate, best) { @@ -701,7 +713,7 @@ func (rp *reportingPlugin) agreeOnVolatileValue(requestID string, aos []attribut }, best.supporters, nil } - errPayload, errorCount, err := modeForError(rp.config.N, rp.config.F, requestID, aos) + errPayload, errorCount, err := modeForError(rp.config.N, rp.config.F, rp.config.matchingThreshold(), requestID, aos) if err != nil { if errors.Is(err, errInsufficientErrorOb) { return nil, errorCount, errors.New("no volatile outcome candidate reached F+1 supporters") @@ -796,7 +808,7 @@ func (rp *reportingPlugin) Outcome( Outcome: &ctypes.RequestOutcome_LockableToBlock{LockableToBlock: &emptypb.Empty{}}, }) case ctypes.ObservationType_ERROR: - requestErrors, identicalCount, err := modeForError(rp.config.N, rp.config.F, requestID, aos) + requestErrors, identicalCount, err := modeForError(rp.config.N, rp.config.F, rp.config.matchingThreshold(), requestID, aos) rp.metrics.RecordIdenticalResponseCount(ctx, identicalCount, observationType.String()) if err != nil { rp.logger.Infow("Could not determine request error", "requestID", requestID, "err", err) diff --git a/libs/chainconsensus/oracle/reporting_plugin_factory.go b/libs/chainconsensus/oracle/reporting_plugin_factory.go index f916e170d..234200922 100644 --- a/libs/chainconsensus/oracle/reporting_plugin_factory.go +++ b/libs/chainconsensus/oracle/reporting_plugin_factory.go @@ -50,14 +50,21 @@ func (rpf *ReportingPluginFactory) NewReportingPlugin( return nil, ocr3types.ReportingPluginInfo{}, fmt.Errorf("failed to read reporting plugin config: %w", err) } + //nolint:gosec // F and N values will never exceed uint32 max + // Allow MinResponsesToAggregate to be set to 0 to use the default of F+1. If set, it must be between F+1 and N. + if offchainCfg.MinResponsesToAggregate != 0 && (offchainCfg.MinResponsesToAggregate < uint32(config.F+1) || offchainCfg.MinResponsesToAggregate > uint32(config.N)) { + return nil, ocr3types.ReportingPluginInfo{}, fmt.Errorf("invalid MinResponsesToAggregate: %d; must be gte to %d (F+1) and lte to %d (N)", offchainCfg.MinResponsesToAggregate, config.F+1, config.N) + } + rpf.logger.Infof("Using reporting plugin config: %+v", offchainCfg) cfg := Config{ - ReportingPluginConfig: config, - MaxBatchSize: int(offchainCfg.MaxBatchSize), - MaxObservationLength: int(offchainCfg.MaxObservationLengthBytes), - MaxReportLengthBytes: int(offchainCfg.MaxReportLengthBytes), - MaxReportCount: int(offchainCfg.MaxReportCount), + ReportingPluginConfig: config, + MaxBatchSize: int(offchainCfg.MaxBatchSize), + MaxObservationLength: int(offchainCfg.MaxObservationLengthBytes), + MaxReportLengthBytes: int(offchainCfg.MaxReportLengthBytes), + MaxReportCount: int(offchainCfg.MaxReportCount), + MinResponsesToAggregate: int(offchainCfg.MinResponsesToAggregate), } return newReportingPlugin(cfg, rpf.logger, rpf.blocksProvider, rpf.requestsStore, rpf.metrics), ocr3types.ReportingPluginInfo{ diff --git a/libs/chainconsensus/oracle/reporting_plugin_test.go b/libs/chainconsensus/oracle/reporting_plugin_test.go index a7918fa6d..82c453125 100644 --- a/libs/chainconsensus/oracle/reporting_plugin_test.go +++ b/libs/chainconsensus/oracle/reporting_plugin_test.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/capabilities/libs/chainconsensus/test" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + evmcapocr3types "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/chain-capabilities/consensus/ocr3/types" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" valuespb "github.com/smartcontractkit/chainlink-protos/cre/go/values/pb" @@ -1757,3 +1758,158 @@ func TestIsVolatileCandidateBetter(t *testing.T) { }) } } + +// TestAgreeOnEventuallyConsistentValue_TwoFPlusOne verifies that setting +// MinIdenticalObservations=2F+1 raises the matching bar for read results. +func TestAgreeOnEventuallyConsistentValue_TwoFPlusOne(t *testing.T) { + const id = "req-2f1" + // N=7, F=2 → require 5 identical (2F+1) + plugin := newReportingPlugin(Config{ + ReportingPluginConfig: ocr3types.ReportingPluginConfig{F: 2, N: 7}, + MinResponsesToAggregate: 5, + }, logger.Sugared(logger.Test(t)), nil, nil, test.GetConsensusMetrics(t)) + + makeAos := func(values []string) []attributedObservation { + aos := make([]attributedObservation, len(values)) + for i, v := range values { + //nolint:gosec + aos[i] = attributedObservation{ + Observer: commontypes.OracleID(i), + Observation: &types.Observation{ + Observations: map[string]*types.RequestObservation{ + id: {Observation: &types.RequestObservation_EventuallyConsistent{EventuallyConsistent: []byte(v)}}, + }, + }, + } + } + return aos + } + + t.Run("succeeds with 5 of 7 identical", func(t *testing.T) { + aos := makeAos([]string{"v", "v", "v", "v", "v", "other", "other"}) + got, err := plugin.agreeOnEventuallyConsistentValue(id, aos) + require.NoError(t, err) + require.Equal(t, []byte("v"), got) + }) + + t.Run("fails with only 4 of 7 identical", func(t *testing.T) { + aos := makeAos([]string{"v", "v", "v", "v", "x", "y", "z"}) + _, err := plugin.agreeOnEventuallyConsistentValue(id, aos) + require.ErrorContains(t, err, "insufficient number of identical observations: expected 5, got 4") + }) + + t.Run("default F+1 still works when MinIdenticalObservations is zero", func(t *testing.T) { + pluginDefault := newReportingPlugin(Config{ + ReportingPluginConfig: ocr3types.ReportingPluginConfig{F: 2, N: 7}, + }, logger.Sugared(logger.Test(t)), nil, nil, test.GetConsensusMetrics(t)) + // 3 of 7 matching → F+1=3, should succeed + aos := makeAos([]string{"v", "v", "v", "a", "b", "c", "d"}) + got, err := pluginDefault.agreeOnEventuallyConsistentValue(id, aos) + require.NoError(t, err) + require.Equal(t, []byte("v"), got) + }) +} + +func marshalOffchainConfig(t *testing.T, cfg *evmcapocr3types.ReportingPluginConfig) []byte { + t.Helper() + b, err := proto.Marshal(cfg) + require.NoError(t, err) + return b +} + +func TestNewReportingPlugin_MinResponsesToAggregateValidation(t *testing.T) { + const N = 4 + const F = 1 + // F+1 = 2 + + newFactory := func(t *testing.T) *ReportingPluginFactory { + t.Helper() + return NewReportingPluginFactory( + logger.Sugared(logger.Test(t)), + mocks.NewRequestsHandler(t), + mocks.NewBlocksProvider(t), + test.GetConsensusMetrics(t), + ) + } + + baseOffchainCfg := &evmcapocr3types.ReportingPluginConfig{ + MaxQueryLengthBytes: 1024 * 1024, + MaxObservationLengthBytes: 95 * 1024, + MaxOutcomeLengthBytes: uint32(ocr3types.MaxMaxOutcomeLength), + MaxReportLengthBytes: uint32(ocr3types.MaxMaxReportLength), + MaxReportCount: uint32(ocr3types.MaxMaxReportCount), + MaxBatchSize: 200, + } + + t.Run("below F+1 is rejected", func(t *testing.T) { + cfg := proto.Clone(baseOffchainCfg).(*evmcapocr3types.ReportingPluginConfig) + cfg.MinResponsesToAggregate = 1 // less than F+1=2 + + _, _, err := newFactory(t).NewReportingPlugin(t.Context(), ocr3types.ReportingPluginConfig{ + F: F, + N: N, + OffchainConfig: marshalOffchainConfig(t, cfg), + }) + require.ErrorContains(t, err, "invalid MinResponsesToAggregate") + }) + + t.Run("zero is allowed (default case)", func(t *testing.T) { + cfg := proto.Clone(baseOffchainCfg).(*evmcapocr3types.ReportingPluginConfig) + cfg.MinResponsesToAggregate = 0 + + _, _, err := newFactory(t).NewReportingPlugin(t.Context(), ocr3types.ReportingPluginConfig{ + F: F, + N: N, + OffchainConfig: marshalOffchainConfig(t, cfg), + }) + require.NoError(t, err) + }) + + t.Run("above N is rejected", func(t *testing.T) { + cfg := proto.Clone(baseOffchainCfg).(*evmcapocr3types.ReportingPluginConfig) + cfg.MinResponsesToAggregate = N + 1 + + _, _, err := newFactory(t).NewReportingPlugin(t.Context(), ocr3types.ReportingPluginConfig{ + F: F, + N: N, + OffchainConfig: marshalOffchainConfig(t, cfg), + }) + require.ErrorContains(t, err, "invalid MinResponsesToAggregate") + }) + + t.Run("equal to F+1 is accepted", func(t *testing.T) { + cfg := proto.Clone(baseOffchainCfg).(*evmcapocr3types.ReportingPluginConfig) + cfg.MinResponsesToAggregate = F + 1 + + _, _, err := newFactory(t).NewReportingPlugin(t.Context(), ocr3types.ReportingPluginConfig{ + F: F, + N: N, + OffchainConfig: marshalOffchainConfig(t, cfg), + }) + require.NoError(t, err) + }) + + t.Run("equal to N is accepted", func(t *testing.T) { + cfg := proto.Clone(baseOffchainCfg).(*evmcapocr3types.ReportingPluginConfig) + cfg.MinResponsesToAggregate = N + + _, _, err := newFactory(t).NewReportingPlugin(t.Context(), ocr3types.ReportingPluginConfig{ + F: F, + N: N, + OffchainConfig: marshalOffchainConfig(t, cfg), + }) + require.NoError(t, err) + }) + + t.Run("value between F+1 and N is accepted", func(t *testing.T) { + cfg := proto.Clone(baseOffchainCfg).(*evmcapocr3types.ReportingPluginConfig) + cfg.MinResponsesToAggregate = 3 // F+1=2, N=4 + + _, _, err := newFactory(t).NewReportingPlugin(t.Context(), ocr3types.ReportingPluginConfig{ + F: F, + N: N, + OffchainConfig: marshalOffchainConfig(t, cfg), + }) + require.NoError(t, err) + }) +} From 8c25399c5a7406414151133adc8bf542708b3ebe Mon Sep 17 00:00:00 2001 From: amit-momin Date: Wed, 3 Jun 2026 19:02:56 -0500 Subject: [PATCH 2/4] Fixed tests --- libs/chainconsensus/oracle/error_mode_test.go | 22 ++++++++++++++++--- libs/chainconsensus/oracle/mode_test.go | 15 ++++++++----- .../oracle/reporting_plugin_test.go | 9 +++++--- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/libs/chainconsensus/oracle/error_mode_test.go b/libs/chainconsensus/oracle/error_mode_test.go index b5cccfd2d..29b460fc2 100644 --- a/libs/chainconsensus/oracle/error_mode_test.go +++ b/libs/chainconsensus/oracle/error_mode_test.go @@ -176,10 +176,11 @@ func TestErrorMode_TwoFPlusOneThreshold(t *testing.T) { return aos } - t.Run("succeeds when 5 of 7 report same error", func(t *testing.T) { + t.Run("succeeds when minMatching number of identical errors are reported", func(t *testing.T) { errors := []string{"err", "err", "err", "err", "err", "other", "other"} - result, err := modeForError(N, F, minMatching, requestID, makeAos(errors)) + result, actualCount, err := modeForError(N, F, minMatching, requestID, makeAos(errors)) require.NoError(t, err) + require.Equal(t, 5, actualCount) require.Equal(t, []string{"err"}, func() []string { s := make([]string, len(result)) for i, b := range result { @@ -189,6 +190,20 @@ func TestErrorMode_TwoFPlusOneThreshold(t *testing.T) { }()) }) + t.Run("succeeds when minMatching number of different errors are reported", func(t *testing.T) { + errors := []string{"err-a", "err-a", "err-b", "err-b", "err-c", "err-d", "err-e"} + result, actualCount, err := modeForError(N, F, minMatching, requestID, makeAos(errors)) + require.NoError(t, err) + require.Equal(t, 5, actualCount) + require.Equal(t, []string{"err-a", "err-b", "err-c"}, func() []string { + s := make([]string, len(result)) + for i, b := range result { + s[i] = string(b) + } + return s + }()) + }) + t.Run("fails when combined error observations don't reach minMatching", func(t *testing.T) { // Only 4 error observations total (3 distinct errors), non-errors fill the remaining 3 slots allObs := make([]attributedObservation, N) @@ -216,7 +231,8 @@ func TestErrorMode_TwoFPlusOneThreshold(t *testing.T) { }, } } - _, err := modeForError(N, F, minMatching, requestID, allObs) + _, actualCount, err := modeForError(N, F, minMatching, requestID, allObs) require.ErrorContains(t, err, "insufficient number of errors") + require.Equal(t, 4, actualCount) }) } diff --git a/libs/chainconsensus/oracle/mode_test.go b/libs/chainconsensus/oracle/mode_test.go index 4526cd564..6c1a7202a 100644 --- a/libs/chainconsensus/oracle/mode_test.go +++ b/libs/chainconsensus/oracle/mode_test.go @@ -31,36 +31,41 @@ func stringObs(values ...string) iter.Seq2[commontypes.OracleID, *observation[st func TestMode_DefaultFPlusOne(t *testing.T) { // N=7, F=2 → byzQuorumSize=5, default minMatching=F+1=3 N, F := 7, 2 - got, err := mode[string, string](N, F, F+1, stringObs("a", "a", "a", "b", "b", "c", "")) + got, actualCount, err := mode[string, string](N, F, F+1, stringObs("a", "a", "a", "b", "b", "c", "")) require.NoError(t, err) require.Equal(t, "a", got) + require.Equal(t, 3, actualCount) } func TestMode_DefaultFPlusOne_InsufficientMatching(t *testing.T) { // N=7, F=2 → byzQuorumSize=5; default minMatching=F+1=3 N, F := 7, 2 - _, err := mode[string, string](N, F, F+1, stringObs("a", "a", "b", "b", "c", "c", "d")) + _, actualCount, err := mode[string, string](N, F, F+1, stringObs("a", "a", "b", "b", "c", "c", "d")) require.ErrorContains(t, err, "insufficient number of identical observations: expected 3, got 2") + require.Equal(t, 2, actualCount) } func TestMode_TwoFPlusOne(t *testing.T) { // N=7, F=2 → minMatching=5; 5 agree on "a" N, F := 7, 2 - got, err := mode[string, string](N, F, 2*F+1, stringObs("a", "a", "a", "a", "a", "b", "c")) + got, actualCount, err := mode[string, string](N, F, 2*F+1, stringObs("a", "a", "a", "a", "a", "b", "c")) require.NoError(t, err) require.Equal(t, "a", got) + require.Equal(t, 5, actualCount) } func TestMode_TwoFPlusOne_InsufficientMatching(t *testing.T) { // N=7, F=2 → minMatching=5; only 4 agree on "a" → fail N, F := 7, 2 - _, err := mode[string, string](N, F, 2*F+1, stringObs("a", "a", "a", "a", "b", "b", "c")) + _, actualCount, err := mode[string, string](N, F, 2*F+1, stringObs("a", "a", "a", "a", "b", "b", "c")) require.ErrorContains(t, err, "insufficient number of identical observations: expected 5, got 4") + require.Equal(t, 4, actualCount) } func TestMode_InsufficientTotalObservations(t *testing.T) { // N=7, F=2 → byzQuorumSize=5; only 4 provided → fail before matching check N, F := 7, 2 - _, err := mode[string, string](N, F, F+1, stringObs("a", "a", "a", "a")) + _, actualCount, err := mode[string, string](N, F, F+1, stringObs("a", "a", "a", "a")) require.ErrorContains(t, err, "insufficient number of observations: expected 5, got 4") + require.Equal(t, 0, actualCount) } diff --git a/libs/chainconsensus/oracle/reporting_plugin_test.go b/libs/chainconsensus/oracle/reporting_plugin_test.go index 82c453125..464749211 100644 --- a/libs/chainconsensus/oracle/reporting_plugin_test.go +++ b/libs/chainconsensus/oracle/reporting_plugin_test.go @@ -1787,15 +1787,17 @@ func TestAgreeOnEventuallyConsistentValue_TwoFPlusOne(t *testing.T) { t.Run("succeeds with 5 of 7 identical", func(t *testing.T) { aos := makeAos([]string{"v", "v", "v", "v", "v", "other", "other"}) - got, err := plugin.agreeOnEventuallyConsistentValue(id, aos) + got, actualCount, err := plugin.agreeOnEventuallyConsistentValue(id, aos) require.NoError(t, err) require.Equal(t, []byte("v"), got) + require.Equal(t, 5, actualCount) }) t.Run("fails with only 4 of 7 identical", func(t *testing.T) { aos := makeAos([]string{"v", "v", "v", "v", "x", "y", "z"}) - _, err := plugin.agreeOnEventuallyConsistentValue(id, aos) + _, actualCount, err := plugin.agreeOnEventuallyConsistentValue(id, aos) require.ErrorContains(t, err, "insufficient number of identical observations: expected 5, got 4") + require.Equal(t, 4, actualCount) }) t.Run("default F+1 still works when MinIdenticalObservations is zero", func(t *testing.T) { @@ -1804,9 +1806,10 @@ func TestAgreeOnEventuallyConsistentValue_TwoFPlusOne(t *testing.T) { }, logger.Sugared(logger.Test(t)), nil, nil, test.GetConsensusMetrics(t)) // 3 of 7 matching → F+1=3, should succeed aos := makeAos([]string{"v", "v", "v", "a", "b", "c", "d"}) - got, err := pluginDefault.agreeOnEventuallyConsistentValue(id, aos) + got, actualCount, err := pluginDefault.agreeOnEventuallyConsistentValue(id, aos) require.NoError(t, err) require.Equal(t, []byte("v"), got) + require.Equal(t, 3, actualCount) }) } From b72e3c0829c7be0bc9eb815fd4f18532555ccf96 Mon Sep 17 00:00:00 2001 From: amit-momin Date: Tue, 30 Jun 2026 11:38:41 -0500 Subject: [PATCH 3/4] Bumped cl-common --- libs/go.mod | 6 +++--- libs/go.sum | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libs/go.mod b/libs/go.mod index e47bc7838..c6530649c 100644 --- a/libs/go.mod +++ b/libs/go.mod @@ -8,8 +8,8 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/go-plugin v1.8.0 github.com/shopspring/decimal v1.4.0 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260601182856-0b9e9346b65c - github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260526195338-adcf8013a1b7 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96 + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d github.com/stretchr/testify v1.11.1 go.opentelemetry.io/otel v1.43.0 @@ -81,7 +81,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/smartcontractkit/chain-selectors v1.0.100 // indirect - github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0 // indirect + github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 // indirect github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b // indirect github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b // indirect github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e // indirect diff --git a/libs/go.sum b/libs/go.sum index 71323b09c..95a4e155b 100644 --- a/libs/go.sum +++ b/libs/go.sum @@ -208,12 +208,18 @@ github.com/smartcontractkit/chain-selectors v1.0.100 h1:wpiSpmI/eFjY+wx/nPr5VuNF github.com/smartcontractkit/chain-selectors v1.0.100/go.mod h1:qy7whtgG5g+7z0jt0nRyii9bLND9m15NZTzuQPkMZ5w= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260601182856-0b9e9346b65c h1:YSlNhm723PwpFeRbPJtZrQBbT5Mr/EpsKBXbAlsa82Y= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260601182856-0b9e9346b65c/go.mod h1:noBAXFIyadzhElKzb6a7pngnRsVTtV91muoeDqNnuUg= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96 h1:Nn8uoKM2YDYK9j7Nj0FzoWz5WkfWiZGQan07OeTjtKI= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0 h1:NExKM/D0HneOq/N5LGTbkV4VOa0UHCvfTNEb4GqYpto= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0/go.mod h1:HmUyH2oD9m+GRpKq7q3vuRnm1F2Uczf/Nd1v3ipMSK8= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62/go.mod h1:HmUyH2oD9m+GRpKq7q3vuRnm1F2Uczf/Nd1v3ipMSK8= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4 h1:GCzrxDWn3b7jFfEA+WiYRi8CKoegsayiDoJBCjYkneE= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4/go.mod h1:HHGeDUpAsPa0pmOx7wrByCitjQ0mbUxf0R9v+g67uCA= github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260526195338-adcf8013a1b7 h1:iljEJss3WOwcsMkWy72Yn2zvjw7Gyxc+RXL7r8YKM6g= github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260526195338-adcf8013a1b7/go.mod h1:vTFHTCbLui4Vn8fTmAadfE3rdnvfrDwOmMujmW857D0= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b h1:VDgJWDipihV9f7M5+d21d1RzSsg5rEv+iI12oN1VQbo= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b/go.mod h1:vTFHTCbLui4Vn8fTmAadfE3rdnvfrDwOmMujmW857D0= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b h1:QuI6SmQFK/zyUlVWEf0GMkiUYBPY4lssn26nKSd/bOM= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b/go.mod h1:qSTSwX3cBP3FKQwQacdjArqv0g6QnukjV4XuzO6UyoY= github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b h1:36knUpKHHAZ86K4FGWXtx8i/EQftGdk2bqCoEu/Cha8= From d00b5e2884ff9505a8b55a70ab94ff9958d613e0 Mon Sep 17 00:00:00 2001 From: amit-momin Date: Tue, 30 Jun 2026 12:13:54 -0500 Subject: [PATCH 4/4] Bumped capabilities/libs in evm --- chain_capabilities/evm/go.mod | 8 ++++---- chain_capabilities/evm/go.sum | 16 ++++++++-------- integration_tests/go.mod | 8 ++++---- integration_tests/go.sum | 16 ++++++++-------- libs/go.sum | 6 ------ 5 files changed, 24 insertions(+), 30 deletions(-) diff --git a/chain_capabilities/evm/go.mod b/chain_capabilities/evm/go.mod index 753e68deb..70a3decc5 100644 --- a/chain_capabilities/evm/go.mod +++ b/chain_capabilities/evm/go.mod @@ -6,13 +6,13 @@ require ( github.com/ethereum/go-ethereum v1.17.0 github.com/google/go-cmp v0.7.0 github.com/smartcontractkit/capabilities/chain_capabilities/common v0.0.0-20260615195421-fb87220e503f - github.com/smartcontractkit/capabilities/libs v0.0.0-20260609124022-2749e4a32bfb + github.com/smartcontractkit/capabilities/libs v0.0.0-20260630163841-b72e3c0829c7 github.com/smartcontractkit/chain-selectors v1.0.104 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260619153749-934b00c44d37 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260410162948-2dca02f24e98 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20251022073203-7d8ae8cf67c1 github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20260410144512-ca02ad6ed16a - github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260618082634-432eb85805e7 + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b github.com/stretchr/testify v1.11.1 go.opentelemetry.io/otel v1.43.0 go.uber.org/zap v1.27.1 @@ -90,7 +90,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/smartcontractkit/chainlink-common/keystore v1.1.1-0.20260529092756-a94bc8ce96d6 // indirect - github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0 // indirect + github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20260326122810-b657beadfb57 // indirect github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260401162955-be2bc6b5264b // indirect github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b // indirect diff --git a/chain_capabilities/evm/go.sum b/chain_capabilities/evm/go.sum index 02eed31f7..9880b96c2 100644 --- a/chain_capabilities/evm/go.sum +++ b/chain_capabilities/evm/go.sum @@ -469,16 +469,16 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/smartcontractkit/capabilities/chain_capabilities/common v0.0.0-20260615195421-fb87220e503f h1:ovzaEXpe8k5Lx7MjQKrwxZZNV6uXGt9xPhtXr87k2Ow= github.com/smartcontractkit/capabilities/chain_capabilities/common v0.0.0-20260615195421-fb87220e503f/go.mod h1:gp/Xrw5nvPswONfr48WKWvAoTTg+Xv/tlk0SRrru8Qw= -github.com/smartcontractkit/capabilities/libs v0.0.0-20260609124022-2749e4a32bfb h1:TskymCV/uP2plDgR2PDqGdavIXnR/rK+wxelqAW5u+s= -github.com/smartcontractkit/capabilities/libs v0.0.0-20260609124022-2749e4a32bfb/go.mod h1:LS7F8U2YZNc0Vt8f6SVWUUigGLxdxZMpyC7VCcUTagg= +github.com/smartcontractkit/capabilities/libs v0.0.0-20260630163841-b72e3c0829c7 h1:53Guxfa/UXq0euESoBnSX7T8M9QCa/94LFhdtQkqu0k= +github.com/smartcontractkit/capabilities/libs v0.0.0-20260630163841-b72e3c0829c7/go.mod h1:33p2TZjbKF126UaNbmQIiJDq8m55wfl+irZq0n19pFA= github.com/smartcontractkit/chain-selectors v1.0.104 h1:/n9pPGM5W/+r1eHoWZv4VwX9LNS1af4+ICyhM8zKRNM= github.com/smartcontractkit/chain-selectors v1.0.104/go.mod h1:qy7whtgG5g+7z0jt0nRyii9bLND9m15NZTzuQPkMZ5w= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260619153749-934b00c44d37 h1:ZZlU2e+hVC1Y8VAczVNGZBM3rU3HSqkOCn2KZHHV7gc= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260619153749-934b00c44d37/go.mod h1:paOB/6dy57owHtOGzhgaRBWRDT5BEWfnJF5M7sgkcro= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96 h1:Nn8uoKM2YDYK9j7Nj0FzoWz5WkfWiZGQan07OeTjtKI= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= github.com/smartcontractkit/chainlink-common/keystore v1.1.1-0.20260529092756-a94bc8ce96d6 h1:fWsYxxj35fp1/6YZngoTsOTMLqDie4N5X0osAOdhUTE= github.com/smartcontractkit/chainlink-common/keystore v1.1.1-0.20260529092756-a94bc8ce96d6/go.mod h1:6JexOOhPhknQ0QMuppFIlOpm6wCp54yZMxai+tWugwY= -github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0 h1:NExKM/D0HneOq/N5LGTbkV4VOa0UHCvfTNEb4GqYpto= -github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0/go.mod h1:HmUyH2oD9m+GRpKq7q3vuRnm1F2Uczf/Nd1v3ipMSK8= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62/go.mod h1:HmUyH2oD9m+GRpKq7q3vuRnm1F2Uczf/Nd1v3ipMSK8= github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260410162948-2dca02f24e98 h1:h/L6wrXYLQalI/vHm6qg/KBv6d7kMb3geMHV5hCM1t4= github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260410162948-2dca02f24e98/go.mod h1:6vCMfxz7cMW0wWseNKtct+b1JJbbRVJJhh/t6pQWN3M= github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20251022073203-7d8ae8cf67c1 h1:NTODgwAil7BLoijS7y6KnEuNbQ9v60VUhIR9FcAzIhg= @@ -491,8 +491,8 @@ github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20260410144512- github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20260410144512-ca02ad6ed16a/go.mod h1:7ketk4ischPQW/JQgmyHz6zdzLUJv1VC29SiSgosydQ= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4 h1:GCzrxDWn3b7jFfEA+WiYRi8CKoegsayiDoJBCjYkneE= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4/go.mod h1:HHGeDUpAsPa0pmOx7wrByCitjQ0mbUxf0R9v+g67uCA= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260618082634-432eb85805e7 h1:iRFmfMFQtcnhGDjCuARQG4MPbcmbbJDDw7MUH3GcGy8= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260618082634-432eb85805e7/go.mod h1:vTFHTCbLui4Vn8fTmAadfE3rdnvfrDwOmMujmW857D0= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b h1:VDgJWDipihV9f7M5+d21d1RzSsg5rEv+iI12oN1VQbo= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b/go.mod h1:vTFHTCbLui4Vn8fTmAadfE3rdnvfrDwOmMujmW857D0= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b h1:QuI6SmQFK/zyUlVWEf0GMkiUYBPY4lssn26nKSd/bOM= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b/go.mod h1:qSTSwX3cBP3FKQwQacdjArqv0g6QnukjV4XuzO6UyoY= github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b h1:36knUpKHHAZ86K4FGWXtx8i/EQftGdk2bqCoEu/Cha8= diff --git a/integration_tests/go.mod b/integration_tests/go.mod index ecd6d51c2..a53676360 100644 --- a/integration_tests/go.mod +++ b/integration_tests/go.mod @@ -26,10 +26,10 @@ require ( github.com/smartcontractkit/capabilities/http_trigger v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/capabilities/loadtestwritetarget v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chain-selectors v1.0.104 - github.com/smartcontractkit/chainlink-common v0.11.2-0.20260619153749-934b00c44d37 + github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96 github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260609161557-8ceae53b8ab1 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260512150409-b4068bf735e6 - github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260618082634-432eb85805e7 + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260528221400-84746b70eeeb github.com/smartcontractkit/chainlink/v2 v2.29.1-cre-beta.0.0.20260609174137-e2407e0bdd98 github.com/smartcontractkit/cre-sdk-go v1.5.0 @@ -304,7 +304,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect github.com/smartcontractkit/capabilities/chain_capabilities/common v0.0.0-20260615195421-fb87220e503f // indirect - github.com/smartcontractkit/capabilities/libs v0.0.0-20260609124022-2749e4a32bfb // indirect + github.com/smartcontractkit/capabilities/libs v0.0.0-20260630163841-b72e3c0829c7 // indirect github.com/smartcontractkit/chainlink-aptos v0.0.0-20260507123701-77fc93b573bb // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20260428205619-2db1389501a1 // indirect @@ -314,7 +314,7 @@ require ( github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20260415165642-49f23e4d76cc // indirect github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd // indirect github.com/smartcontractkit/chainlink-common/keystore v1.2.0 // indirect - github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0 // indirect + github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 // indirect github.com/smartcontractkit/chainlink-data-streams v0.1.15-0.20260522094612-5f9f748bd87a // indirect github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.2-0.20250227211209-7cd000095135 // indirect diff --git a/integration_tests/go.sum b/integration_tests/go.sum index ce890a667..1587f7bad 100644 --- a/integration_tests/go.sum +++ b/integration_tests/go.sum @@ -1139,8 +1139,8 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= -github.com/smartcontractkit/capabilities/libs v0.0.0-20260609124022-2749e4a32bfb h1:TskymCV/uP2plDgR2PDqGdavIXnR/rK+wxelqAW5u+s= -github.com/smartcontractkit/capabilities/libs v0.0.0-20260609124022-2749e4a32bfb/go.mod h1:LS7F8U2YZNc0Vt8f6SVWUUigGLxdxZMpyC7VCcUTagg= +github.com/smartcontractkit/capabilities/libs v0.0.0-20260630163841-b72e3c0829c7 h1:53Guxfa/UXq0euESoBnSX7T8M9QCa/94LFhdtQkqu0k= +github.com/smartcontractkit/capabilities/libs v0.0.0-20260630163841-b72e3c0829c7/go.mod h1:33p2TZjbKF126UaNbmQIiJDq8m55wfl+irZq0n19pFA= github.com/smartcontractkit/chain-selectors v1.0.104 h1:/n9pPGM5W/+r1eHoWZv4VwX9LNS1af4+ICyhM8zKRNM= github.com/smartcontractkit/chain-selectors v1.0.104/go.mod h1:qy7whtgG5g+7z0jt0nRyii9bLND9m15NZTzuQPkMZ5w= github.com/smartcontractkit/chainlink-aptos v0.0.0-20260507123701-77fc93b573bb h1:6UjHnVanvb+6yJuefhyVlfv6YKFGMeZY5jv+a7Sexyo= @@ -1159,12 +1159,12 @@ 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.20260428133800-3b1484e8b1fd h1:IMopuENFVS63AerRELdfWo6o60UNUidcldJOxJLmk24= github.com/smartcontractkit/chainlink-ccv v0.0.2-0.20260428133800-3b1484e8b1fd/go.mod h1:SBN8Urnh5sQvrQRbSo1Nr8coWatHg8LZoPw3R/42sho= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260619153749-934b00c44d37 h1:ZZlU2e+hVC1Y8VAczVNGZBM3rU3HSqkOCn2KZHHV7gc= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260619153749-934b00c44d37/go.mod h1:paOB/6dy57owHtOGzhgaRBWRDT5BEWfnJF5M7sgkcro= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96 h1:Nn8uoKM2YDYK9j7Nj0FzoWz5WkfWiZGQan07OeTjtKI= +github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96/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.20260601211238-9f526774fef0 h1:NExKM/D0HneOq/N5LGTbkV4VOa0UHCvfTNEb4GqYpto= -github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0/go.mod h1:HmUyH2oD9m+GRpKq7q3vuRnm1F2Uczf/Nd1v3ipMSK8= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= +github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62/go.mod h1:HmUyH2oD9m+GRpKq7q3vuRnm1F2Uczf/Nd1v3ipMSK8= github.com/smartcontractkit/chainlink-data-streams v0.1.15-0.20260522094612-5f9f748bd87a h1:8bIqv4r7SgDWkXL2Qz/Ijw+YjZY1uroIte3E2v2keVk= github.com/smartcontractkit/chainlink-data-streams v0.1.15-0.20260522094612-5f9f748bd87a/go.mod h1:dF5JiHWueHjYguUUUrFeb03MkcDqha/tssEkqTkgzp4= github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260609161557-8ceae53b8ab1 h1:VdJBtNmasHzISQQF0k0LHFh44WDKO7S00VyaT7qykuc= @@ -1193,8 +1193,8 @@ github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0. github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0.0.0-20251211142334-5c3421fe2c8d/go.mod h1:ATjAPIVJibHRcIfiG47rEQkUIOoYa6KDvWj3zwCAw6g= github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d h1:AJy55QJ/pBhXkZjc7N+ATnWfxrcjq9BI9DmdtdjwDUQ= github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d/go.mod h1:5JdppgngCOUS76p61zCinSCgOhPeYQ+OcDUuome5THQ= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260618082634-432eb85805e7 h1:iRFmfMFQtcnhGDjCuARQG4MPbcmbbJDDw7MUH3GcGy8= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260618082634-432eb85805e7/go.mod h1:vTFHTCbLui4Vn8fTmAadfE3rdnvfrDwOmMujmW857D0= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b h1:VDgJWDipihV9f7M5+d21d1RzSsg5rEv+iI12oN1VQbo= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b/go.mod h1:vTFHTCbLui4Vn8fTmAadfE3rdnvfrDwOmMujmW857D0= github.com/smartcontractkit/chainlink-protos/data-feeds v0.1.1-0.20260501174546-2e8846986b36 h1:SG+wAsNyAcA6Kk19ljuxi3HK9Ll2lpHik8OKoY4x7A0= github.com/smartcontractkit/chainlink-protos/data-feeds v0.1.1-0.20260501174546-2e8846986b36/go.mod h1:vL1bDgPSJjV0EqHYs4dDlR+EEE0cJchgvGLYXhwIjXY= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20260512230622-65f10f4cd305 h1:NJdGFhzT6zMaTod4QkBqVD2sg0I25iw1boOYtTpEwRo= diff --git a/libs/go.sum b/libs/go.sum index 95a4e155b..87c4871ba 100644 --- a/libs/go.sum +++ b/libs/go.sum @@ -206,18 +206,12 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/smartcontractkit/chain-selectors v1.0.100 h1:wpiSpmI/eFjY+wx/nPr5VuNF4hki0prIBMKEaQWn3g4= github.com/smartcontractkit/chain-selectors v1.0.100/go.mod h1:qy7whtgG5g+7z0jt0nRyii9bLND9m15NZTzuQPkMZ5w= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260601182856-0b9e9346b65c h1:YSlNhm723PwpFeRbPJtZrQBbT5Mr/EpsKBXbAlsa82Y= -github.com/smartcontractkit/chainlink-common v0.11.2-0.20260601182856-0b9e9346b65c/go.mod h1:noBAXFIyadzhElKzb6a7pngnRsVTtV91muoeDqNnuUg= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96 h1:Nn8uoKM2YDYK9j7Nj0FzoWz5WkfWiZGQan07OeTjtKI= github.com/smartcontractkit/chainlink-common v0.11.2-0.20260630163725-715aee90ca96/go.mod h1:ncZiIgraMh4F9lWDoJwB1TX395qZFR5bvnZcHbD0A1Q= -github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0 h1:NExKM/D0HneOq/N5LGTbkV4VOa0UHCvfTNEb4GqYpto= -github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260601211238-9f526774fef0/go.mod h1:HmUyH2oD9m+GRpKq7q3vuRnm1F2Uczf/Nd1v3ipMSK8= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62 h1:o7vfwNQjQbMKQ9YsZFQOxvU7RMXD/wKnZsX5N9sDS3w= github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.11-0.20260626151909-052e55e62e62/go.mod h1:HmUyH2oD9m+GRpKq7q3vuRnm1F2Uczf/Nd1v3ipMSK8= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4 h1:GCzrxDWn3b7jFfEA+WiYRi8CKoegsayiDoJBCjYkneE= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4/go.mod h1:HHGeDUpAsPa0pmOx7wrByCitjQ0mbUxf0R9v+g67uCA= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260526195338-adcf8013a1b7 h1:iljEJss3WOwcsMkWy72Yn2zvjw7Gyxc+RXL7r8YKM6g= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260526195338-adcf8013a1b7/go.mod h1:vTFHTCbLui4Vn8fTmAadfE3rdnvfrDwOmMujmW857D0= github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b h1:VDgJWDipihV9f7M5+d21d1RzSsg5rEv+iI12oN1VQbo= github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260622152157-c8e129347b8b/go.mod h1:vTFHTCbLui4Vn8fTmAadfE3rdnvfrDwOmMujmW857D0= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b h1:QuI6SmQFK/zyUlVWEf0GMkiUYBPY4lssn26nKSd/bOM=