@@ -723,23 +723,7 @@ func TestLogPoller_SynchronizedWithGeth(t *testing.T) {
723723 lp .PollAndSaveLogs (testutils .Context (t ), currentBlockNumber , false )
724724 currentBlock , err := lp .LatestBlock (testutils .Context (t ))
725725 require .NoError (t , err )
726- matchesGeth := func () bool {
727- // Check every block is identical
728- latest , err1 := ec .BlockByNumber (testutils .Context (t ), nil )
729- require .NoError (t , err1 )
730- for i := 1 ; i < int (latest .NumberU64 ()); i ++ {
731- ourBlock , err1 := lp .BlockByNumber (testutils .Context (t ), int64 (i ))
732- require .NoError (t , err1 )
733- gethBlock , err1 := ec .BlockByNumber (testutils .Context (t ), big .NewInt (int64 (i )))
734- require .NoError (t , err1 )
735- if ourBlock .BlockHash != gethBlock .Hash () {
736- t .Logf ("Initial poll our block differs at height %d got %x want %x\n " , i , ourBlock .BlockHash , gethBlock .Hash ())
737- return false
738- }
739- }
740- return true
741- }
742- if ! matchesGeth () {
726+ if ! checkDBMatchesGeth (t , orm , simulatedClient ) {
743727 return false
744728 }
745729 // Randomly pick to mine or reorg
@@ -776,7 +760,7 @@ func TestLogPoller_SynchronizedWithGeth(t *testing.T) {
776760 currentBlock , err = lp .LatestBlock (testutils .Context (t ))
777761 require .NoError (t , err )
778762 }
779- return matchesGeth ( )
763+ return checkDBMatchesGeth ( t , orm , simulatedClient )
780764 }, gen .SliceOfN (numChainInserts , gen .UInt64Range (1 , uint64 (finalityDepth - 1 ))))) // Max reorg depth is finality depth - 1
781765 p .TestingRun (t )
782766}
@@ -841,15 +825,15 @@ func TestLogPoller_PollAndSaveLogs(t *testing.T) {
841825 lgs , err := th .ORM .SelectLogsByBlockRange (testutils .Context (t ), 1 , 1 )
842826 require .NoError (t , err )
843827 assert .Empty (t , lgs )
844- th . assertHaveCanonical (t , 1 , 1 )
828+ requireDBMatchesGeth (t , th . ORM , th . Client )
845829
846830 // Polling again should be a noop, since we are at the latest.
847831 newStart = th .PollAndSaveLogs (testutils .Context (t ), newStart )
848832 assert .Equal (t , int64 (2 ), newStart )
849833 latest , err := th .ORM .SelectLatestBlock (testutils .Context (t ))
850834 require .NoError (t , err )
851835 assert .Equal (t , int64 (1 ), latest .BlockNumber )
852- th . assertHaveCanonical (t , 1 , 1 )
836+ requireDBMatchesGeth (t , th . ORM , th . Client )
853837
854838 // Test scenario: one log 2 block chain.
855839 // Chain gen <- 1 <- 2 (L1)
@@ -901,7 +885,7 @@ func TestLogPoller_PollAndSaveLogs(t *testing.T) {
901885 require .NoError (t , err )
902886 require .Len (t , lgs , 1 )
903887 assert .Equal (t , hexutil .MustDecode (`0x0000000000000000000000000000000000000000000000000000000000000002` ), lgs [0 ].Data )
904- th . assertHaveCanonical (t , 1 , 3 )
888+ requireDBMatchesGeth (t , th . ORM , th . Client )
905889
906890 parent , err := th .Client .BlockByNumber (testutils .Context (t ), big .NewInt (1 ))
907891 require .NoError (t , err )
@@ -936,8 +920,7 @@ func TestLogPoller_PollAndSaveLogs(t *testing.T) {
936920 assert .Equal (t , hexutil .MustDecode (`0x0000000000000000000000000000000000000000000000000000000000000001` ), lgs [0 ].Data )
937921 assert .Equal (t , int64 (3 ), lgs [1 ].BlockNumber )
938922 assert .Equal (t , hexutil .MustDecode (`0x0000000000000000000000000000000000000000000000000000000000000003` ), lgs [1 ].Data )
939- th .assertHaveCanonical (t , 1 , 1 )
940- th .assertHaveCanonical (t , 3 , 4 )
923+ requireDBMatchesGeth (t , th .ORM , th .Client )
941924 th .assertDontHave (t , 2 , 2 ) // 2 gets backfilled
942925
943926 // Test scenario: multiple logs per block for many blocks (also after reorg).
@@ -968,9 +951,7 @@ func TestLogPoller_PollAndSaveLogs(t *testing.T) {
968951 assert .Equal (t , th .EmitterAddress2 , lgs [1 ].Address )
969952 assert .Equal (t , hexutil .MustDecode (`0x0000000000000000000000000000000000000000000000000000000000000006` ), lgs [2 ].Data )
970953 assert .Equal (t , th .EmitterAddress1 , lgs [2 ].Address )
971- th .assertHaveCanonical (t , 1 , 1 )
972- th .assertDontHave (t , 2 , 2 ) // 2 gets backfilled
973- th .assertHaveCanonical (t , 3 , 6 )
954+ requireDBMatchesGeth (t , th .ORM , th .Client )
974955
975956 // Test scenario: node down for exactly finality + 2 blocks
976957 // Note we only backfill up to finalized - 1 blocks, because we need to save the
@@ -996,7 +977,7 @@ func TestLogPoller_PollAndSaveLogs(t *testing.T) {
996977 assert .Equal (t , int64 (8 ), lgs [1 ].BlockNumber )
997978 assert .Equal (t , hexutil .MustDecode (`0x0000000000000000000000000000000000000000000000000000000000000009` ), lgs [2 ].Data )
998979 assert .Equal (t , int64 (9 ), lgs [2 ].BlockNumber )
999- th . assertHaveCanonical (t , 8 , 10 )
980+ requireDBMatchesGeth (t , th . ORM , th . Client )
1000981
1001982 // Test scenario large backfill (multiple batches)
1002983 // Chain gen <- 1 <- 2 (L1_1) <- 3' L1_3 <- 4 <- 5 (L1_4, L2_5) <- 6 (L1_6) <- 7 (L1_7) <- 8 (L1_8) <- 9 (L1_9) <- 10..32
@@ -1017,9 +998,9 @@ func TestLogPoller_PollAndSaveLogs(t *testing.T) {
1017998 lgs , err = th .ORM .SelectLogsByBlockRange (testutils .Context (t ), 11 , 36 )
1018999 require .NoError (t , err )
10191000 assert .Len (t , lgs , 25 )
1020- th . assertHaveCanonical (t , 32 , 36 ) // Should have last finalized block plus unfinalized blocks
1021- th .assertDontHave (t , 11 , 13 ) // Should not have older finalized blocks
1022- th .assertDontHave (t , 14 , 16 ) // Should not have older finalized blocks
1001+ requireDBMatchesGeth (t , th . ORM , th . Client )
1002+ th .assertDontHave (t , 11 , 13 ) // Should not have older finalized blocks
1003+ th .assertDontHave (t , 14 , 16 ) // Should not have older finalized blocks
10231004
10241005 // Verify that a custom block timestamp will get written to db correctly also
10251006 b , err = th .Client .BlockByNumber (testutils .Context (t ), nil )
@@ -1206,9 +1187,8 @@ func TestLogPoller_PollAndSaveLogsDeepReorg(t *testing.T) {
12061187 require .NoError (t , err )
12071188 require .Len (t , lgs , 30 )
12081189 assert .Equal (t , hexutil .MustDecode (`0x0000000000000000000000000000000000000000000000000000000000000002` ), lgs [0 ].Data )
1209- th .assertHaveCanonical (t , 1 , 2 )
1210- th .assertDontHave (t , 2 , 31 ) // These blocks are backfilled
1211- th .assertHaveCanonical (t , 32 , 36 )
1190+ requireLBBlockIsFinalized (t , th .ORM , 30 )
1191+ requireDBMatchesGeth (t , th .ORM , th .Client )
12121192 })
12131193 }
12141194}
@@ -1557,27 +1537,25 @@ func TestTooManyLogResults(t *testing.T) {
15571537 }
15581538
15591539 var filterLogsCall * mock.Call
1560- head := & evmtypes.Head {}
1561- finalized := & evmtypes.Head {}
15621540
15631541 ec .On ("HeadByNumber" , mock .Anything , mock .Anything ).Return (func (ctx context.Context , blockNumber * big.Int ) (* evmtypes.Head , error ) {
15641542 if blockNumber == nil {
15651543 require .FailNow (t , "unexpected call to get current head" )
15661544 }
1567- return & evmtypes. Head { Number : blockNumber . Int64 (), ParentHash : common . HexToHash ( fmt . Sprintf ( "0x%x" , blockNumber .Int64 ()- 1 ))} , nil
1545+ return newHead ( blockNumber .Int64 ()) , nil
15681546 })
15691547
15701548 t .Run ("halves size until small enough, then succeeds" , func (t * testing.T ) {
15711549 // Simulate latestBlock = 300
1572- head .Number = 300
1573- head .Hash = common .HexToHash ("0x1234" ) // needed to satisfy validation in fetchBlocks()
1574- finalized .Number = head .Number - lpOpts .FinalityDepth
1550+ head := newHead (300 )
1551+ finalized := newHead (head .Number - lpOpts .FinalityDepth )
15751552
15761553 headTracker .On ("LatestAndFinalizedBlock" , mock .Anything ).Return (head , finalized , nil ).Once ()
15771554 headTracker .On ("LatestSafeBlock" , mock .Anything ).Return (finalized , nil ).Once ()
15781555
15791556 headByHash := ec .On ("HeadByHash" , mock .Anything , mock .Anything ).Return (func (ctx context.Context , blockHash common.Hash ) (* evmtypes.Head , error ) {
1580- return & evmtypes.Head {Hash : blockHash }, nil
1557+ num := new (big.Int ).SetBytes (blockHash .Bytes ()).Int64 ()
1558+ return newHead (num ), nil
15811559 })
15821560
15831561 batchCallContext := ec .On ("BatchCallContext" , mock .Anything , mock .Anything ).Return (
@@ -1591,11 +1569,7 @@ func TestTooManyLogResults(t *testing.T) {
15911569 blockNumber , ok := new (big.Int ).SetString (blockNumberHex [2 :], 16 )
15921570 require .True (t , ok , blockNumberHex )
15931571
1594- calls [i ].Result = & evmtypes.Head {
1595- Number : blockNumber .Int64 (),
1596- Hash : common .HexToHash (fmt .Sprintf ("0x%x" , blockNumber .Int64 ())),
1597- ParentHash : common .HexToHash (fmt .Sprintf ("0x%x" , blockNumber .Int64 ()- 1 )),
1598- }
1572+ calls [i ].Result = newHead (blockNumber .Int64 ())
15991573 }
16001574 return nil
16011575 },
@@ -1626,7 +1600,7 @@ func TestTooManyLogResults(t *testing.T) {
16261600 lp .PollAndSaveLogs (ctx , 5 , false )
16271601 block , err2 := o .SelectLatestBlock (ctx )
16281602 require .NoError (t , err2 )
1629- assert .Equal (t , int64 (298 ), block .BlockNumber )
1603+ assert .Equal (t , int64 (300 ), block .BlockNumber )
16301604
16311605 logs := obs .FilterLevelExact (zapcore .WarnLevel ).FilterMessageSnippet ("halving block range batch size" ).FilterFieldKey ("newBatchSize" ).All ()
16321606 // Should have tried again 3 times--first reducing batch size to 10, then 5, then 2
@@ -1644,8 +1618,8 @@ func TestTooManyLogResults(t *testing.T) {
16441618
16451619 // Now jump to block 500, but return error no matter how small the block range gets.
16461620 // Should exit the loop with a critical error instead of hanging.
1647- head . Number = 500
1648- finalized . Number = head .Number - lpOpts .FinalityDepth
1621+ head := newHead ( 500 )
1622+ finalized := newHead ( head .Number - lpOpts .FinalityDepth )
16491623 headTracker .On ("LatestAndFinalizedBlock" , mock .Anything ).Return (head , finalized , nil ).Once ()
16501624 headTracker .On ("LatestSafeBlock" , mock .Anything ).Return (finalized , nil ).Once ()
16511625 filterLogsCall = ec .On ("FilterLogs" , mock .Anything , mock .Anything ).Return (func (ctx context.Context , fq ethereum.FilterQuery ) (logs []types.Log , err error ) {
@@ -1660,7 +1634,7 @@ func TestTooManyLogResults(t *testing.T) {
16601634 if err != nil {
16611635 require .ErrorContains (t , err , "no rows" ) // In case this subtest is run by itself
16621636 } else {
1663- assert .Equal (t , int64 (298 ), block .BlockNumber )
1637+ assert .Equal (t , int64 (300 ), block .BlockNumber )
16641638 }
16651639 warns := obs .FilterMessageSnippet ("halving block range" ).FilterLevelExact (zapcore .WarnLevel ).All ()
16661640 crit := obs .FilterMessageSnippet ("failed to retrieve logs" ).FilterLevelExact (zapcore .DPanicLevel ).All ()
@@ -1676,8 +1650,8 @@ func TestTooManyLogResults(t *testing.T) {
16761650
16771651 t .Run ("Unrelated error are retried without adjusting size" , func (t * testing.T ) {
16781652 unrelatedError := errors .New ("Unrelated to the size of the request" )
1679- head . Number = 500
1680- finalized . Number = head .Number - lpOpts .FinalityDepth
1653+ head := newHead ( 500 )
1654+ finalized := newHead ( head .Number - lpOpts .FinalityDepth )
16811655
16821656 obs .TakeAll ()
16831657 filterLogsCall = ec .On ("FilterLogs" , mock .Anything , mock .Anything ).Return (func (ctx context.Context , fq ethereum.FilterQuery ) (logs []types.Log , err error ) {
@@ -1694,7 +1668,7 @@ func TestTooManyLogResults(t *testing.T) {
16941668 if err != nil {
16951669 require .ErrorContains (t , err , "no rows" ) // In case this subtest is run by itself
16961670 } else {
1697- assert .Equal (t , int64 (298 ), block .BlockNumber )
1671+ assert .Equal (t , int64 (300 ), block .BlockNumber )
16981672 }
16991673 crit := obs .FilterLevelExact (zapcore .DPanicLevel ).All ()
17001674 errors := obs .FilterLevelExact (zapcore .ErrorLevel ).All ()
@@ -2258,10 +2232,59 @@ func TestLogPoller_Reorg_On_Replay(t *testing.T) {
22582232 require .Len (t , logs , 1 )
22592233 require .Equal (t , newLogData , big .NewInt (0 ).SetBytes (logs [0 ].Data ).Int64 (), "Log data should match the log from the new block, indicating that the old block's log was properly removed during replay" )
22602234 // Ensure reorged block was replaced by a new one
2261- dbBlock , err := th .ORM .SelectBlockByNumber (testutils .Context (t ), reorgedBlock .Number ().Int64 ())
2262- require .NoError (t , err )
2263- require .Equal (t , reorgedBlock .Number ().Int64 (), dbBlock .BlockNumber )
2264- require .NotEqual (t , reorgedBlock .Hash (), dbBlock .BlockHash )
2235+ requireDBMatchesGeth (t , th .ORM , th .Client )
22652236 })
22662237 }
22672238}
2239+
2240+ func requireDBMatchesGeth (t * testing.T , orm logpoller.ORM , client logpoller.Client ) {
2241+ require .True (t , checkDBMatchesGeth (t , orm , client ), "DB state does not match geth canonical chain" )
2242+ }
2243+
2244+ func checkDBMatchesGeth (t * testing.T , orm logpoller.ORM , client logpoller.Client ) bool {
2245+ // Check every block is identical
2246+ latest , err1 := client .HeadByNumber (testutils .Context (t ), nil )
2247+ require .NoError (t , err1 )
2248+ dbBlocks , err := orm .SelectLogsByBlockRange (t .Context (), 0 , latest .Number )
2249+ require .NoError (t , err )
2250+ // ensure all blocks present in db are on geth canonical chain
2251+ for _ , ourBlock := range dbBlocks {
2252+ gethBlock , err1 := client .HeadByNumber (testutils .Context (t ), big .NewInt (ourBlock .BlockNumber ))
2253+ require .NoError (t , err1 )
2254+ if ourBlock .BlockHash != gethBlock .Hash {
2255+ t .Logf ("Initial poll our block differs at height %d got %x want %x\n " , ourBlock .BlockNumber , ourBlock .BlockHash , gethBlock .Hash )
2256+ return false
2257+ }
2258+ }
2259+
2260+ latestDB , err := orm .SelectLatestBlock (t .Context ())
2261+ require .NoError (t , err )
2262+ require .Equal (t , latest .Number , latestDB .BlockNumber , "latest block number in db should match geth" )
2263+
2264+ // ensure all logs present in db are on geth canonical chain
2265+ logs , err1 := orm .SelectLogsByBlockRange (t .Context (), 0 , latest .Number )
2266+ require .NoError (t , err1 )
2267+ for _ , log := range logs {
2268+ gethBlock , err1 := client .HeadByNumber (testutils .Context (t ), big .NewInt (log .BlockNumber ))
2269+ require .NoError (t , err1 )
2270+ if log .BlockHash != gethBlock .Hash {
2271+ t .Logf ("Log present in db, is not present in canonical chain. Log block number %d, Log block Hash: %s, block hash %s\n " , log .BlockNumber , log .BlockHash , gethBlock .Hash )
2272+ return false
2273+ }
2274+ }
2275+ return true
2276+ }
2277+
2278+ func requireLBBlockIsFinalized (t * testing.T , orm logpoller.ORM , block int64 ) {
2279+ latest , err := orm .SelectLatestBlock (t .Context ())
2280+ require .NoError (t , err )
2281+ require .GreaterOrEqual (t , latest .FinalizedBlockNumber , block , "specified block should be finalized" )
2282+ }
2283+
2284+ func newHead (num int64 ) * evmtypes.Head {
2285+ return & evmtypes.Head {
2286+ Number : num ,
2287+ Hash : common .BigToHash (big .NewInt (num )),
2288+ ParentHash : common .BigToHash (big .NewInt (num - 1 )),
2289+ }
2290+ }
0 commit comments