From 6d50a495ca068bab81367d8434eff58d4ef427df Mon Sep 17 00:00:00 2001 From: nogo <0xnogo@gmail.com> Date: Thu, 21 Nov 2024 18:21:00 +0400 Subject: [PATCH 1/8] benchmarkCommitReports --- .../ccipreader/ccipreader_test.go | 318 ++++++++++++++---- 1 file changed, 259 insertions(+), 59 deletions(-) diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go index 192bf12f7f5..84b95900c24 100644 --- a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go @@ -3,6 +3,7 @@ package ccipreader import ( "context" "encoding/hex" + "fmt" "math/big" "sort" "testing" @@ -18,7 +19,16 @@ import ( "go.uber.org/zap/zapcore" "golang.org/x/exp/maps" + "github.com/jmoiron/sqlx" + readermocks "github.com/smartcontractkit/chainlink-ccip/mocks/pkg/contractreader" + + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" + + "github.com/smartcontractkit/chainlink-common/pkg/types/query" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" @@ -26,6 +36,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -45,6 +57,10 @@ import ( "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" "github.com/smartcontractkit/chainlink-ccip/plugintypes" + + evmchaintypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" ) const ( @@ -62,6 +78,11 @@ var ( wethAddress = utils.RandomAddress() ) +var ( + onrampABI = evmchaintypes.MustGetABI(onramp.OnRampABI) + offrampABI = evmchaintypes.MustGetABI(offramp.OffRampABI) +) + func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { ctx := testutils.Context(t) @@ -95,6 +116,7 @@ func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { true, sb, auth, + false, ) tokenA := common.HexToAddress("123") @@ -210,7 +232,7 @@ func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { } sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil, nil, true, sb, auth) + s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil, nil, true, sb, auth, false) _, err := s.contract.EmitExecutionStateChanged( s.auth, @@ -296,7 +318,7 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { } sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil, nil, true, sb, auth) + s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil, nil, true, sb, auth, false) _, err := s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ Header: ccip_reader_tester.InternalRampMessageHeader{ @@ -398,7 +420,7 @@ func TestCCIPReader_NextSeqNum(t *testing.T) { } sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainD, chainD, onChainSeqNums, cfg, nil, nil, true, sb, auth) + s := testSetup(ctx, t, chainD, chainD, onChainSeqNums, cfg, nil, nil, true, sb, auth, false) seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) assert.NoError(t, err) @@ -426,7 +448,7 @@ func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { } sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil, nil, true, sb, auth) + s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil, nil, true, sb, auth, false) _, err := s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 10) require.NoError(t, err) @@ -477,7 +499,7 @@ func TestCCIPReader_Nonces(t *testing.T) { } sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil, nil, true, sb, auth) + s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil, nil, true, sb, auth, false) // Add some nonces. for chain, addrs := range nonces { @@ -522,6 +544,7 @@ func Test_GetChainFeePriceUpdates(t *testing.T) { false, sb, auth, + false, ) updates := s.reader.GetChainFeePriceUpdate(ctx, []cciptypes.ChainSelector{chainS1, chainS2}) @@ -548,6 +571,7 @@ func Test_LinkPriceUSD(t *testing.T) { false, sb, auth, + false, ) linkPriceUSD, err := s.reader.LinkPriceUSD(ctx) @@ -609,6 +633,7 @@ func Test_GetMedianDataAvailabilityGasConfig(t *testing.T) { false, sb, auth, + false, ) daConfig, err := s.reader.GetMedianDataAvailabilityGasConfig(ctx) @@ -645,6 +670,7 @@ func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { false, sb, auth, + false, ) prices := s.reader.GetWrappedNativeTokenPriceUSD(ctx, []cciptypes.ChainSelector{chainD, chainS1}) @@ -757,7 +783,7 @@ func defaultFeeQuoterDestChainConfig() fee_quoter.FeeQuoterDestChainConfig { } } -func setupSimulatedBackendAndAuth(t *testing.T) (*simulated.Backend, *bind.TransactOpts) { +func setupSimulatedBackendAndAuth(t testing.TB) (*simulated.Backend, *bind.TransactOpts) { privateKey, err := crypto.GenerateKey() require.NoError(t, err) @@ -774,9 +800,161 @@ func setupSimulatedBackendAndAuth(t *testing.T) (*simulated.Backend, *bind.Trans return simulatedBackend, auth } +func Benchmark_CCIPReader_CommitReportsGTETimestampParameterized(b *testing.B) { + tests := []struct { + logsInsertedFirst int + logsInsertedToMatchQuery int + }{ + {0, 0}, + {1, 10}, + {10, 100}, + {100, 10_000}, + } + + for _, tt := range tests { + b.Run(fmt.Sprintf("FirstLogs_%d_MatchLogs_%d", tt.logsInsertedFirst, tt.logsInsertedToMatchQuery), func(b *testing.B) { + benchmarkCommitReports(b, tt.logsInsertedFirst, tt.logsInsertedToMatchQuery) + }) + } +} + +func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedToMatchQuery int) { + ctx := testutils.Context(b) + finalityDepth := 5 + sb, auth := setupSimulatedBackendAndAuth(b) + + // Initialize test setup + ts := testSetup( + ctx, + b, + chainS1, + chainS1, + nil, + evmconfig.DestReaderConfig, + nil, + nil, + false, + sb, + auth, + true) + + err := ts.extendedCR.Bind(ctx, []types.BoundContract{ + { + Address: ts.contractAddr.String(), + Name: consts.ContractNameOffRamp, + }, + }) + require.NoError(b, err) + + // Insert logs in two phases based on parameters + if logsInsertedFirst > 0 { + populateDatabaseForCommitReportAccepted(b, ts, chainS1, logsInsertedFirst, finalityDepth, 0) + } + + queryTimestamp := time.Now() + + if logsInsertedToMatchQuery > 0 { + populateDatabaseForCommitReportAccepted(b, ts, chainS1, logsInsertedToMatchQuery, finalityDepth, logsInsertedFirst) + } + + // Reset timer to measure only the query time + b.ResetTimer() + + // Execute the query + _, err = ts.extendedCR.ExtendedQueryKey( + ctx, + consts.ContractNameOffRamp, + query.KeyFilter{ + Key: consts.EventNameCommitReportAccepted, + Expressions: []query.Expression{ + query.Timestamp(uint64(queryTimestamp.Unix()), primitives.Gte), + query.Confidence(primitives.Finalized), + }, + }, + query.LimitAndSort{ + SortBy: []query.SortBy{query.NewSortByTimestamp(query.Asc)}, + }, + &offramp.OffRampCommitReportAccepted{}, + ) + require.NoError(b, err) +} + +func populateDatabaseForCommitReportAccepted( + b *testing.B, + testEnv *testSetupData, + sourceChain cciptypes.ChainSelector, + numOfReports int, + finalityDepth int, + offset int, // New offset parameter +) { + ctx := testutils.Context(b) + + var logs []logpoller.Log + commitReportEvent, exists := offrampABI.Events[consts.EventNameCommitReportAccepted] + require.True(b, exists, "Event CommitReportAccepted not found in ABI") + + commitReportEventSig := commitReportEvent.ID + commitReportAddress := testEnv.contractAddr + + for i := 0; i < numOfReports; i++ { + // Calculate unique BlockNumber and LogIndex + blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers + logIndex := int64(offset + i + 1) // Offset ensures unique log indices + + // Simulate merkleRoots + merkleRoots := []offramp.InternalMerkleRoot{ + { + SourceChainSelector: uint64(sourceChain), + OnRampAddress: []byte{0x12, 0x34}, + MinSeqNr: uint64(i * 100), + MaxSeqNr: uint64(i*100 + 99), + MerkleRoot: ccipocr3.Bytes32(utils.NewHash().Bytes()), + }, + } + + // Simulate priceUpdates + priceUpdates := offramp.InternalPriceUpdates{ + TokenPriceUpdates: []offramp.InternalTokenPriceUpdate{ + {SourceToken: common.Address{0xAB, 0xCD}, UsdPerToken: big.NewInt(8)}, + }, + GasPriceUpdates: []offramp.InternalGasPriceUpdate{ + {DestChainSelector: uint64(1), UsdPerUnitGas: big.NewInt(10)}, + }, + } + + // Combine encoded data + encodedData, err := commitReportEvent.Inputs.Pack(merkleRoots, priceUpdates) + require.NoError(b, err) + + // Topics (first one is the event signature) + topics := [][]byte{ + commitReportEventSig[:], + } + + // Create log entry + logs = append(logs, logpoller.Log{ + EvmChainId: ubig.New(big.NewInt(int64(sourceChain))), + LogIndex: logIndex, + BlockHash: utils.NewHash(), + BlockNumber: blockNumber, + BlockTimestamp: time.Now(), + EventSig: commitReportEventSig, + Topics: topics, + Address: commitReportAddress, + TxHash: utils.NewHash(), + Data: encodedData, + CreatedAt: time.Now(), + }) + } + + // Insert logs into the database + require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfReports+finalityDepth), time.Now(), int64(offset+numOfReports+finalityDepth))) +} + func testSetup( ctx context.Context, - t *testing.T, + t testing.TB, readerChain, destChain cciptypes.ChainSelector, onChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum, @@ -786,19 +964,33 @@ func testSetup( bindTester bool, simulatedBackend *simulated.Backend, auth *bind.TransactOpts, + useHeavyDB bool, ) *testSetupData { + const chainID = 1337 + + // Initialize logger + lggr := logger.TestLogger(t) + lggr.SetLogLevel(zapcore.ErrorLevel) + + // Parameterize database selection + var db *sqlx.DB + if useHeavyDB { + _, db = heavyweight.FullTestDBV2(t, nil) // Heavyweight database for benchmarks + } else { + db = pgtest.NewSqlxDB(t) // Simple in-memory DB for tests + } + t.Cleanup(func() { assert.NoError(t, db.Close()) }) + + // Deploy the contract address, _, _, err := ccip_reader_tester.DeployCCIPReaderTester(auth, simulatedBackend.Client()) assert.NoError(t, err) simulatedBackend.Commit() - // Setup contract client + // Create contract instance contract, err := ccip_reader_tester.NewCCIPReaderTester(address, simulatedBackend.Client()) assert.NoError(t, err) - lggr := logger.TestLogger(t) - lggr.SetLogLevel(zapcore.ErrorLevel) - db := pgtest.NewSqlxDB(t) - t.Cleanup(func() { assert.NoError(t, db.Close()) }) + // Setup log poller lpOpts := logpoller.Opts{ PollPeriod: time.Millisecond, FinalityDepth: 0, @@ -808,14 +1000,11 @@ func testSetup( } cl := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(readerChain))) headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(readerChain)), db, lggr), - cl, - lggr, - headTracker, - lpOpts, - ) + orm := logpoller.NewORM(big.NewInt(0).SetUint64(uint64(readerChain)), db, lggr) + lp := logpoller.NewLogPoller(orm, cl, lggr, headTracker, lpOpts) servicetest.Run(t, lp) + // Set source chain configurations for sourceChain, seqNum := range onChainSeqNums { _, err1 := contract.SetSourceChainConfig(auth, uint64(sourceChain), ccip_reader_tester.OffRampSourceChainConfig{ IsEnabled: true, @@ -824,67 +1013,32 @@ func testSetup( }) assert.NoError(t, err1) simulatedBackend.Commit() - scc, err1 := contract.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, uint64(sourceChain)) - assert.NoError(t, err1) - assert.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) } - contractNames := maps.Keys(cfg.Contracts) - + // Initialize chain reader service cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, cfg) require.NoError(t, err) extendedCr := contractreader.NewExtendedContractReader(cr) - if bindTester { err = extendedCr.Bind(ctx, []types.BoundContract{ { Address: address.String(), - Name: contractNames[0], + Name: maps.Keys(cfg.Contracts)[0], }, }) require.NoError(t, err) } - var otherCrs = make(map[cciptypes.ChainSelector]contractreader.Extended) - for chain, bindings := range toBindContracts { - cl2 := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(chain))) - headTracker2 := headtracker.NewSimulatedHeadTracker(cl2, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp2 := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(chain)), db, lggr), - cl2, - lggr, - headTracker2, - lpOpts, - ) - servicetest.Run(t, lp2) - - cr2, err2 := evm.NewChainReaderService(ctx, lggr, lp2, headTracker2, cl2, cfg) - require.NoError(t, err2) - - extendedCr2 := contractreader.NewExtendedContractReader(cr2) - err2 = extendedCr2.Bind(ctx, bindings) - require.NoError(t, err2) - otherCrs[chain] = extendedCr2 - } - - for chain, bindings := range toMockBindings { - if _, ok := otherCrs[chain]; ok { - require.False(t, ok, "chain %d already exists", chain) - } - m := readermocks.NewMockContractReaderFacade(t) - m.EXPECT().Bind(ctx, bindings).Return(nil) - ecr := contractreader.NewExtendedContractReader(m) - err = ecr.Bind(ctx, bindings) - require.NoError(t, err) - otherCrs[chain] = ecr - } - - servicetest.Run(t, cr) + // Handle additional contract readers + otherCrs := setupAdditionalContractReaders(ctx, t, toBindContracts, toMockBindings, simulatedBackend, db, lggr, lpOpts) + // Combine all contract readers contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{readerChain: extendedCr} for chain, cr := range otherCrs { contractReaders[chain] = cr } + contractWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, destChain, nil) @@ -897,7 +1051,51 @@ func testSetup( cl: cl, reader: reader, extendedCR: extendedCr, + db: db, + orm: orm, + } +} + +func setupAdditionalContractReaders( + ctx context.Context, + t testing.TB, + toBindContracts map[cciptypes.ChainSelector][]types.BoundContract, + toMockBindings map[cciptypes.ChainSelector][]types.BoundContract, + simulatedBackend *simulated.Backend, + db *sqlx.DB, + lggr logger.Logger, + lpOpts logpoller.Opts, +) map[cciptypes.ChainSelector]contractreader.Extended { + otherCrs := make(map[cciptypes.ChainSelector]contractreader.Extended) + + for chain, bindings := range toBindContracts { + cl := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(chain))) + headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(chain)), db, lggr), cl, lggr, headTracker, lpOpts) + servicetest.Run(t, lp) + + cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, evmtypes.ChainReaderConfig{}) + require.NoError(t, err) + + extendedCr := contractreader.NewExtendedContractReader(cr) + err = extendedCr.Bind(ctx, bindings) + require.NoError(t, err) + otherCrs[chain] = extendedCr + } + + for chain, bindings := range toMockBindings { + if _, ok := otherCrs[chain]; ok { + require.False(t, ok, "chain %d already exists", chain) + } + m := readermocks.NewMockContractReaderFacade(t) + m.EXPECT().Bind(ctx, bindings).Return(nil) + ecr := contractreader.NewExtendedContractReader(m) + err := ecr.Bind(ctx, bindings) + require.NoError(t, err) + otherCrs[chain] = ecr } + + return otherCrs } type testSetupData struct { @@ -905,6 +1103,8 @@ type testSetupData struct { contract *ccip_reader_tester.CCIPReaderTester sb *simulated.Backend auth *bind.TransactOpts + orm logpoller.ORM + db *sqlx.DB lp logpoller.LogPoller cl client.Client reader ccipreaderpkg.CCIPReader From 2968fcb6a9ca97bf0fdcb53d034d694c2d8ff328 Mon Sep 17 00:00:00 2001 From: nogo <0xnogo@gmail.com> Date: Sat, 23 Nov 2024 08:24:42 +0400 Subject: [PATCH 2/8] adding more bench tests + lint --- .../ccipreader/ccipreader_test.go | 426 +++++++++++++++++- 1 file changed, 401 insertions(+), 25 deletions(-) diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go index 84b95900c24..97c6e20cf99 100644 --- a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go @@ -159,7 +159,7 @@ func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { }, }, }) - assert.NoError(t, err) + require.NoError(t, err) bh := s.sb.Commit() b, err := s.sb.Client().BlockByHash(ctx, bh) require.NoError(t, err) @@ -244,7 +244,7 @@ func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { []byte{1, 2, 3, 4}, big.NewInt(250_000), ) - assert.NoError(t, err) + require.NoError(t, err) s.sb.Commit() _, err = s.contract.EmitExecutionStateChanged( @@ -257,7 +257,7 @@ func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { []byte{1, 2, 3, 4, 5}, big.NewInt(350_000), ) - assert.NoError(t, err) + require.NoError(t, err) s.sb.Commit() // Need to replay as sometimes the logs are not picked up by the log poller (?) @@ -336,7 +336,7 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { FeeValueJuels: big.NewInt(2), TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(1)}, {Amount: big.NewInt(2)}}, }) - assert.NoError(t, err) + require.NoError(t, err) _, err = s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ Header: ccip_reader_tester.InternalRampMessageHeader{ @@ -354,7 +354,7 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { FeeValueJuels: big.NewInt(4), TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(3)}, {Amount: big.NewInt(4)}}, }) - assert.NoError(t, err) + require.NoError(t, err) s.sb.Commit() @@ -423,7 +423,7 @@ func TestCCIPReader_NextSeqNum(t *testing.T) { s := testSetup(ctx, t, chainD, chainD, onChainSeqNums, cfg, nil, nil, true, sb, auth, false) seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, seqNums, 3) assert.Equal(t, cciptypes.SeqNum(10), seqNums[0]) assert.Equal(t, cciptypes.SeqNum(20), seqNums[1]) @@ -505,7 +505,7 @@ func TestCCIPReader_Nonces(t *testing.T) { for chain, addrs := range nonces { for addr, nonce := range addrs { _, err := s.contract.SetInboundNonce(s.auth, uint64(chain), nonce, common.LeftPadBytes(addr.Bytes(), 32)) - assert.NoError(t, err) + require.NoError(t, err) } } s.sb.Commit() @@ -518,7 +518,7 @@ func TestCCIPReader_Nonces(t *testing.T) { addrQuery = append(addrQuery, utils.RandomAddress().String()) results, err := s.reader.Nonces(ctx, sourceChain, chainD, addrQuery) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, results, len(addrQuery)) for addr, nonce := range addrs { assert.Equal(t, nonce, results[addr.String()]) @@ -800,7 +800,18 @@ func setupSimulatedBackendAndAuth(t testing.TB) (*simulated.Backend, *bind.Trans return simulatedBackend, auth } -func Benchmark_CCIPReader_CommitReportsGTETimestampParameterized(b *testing.B) { +// Benchmark Results: +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_0_MatchLogs_0-14 1000000000 0.001046 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1000000000 0.001074 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_10_MatchLogs_100-14 1000000000 0.006228 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_100_MatchLogs_10000-14 1000000000 0.5138 ns/op 0 B/op 0 allocs/op +// +// Notes: +// - Case `FirstLogs_0_MatchLogs_0`: No logs match the query, yielding near-zero overhead. +// - Case `FirstLogs_1_MatchLogs_10`: Small dataset with 1 initial log and 10 matches, minimal processing time observed. +// - Case `FirstLogs_10_MatchLogs_100`: Medium dataset with 10 initial logs and 100 matches, showing a slight increase in time. +// - Case `FirstLogs_100_MatchLogs_10000`: Large dataset with 100 initial logs and 10,000 matches, demonstrating efficient scaling with marginal increase in processing time. +func Benchmark_CCIPReader_CommitReportsGTETimestamp(b *testing.B) { tests := []struct { logsInsertedFirst int logsInsertedToMatchQuery int @@ -820,7 +831,6 @@ func Benchmark_CCIPReader_CommitReportsGTETimestampParameterized(b *testing.B) { func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedToMatchQuery int) { ctx := testutils.Context(b) - finalityDepth := 5 sb, auth := setupSimulatedBackendAndAuth(b) // Initialize test setup @@ -848,13 +858,13 @@ func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedToM // Insert logs in two phases based on parameters if logsInsertedFirst > 0 { - populateDatabaseForCommitReportAccepted(b, ts, chainS1, logsInsertedFirst, finalityDepth, 0) + populateDatabaseForCommitReportAccepted(b, ts, chainS1, logsInsertedFirst, 0) } queryTimestamp := time.Now() if logsInsertedToMatchQuery > 0 { - populateDatabaseForCommitReportAccepted(b, ts, chainS1, logsInsertedToMatchQuery, finalityDepth, logsInsertedFirst) + populateDatabaseForCommitReportAccepted(b, ts, chainS1, logsInsertedToMatchQuery, logsInsertedFirst) } // Reset timer to measure only the query time @@ -867,7 +877,8 @@ func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedToM query.KeyFilter{ Key: consts.EventNameCommitReportAccepted, Expressions: []query.Expression{ - query.Timestamp(uint64(queryTimestamp.Unix()), primitives.Gte), + // #nosec G115 + query.Timestamp(uint64(queryTimestamp.Unix()), primitives.Gte), // Safe: offset and i are always non-negative and within range query.Confidence(primitives.Finalized), }, }, @@ -884,8 +895,7 @@ func populateDatabaseForCommitReportAccepted( testEnv *testSetupData, sourceChain cciptypes.ChainSelector, numOfReports int, - finalityDepth int, - offset int, // New offset parameter + offset int, ) { ctx := testutils.Context(b) @@ -906,9 +916,11 @@ func populateDatabaseForCommitReportAccepted( { SourceChainSelector: uint64(sourceChain), OnRampAddress: []byte{0x12, 0x34}, - MinSeqNr: uint64(i * 100), - MaxSeqNr: uint64(i*100 + 99), - MerkleRoot: ccipocr3.Bytes32(utils.NewHash().Bytes()), + // #nosec G115 + MinSeqNr: uint64(i * 100), + // #nosec G115 + MaxSeqNr: uint64(i*100 + 99), + MerkleRoot: ccipocr3.Bytes32(utils.NewHash().Bytes()), }, } @@ -933,7 +945,7 @@ func populateDatabaseForCommitReportAccepted( // Create log entry logs = append(logs, logpoller.Log{ - EvmChainId: ubig.New(big.NewInt(int64(sourceChain))), + EvmChainId: ubig.New(new(big.Int).SetUint64(uint64(sourceChain))), LogIndex: logIndex, BlockHash: utils.NewHash(), BlockNumber: blockNumber, @@ -949,7 +961,373 @@ func populateDatabaseForCommitReportAccepted( // Insert logs into the database require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) - require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfReports+finalityDepth), time.Now(), int64(offset+numOfReports+finalityDepth))) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfReports), time.Now(), int64(offset+numOfReports))) +} + +// Benchmark Results: +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 1000000000 0.004432 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_10_EndSeq_20-14 1000000000 0.0006731 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.0009501 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 1000000000 0.004103 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 1000000000 0.04908 ns/op 0 B/op 0 allocs/op +// +// Notes: +// - LogsInserted_0_StartSeq_0_EndSeq_10: No logs inserted, performance is optimal with negligible overhead. +// - LogsInserted_10_StartSeq_10_EndSeq_20: Querying the next sequence, minimal latency observed. +// - LogsInserted_10_StartSeq_0_EndSeq_9: Queries a smaller range of 10 logs, overhead is slightly higher due to range filter. +// - LogsInserted_100_StartSeq_0_EndSeq_100: Dataset of 100 logs shows a linear scaling in overhead, consistent with expectations. +// - LogsInserted_100000_StartSeq_99744_EndSeq_100000: Queries for the last ~256 logs in a large dataset of 100,000. Performance remains efficient, but with a slight increase in latency due to the dataset size. +func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) { + tests := []struct { + logsInserted int + startSeqNum cciptypes.SeqNum + endSeqNum cciptypes.SeqNum + }{ + {0, 0, 10}, // no logs + {10, 10, 20}, // out of bounds + {10, 0, 9}, // get all messages with 10 logs + {100, 0, 100}, // get all messages with 100 logs + {100_000, 100_000 - 256, 100_000}, // get the last 256 messages + } + + for _, tt := range tests { + b.Run(fmt.Sprintf("LogsInserted_%d_StartSeq_%d_EndSeq_%d", tt.logsInserted, tt.startSeqNum, tt.endSeqNum), func(b *testing.B) { + benchmarkExecutedMessageRanges(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum) + }) + } +} + +func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSeqNum, endSeqNum cciptypes.SeqNum) { + ctx := testutils.Context(b) + sb, auth := setupSimulatedBackendAndAuth(b) + + // Initialize test setup + ts := testSetup( + ctx, + b, + chainS1, + chainS1, + nil, + evmconfig.DestReaderConfig, + nil, + nil, + false, + sb, + auth, + true) + + err := ts.extendedCR.Bind(ctx, []types.BoundContract{ + { + Address: ts.contractAddr.String(), + Name: consts.ContractNameOffRamp, + }, + }) + require.NoError(b, err) + + // Insert logs in two phases based on parameters + if logsInsertedFirst > 0 { + populateDatabaseForExecutionStateChanged(b, ts, chainS1, logsInsertedFirst, 0) + } + + // Reset timer to measure only the query time + b.ResetTimer() + + // Execute the query + _, err = ts.extendedCR.ExtendedQueryKey( + ctx, + consts.ContractNameOffRamp, + query.KeyFilter{ + Key: consts.EventNameExecutionStateChanged, + Expressions: []query.Expression{ + query.Comparator(consts.EventAttributeSourceChain, primitives.ValueComparator{ + Value: chainS1, + Operator: primitives.Eq, + }), + query.Comparator(consts.EventAttributeSequenceNumber, primitives.ValueComparator{ + Value: startSeqNum, + Operator: primitives.Gte, + }, primitives.ValueComparator{ + Value: endSeqNum, + Operator: primitives.Lte, + }), + query.Comparator(consts.EventAttributeState, primitives.ValueComparator{ + Value: 0, + Operator: primitives.Gt, + }), + query.Confidence(primitives.Finalized), + }, + }, + query.LimitAndSort{ + SortBy: []query.SortBy{query.NewSortByTimestamp(query.Asc)}, + }, + &offramp.OffRampExecutionStateChanged{}, + ) + require.NoError(b, err) +} + +func populateDatabaseForExecutionStateChanged( + b *testing.B, + testEnv *testSetupData, + sourceChain cciptypes.ChainSelector, + numOfEvents int, + offset int, +) { + ctx := testutils.Context(b) + + var logs []logpoller.Log + executionStateEvent, exists := offrampABI.Events[consts.EventNameExecutionStateChanged] + require.True(b, exists, "Event ExecutionStateChanged not found in ABI") + + executionStateEventSig := executionStateEvent.ID + executionStateEventAddress := testEnv.contractAddr + + for i := 0; i < numOfEvents; i++ { + // Calculate unique BlockNumber and LogIndex + blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers + logIndex := int64(offset + i + 1) // Offset ensures unique log indices + + // Populate fields for the event + sourceChainSelector := uint64(sourceChain) + // #nosec G115 + sequenceNumber := uint64(offset + i) + messageID := utils.NewHash() + messageHash := utils.NewHash() + state := uint8(1) + returnData := []byte{0x01, 0x02} + gasUsed := big.NewInt(int64(10000 + i)) + + // Encode the non indexed event data + encodedData, err := executionStateEvent.Inputs.NonIndexed().Pack( + messageHash, + state, + returnData, + gasUsed, + ) + require.NoError(b, err) + + // Topics (event signature and indexed fields) + topics := [][]byte{ + executionStateEventSig[:], // Event signature + logpoller.EvmWord(sourceChainSelector).Bytes(), // Indexed sourceChainSelector + logpoller.EvmWord(sequenceNumber).Bytes(), // Indexed sequenceNumber + messageID[:], // Indexed messageId + } + + // Create log entry + logs = append(logs, logpoller.Log{ + EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(sourceChain))), + LogIndex: logIndex, + BlockHash: utils.NewHash(), + BlockNumber: blockNumber, + BlockTimestamp: time.Now(), + EventSig: executionStateEventSig, + Topics: topics, + Address: executionStateEventAddress, + TxHash: utils.NewHash(), + Data: encodedData, + CreatedAt: time.Now(), + }) + } + + // Insert logs into the database + require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) +} + +// Benchmark Results: +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 1000000000 0.001293 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.001694 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 1000000000 0.01251 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 1000000000 0.1788 ns/op 0 B/op 0 allocs/op +// +// Observations: +// - LogsInserted_0_StartSeq_0_EndSeq_10: Baseline test with no logs inserted exhibits minimal overhead. +// - LogsInserted_10_StartSeq_0_EndSeq_9: Queries a range of 10 logs; performance remains optimal with negligible increase in latency. +// - LogsInserted_100_StartSeq_0_EndSeq_100: Dataset of 100 logs demonstrates scaling in query latency as the data range increases. +// - LogsInserted_100000_StartSeq_99744_EndSeq_100000: Large dataset (100,000 logs) shows significant scaling in latency but remains efficient. +func Benchmark_CCIPReader_MessageSentRanges(b *testing.B) { + tests := []struct { + logsInserted int + startSeqNum cciptypes.SeqNum + endSeqNum cciptypes.SeqNum + }{ + {0, 0, 10}, // No logs + {10, 0, 9}, // Get all messages with 10 logs + {100, 0, 100}, // Get all messages with 100 logs + {100_000, 100_000 - 256, 100_000}, // Get the last 256 messages + } + + for _, tt := range tests { + b.Run(fmt.Sprintf("LogsInserted_%d_StartSeq_%d_EndSeq_%d", tt.logsInserted, tt.startSeqNum, tt.endSeqNum), func(b *testing.B) { + benchmarkMessageSentRanges(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum) + }) + } +} + +func benchmarkMessageSentRanges(b *testing.B, logsInserted int, startSeqNum, endSeqNum cciptypes.SeqNum) { + ctx := testutils.Context(b) + sb, auth := setupSimulatedBackendAndAuth(b) + + // Initialize test setup + ts := testSetup( + ctx, + b, + chainS1, + chainS1, + nil, + evmconfig.SourceReaderConfig, + nil, + nil, + false, + sb, + auth, + true) + + err := ts.extendedCR.Bind(ctx, []types.BoundContract{ + { + Address: ts.contractAddr.String(), + Name: consts.ContractNameOnRamp, + }, + }) + require.NoError(b, err) + + // Insert logs if needed + if logsInserted > 0 { + populateDatabaseForMessageSent(b, ts, chainS1, logsInserted, 0) + } + + // Reset timer to measure only the query time + b.ResetTimer() + + // Execute the query + _, err = ts.extendedCR.ExtendedQueryKey( + ctx, + consts.ContractNameOnRamp, + query.KeyFilter{ + Key: consts.EventNameCCIPMessageSent, + Expressions: []query.Expression{ + query.Comparator(consts.EventAttributeSourceChain, primitives.ValueComparator{ + Value: chainS1, + Operator: primitives.Eq, + }), + query.Comparator(consts.EventAttributeDestChain, primitives.ValueComparator{ + Value: chainS2, // Replace with appropriate chain + Operator: primitives.Eq, + }), + query.Comparator(consts.EventAttributeSequenceNumber, primitives.ValueComparator{ + Value: startSeqNum, + Operator: primitives.Gte, + }, primitives.ValueComparator{ + Value: endSeqNum, + Operator: primitives.Lte, + }), + query.Confidence(primitives.Finalized), + }, + }, + query.LimitAndSort{ + SortBy: []query.SortBy{query.NewSortByTimestamp(query.Asc)}, + }, + &onramp.OnRampCCIPMessageSent{}, + ) + require.NoError(b, err) +} + +func populateDatabaseForMessageSent( + b *testing.B, + testEnv *testSetupData, + sourceChain cciptypes.ChainSelector, + numOfEvents int, + offset int, +) { + ctx := testutils.Context(b) + + var logs []logpoller.Log + messageSentEvent, exists := onrampABI.Events[consts.EventNameCCIPMessageSent] + require.True(b, exists, "Event CCIPMessageSent not found in ABI") + + messageSentEventSig := messageSentEvent.ID + messageSentEventAddress := testEnv.contractAddr + + for i := 0; i < numOfEvents; i++ { + // Calculate unique BlockNumber and LogIndex + blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers + logIndex := int64(offset + i + 1) // Offset ensures unique log indices + + // Populate fields for the event + destChainSelector := uint64(chainS2) + // #nosec G115 + sequenceNumber := uint64(offset + i) + + // Create InternalRampMessageHeader struct + header := onramp.InternalRampMessageHeader{ + MessageId: utils.NewHash(), + SourceChainSelector: uint64(sourceChain), + DestChainSelector: destChainSelector, + SequenceNumber: sequenceNumber, + // #nosec G115 + Nonce: uint64(i), + } + + // Create InternalEVM2AnyTokenTransfer slice + tokenTransfers := []onramp.InternalEVM2AnyTokenTransfer{ + { + SourcePoolAddress: utils.RandomAddress(), + DestTokenAddress: []byte{0x01, 0x02}, + ExtraData: []byte{0x03}, + // #nosec G115 + Amount: big.NewInt(1000 + int64(i)), + DestExecData: []byte{}, + }, + } + + // Create InternalEVM2AnyRampMessage struct + message := onramp.InternalEVM2AnyRampMessage{ + Header: header, + Sender: utils.RandomAddress(), + Data: []byte{0x04, 0x05}, + Receiver: []byte{0x06, 0x07}, + ExtraArgs: []byte{0x08}, + FeeToken: utils.RandomAddress(), + // #nosec G115 + FeeTokenAmount: big.NewInt(2000 + int64(i)), + // #nosec G115 + + FeeValueJuels: big.NewInt(3000 + int64(i)), + TokenAmounts: tokenTransfers, + } + + // Encode the non-indexed event data + encodedData, err := messageSentEvent.Inputs.NonIndexed().Pack( + message, + ) + require.NoError(b, err) + + // Topics (event signature and indexed fields) + topics := [][]byte{ + messageSentEventSig[:], // Event signature + logpoller.EvmWord(destChainSelector).Bytes(), // Indexed destChainSelector + logpoller.EvmWord(sequenceNumber).Bytes(), // Indexed sequenceNumber + } + + // Create log entry + logs = append(logs, logpoller.Log{ + EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(sourceChain))), + LogIndex: logIndex, + BlockHash: utils.NewHash(), + BlockNumber: blockNumber, + BlockTimestamp: time.Now(), + EventSig: messageSentEventSig, + Topics: topics, + Address: messageSentEventAddress, + TxHash: utils.NewHash(), + Data: encodedData, + CreatedAt: time.Now(), + }) + } + + // Insert logs into the database + require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) } func testSetup( @@ -966,8 +1344,6 @@ func testSetup( auth *bind.TransactOpts, useHeavyDB bool, ) *testSetupData { - const chainID = 1337 - // Initialize logger lggr := logger.TestLogger(t) lggr.SetLogLevel(zapcore.ErrorLevel) @@ -983,12 +1359,12 @@ func testSetup( // Deploy the contract address, _, _, err := ccip_reader_tester.DeployCCIPReaderTester(auth, simulatedBackend.Client()) - assert.NoError(t, err) + require.NoError(t, err) simulatedBackend.Commit() // Create contract instance contract, err := ccip_reader_tester.NewCCIPReaderTester(address, simulatedBackend.Client()) - assert.NoError(t, err) + require.NoError(t, err) // Setup log poller lpOpts := logpoller.Opts{ @@ -1011,7 +1387,7 @@ func testSetup( MinSeqNr: uint64(seqNum), OnRamp: utils.RandomAddress().Bytes(), }) - assert.NoError(t, err1) + require.NoError(t, err1) simulatedBackend.Commit() } From b1be57104145a0b7da500e8c67949e705119294e Mon Sep 17 00:00:00 2001 From: nogo <0xnogo@gmail.com> Date: Sat, 23 Nov 2024 12:31:01 +0400 Subject: [PATCH 3/8] fix test --- .../ccipreader/ccipreader_test.go | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go index 97c6e20cf99..dca68ee9214 100644 --- a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go @@ -805,12 +805,6 @@ func setupSimulatedBackendAndAuth(t testing.TB) (*simulated.Backend, *bind.Trans // Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1000000000 0.001074 ns/op 0 B/op 0 allocs/op // Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_10_MatchLogs_100-14 1000000000 0.006228 ns/op 0 B/op 0 allocs/op // Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_100_MatchLogs_10000-14 1000000000 0.5138 ns/op 0 B/op 0 allocs/op -// -// Notes: -// - Case `FirstLogs_0_MatchLogs_0`: No logs match the query, yielding near-zero overhead. -// - Case `FirstLogs_1_MatchLogs_10`: Small dataset with 1 initial log and 10 matches, minimal processing time observed. -// - Case `FirstLogs_10_MatchLogs_100`: Medium dataset with 10 initial logs and 100 matches, showing a slight increase in time. -// - Case `FirstLogs_100_MatchLogs_10000`: Large dataset with 100 initial logs and 10,000 matches, demonstrating efficient scaling with marginal increase in processing time. func Benchmark_CCIPReader_CommitReportsGTETimestamp(b *testing.B) { tests := []struct { logsInsertedFirst int @@ -970,13 +964,6 @@ func populateDatabaseForCommitReportAccepted( // Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.0009501 ns/op 0 B/op 0 allocs/op // Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 1000000000 0.004103 ns/op 0 B/op 0 allocs/op // Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 1000000000 0.04908 ns/op 0 B/op 0 allocs/op -// -// Notes: -// - LogsInserted_0_StartSeq_0_EndSeq_10: No logs inserted, performance is optimal with negligible overhead. -// - LogsInserted_10_StartSeq_10_EndSeq_20: Querying the next sequence, minimal latency observed. -// - LogsInserted_10_StartSeq_0_EndSeq_9: Queries a smaller range of 10 logs, overhead is slightly higher due to range filter. -// - LogsInserted_100_StartSeq_0_EndSeq_100: Dataset of 100 logs shows a linear scaling in overhead, consistent with expectations. -// - LogsInserted_100000_StartSeq_99744_EndSeq_100000: Queries for the last ~256 logs in a large dataset of 100,000. Performance remains efficient, but with a slight increase in latency due to the dataset size. func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) { tests := []struct { logsInserted int @@ -1389,6 +1376,9 @@ func testSetup( }) require.NoError(t, err1) simulatedBackend.Commit() + scc, err1 := contract.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, uint64(sourceChain)) + require.NoError(t, err1) + require.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) } // Initialize chain reader service @@ -1407,7 +1397,9 @@ func testSetup( } // Handle additional contract readers - otherCrs := setupAdditionalContractReaders(ctx, t, toBindContracts, toMockBindings, simulatedBackend, db, lggr, lpOpts) + otherCrs := setupAdditionalContractReaders(ctx, t, toBindContracts, toMockBindings, simulatedBackend, db, lggr, lpOpts, cfg) + + servicetest.Run(t, cr) // Combine all contract readers contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{readerChain: extendedCr} @@ -1441,6 +1433,7 @@ func setupAdditionalContractReaders( db *sqlx.DB, lggr logger.Logger, lpOpts logpoller.Opts, + cfg evmtypes.ChainReaderConfig, ) map[cciptypes.ChainSelector]contractreader.Extended { otherCrs := make(map[cciptypes.ChainSelector]contractreader.Extended) @@ -1450,7 +1443,7 @@ func setupAdditionalContractReaders( lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(chain)), db, lggr), cl, lggr, headTracker, lpOpts) servicetest.Run(t, lp) - cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, evmtypes.ChainReaderConfig{}) + cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, cfg) require.NoError(t, err) extendedCr := contractreader.NewExtendedContractReader(cr) From 8e555707026046bfde0f3c7232ed84c295fa7d8d Mon Sep 17 00:00:00 2001 From: nogo <0xnogo@gmail.com> Date: Sat, 30 Nov 2024 12:28:08 +0400 Subject: [PATCH 4/8] addressing comments --- .../ccipreader/ccipreader_test.go | 274 ++++++++---------- 1 file changed, 122 insertions(+), 152 deletions(-) diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go index dca68ee9214..cabcade0a74 100644 --- a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go @@ -26,9 +26,6 @@ import ( ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" @@ -36,8 +33,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" @@ -801,14 +796,14 @@ func setupSimulatedBackendAndAuth(t testing.TB) (*simulated.Backend, *bind.Trans } // Benchmark Results: -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_0_MatchLogs_0-14 1000000000 0.001046 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1000000000 0.001074 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_10_MatchLogs_100-14 1000000000 0.006228 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_100_MatchLogs_10000-14 1000000000 0.5138 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_0_MatchLogs_0-14 1000000000 0.001293 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1000000000 0.002117 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_10_MatchLogs_100-14 1000000000 0.007866 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_100_MatchLogs_10000-14 1000000000 0.5481 ns/op 0 B/op 0 allocs/op func Benchmark_CCIPReader_CommitReportsGTETimestamp(b *testing.B) { tests := []struct { - logsInsertedFirst int - logsInsertedToMatchQuery int + logsInsertedFirst int + logsInsertedMatching int }{ {0, 0}, {1, 10}, @@ -817,76 +812,70 @@ func Benchmark_CCIPReader_CommitReportsGTETimestamp(b *testing.B) { } for _, tt := range tests { - b.Run(fmt.Sprintf("FirstLogs_%d_MatchLogs_%d", tt.logsInsertedFirst, tt.logsInsertedToMatchQuery), func(b *testing.B) { - benchmarkCommitReports(b, tt.logsInsertedFirst, tt.logsInsertedToMatchQuery) + b.Run(fmt.Sprintf("FirstLogs_%d_MatchLogs_%d", tt.logsInsertedMatching, tt.logsInsertedFirst), func(b *testing.B) { + benchmarkCommitReports(b, tt.logsInsertedFirst, tt.logsInsertedMatching) }) } } -func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedToMatchQuery int) { +func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedMatching int) { ctx := testutils.Context(b) sb, auth := setupSimulatedBackendAndAuth(b) + onRampAddress := utils.RandomAddress() + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameCommitReportAccepted}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameCommitReportAccepted: { + ChainSpecificName: consts.EventNameCommitReportAccepted, + ReadType: evmtypes.Event, + }, + }, + }, + }, + } // Initialize test setup - ts := testSetup( - ctx, - b, - chainS1, - chainS1, - nil, - evmconfig.DestReaderConfig, - nil, - nil, - false, + s := testSetup(ctx, b, chainD, chainD, nil, cfg, nil, map[cciptypes.ChainSelector][]types.BoundContract{ + chainS1: { + { + Address: onRampAddress.Hex(), + Name: consts.ContractNameOnRamp, + }, + }, + }, + true, sb, auth, - true) - - err := ts.extendedCR.Bind(ctx, []types.BoundContract{ - { - Address: ts.contractAddr.String(), - Name: consts.ContractNameOffRamp, - }, - }) - require.NoError(b, err) + true, + ) - // Insert logs in two phases based on parameters if logsInsertedFirst > 0 { - populateDatabaseForCommitReportAccepted(b, ts, chainS1, logsInsertedFirst, 0) + populateDatabaseForCommitReportAccepted(b, s, chainD, chainS1, logsInsertedFirst, 0) } queryTimestamp := time.Now() - if logsInsertedToMatchQuery > 0 { - populateDatabaseForCommitReportAccepted(b, ts, chainS1, logsInsertedToMatchQuery, logsInsertedFirst) + if logsInsertedMatching > 0 { + populateDatabaseForCommitReportAccepted(b, s, chainD, chainS1, logsInsertedMatching, logsInsertedFirst) } // Reset timer to measure only the query time b.ResetTimer() - // Execute the query - _, err = ts.extendedCR.ExtendedQueryKey( - ctx, - consts.ContractNameOffRamp, - query.KeyFilter{ - Key: consts.EventNameCommitReportAccepted, - Expressions: []query.Expression{ - // #nosec G115 - query.Timestamp(uint64(queryTimestamp.Unix()), primitives.Gte), // Safe: offset and i are always non-negative and within range - query.Confidence(primitives.Finalized), - }, - }, - query.LimitAndSort{ - SortBy: []query.SortBy{query.NewSortByTimestamp(query.Asc)}, - }, - &offramp.OffRampCommitReportAccepted{}, - ) + reports, err := s.reader.CommitReportsGTETimestamp(ctx, chainD, queryTimestamp, logsInsertedFirst) require.NoError(b, err) + require.Len(b, reports, logsInsertedFirst) } func populateDatabaseForCommitReportAccepted( b *testing.B, testEnv *testSetupData, + destChain cciptypes.ChainSelector, sourceChain cciptypes.ChainSelector, numOfReports int, offset int, @@ -900,6 +889,16 @@ func populateDatabaseForCommitReportAccepted( commitReportEventSig := commitReportEvent.ID commitReportAddress := testEnv.contractAddr + // Calculate timestamp based on whether these are the first logs or matching logs + var timestamp time.Time + if offset == 0 { + // For first set of logs, set timestamp to 1 hour ago + timestamp = time.Now().Add(-1 * time.Hour) + } else { + // For matching logs, use current time + timestamp = time.Now() + } + for i := 0; i < numOfReports; i++ { // Calculate unique BlockNumber and LogIndex blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers @@ -909,19 +908,21 @@ func populateDatabaseForCommitReportAccepted( merkleRoots := []offramp.InternalMerkleRoot{ { SourceChainSelector: uint64(sourceChain), - OnRampAddress: []byte{0x12, 0x34}, + OnRampAddress: utils.RandomAddress().Bytes(), // #nosec G115 MinSeqNr: uint64(i * 100), // #nosec G115 MaxSeqNr: uint64(i*100 + 99), - MerkleRoot: ccipocr3.Bytes32(utils.NewHash().Bytes()), + MerkleRoot: utils.RandomBytes32(), }, } + sourceToken := utils.RandomAddress() + // Simulate priceUpdates priceUpdates := offramp.InternalPriceUpdates{ TokenPriceUpdates: []offramp.InternalTokenPriceUpdate{ - {SourceToken: common.Address{0xAB, 0xCD}, UsdPerToken: big.NewInt(8)}, + {SourceToken: sourceToken, UsdPerToken: big.NewInt(8)}, }, GasPriceUpdates: []offramp.InternalGasPriceUpdate{ {DestChainSelector: uint64(1), UsdPerUnitGas: big.NewInt(10)}, @@ -939,11 +940,11 @@ func populateDatabaseForCommitReportAccepted( // Create log entry logs = append(logs, logpoller.Log{ - EvmChainId: ubig.New(new(big.Int).SetUint64(uint64(sourceChain))), + EvmChainId: ubig.New(new(big.Int).SetUint64(uint64(destChain))), LogIndex: logIndex, BlockHash: utils.NewHash(), BlockNumber: blockNumber, - BlockTimestamp: time.Now(), + BlockTimestamp: timestamp, EventSig: commitReportEventSig, Topics: topics, Address: commitReportAddress, @@ -955,15 +956,15 @@ func populateDatabaseForCommitReportAccepted( // Insert logs into the database require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) - require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfReports), time.Now(), int64(offset+numOfReports))) + require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfReports), timestamp, int64(offset+numOfReports))) } // Benchmark Results: -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 1000000000 0.004432 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_10_EndSeq_20-14 1000000000 0.0006731 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.0009501 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 1000000000 0.004103 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 1000000000 0.04908 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 1000000000 0.001348 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_10_EndSeq_20-14 1000000000 0.0007784 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.001305 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 1000000000 0.005580 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 1000000000 0.04583 ns/op 0 B/op 0 allocs/op func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) { tests := []struct { logsInserted int @@ -987,75 +988,47 @@ func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) { func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSeqNum, endSeqNum cciptypes.SeqNum) { ctx := testutils.Context(b) sb, auth := setupSimulatedBackendAndAuth(b) + expectedRangeLen := calculateExpectedRangeLen(logsInsertedFirst, startSeqNum, endSeqNum) // Initialize test setup - ts := testSetup( + s := testSetup( ctx, b, - chainS1, - chainS1, + chainD, + chainD, nil, evmconfig.DestReaderConfig, nil, nil, - false, + true, sb, auth, true) - err := ts.extendedCR.Bind(ctx, []types.BoundContract{ - { - Address: ts.contractAddr.String(), - Name: consts.ContractNameOffRamp, - }, - }) - require.NoError(b, err) - // Insert logs in two phases based on parameters if logsInsertedFirst > 0 { - populateDatabaseForExecutionStateChanged(b, ts, chainS1, logsInsertedFirst, 0) + populateDatabaseForExecutionStateChanged(b, s, chainS1, chainD, logsInsertedFirst, 0) } // Reset timer to measure only the query time b.ResetTimer() - // Execute the query - _, err = ts.extendedCR.ExtendedQueryKey( + executedRanges, err := s.reader.ExecutedMessageRanges( ctx, - consts.ContractNameOffRamp, - query.KeyFilter{ - Key: consts.EventNameExecutionStateChanged, - Expressions: []query.Expression{ - query.Comparator(consts.EventAttributeSourceChain, primitives.ValueComparator{ - Value: chainS1, - Operator: primitives.Eq, - }), - query.Comparator(consts.EventAttributeSequenceNumber, primitives.ValueComparator{ - Value: startSeqNum, - Operator: primitives.Gte, - }, primitives.ValueComparator{ - Value: endSeqNum, - Operator: primitives.Lte, - }), - query.Comparator(consts.EventAttributeState, primitives.ValueComparator{ - Value: 0, - Operator: primitives.Gt, - }), - query.Confidence(primitives.Finalized), - }, - }, - query.LimitAndSort{ - SortBy: []query.SortBy{query.NewSortByTimestamp(query.Asc)}, - }, - &offramp.OffRampExecutionStateChanged{}, + chainS1, + chainD, + cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), ) require.NoError(b, err) + require.Len(b, executedRanges, expectedRangeLen) + fmt.Println(len(executedRanges)) } func populateDatabaseForExecutionStateChanged( b *testing.B, testEnv *testSetupData, sourceChain cciptypes.ChainSelector, + destChain cciptypes.ChainSelector, numOfEvents int, offset int, ) { @@ -1102,7 +1075,7 @@ func populateDatabaseForExecutionStateChanged( // Create log entry logs = append(logs, logpoller.Log{ - EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(sourceChain))), + EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(destChain))), LogIndex: logIndex, BlockHash: utils.NewHash(), BlockNumber: blockNumber, @@ -1121,17 +1094,36 @@ func populateDatabaseForExecutionStateChanged( require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) } +func calculateExpectedRangeLen(logsInserted int, startSeq, endSeq cciptypes.SeqNum) int { + // If no logs inserted, result should be 0 + if logsInserted == 0 { + return 0 + } + + // Convert to int64 for safer arithmetic + start := uint64(startSeq) + end := uint64(endSeq) + logs := uint64(logsInserted) + + // If start is beyond our available logs, return 0 + if start >= logs { + return 0 + } + + // If end is beyond our available logs, cap it + if end >= logs { + end = logs - 1 + } + + // Calculate length of valid range + return int(end - start + 1) +} + // Benchmark Results: -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 1000000000 0.001293 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.001694 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 1000000000 0.01251 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 1000000000 0.1788 ns/op 0 B/op 0 allocs/op -// -// Observations: -// - LogsInserted_0_StartSeq_0_EndSeq_10: Baseline test with no logs inserted exhibits minimal overhead. -// - LogsInserted_10_StartSeq_0_EndSeq_9: Queries a range of 10 logs; performance remains optimal with negligible increase in latency. -// - LogsInserted_100_StartSeq_0_EndSeq_100: Dataset of 100 logs demonstrates scaling in query latency as the data range increases. -// - LogsInserted_100000_StartSeq_99744_EndSeq_100000: Large dataset (100,000 logs) shows significant scaling in latency but remains efficient. +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 1000000000 0.001557 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.003141 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 1000000000 0.01201 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 1000000000 0.1976 ns/op 0 B/op 0 allocs/op func Benchmark_CCIPReader_MessageSentRanges(b *testing.B) { tests := []struct { logsInserted int @@ -1154,25 +1146,26 @@ func Benchmark_CCIPReader_MessageSentRanges(b *testing.B) { func benchmarkMessageSentRanges(b *testing.B, logsInserted int, startSeqNum, endSeqNum cciptypes.SeqNum) { ctx := testutils.Context(b) sb, auth := setupSimulatedBackendAndAuth(b) + expectedRangeLen := calculateExpectedRangeLen(logsInserted, startSeqNum, endSeqNum) // Initialize test setup - ts := testSetup( + s := testSetup( ctx, b, chainS1, - chainS1, + chainD, nil, evmconfig.SourceReaderConfig, nil, nil, - false, + true, sb, auth, true) - err := ts.extendedCR.Bind(ctx, []types.BoundContract{ + err := s.extendedCR.Bind(ctx, []types.BoundContract{ { - Address: ts.contractAddr.String(), + Address: s.contractAddr.String(), Name: consts.ContractNameOnRamp, }, }) @@ -1180,49 +1173,26 @@ func benchmarkMessageSentRanges(b *testing.B, logsInserted int, startSeqNum, end // Insert logs if needed if logsInserted > 0 { - populateDatabaseForMessageSent(b, ts, chainS1, logsInserted, 0) + populateDatabaseForMessageSent(b, s, chainS1, chainD, logsInserted, 0) } // Reset timer to measure only the query time b.ResetTimer() - // Execute the query - _, err = ts.extendedCR.ExtendedQueryKey( + msgs, err := s.reader.MsgsBetweenSeqNums( ctx, - consts.ContractNameOnRamp, - query.KeyFilter{ - Key: consts.EventNameCCIPMessageSent, - Expressions: []query.Expression{ - query.Comparator(consts.EventAttributeSourceChain, primitives.ValueComparator{ - Value: chainS1, - Operator: primitives.Eq, - }), - query.Comparator(consts.EventAttributeDestChain, primitives.ValueComparator{ - Value: chainS2, // Replace with appropriate chain - Operator: primitives.Eq, - }), - query.Comparator(consts.EventAttributeSequenceNumber, primitives.ValueComparator{ - Value: startSeqNum, - Operator: primitives.Gte, - }, primitives.ValueComparator{ - Value: endSeqNum, - Operator: primitives.Lte, - }), - query.Confidence(primitives.Finalized), - }, - }, - query.LimitAndSort{ - SortBy: []query.SortBy{query.NewSortByTimestamp(query.Asc)}, - }, - &onramp.OnRampCCIPMessageSent{}, + chainS1, + cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), ) require.NoError(b, err) + require.Len(b, msgs, expectedRangeLen) } func populateDatabaseForMessageSent( b *testing.B, testEnv *testSetupData, sourceChain cciptypes.ChainSelector, + destChain cciptypes.ChainSelector, numOfEvents int, offset int, ) { @@ -1241,7 +1211,7 @@ func populateDatabaseForMessageSent( logIndex := int64(offset + i + 1) // Offset ensures unique log indices // Populate fields for the event - destChainSelector := uint64(chainS2) + destChainSelector := uint64(destChain) // #nosec G115 sequenceNumber := uint64(offset + i) From 01054f7e6065c6984c66314241b1ceaef1998e15 Mon Sep 17 00:00:00 2001 From: nogo <0xnogo@gmail.com> Date: Sat, 30 Nov 2024 16:10:46 +0400 Subject: [PATCH 5/8] change with merge --- .../contracts/ccipreader_test.go | 119 +++++++++++------- 1 file changed, 74 insertions(+), 45 deletions(-) diff --git a/integration-tests/contracts/ccipreader_test.go b/integration-tests/contracts/ccipreader_test.go index 835ebdea0d8..d6d04ce405a 100644 --- a/integration-tests/contracts/ccipreader_test.go +++ b/integration-tests/contracts/ccipreader_test.go @@ -832,23 +832,6 @@ func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { require.Equal(t, changeset.DefaultInitialPrices.WethPrice, prices[cciptypes.ChainSelector(chain1)].Int) } -func setupSimulatedBackendAndAuth(t testing.TB) (*simulated.Backend, *bind.TransactOpts) { - privateKey, err := crypto.GenerateKey() - require.NoError(t, err) - - blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) - require.True(t, ok) - - alloc := map[common.Address]ethtypes.Account{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} - simulatedBackend := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(8000000)) - - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) - require.NoError(t, err) - auth.GasLimit = uint64(6000000) - - return simulatedBackend, auth -} - // Benchmark Results: // Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_0_MatchLogs_0-14 1000000000 0.001293 ns/op 0 B/op 0 allocs/op // Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1000000000 0.002117 ns/op 0 B/op 0 allocs/op @@ -1011,12 +994,39 @@ func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSe // Initialize test setup ctx := tests.Context(b) sb, auth := setupSimulatedBackendAndAuth(b) + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameExecutionStateChanged}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameExecutionStateChanged: { + ChainSpecificName: consts.EventNameExecutionStateChanged, + ReadType: evmtypes.Event, + EventDefinitions: &evmtypes.EventDefinitions{ + GenericTopicNames: map[string]string{ + "sourceChainSelector": consts.EventAttributeSourceChain, + "sequenceNumber": consts.EventAttributeSequenceNumber, + }, + GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ + consts.EventAttributeState: { + Name: "state", + }, + }, + }, + }, + }, + }, + }, + } expectedRangeLen := calculateExpectedRangeLen(logsInsertedFirst, startSeqNum, endSeqNum) s := testSetup(ctx, &testing.B{}, testSetupParams{ ReaderChain: chainD, DestChain: chainD, OnChainSeqNums: nil, - Cfg: evmconfig.DestReaderConfig, + Cfg: cfg, ToBindContracts: nil, ToMockBindings: nil, BindTester: true, @@ -1113,31 +1123,6 @@ func populateDatabaseForExecutionStateChanged( require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) } -func calculateExpectedRangeLen(logsInserted int, startSeq, endSeq cciptypes.SeqNum) int { - // If no logs inserted, result should be 0 - if logsInserted == 0 { - return 0 - } - - // Convert to int64 for safer arithmetic - start := uint64(startSeq) - end := uint64(endSeq) - logs := uint64(logsInserted) - - // If start is beyond our available logs, return 0 - if start >= logs { - return 0 - } - - // If end is beyond our available logs, cap it - if end >= logs { - end = logs - 1 - } - - // Calculate length of valid range - return int(end - start + 1) -} - // Benchmark Results: // Benchmark_CCIPReader_MessageSentRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 1000000000 0.001557 ns/op 0 B/op 0 allocs/op // Benchmark_CCIPReader_MessageSentRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.003141 ns/op 0 B/op 0 allocs/op @@ -1302,6 +1287,48 @@ func populateDatabaseForMessageSent( require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) } +func calculateExpectedRangeLen(logsInserted int, startSeq, endSeq cciptypes.SeqNum) int { + // If no logs inserted, result should be 0 + if logsInserted == 0 { + return 0 + } + + // Convert to int64 for safer arithmetic + start := uint64(startSeq) + end := uint64(endSeq) + logs := uint64(logsInserted) + + // If start is beyond our available logs, return 0 + if start >= logs { + return 0 + } + + // If end is beyond our available logs, cap it + if end >= logs { + end = logs - 1 + } + + // Calculate length of valid range + return int(end - start + 1) +} + +func setupSimulatedBackendAndAuth(t testing.TB) (*simulated.Backend, *bind.TransactOpts) { + privateKey, err := crypto.GenerateKey() + require.NoError(t, err) + + blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) + require.True(t, ok) + + alloc := map[common.Address]ethtypes.Account{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} + simulatedBackend := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(8000000)) + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) + require.NoError(t, err) + auth.GasLimit = uint64(6000000) + + return simulatedBackend, auth +} + func testSetupRealContracts( ctx context.Context, t *testing.T, @@ -1412,7 +1439,9 @@ func testSetup( } cl := client.NewSimulatedBackendClient(t, params.SimulatedBackend, big.NewInt(0).SetUint64(uint64(params.ReaderChain))) headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(params.ReaderChain)), db, lggr), + orm := logpoller.NewORM(big.NewInt(0).SetUint64(uint64(params.ReaderChain)), db, lggr) + lp := logpoller.NewLogPoller( + orm, cl, lggr, headTracker, @@ -1504,6 +1533,7 @@ func testSetup( contract: contract, sb: params.SimulatedBackend, auth: params.Auth, + orm: orm, lp: lp, cl: cl, reader: reader, @@ -1531,7 +1561,6 @@ type testSetupData struct { sb *simulated.Backend auth *bind.TransactOpts orm logpoller.ORM - db *sqlx.DB lp logpoller.LogPoller cl client.Client reader ccipreaderpkg.CCIPReader From 59d5284f468ea5bd860cd43cc2b7fe809bcbf360 Mon Sep 17 00:00:00 2001 From: nogo <0xnogo@gmail.com> Date: Sun, 1 Dec 2024 05:19:26 +0400 Subject: [PATCH 6/8] refactor --- .../contracts/ccipreader_test.go | 240 +++++++----------- 1 file changed, 97 insertions(+), 143 deletions(-) diff --git a/integration-tests/contracts/ccipreader_test.go b/integration-tests/contracts/ccipreader_test.go index d6d04ce405a..702e3dd9fbb 100644 --- a/integration-tests/contracts/ccipreader_test.go +++ b/integration-tests/contracts/ccipreader_test.go @@ -116,6 +116,97 @@ func setupGetCommitGTETimestampTest(ctx context.Context, t testing.TB, finalityD return s, finalityDepth, onRampAddress } +func setupExecutedMessageRangesTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameExecutionStateChanged}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameExecutionStateChanged: { + ChainSpecificName: consts.EventNameExecutionStateChanged, + ReadType: evmtypes.Event, + EventDefinitions: &evmtypes.EventDefinitions{ + GenericTopicNames: map[string]string{ + "sourceChainSelector": consts.EventAttributeSourceChain, + "sequenceNumber": consts.EventAttributeSequenceNumber, + }, + GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ + consts.EventAttributeState: { + Name: "state", + }, + }, + }, + }, + }, + }, + }, + } + + sb, auth := setupSimulatedBackendAndAuth(t) + return testSetup(ctx, t, testSetupParams{ + ReaderChain: chainD, + DestChain: chainD, + OnChainSeqNums: nil, + Cfg: cfg, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + SimulatedBackend: sb, + Auth: auth, + UseHeavyDB: useHeavyDB, + }) +} + +func setupMsgsBetweenSeqNumsTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOnRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameCCIPMessageSent}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameCCIPMessageSent: { + ChainSpecificName: "CCIPMessageSent", + ReadType: evmtypes.Event, + EventDefinitions: &evmtypes.EventDefinitions{ + GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ + consts.EventAttributeSourceChain: {Name: "message.header.sourceChainSelector"}, + consts.EventAttributeDestChain: {Name: "message.header.destChainSelector"}, + consts.EventAttributeSequenceNumber: {Name: "message.header.sequenceNumber"}, + }, + }, + OutputModifications: codec.ModifiersConfig{ + &codec.WrapperModifierConfig{Fields: map[string]string{ + "Message.FeeTokenAmount": "Int", + "Message.FeeValueJuels": "Int", + "Message.TokenAmounts.Amount": "Int", + }}, + }, + }, + }, + }, + }, + } + + sb, auth := setupSimulatedBackendAndAuth(t) + return testSetup(ctx, t, testSetupParams{ + ReaderChain: chainS1, + DestChain: chainD, + OnChainSeqNums: nil, + Cfg: cfg, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + SimulatedBackend: sb, + Auth: auth, + UseHeavyDB: useHeavyDB, + }) +} + func emitCommitReports(ctx context.Context, t *testing.T, s *testSetupData, numReports int, tokenA common.Address, onRampAddress common.Address) uint64 { var firstReportTs uint64 for i := 0; i < numReports; i++ { @@ -274,46 +365,7 @@ func TestCCIPReader_CommitReportsGTETimestamp_RespectsFinality(t *testing.T) { func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { t.Parallel() ctx := tests.Context(t) - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameExecutionStateChanged}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameExecutionStateChanged: { - ChainSpecificName: consts.EventNameExecutionStateChanged, - ReadType: evmtypes.Event, - EventDefinitions: &evmtypes.EventDefinitions{ - GenericTopicNames: map[string]string{ - "sourceChainSelector": consts.EventAttributeSourceChain, - "sequenceNumber": consts.EventAttributeSequenceNumber, - }, - GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ - consts.EventAttributeState: { - Name: "state", - }, - }, - }, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - }) + s := setupExecutedMessageRangesTest(ctx, t, false) _, err := s.contract.EmitExecutionStateChanged( s.auth, uint64(chainS1), @@ -367,50 +419,7 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { t.Parallel() ctx := tests.Context(t) - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOnRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCCIPMessageSent}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCCIPMessageSent: { - ChainSpecificName: "CCIPMessageSent", - ReadType: evmtypes.Event, - EventDefinitions: &evmtypes.EventDefinitions{ - GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ - consts.EventAttributeSourceChain: {Name: "message.header.sourceChainSelector"}, - consts.EventAttributeDestChain: {Name: "message.header.destChainSelector"}, - consts.EventAttributeSequenceNumber: {Name: "message.header.sequenceNumber"}, - }, - }, - OutputModifications: codec.ModifiersConfig{ - &codec.WrapperModifierConfig{Fields: map[string]string{ - "Message.FeeTokenAmount": "Int", - "Message.FeeValueJuels": "Int", - "Message.TokenAmounts.Amount": "Int", - }}, - }, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainS1, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - }) - + s := setupMsgsBetweenSeqNumsTest(ctx, t, false) _, err := s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ Header: ccip_reader_tester.InternalRampMessageHeader{ MessageId: [32]byte{1, 0, 0, 0, 0}, @@ -993,47 +1002,8 @@ func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) { func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSeqNum, endSeqNum cciptypes.SeqNum) { // Initialize test setup ctx := tests.Context(b) - sb, auth := setupSimulatedBackendAndAuth(b) - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameExecutionStateChanged}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameExecutionStateChanged: { - ChainSpecificName: consts.EventNameExecutionStateChanged, - ReadType: evmtypes.Event, - EventDefinitions: &evmtypes.EventDefinitions{ - GenericTopicNames: map[string]string{ - "sourceChainSelector": consts.EventAttributeSourceChain, - "sequenceNumber": consts.EventAttributeSequenceNumber, - }, - GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ - consts.EventAttributeState: { - Name: "state", - }, - }, - }, - }, - }, - }, - }, - } + s := setupExecutedMessageRangesTest(ctx, b, true) expectedRangeLen := calculateExpectedRangeLen(logsInsertedFirst, startSeqNum, endSeqNum) - s := testSetup(ctx, &testing.B{}, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - UseHeavyDB: true, - }) // Insert logs in two phases based on parameters if logsInsertedFirst > 0 { @@ -1150,19 +1120,8 @@ func Benchmark_CCIPReader_MessageSentRanges(b *testing.B) { func benchmarkMessageSentRanges(b *testing.B, logsInserted int, startSeqNum, endSeqNum cciptypes.SeqNum) { // Initialize test setup ctx := tests.Context(b) - sb, auth := setupSimulatedBackendAndAuth(b) + s := setupMsgsBetweenSeqNumsTest(ctx, b, true) expectedRangeLen := calculateExpectedRangeLen(logsInserted, startSeqNum, endSeqNum) - s := testSetup(ctx, b, testSetupParams{ - ReaderChain: chainS1, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: evmconfig.SourceReaderConfig, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - }) err := s.extendedCR.Bind(ctx, []types.BoundContract{ { @@ -1288,27 +1247,23 @@ func populateDatabaseForMessageSent( } func calculateExpectedRangeLen(logsInserted int, startSeq, endSeq cciptypes.SeqNum) int { - // If no logs inserted, result should be 0 if logsInserted == 0 { return 0 } - - // Convert to int64 for safer arithmetic start := uint64(startSeq) end := uint64(endSeq) + // #nosec G115 logs := uint64(logsInserted) - // If start is beyond our available logs, return 0 if start >= logs { return 0 } - // If end is beyond our available logs, cap it if end >= logs { end = logs - 1 } - // Calculate length of valid range + // #nosec G115 return int(end - start + 1) } @@ -1429,7 +1384,6 @@ func testSetup( } else { db = pgtest.NewSqlxDB(t) // Simple in-memory DB for tests } - t.Cleanup(func() { assert.NoError(t, db.Close()) }) lpOpts := logpoller.Opts{ PollPeriod: time.Millisecond, FinalityDepth: params.FinalityDepth, From 383732affd4dc5a5438aa62d9a48808195753503 Mon Sep 17 00:00:00 2001 From: nogo <0xnogo@gmail.com> Date: Wed, 4 Dec 2024 15:22:00 +0400 Subject: [PATCH 7/8] addressing comments --- .../contracts/ccipreader_test.go | 230 ++++++------------ 1 file changed, 80 insertions(+), 150 deletions(-) diff --git a/integration-tests/contracts/ccipreader_test.go b/integration-tests/contracts/ccipreader_test.go index 702e3dd9fbb..9f157960cb1 100644 --- a/integration-tests/contracts/ccipreader_test.go +++ b/integration-tests/contracts/ccipreader_test.go @@ -17,7 +17,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" @@ -32,7 +31,6 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" @@ -74,30 +72,13 @@ var ( ) func setupGetCommitGTETimestampTest(ctx context.Context, t testing.TB, finalityDepth int64, useHeavyDB bool) (*testSetupData, int64, common.Address) { - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCommitReportAccepted}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCommitReportAccepted: { - ChainSpecificName: consts.EventNameCommitReportAccepted, - ReadType: evmtypes.Event, - }, - }, - }, - }, - } - sb, auth := setupSimulatedBackendAndAuth(t) onRampAddress := utils.RandomAddress() s := testSetup(ctx, t, testSetupParams{ ReaderChain: chainD, DestChain: chainD, OnChainSeqNums: nil, - Cfg: cfg, + Cfg: evmconfig.DestReaderConfig, ToMockBindings: map[cciptypes.ChainSelector][]types.BoundContract{ chainS1: { { @@ -106,104 +87,49 @@ func setupGetCommitGTETimestampTest(ctx context.Context, t testing.TB, finalityD }, }, }, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - FinalityDepth: finalityDepth, - UseHeavyDB: useHeavyDB, + BindTester: true, + ContractNameToBind: consts.ContractNameOffRamp, + SimulatedBackend: sb, + Auth: auth, + FinalityDepth: finalityDepth, + UseHeavyDB: useHeavyDB, }) return s, finalityDepth, onRampAddress } func setupExecutedMessageRangesTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameExecutionStateChanged}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameExecutionStateChanged: { - ChainSpecificName: consts.EventNameExecutionStateChanged, - ReadType: evmtypes.Event, - EventDefinitions: &evmtypes.EventDefinitions{ - GenericTopicNames: map[string]string{ - "sourceChainSelector": consts.EventAttributeSourceChain, - "sequenceNumber": consts.EventAttributeSequenceNumber, - }, - GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ - consts.EventAttributeState: { - Name: "state", - }, - }, - }, - }, - }, - }, - }, - } - sb, auth := setupSimulatedBackendAndAuth(t) return testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - UseHeavyDB: useHeavyDB, + ReaderChain: chainD, + DestChain: chainD, + OnChainSeqNums: nil, + Cfg: evmconfig.DestReaderConfig, + // Cfg: cfg, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + ContractNameToBind: consts.ContractNameOffRamp, + SimulatedBackend: sb, + Auth: auth, + UseHeavyDB: useHeavyDB, }) } func setupMsgsBetweenSeqNumsTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOnRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCCIPMessageSent}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCCIPMessageSent: { - ChainSpecificName: "CCIPMessageSent", - ReadType: evmtypes.Event, - EventDefinitions: &evmtypes.EventDefinitions{ - GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ - consts.EventAttributeSourceChain: {Name: "message.header.sourceChainSelector"}, - consts.EventAttributeDestChain: {Name: "message.header.destChainSelector"}, - consts.EventAttributeSequenceNumber: {Name: "message.header.sequenceNumber"}, - }, - }, - OutputModifications: codec.ModifiersConfig{ - &codec.WrapperModifierConfig{Fields: map[string]string{ - "Message.FeeTokenAmount": "Int", - "Message.FeeValueJuels": "Int", - "Message.TokenAmounts.Amount": "Int", - }}, - }, - }, - }, - }, - }, - } - sb, auth := setupSimulatedBackendAndAuth(t) return testSetup(ctx, t, testSetupParams{ - ReaderChain: chainS1, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, - UseHeavyDB: useHeavyDB, + ReaderChain: chainS1, + DestChain: chainD, + OnChainSeqNums: nil, + Cfg: evmconfig.SourceReaderConfig, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + ContractNameToBind: consts.ContractNameOnRamp, + SimulatedBackend: sb, + Auth: auth, + UseHeavyDB: useHeavyDB, }) } @@ -842,10 +768,10 @@ func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { } // Benchmark Results: -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_0_MatchLogs_0-14 1000000000 0.001293 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1000000000 0.002117 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_10_MatchLogs_100-14 1000000000 0.007866 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_100_MatchLogs_10000-14 1000000000 0.5481 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_0_MatchLogs_0-14 16948 67728 ns/op 30387 B/op 417 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1650 741741 ns/op 528334 B/op 9929 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_10_MatchLogs_100-14 195 6096328 ns/op 4739856 B/op 92345 allocs/op +// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_100_MatchLogs_10000-14 2 582712583 ns/op 454375304 B/op 8931990 allocs/op func Benchmark_CCIPReader_CommitReportsGTETimestamp(b *testing.B) { tests := []struct { logsInsertedFirst int @@ -882,9 +808,11 @@ func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedMat // Reset timer to measure only the query time b.ResetTimer() - reports, err := s.reader.CommitReportsGTETimestamp(ctx, chainD, queryTimestamp, logsInsertedFirst) - require.NoError(b, err) - require.Len(b, reports, logsInsertedFirst) + for i := 0; i < b.N; i++ { + reports, err := s.reader.CommitReportsGTETimestamp(ctx, chainD, queryTimestamp, logsInsertedFirst) + require.NoError(b, err) + require.Len(b, reports, logsInsertedFirst) + } } func populateDatabaseForCommitReportAccepted( @@ -974,11 +902,11 @@ func populateDatabaseForCommitReportAccepted( } // Benchmark Results: -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 1000000000 0.001348 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_10_EndSeq_20-14 1000000000 0.0007784 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.001305 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 1000000000 0.005580 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 1000000000 0.04583 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 13599 93414 ns/op 43389 B/op 654 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_10_EndSeq_20-14 13471 88392 ns/op 43011 B/op 651 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 2799 473396 ns/op 303737 B/op 4535 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 438 2724414 ns/op 2477573 B/op 37468 allocs/op +// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 40 29118796 ns/op 12607995 B/op 179396 allocs/op func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) { tests := []struct { logsInserted int @@ -1013,15 +941,16 @@ func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSe // Reset timer to measure only the query time b.ResetTimer() - executedRanges, err := s.reader.ExecutedMessageRanges( - ctx, - chainS1, - chainD, - cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), - ) - require.NoError(b, err) - require.Len(b, executedRanges, expectedRangeLen) - fmt.Println(len(executedRanges)) + for i := 0; i < b.N; i++ { + executedRanges, err := s.reader.ExecutedMessageRanges( + ctx, + chainS1, + chainD, + cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), + ) + require.NoError(b, err) + require.Len(b, executedRanges, expectedRangeLen) + } } func populateDatabaseForExecutionStateChanged( @@ -1094,10 +1023,10 @@ func populateDatabaseForExecutionStateChanged( } // Benchmark Results: -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 1000000000 0.001557 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 1000000000 0.003141 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 1000000000 0.01201 ns/op 0 B/op 0 allocs/op -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 1000000000 0.1976 ns/op 0 B/op 0 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 13729 85838 ns/op 43473 B/op 647 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 870 1405208 ns/op 1156315 B/op 21102 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 90 12129488 ns/op 10833395 B/op 201076 allocs/op +// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 10 105741438 ns/op 49103282 B/op 796213 allocs/op func Benchmark_CCIPReader_MessageSentRanges(b *testing.B) { tests := []struct { logsInserted int @@ -1139,13 +1068,15 @@ func benchmarkMessageSentRanges(b *testing.B, logsInserted int, startSeqNum, end // Reset timer to measure only the query time b.ResetTimer() - msgs, err := s.reader.MsgsBetweenSeqNums( - ctx, - chainS1, - cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), - ) - require.NoError(b, err) - require.Len(b, msgs, expectedRangeLen) + for i := 0; i < b.N; i++ { + msgs, err := s.reader.MsgsBetweenSeqNums( + ctx, + chainS1, + cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), + ) + require.NoError(b, err) + require.Len(b, msgs, expectedRangeLen) + } } func populateDatabaseForMessageSent( @@ -1416,8 +1347,6 @@ func testSetup( assert.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) } - contractNames := maps.Keys(params.Cfg.Contracts) - cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, params.Cfg) require.NoError(t, err) @@ -1427,7 +1356,7 @@ func testSetup( err = extendedCr.Bind(ctx, []types.BoundContract{ { Address: address.String(), - Name: contractNames[0], + Name: params.ContractNameToBind, }, }) require.NoError(t, err) @@ -1496,17 +1425,18 @@ func testSetup( } type testSetupParams struct { - ReaderChain cciptypes.ChainSelector - DestChain cciptypes.ChainSelector - OnChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum - Cfg evmtypes.ChainReaderConfig - ToBindContracts map[cciptypes.ChainSelector][]types.BoundContract - ToMockBindings map[cciptypes.ChainSelector][]types.BoundContract - BindTester bool - SimulatedBackend *simulated.Backend - Auth *bind.TransactOpts - FinalityDepth int64 - UseHeavyDB bool + ReaderChain cciptypes.ChainSelector + DestChain cciptypes.ChainSelector + OnChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum + Cfg evmtypes.ChainReaderConfig + ToBindContracts map[cciptypes.ChainSelector][]types.BoundContract + ToMockBindings map[cciptypes.ChainSelector][]types.BoundContract + BindTester bool + ContractNameToBind string + SimulatedBackend *simulated.Backend + Auth *bind.TransactOpts + FinalityDepth int64 + UseHeavyDB bool } type testSetupData struct { From 7c6a9b1ee772daf24254b089417d5b840be21f7c Mon Sep 17 00:00:00 2001 From: nogo <0xnogo@gmail.com> Date: Wed, 4 Dec 2024 16:38:04 +0400 Subject: [PATCH 8/8] add ContractNameToBind --- .../contracts/ccipreader_test.go | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/integration-tests/contracts/ccipreader_test.go b/integration-tests/contracts/ccipreader_test.go index 9f157960cb1..9ccd296e8e3 100644 --- a/integration-tests/contracts/ccipreader_test.go +++ b/integration-tests/contracts/ccipreader_test.go @@ -448,15 +448,16 @@ func TestCCIPReader_NextSeqNum(t *testing.T) { sb, auth := setupSimulatedBackendAndAuth(t) s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - OnChainSeqNums: onChainSeqNums, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, + ReaderChain: chainD, + DestChain: chainD, + OnChainSeqNums: onChainSeqNums, + Cfg: cfg, + ToBindContracts: nil, + ToMockBindings: nil, + BindTester: true, + ContractNameToBind: consts.ContractNameOffRamp, + SimulatedBackend: sb, + Auth: auth, }) seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) @@ -544,12 +545,13 @@ func TestCCIPReader_Nonces(t *testing.T) { sb, auth := setupSimulatedBackendAndAuth(t) s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - Cfg: cfg, - BindTester: true, - SimulatedBackend: sb, - Auth: auth, + ReaderChain: chainD, + DestChain: chainD, + Cfg: cfg, + BindTester: true, + ContractNameToBind: consts.ContractNameNonceManager, + SimulatedBackend: sb, + Auth: auth, }) // Add some nonces.