From f5894b269ddd85a2ff08762355092dc4b438fccf Mon Sep 17 00:00:00 2001 From: dimkouv Date: Wed, 18 Sep 2024 13:24:12 +0300 Subject: [PATCH 1/6] commit batch sizes > 1 --- commit/merkleroot/observation.go | 53 ++++++++++-- commit/merkleroot/observation_test.go | 11 +-- commit/merkleroot/outcome.go | 22 ++++- commit/merkleroot/outcome_test.go | 81 +++++++++++++++++++ commit/merkleroot/processor.go | 4 + commit/plugin_e2e_test.go | 5 ++ internal/libs/cciptypeutil/seqnumrange.go | 21 +++++ .../libs/cciptypeutil/seqnumrange_test.go | 62 ++++++++++++++ mocks/commit/merkleroot/observer.go | 49 +++++++++++ pluginconfig/commit.go | 8 +- 10 files changed, 301 insertions(+), 15 deletions(-) create mode 100644 internal/libs/cciptypeutil/seqnumrange.go create mode 100644 internal/libs/cciptypeutil/seqnumrange_test.go diff --git a/commit/merkleroot/observation.go b/commit/merkleroot/observation.go index 7e121e2b..a58c59f4 100644 --- a/commit/merkleroot/observation.go +++ b/commit/merkleroot/observation.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -114,12 +115,10 @@ func (w *Processor) getObservation(ctx context.Context, q Query, previousOutcome switch nextState { case SelectingRangesForReport: offRampNextSeqNums := w.observer.ObserveOffRampNextSeqNums(ctx) + onRampLatestSeqNums := w.observer.ObserveLatestOnRampSeqNums(ctx, w.cfg.DestChain) + return Observation{ - // TODO: observe OnRamp max seq nums. The use of offRampNextSeqNums here effectively disables batching, - // e.g. the ranges selected for each chain will be [x, x] (e.g. [46, 46]), which means reports will only - // contain one message per chain. Querying the OnRamp contract requires changes to reader.CCIPReader, - // which will need to be done in a future change. - OnRampMaxSeqNums: offRampNextSeqNums, + OnRampMaxSeqNums: onRampLatestSeqNums, OffRampNextSeqNums: offRampNextSeqNums, FChain: w.observer.ObserveFChain(), }, nextState @@ -145,9 +144,12 @@ func (w *Processor) getObservation(ctx context.Context, q Query, previousOutcome } type Observer interface { - // ObserveOffRampNextSeqNums observes the next sequence numbers for each source chain from the OffRamp + // ObserveOffRampNextSeqNums observes the next OffRamp sequence numbers for each source chain ObserveOffRampNextSeqNums(ctx context.Context) []plugintypes.SeqNumChain + // ObserveLatestOnRampSeqNums observes the latest OnRamp sequence numbers for each configured source chain. + ObserveLatestOnRampSeqNums(ctx context.Context, destChain cciptypes.ChainSelector) []plugintypes.SeqNumChain + // ObserveMerkleRoots computes the merkle roots for the given sequence number ranges ObserveMerkleRoots(ctx context.Context, ranges []plugintypes.ChainRange) []cciptypes.MerkleRootChain @@ -202,6 +204,45 @@ func (o ObserverImpl) ObserveOffRampNextSeqNums(ctx context.Context) []plugintyp return result } +// ObserveLatestOnRampSeqNums observes the latest onRamp sequence numbers for each configured source chain. +func (o ObserverImpl) ObserveLatestOnRampSeqNums( + ctx context.Context, destChain cciptypes.ChainSelector) []plugintypes.SeqNumChain { + sourceChains, err := o.chainSupport.KnownSourceChainsSlice() + if err != nil { + o.lggr.Warnw("call to KnownSourceChainsSlice failed", "err", err) + return nil + } + + latestOnRampSeqNums := make([]plugintypes.SeqNumChain, len(sourceChains)) + eg := &errgroup.Group{} + + for i, sourceChain := range sourceChains { + i, sourceChain := i, sourceChain + eg.Go(func() error { + nextOnRampSeqNum, err := o.ccipReader.GetExpectedNextSequenceNumber(ctx, sourceChain, destChain) + if err != nil { + return fmt.Errorf("failed to get expected next sequence number for source chain %d: %w", sourceChain, err) + } + if nextOnRampSeqNum == 0 { + return fmt.Errorf("expected next sequence number for source chain %d is 0", sourceChain) + } + + latestOnRampSeqNums[i] = plugintypes.SeqNumChain{ + ChainSel: sourceChain, + SeqNum: nextOnRampSeqNum - 1, // Latest is the next one minus one. + } + return nil + }) + } + + if err := eg.Wait(); err != nil { + o.lggr.Warnw("call to GetExpectedNextSequenceNumber failed", "err", err) + return nil + } + + return latestOnRampSeqNums +} + // ObserveMerkleRoots computes the merkle roots for the given sequence number ranges func (o ObserverImpl) ObserveMerkleRoots( ctx context.Context, diff --git a/commit/merkleroot/observation_test.go b/commit/merkleroot/observation_test.go index 167e207d..88e19d66 100644 --- a/commit/merkleroot/observation_test.go +++ b/commit/merkleroot/observation_test.go @@ -35,10 +35,10 @@ func Test_Observation(t *testing.T) { }, } offRampNextSeqNums := []plugintypes.SeqNumChain{ - { - ChainSel: 456, - SeqNum: 9987, - }, + {ChainSel: 456, SeqNum: 9987}, + } + onRampLatestSeqNums := []plugintypes.SeqNumChain{ + {ChainSel: 456, SeqNum: 9990}, } fChain := map[cciptypes.ChainSelector]int{ 872: 3, @@ -58,11 +58,12 @@ func Test_Observation(t *testing.T) { getObserver: func(t *testing.T) *merkleroot.MockObserver { observer := merkleroot.NewMockObserver(t) observer.EXPECT().ObserveOffRampNextSeqNums(mock.Anything).Once().Return(offRampNextSeqNums) + observer.EXPECT().ObserveLatestOnRampSeqNums(mock.Anything, mock.Anything).Return(onRampLatestSeqNums) observer.EXPECT().ObserveFChain().Once().Return(fChain) return observer }, expObs: Observation{ - OnRampMaxSeqNums: offRampNextSeqNums, + OnRampMaxSeqNums: onRampLatestSeqNums, OffRampNextSeqNums: offRampNextSeqNums, FChain: fChain, }, diff --git a/commit/merkleroot/outcome.go b/commit/merkleroot/outcome.go index cb61b1e4..96ce94cd 100644 --- a/commit/merkleroot/outcome.go +++ b/commit/merkleroot/outcome.go @@ -10,6 +10,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/internal/libs/cciptypeutil" + "github.com/smartcontractkit/chainlink-ccip/commit/merkleroot/rmn" "github.com/smartcontractkit/chainlink-ccip/plugintypes" "github.com/smartcontractkit/chainlink-ccip/shared" @@ -46,7 +48,7 @@ func (w *Processor) getOutcome( switch nextState { case SelectingRangesForReport: - return reportRangesOutcome(q, consensusObservation), nextState + return reportRangesOutcome(q, w.lggr, consensusObservation, w.cfg.BatchLimits), nextState case BuildingReport: if q.RetryRMNSignatures { // We want to retry getting the RMN signatures on the exact same outcome we had before. @@ -64,10 +66,11 @@ func (w *Processor) getOutcome( } // reportRangesOutcome determines the sequence number ranges for each chain to build a report from in the next round -// TODO: ensure each range is below a limit func reportRangesOutcome( _ Query, + lggr logger.Logger, consensusObservation ConsensusObservation, + rangeLimitsPerSourceChain map[cciptypes.ChainSelector]uint64, ) Outcome { rangesToReport := make([]plugintypes.ChainRange, 0) @@ -82,11 +85,24 @@ func reportRangesOutcome( } if offRampNextSeqNum <= onRampMaxSeqNum { + rngLimit, ok := rangeLimitsPerSourceChain[chainSel] + if !ok { + rngLimit = DefaultSeqNumsBatchLimit + } + + rng := cciptypes.NewSeqNumRange(offRampNextSeqNum, onRampMaxSeqNum) + chainRange := plugintypes.ChainRange{ ChainSel: chainSel, - SeqNumRange: [2]cciptypes.SeqNum{offRampNextSeqNum, onRampMaxSeqNum}, + SeqNumRange: cciptypeutil.SeqNumRangeLimit(rng, rngLimit), } rangesToReport = append(rangesToReport, chainRange) + + if wasTruncated := rng.End() != chainRange.SeqNumRange.End(); wasTruncated { + lggr.Infof("Range for chain %d: %s (before truncate: %v)", chainSel, chainRange.SeqNumRange, rng) + } else { + lggr.Infof("Range for chain %d: %s", chainSel, chainRange.SeqNumRange) + } } offRampNextSeqNums = append(offRampNextSeqNums, plugintypes.SeqNumChain{ diff --git a/commit/merkleroot/outcome_test.go b/commit/merkleroot/outcome_test.go index 34309587..35915d79 100644 --- a/commit/merkleroot/outcome_test.go +++ b/commit/merkleroot/outcome_test.go @@ -7,6 +7,8 @@ import ( "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + + "github.com/smartcontractkit/chainlink-ccip/plugintypes" ) func Test_buildReport(t *testing.T) { @@ -37,3 +39,82 @@ func Test_buildReport(t *testing.T) { } }) } + +func Test_reportRangesOutcome(t *testing.T) { + lggr := logger.Test(t) + + testCases := []struct { + name string + consensusObservation ConsensusObservation + rangeLimitsPerSourceChain map[cciptypes.ChainSelector]uint64 + expectedOutcome Outcome + }{ + { + name: "base empty outcome", + expectedOutcome: Outcome{ + OutcomeType: ReportIntervalsSelected, + RangesSelectedForReport: []plugintypes.ChainRange{}, + OffRampNextSeqNums: []plugintypes.SeqNumChain{}, + }, + }, + { + name: "simple scenario with one chain", + consensusObservation: ConsensusObservation{ + OnRampMaxSeqNums: map[cciptypes.ChainSelector]cciptypes.SeqNum{ + 1: 20, + }, + OffRampNextSeqNums: map[cciptypes.ChainSelector]cciptypes.SeqNum{ + 1: 18, // off ramp next is 18, on ramp max is 20 so new msgs are: [18, 19, 20] + }, + }, + rangeLimitsPerSourceChain: map[cciptypes.ChainSelector]uint64{}, + expectedOutcome: Outcome{ + OutcomeType: ReportIntervalsSelected, + RangesSelectedForReport: []plugintypes.ChainRange{ + {ChainSel: 1, SeqNumRange: cciptypes.NewSeqNumRange(18, 20)}, + }, + OffRampNextSeqNums: []plugintypes.SeqNumChain{ + {ChainSel: 1, SeqNum: 18}, + }, + }, + }, + { + name: "simple scenario with one chain", + consensusObservation: ConsensusObservation{ + OnRampMaxSeqNums: map[cciptypes.ChainSelector]cciptypes.SeqNum{ + 1: 20, + 2: 1000, + 3: 10000, + }, + OffRampNextSeqNums: map[cciptypes.ChainSelector]cciptypes.SeqNum{ + 1: 18, // off ramp next is 18, on ramp max is 20 so new msgs are: [18, 19, 20] + 2: 995, // off ramp next is 995, on ramp max is 1000 so new msgs are: [995, 996, 997, 998, 999, 1000] + 3: 500, // off ramp next is 500, we have new messages up to 10000 (default limit applied) + }, + }, + rangeLimitsPerSourceChain: map[cciptypes.ChainSelector]uint64{ + 2: 5, // limit to 5 messages, [1000] should be excluded + }, + expectedOutcome: Outcome{ + OutcomeType: ReportIntervalsSelected, + RangesSelectedForReport: []plugintypes.ChainRange{ + {ChainSel: 1, SeqNumRange: cciptypes.NewSeqNumRange(18, 20)}, + {ChainSel: 2, SeqNumRange: cciptypes.NewSeqNumRange(995, 999)}, + {ChainSel: 3, SeqNumRange: cciptypes.NewSeqNumRange(500, 755)}, + }, + OffRampNextSeqNums: []plugintypes.SeqNumChain{ + {ChainSel: 1, SeqNum: 18}, + {ChainSel: 2, SeqNum: 995}, + {ChainSel: 3, SeqNum: 500}, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + outc := reportRangesOutcome(Query{}, lggr, tc.consensusObservation, tc.rangeLimitsPerSourceChain) + require.Equal(t, tc.expectedOutcome, outc) + }) + } +} diff --git a/commit/merkleroot/processor.go b/commit/merkleroot/processor.go index 486b2963..c8fc16fb 100644 --- a/commit/merkleroot/processor.go +++ b/commit/merkleroot/processor.go @@ -15,6 +15,10 @@ import ( "github.com/smartcontractkit/chainlink-ccip/shared" ) +// DefaultSeqNumsBatchLimit is the default number of max new messages to scan, we use this value when +// the config is not set for a specific chain. +const DefaultSeqNumsBatchLimit = 256 + // Processor is the processor responsible for // reading next messages and building merkle roots for them, // It's setup to use RMN to query which messages to include in the merkle root and ensures diff --git a/commit/plugin_e2e_test.go b/commit/plugin_e2e_test.go index dbd85ebf..1e6d3055 100644 --- a/commit/plugin_e2e_test.go +++ b/commit/plugin_e2e_test.go @@ -331,6 +331,11 @@ func setupNode( } ccipReader.EXPECT().NextSeqNum(ctx, sourceChains).Return(offRampNextSeqNums, nil).Maybe() + for _, ch := range sourceChains { + ccipReader.EXPECT().GetExpectedNextSequenceNumber( + ctx, ch, destChain).Return(offRampNextSeqNum[ch]+1, nil).Maybe() + } + p := NewPlugin( ctx, nodeID, diff --git a/internal/libs/cciptypeutil/seqnumrange.go b/internal/libs/cciptypeutil/seqnumrange.go new file mode 100644 index 00000000..8c21dcec --- /dev/null +++ b/internal/libs/cciptypeutil/seqnumrange.go @@ -0,0 +1,21 @@ +package cciptypeutil + +import "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + +// SeqNumRangeLimit limits the range to n elements by truncating the end if necessary. +func SeqNumRangeLimit(rng ccipocr3.SeqNumRange, n uint64) ccipocr3.SeqNumRange { + numElems := rng.End() - rng.Start() + 1 + if numElems <= 0 { + return rng + } + + if uint64(numElems) > n { + newEnd := rng.Start() + ccipocr3.SeqNum(n) - 1 + if newEnd > rng.End() { // overflow - do nothing + return rng + } + rng.SetEnd(newEnd) + } + + return rng +} diff --git a/internal/libs/cciptypeutil/seqnumrange_test.go b/internal/libs/cciptypeutil/seqnumrange_test.go new file mode 100644 index 00000000..cfa011b7 --- /dev/null +++ b/internal/libs/cciptypeutil/seqnumrange_test.go @@ -0,0 +1,62 @@ +package cciptypeutil + +import ( + "testing" + + "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" +) + +func TestSeqNumRangeLimit(t *testing.T) { + testCases := []struct { + name string + rng ccipocr3.SeqNumRange + n uint64 + want ccipocr3.SeqNumRange + }{ + { + name: "no truncation", + rng: ccipocr3.NewSeqNumRange(0, 10), + n: 11, + want: ccipocr3.NewSeqNumRange(0, 10), + }, + { + name: "no truncation 2", + rng: ccipocr3.NewSeqNumRange(100, 110), + n: 11, + want: ccipocr3.NewSeqNumRange(100, 110), + }, + { + name: "truncation", + rng: ccipocr3.NewSeqNumRange(0, 10), + n: 10, + want: ccipocr3.NewSeqNumRange(0, 9), + }, + { + name: "truncation 2", + rng: ccipocr3.NewSeqNumRange(100, 110), + n: 10, + want: ccipocr3.NewSeqNumRange(100, 109), + }, + { + name: "empty", + rng: ccipocr3.NewSeqNumRange(0, 0), + n: 0, + want: ccipocr3.NewSeqNumRange(0, 0), + }, + { + name: "wrong range", + rng: ccipocr3.NewSeqNumRange(20, 15), + n: 3, + want: ccipocr3.NewSeqNumRange(20, 15), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := SeqNumRangeLimit(tc.rng, tc.n) + if got != tc.want { + t.Errorf("SeqNumRangeLimit(%v, %v) = %v; want %v", tc.rng, tc.n, got, tc.want) + } + }) + } +} diff --git a/mocks/commit/merkleroot/observer.go b/mocks/commit/merkleroot/observer.go index 86fa4fe1..b76d6009 100644 --- a/mocks/commit/merkleroot/observer.go +++ b/mocks/commit/merkleroot/observer.go @@ -72,6 +72,55 @@ func (_c *MockObserver_ObserveFChain_Call) RunAndReturn(run func() map[ccipocr3. return _c } +// ObserveLatestOnRampSeqNums provides a mock function with given fields: ctx, destChain +func (_m *MockObserver) ObserveLatestOnRampSeqNums(ctx context.Context, destChain ccipocr3.ChainSelector) []plugintypes.SeqNumChain { + ret := _m.Called(ctx, destChain) + + if len(ret) == 0 { + panic("no return value specified for ObserveLatestOnRampSeqNums") + } + + var r0 []plugintypes.SeqNumChain + if rf, ok := ret.Get(0).(func(context.Context, ccipocr3.ChainSelector) []plugintypes.SeqNumChain); ok { + r0 = rf(ctx, destChain) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]plugintypes.SeqNumChain) + } + } + + return r0 +} + +// MockObserver_ObserveLatestOnRampSeqNums_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ObserveLatestOnRampSeqNums' +type MockObserver_ObserveLatestOnRampSeqNums_Call struct { + *mock.Call +} + +// ObserveLatestOnRampSeqNums is a helper method to define mock.On call +// - ctx context.Context +// - destChain ccipocr3.ChainSelector +func (_e *MockObserver_Expecter) ObserveLatestOnRampSeqNums(ctx interface{}, destChain interface{}) *MockObserver_ObserveLatestOnRampSeqNums_Call { + return &MockObserver_ObserveLatestOnRampSeqNums_Call{Call: _e.mock.On("ObserveLatestOnRampSeqNums", ctx, destChain)} +} + +func (_c *MockObserver_ObserveLatestOnRampSeqNums_Call) Run(run func(ctx context.Context, destChain ccipocr3.ChainSelector)) *MockObserver_ObserveLatestOnRampSeqNums_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(ccipocr3.ChainSelector)) + }) + return _c +} + +func (_c *MockObserver_ObserveLatestOnRampSeqNums_Call) Return(_a0 []plugintypes.SeqNumChain) *MockObserver_ObserveLatestOnRampSeqNums_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockObserver_ObserveLatestOnRampSeqNums_Call) RunAndReturn(run func(context.Context, ccipocr3.ChainSelector) []plugintypes.SeqNumChain) *MockObserver_ObserveLatestOnRampSeqNums_Call { + _c.Call.Return(run) + return _c +} + // ObserveMerkleRoots provides a mock function with given fields: ctx, ranges func (_m *MockObserver) ObserveMerkleRoots(ctx context.Context, ranges []plugintypes.ChainRange) []ccipocr3.MerkleRootChain { ret := _m.Called(ctx, ranges) diff --git a/pluginconfig/commit.go b/pluginconfig/commit.go index d51eea5b..9092e08f 100644 --- a/pluginconfig/commit.go +++ b/pluginconfig/commit.go @@ -9,9 +9,10 @@ import ( "strings" "time" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ) type CommitPluginConfig struct { @@ -39,6 +40,11 @@ type CommitPluginConfig struct { // RMNSignaturesTimeout is the timeout for RMN signature verification. // Typically set to `MaxQueryDuration - e`, where e some small duration. RMNSignaturesTimeout time.Duration `json:"rmnSignaturesTimeout"` + + // BatchLimits is the maximum number of messages to include in a single report for a target chain. + // If for example in the next round we have 1000 pending messages and a batch limit of 256, only 256 seq nums + // will be in the report. If a value is not set we fallback to merkleroot.DefaultSeqNumsBatchLimit. + BatchLimits map[cciptypes.ChainSelector]uint64 `json:"batchLimits"` } func (c CommitPluginConfig) Validate() error { From 3dd255cbc8349ca7c52d101570e9c70d97d0cc00 Mon Sep 17 00:00:00 2001 From: dimkouv Date: Wed, 18 Sep 2024 15:20:21 +0300 Subject: [PATCH 2/6] query only node supported source chains --- commit/merkleroot/observation.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/commit/merkleroot/observation.go b/commit/merkleroot/observation.go index a58c59f4..04770f68 100644 --- a/commit/merkleroot/observation.go +++ b/commit/merkleroot/observation.go @@ -8,6 +8,7 @@ import ( "sync" "time" + mapset "github.com/deckarep/golang-set/v2" chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" @@ -207,12 +208,22 @@ func (o ObserverImpl) ObserveOffRampNextSeqNums(ctx context.Context) []plugintyp // ObserveLatestOnRampSeqNums observes the latest onRamp sequence numbers for each configured source chain. func (o ObserverImpl) ObserveLatestOnRampSeqNums( ctx context.Context, destChain cciptypes.ChainSelector) []plugintypes.SeqNumChain { - sourceChains, err := o.chainSupport.KnownSourceChainsSlice() + + allSourceChains, err := o.chainSupport.KnownSourceChainsSlice() + if err != nil { + o.lggr.Warnw("call to KnownSourceChainsSlice failed", "err", err) + return nil + } + + supportedChains, err := o.chainSupport.SupportedChains(o.nodeID) if err != nil { o.lggr.Warnw("call to KnownSourceChainsSlice failed", "err", err) return nil } + sourceChains := mapset.NewSet(allSourceChains...).Intersect(supportedChains).ToSlice() + sort.Slice(sourceChains, func(i, j int) bool { return sourceChains[i] < sourceChains[j] }) + latestOnRampSeqNums := make([]plugintypes.SeqNumChain, len(sourceChains)) eg := &errgroup.Group{} From 44013ba87c2983d851dedc7a735e707cf7456669 Mon Sep 17 00:00:00 2001 From: dimkouv Date: Thu, 19 Sep 2024 11:05:32 +0300 Subject: [PATCH 3/6] code reviews: makramkd, winder --- commit/merkleroot/outcome.go | 15 ++--- commit/merkleroot/outcome_test.go | 18 +++--- commit/merkleroot/processor.go | 4 -- commit/plugin.go | 5 ++ go.mod | 12 ++-- go.sum | 24 +++---- internal/libs/cciptypeutil/seqnumrange.go | 21 ------- .../libs/cciptypeutil/seqnumrange_test.go | 62 ------------------- pluginconfig/commit.go | 13 ++-- 9 files changed, 44 insertions(+), 130 deletions(-) delete mode 100644 internal/libs/cciptypeutil/seqnumrange.go delete mode 100644 internal/libs/cciptypeutil/seqnumrange_test.go diff --git a/commit/merkleroot/outcome.go b/commit/merkleroot/outcome.go index 96ce94cd..2a9acb9e 100644 --- a/commit/merkleroot/outcome.go +++ b/commit/merkleroot/outcome.go @@ -10,8 +10,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-ccip/internal/libs/cciptypeutil" - "github.com/smartcontractkit/chainlink-ccip/commit/merkleroot/rmn" "github.com/smartcontractkit/chainlink-ccip/plugintypes" "github.com/smartcontractkit/chainlink-ccip/shared" @@ -48,7 +46,7 @@ func (w *Processor) getOutcome( switch nextState { case SelectingRangesForReport: - return reportRangesOutcome(q, w.lggr, consensusObservation, w.cfg.BatchLimits), nextState + return reportRangesOutcome(q, w.lggr, consensusObservation, w.cfg.MaxMerkleTreeSize), nextState case BuildingReport: if q.RetryRMNSignatures { // We want to retry getting the RMN signatures on the exact same outcome we had before. @@ -70,7 +68,7 @@ func reportRangesOutcome( _ Query, lggr logger.Logger, consensusObservation ConsensusObservation, - rangeLimitsPerSourceChain map[cciptypes.ChainSelector]uint64, + maxMerkleTreeSize uint64, ) Outcome { rangesToReport := make([]plugintypes.ChainRange, 0) @@ -85,20 +83,15 @@ func reportRangesOutcome( } if offRampNextSeqNum <= onRampMaxSeqNum { - rngLimit, ok := rangeLimitsPerSourceChain[chainSel] - if !ok { - rngLimit = DefaultSeqNumsBatchLimit - } - rng := cciptypes.NewSeqNumRange(offRampNextSeqNum, onRampMaxSeqNum) chainRange := plugintypes.ChainRange{ ChainSel: chainSel, - SeqNumRange: cciptypeutil.SeqNumRangeLimit(rng, rngLimit), + SeqNumRange: rng.Limit(maxMerkleTreeSize), } rangesToReport = append(rangesToReport, chainRange) - if wasTruncated := rng.End() != chainRange.SeqNumRange.End(); wasTruncated { + if rng.End() != chainRange.SeqNumRange.End() { // Check if the range was truncated. lggr.Infof("Range for chain %d: %s (before truncate: %v)", chainSel, chainRange.SeqNumRange, rng) } else { lggr.Infof("Range for chain %d: %s", chainSel, chainRange.SeqNumRange) diff --git a/commit/merkleroot/outcome_test.go b/commit/merkleroot/outcome_test.go index 35915d79..fdbb1ed5 100644 --- a/commit/merkleroot/outcome_test.go +++ b/commit/merkleroot/outcome_test.go @@ -44,10 +44,10 @@ func Test_reportRangesOutcome(t *testing.T) { lggr := logger.Test(t) testCases := []struct { - name string - consensusObservation ConsensusObservation - rangeLimitsPerSourceChain map[cciptypes.ChainSelector]uint64 - expectedOutcome Outcome + name string + consensusObservation ConsensusObservation + merkleTreeSizeLimit uint64 + expectedOutcome Outcome }{ { name: "base empty outcome", @@ -67,7 +67,7 @@ func Test_reportRangesOutcome(t *testing.T) { 1: 18, // off ramp next is 18, on ramp max is 20 so new msgs are: [18, 19, 20] }, }, - rangeLimitsPerSourceChain: map[cciptypes.ChainSelector]uint64{}, + merkleTreeSizeLimit: 256, // default limit should be used expectedOutcome: Outcome{ OutcomeType: ReportIntervalsSelected, RangesSelectedForReport: []plugintypes.ChainRange{ @@ -92,15 +92,13 @@ func Test_reportRangesOutcome(t *testing.T) { 3: 500, // off ramp next is 500, we have new messages up to 10000 (default limit applied) }, }, - rangeLimitsPerSourceChain: map[cciptypes.ChainSelector]uint64{ - 2: 5, // limit to 5 messages, [1000] should be excluded - }, + merkleTreeSizeLimit: 5, expectedOutcome: Outcome{ OutcomeType: ReportIntervalsSelected, RangesSelectedForReport: []plugintypes.ChainRange{ {ChainSel: 1, SeqNumRange: cciptypes.NewSeqNumRange(18, 20)}, {ChainSel: 2, SeqNumRange: cciptypes.NewSeqNumRange(995, 999)}, - {ChainSel: 3, SeqNumRange: cciptypes.NewSeqNumRange(500, 755)}, + {ChainSel: 3, SeqNumRange: cciptypes.NewSeqNumRange(500, 504)}, }, OffRampNextSeqNums: []plugintypes.SeqNumChain{ {ChainSel: 1, SeqNum: 18}, @@ -113,7 +111,7 @@ func Test_reportRangesOutcome(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - outc := reportRangesOutcome(Query{}, lggr, tc.consensusObservation, tc.rangeLimitsPerSourceChain) + outc := reportRangesOutcome(Query{}, lggr, tc.consensusObservation, tc.merkleTreeSizeLimit) require.Equal(t, tc.expectedOutcome, outc) }) } diff --git a/commit/merkleroot/processor.go b/commit/merkleroot/processor.go index c8fc16fb..486b2963 100644 --- a/commit/merkleroot/processor.go +++ b/commit/merkleroot/processor.go @@ -15,10 +15,6 @@ import ( "github.com/smartcontractkit/chainlink-ccip/shared" ) -// DefaultSeqNumsBatchLimit is the default number of max new messages to scan, we use this value when -// the config is not set for a specific chain. -const DefaultSeqNumsBatchLimit = 256 - // Processor is the processor responsible for // reading next messages and building merkle roots for them, // It's setup to use RMN to query which messages to include in the merkle root and ensures diff --git a/commit/plugin.go b/commit/plugin.go index 10cb8bcc..e1734723 100644 --- a/commit/plugin.go +++ b/commit/plugin.go @@ -78,6 +78,11 @@ func NewPlugin( cfg.DestChain, ) + if cfg.MaxMerkleTreeSize == 0 { + lggr.Warnw("MaxMerkleTreeSize not set, using default value", "default", pluginconfig.EvmDefaultMaxMerkleTreeSize) + cfg.MaxMerkleTreeSize = pluginconfig.EvmDefaultMaxMerkleTreeSize + } + merkleRootProcessor := merkleroot.NewProcessor( nodeID, lggr, diff --git a/go.mod b/go.mod index 85de1de7..59f01482 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.22.5 require ( github.com/deckarep/golang-set/v2 v2.6.0 github.com/smartcontractkit/chain-selectors v1.0.23 - github.com/smartcontractkit/chainlink-common v0.2.2-0.20240913100429-aa383c8c4694 + github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919074710-42d4f26a8521 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.26.0 - golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa + golang.org/x/crypto v0.27.0 + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/sync v0.8.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 @@ -46,9 +46,9 @@ require ( go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.28.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 775ce8ab..ccd248d4 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ 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.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240913100429-aa383c8c4694 h1:yhGECtHtzGIIFhEBcoCiMsF4NrZhRZ7XLNt5nI3glFg= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240913100429-aa383c8c4694/go.mod h1:sjiiPwd4KsYOCf68MwL86EKphdXeT66EY7j53WH5DCc= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919074710-42d4f26a8521 h1:CL3053j5Y6zTwXnW3VkHIOm5WvNUEiMIiJflYlsnzyI= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919074710-42d4f26a8521/go.mod h1:zm+l8gN4LQS1+YvwQDhRz/njirVeWGNiDJKIhCGwaoQ= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -87,18 +87,18 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= -golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= diff --git a/internal/libs/cciptypeutil/seqnumrange.go b/internal/libs/cciptypeutil/seqnumrange.go deleted file mode 100644 index 8c21dcec..00000000 --- a/internal/libs/cciptypeutil/seqnumrange.go +++ /dev/null @@ -1,21 +0,0 @@ -package cciptypeutil - -import "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - -// SeqNumRangeLimit limits the range to n elements by truncating the end if necessary. -func SeqNumRangeLimit(rng ccipocr3.SeqNumRange, n uint64) ccipocr3.SeqNumRange { - numElems := rng.End() - rng.Start() + 1 - if numElems <= 0 { - return rng - } - - if uint64(numElems) > n { - newEnd := rng.Start() + ccipocr3.SeqNum(n) - 1 - if newEnd > rng.End() { // overflow - do nothing - return rng - } - rng.SetEnd(newEnd) - } - - return rng -} diff --git a/internal/libs/cciptypeutil/seqnumrange_test.go b/internal/libs/cciptypeutil/seqnumrange_test.go deleted file mode 100644 index cfa011b7..00000000 --- a/internal/libs/cciptypeutil/seqnumrange_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package cciptypeutil - -import ( - "testing" - - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" -) - -func TestSeqNumRangeLimit(t *testing.T) { - testCases := []struct { - name string - rng ccipocr3.SeqNumRange - n uint64 - want ccipocr3.SeqNumRange - }{ - { - name: "no truncation", - rng: ccipocr3.NewSeqNumRange(0, 10), - n: 11, - want: ccipocr3.NewSeqNumRange(0, 10), - }, - { - name: "no truncation 2", - rng: ccipocr3.NewSeqNumRange(100, 110), - n: 11, - want: ccipocr3.NewSeqNumRange(100, 110), - }, - { - name: "truncation", - rng: ccipocr3.NewSeqNumRange(0, 10), - n: 10, - want: ccipocr3.NewSeqNumRange(0, 9), - }, - { - name: "truncation 2", - rng: ccipocr3.NewSeqNumRange(100, 110), - n: 10, - want: ccipocr3.NewSeqNumRange(100, 109), - }, - { - name: "empty", - rng: ccipocr3.NewSeqNumRange(0, 0), - n: 0, - want: ccipocr3.NewSeqNumRange(0, 0), - }, - { - name: "wrong range", - rng: ccipocr3.NewSeqNumRange(20, 15), - n: 3, - want: ccipocr3.NewSeqNumRange(20, 15), - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - got := SeqNumRangeLimit(tc.rng, tc.n) - if got != tc.want { - t.Errorf("SeqNumRangeLimit(%v, %v) = %v; want %v", tc.rng, tc.n, got, tc.want) - } - }) - } -} diff --git a/pluginconfig/commit.go b/pluginconfig/commit.go index 9092e08f..1f5b6a3d 100644 --- a/pluginconfig/commit.go +++ b/pluginconfig/commit.go @@ -9,12 +9,17 @@ import ( "strings" "time" + "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" ) +// EvmDefaultMaxMerkleTreeSize is the default number of max new messages to put in a merkle tree. +// We use this default value when the config is not set for a specific chain. +const EvmDefaultMaxMerkleTreeSize = merklemulti.MaxNumberTreeLeaves + type CommitPluginConfig struct { // DestChain is the ccip destination chain configured for the commit plugin DON. DestChain cciptypes.ChainSelector `json:"destChain"` @@ -41,10 +46,10 @@ type CommitPluginConfig struct { // Typically set to `MaxQueryDuration - e`, where e some small duration. RMNSignaturesTimeout time.Duration `json:"rmnSignaturesTimeout"` - // BatchLimits is the maximum number of messages to include in a single report for a target chain. - // If for example in the next round we have 1000 pending messages and a batch limit of 256, only 256 seq nums - // will be in the report. If a value is not set we fallback to merkleroot.DefaultSeqNumsBatchLimit. - BatchLimits map[cciptypes.ChainSelector]uint64 `json:"batchLimits"` + // MaxMerkleTreeSize is the maximum size of a merkle tree to create prior to calculating the merkle root. + // If for example in the next round we have 1000 pending messages and a max tree size of 256, only 256 seq nums + // will be in the report. If a value is not set we fallback to EvmDefaultMaxMerkleTreeSize. + MaxMerkleTreeSize uint64 `json:"maxTreeSize"` } func (c CommitPluginConfig) Validate() error { From 525193a1830efb138fb11446fdc152bfb6519af0 Mon Sep 17 00:00:00 2001 From: dimkouv Date: Thu, 19 Sep 2024 11:08:37 +0300 Subject: [PATCH 4/6] cfg override earlier --- commit/plugin.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/commit/plugin.go b/commit/plugin.go index d3d94f3c..2e46288d 100644 --- a/commit/plugin.go +++ b/commit/plugin.go @@ -59,6 +59,11 @@ func NewPlugin( reportingCfg ocr3types.ReportingPluginConfig, rmnConfig rmn.Config, ) *Plugin { + if cfg.MaxMerkleTreeSize == 0 { + lggr.Warnw("MaxMerkleTreeSize not set, using default value", "default", pluginconfig.EvmDefaultMaxMerkleTreeSize) + cfg.MaxMerkleTreeSize = pluginconfig.EvmDefaultMaxMerkleTreeSize + } + readerSyncer := plugincommon.NewBackgroundReaderSyncer( lggr, ccipReader, @@ -77,11 +82,6 @@ func NewPlugin( cfg.DestChain, ) - if cfg.MaxMerkleTreeSize == 0 { - lggr.Warnw("MaxMerkleTreeSize not set, using default value", "default", pluginconfig.EvmDefaultMaxMerkleTreeSize) - cfg.MaxMerkleTreeSize = pluginconfig.EvmDefaultMaxMerkleTreeSize - } - merkleRootProcessor := merkleroot.NewProcessor( nodeID, lggr, From 6df9088aec958b6e58704117e3e87858ff87c825 Mon Sep 17 00:00:00 2001 From: dimkouv Date: Thu, 19 Sep 2024 11:18:35 +0300 Subject: [PATCH 5/6] fix import --- commit/merkleroot/outcome_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commit/merkleroot/outcome_test.go b/commit/merkleroot/outcome_test.go index fdbb1ed5..6241dc63 100644 --- a/commit/merkleroot/outcome_test.go +++ b/commit/merkleroot/outcome_test.go @@ -8,7 +8,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-ccip/plugintypes" + "github.com/smartcontractkit/chainlink-ccip/internal/plugintypes" ) func Test_buildReport(t *testing.T) { From 4947a725420b21b5f9d3d255a81144468ebed10b Mon Sep 17 00:00:00 2001 From: dimkouv Date: Thu, 19 Sep 2024 12:25:50 +0300 Subject: [PATCH 6/6] upgrade cl-common --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 59f01482..084c6b60 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22.5 require ( github.com/deckarep/golang-set/v2 v2.6.0 github.com/smartcontractkit/chain-selectors v1.0.23 - github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919074710-42d4f26a8521 + github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919092417-53e784c2e420 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 diff --git a/go.sum b/go.sum index ccd248d4..992bddc6 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ 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.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919074710-42d4f26a8521 h1:CL3053j5Y6zTwXnW3VkHIOm5WvNUEiMIiJflYlsnzyI= -github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919074710-42d4f26a8521/go.mod h1:zm+l8gN4LQS1+YvwQDhRz/njirVeWGNiDJKIhCGwaoQ= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919092417-53e784c2e420 h1:+xNnYYgkxzKUIkLCOfzfAKUxeLLtuxlalDI70kNJ8No= +github.com/smartcontractkit/chainlink-common v0.2.3-0.20240919092417-53e784c2e420/go.mod h1:zm+l8gN4LQS1+YvwQDhRz/njirVeWGNiDJKIhCGwaoQ= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=