@@ -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 },
@@ -1629,7 +1603,7 @@ func TestTooManyLogResults(t *testing.T) {
16291603 lp .PollAndSaveLogs (ctx , 5 , false )
16301604 block , err2 := o .SelectLatestBlock (ctx )
16311605 require .NoError (t , err2 )
1632- assert .Equal (t , int64 (298 ), block .BlockNumber )
1606+ assert .Equal (t , int64 (300 ), block .BlockNumber )
16331607
16341608 logs := obs .FilterLevelExact (zapcore .WarnLevel ).FilterMessageSnippet ("halving block range batch size" ).FilterFieldKey ("newBatchSize" ).All ()
16351609 // Should have tried again 3 times--first reducing batch size to 10, then 5, then 2
@@ -1647,8 +1621,8 @@ func TestTooManyLogResults(t *testing.T) {
16471621
16481622 // Now jump to block 500, but return error no matter how small the block range gets.
16491623 // Should exit the loop with a critical error instead of hanging.
1650- head . Number = 500
1651- finalized . Number = head .Number - lpOpts .FinalityDepth
1624+ head := newHead ( 500 )
1625+ finalized := newHead ( head .Number - lpOpts .FinalityDepth )
16521626 headTracker .On ("LatestAndFinalizedBlock" , mock .Anything ).Return (head , finalized , nil ).Once ()
16531627 headTracker .On ("LatestSafeBlock" , mock .Anything ).Return (finalized , nil ).Once ()
16541628 filterLogsCall = ec .On ("FilterLogs" , mock .Anything , mock .Anything ).Return (func (ctx context.Context , fq ethereum.FilterQuery ) (logs []types.Log , err error ) {
@@ -1663,7 +1637,7 @@ func TestTooManyLogResults(t *testing.T) {
16631637 if err != nil {
16641638 require .ErrorContains (t , err , "no rows" ) // In case this subtest is run by itself
16651639 } else {
1666- assert .Equal (t , int64 (298 ), block .BlockNumber )
1640+ assert .Equal (t , int64 (300 ), block .BlockNumber )
16671641 }
16681642 warns := obs .FilterMessageSnippet ("halving block range" ).FilterLevelExact (zapcore .WarnLevel ).All ()
16691643 crit := obs .FilterMessageSnippet ("failed to retrieve logs" ).FilterLevelExact (zapcore .DPanicLevel ).All ()
@@ -1679,8 +1653,8 @@ func TestTooManyLogResults(t *testing.T) {
16791653
16801654 t .Run ("Unrelated error are retried without adjusting size" , func (t * testing.T ) {
16811655 unrelatedError := errors .New ("Unrelated to the size of the request" )
1682- head . Number = 500
1683- finalized . Number = head .Number - lpOpts .FinalityDepth
1656+ head := newHead ( 500 )
1657+ finalized := newHead ( head .Number - lpOpts .FinalityDepth )
16841658
16851659 obs .TakeAll ()
16861660 filterLogsCall = ec .On ("FilterLogs" , mock .Anything , mock .Anything ).Return (func (ctx context.Context , fq ethereum.FilterQuery ) (logs []types.Log , err error ) {
@@ -1697,7 +1671,7 @@ func TestTooManyLogResults(t *testing.T) {
16971671 if err != nil {
16981672 require .ErrorContains (t , err , "no rows" ) // In case this subtest is run by itself
16991673 } else {
1700- assert .Equal (t , int64 (298 ), block .BlockNumber )
1674+ assert .Equal (t , int64 (300 ), block .BlockNumber )
17011675 }
17021676 crit := obs .FilterLevelExact (zapcore .DPanicLevel ).All ()
17031677 errors := obs .FilterLevelExact (zapcore .ErrorLevel ).All ()
@@ -2261,10 +2235,59 @@ func TestLogPoller_Reorg_On_Replay(t *testing.T) {
22612235 require .Len (t , logs , 1 )
22622236 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" )
22632237 // Ensure reorged block was replaced by a new one
2264- dbBlock , err := th .ORM .SelectBlockByNumber (testutils .Context (t ), reorgedBlock .Number ().Int64 ())
2265- require .NoError (t , err )
2266- require .Equal (t , reorgedBlock .Number ().Int64 (), dbBlock .BlockNumber )
2267- require .NotEqual (t , reorgedBlock .Hash (), dbBlock .BlockHash )
2238+ requireDBMatchesGeth (t , th .ORM , th .Client )
22682239 })
22692240 }
22702241}
2242+
2243+ func requireDBMatchesGeth (t * testing.T , orm logpoller.ORM , client logpoller.Client ) {
2244+ require .True (t , checkDBMatchesGeth (t , orm , client ), "DB state does not match geth canonical chain" )
2245+ }
2246+
2247+ func checkDBMatchesGeth (t * testing.T , orm logpoller.ORM , client logpoller.Client ) bool {
2248+ // Check every block is identical
2249+ latest , err1 := client .HeadByNumber (testutils .Context (t ), nil )
2250+ require .NoError (t , err1 )
2251+ dbBlocks , err := orm .SelectLogsByBlockRange (t .Context (), 0 , latest .Number )
2252+ require .NoError (t , err )
2253+ // ensure all blocks present in db are on geth canonical chain
2254+ for _ , ourBlock := range dbBlocks {
2255+ gethBlock , err1 := client .HeadByNumber (testutils .Context (t ), big .NewInt (ourBlock .BlockNumber ))
2256+ require .NoError (t , err1 )
2257+ if ourBlock .BlockHash != gethBlock .Hash {
2258+ t .Logf ("Initial poll our block differs at height %d got %x want %x\n " , ourBlock .BlockNumber , ourBlock .BlockHash , gethBlock .Hash )
2259+ return false
2260+ }
2261+ }
2262+
2263+ latestDB , err := orm .SelectLatestBlock (t .Context ())
2264+ require .NoError (t , err )
2265+ require .Equal (t , latest .Number , latestDB .BlockNumber , "latest block number in db should match geth" )
2266+
2267+ // ensure all logs present in db are on geth canonical chain
2268+ logs , err1 := orm .SelectLogsByBlockRange (t .Context (), 0 , latest .Number )
2269+ require .NoError (t , err1 )
2270+ for _ , log := range logs {
2271+ gethBlock , err1 := client .HeadByNumber (testutils .Context (t ), big .NewInt (log .BlockNumber ))
2272+ require .NoError (t , err1 )
2273+ if log .BlockHash != gethBlock .Hash {
2274+ 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 )
2275+ return false
2276+ }
2277+ }
2278+ return true
2279+ }
2280+
2281+ func requireLBBlockIsFinalized (t * testing.T , orm logpoller.ORM , block int64 ) {
2282+ latest , err := orm .SelectLatestBlock (t .Context ())
2283+ require .NoError (t , err )
2284+ require .GreaterOrEqual (t , latest .FinalizedBlockNumber , block , "specified block should be finalized" )
2285+ }
2286+
2287+ func newHead (num int64 ) * evmtypes.Head {
2288+ return & evmtypes.Head {
2289+ Number : num ,
2290+ Hash : common .BigToHash (big .NewInt (num )),
2291+ ParentHash : common .BigToHash (big .NewInt (num - 1 )),
2292+ }
2293+ }
0 commit comments