@@ -3758,3 +3758,112 @@ func TestSetCanonical(t *testing.T) {
37583758 chain .SetCanonical (canon [TriesInMemory - 1 ])
37593759 verify (canon [TriesInMemory - 1 ])
37603760}
3761+
3762+ // TestCanonicalHashMarker tests all the canonical hash markers are updated/deleted
3763+ // correctly in case reorg is called.
3764+ func TestCanonicalHashMarker (t * testing.T ) {
3765+ var cases = []struct {
3766+ forkA int
3767+ forkB int
3768+ }{
3769+ // ForkA: 10 blocks
3770+ // ForkB: 1 blocks
3771+ //
3772+ // reorged:
3773+ // markers [2, 10] should be deleted
3774+ // markers [1] should be updated
3775+ {10 , 1 },
3776+
3777+ // ForkA: 10 blocks
3778+ // ForkB: 2 blocks
3779+ //
3780+ // reorged:
3781+ // markers [3, 10] should be deleted
3782+ // markers [1, 2] should be updated
3783+ {10 , 2 },
3784+
3785+ // ForkA: 10 blocks
3786+ // ForkB: 10 blocks
3787+ //
3788+ // reorged:
3789+ // markers [1, 10] should be updated
3790+ {10 , 10 },
3791+
3792+ // ForkA: 10 blocks
3793+ // ForkB: 11 blocks
3794+ //
3795+ // reorged:
3796+ // markers [1, 11] should be updated
3797+ {10 , 11 },
3798+ }
3799+ for _ , c := range cases {
3800+ var (
3801+ db = rawdb .NewMemoryDatabase ()
3802+ gspec = & Genesis {
3803+ Config : params .TestChainConfig ,
3804+ Alloc : GenesisAlloc {},
3805+ BaseFee : big .NewInt (params .InitialBaseFee ),
3806+ }
3807+ genesis = gspec .MustCommit (db )
3808+ engine = ethash .NewFaker ()
3809+ )
3810+ forkA , _ := GenerateChain (params .TestChainConfig , genesis , engine , db , c .forkA , func (i int , gen * BlockGen ) {})
3811+ forkB , _ := GenerateChain (params .TestChainConfig , genesis , engine , db , c .forkB , func (i int , gen * BlockGen ) {})
3812+
3813+ // Initialize test chain
3814+ diskdb := rawdb .NewMemoryDatabase ()
3815+ gspec .MustCommit (diskdb )
3816+ chain , err := NewBlockChain (diskdb , nil , params .TestChainConfig , engine , vm.Config {}, nil , nil )
3817+ if err != nil {
3818+ t .Fatalf ("failed to create tester chain: %v" , err )
3819+ }
3820+ // Insert forkA and forkB, the canonical should on forkA still
3821+ if n , err := chain .InsertChain (forkA ); err != nil {
3822+ t .Fatalf ("block %d: failed to insert into chain: %v" , n , err )
3823+ }
3824+ if n , err := chain .InsertChain (forkB ); err != nil {
3825+ t .Fatalf ("block %d: failed to insert into chain: %v" , n , err )
3826+ }
3827+
3828+ verify := func (head * types.Block ) {
3829+ if chain .CurrentBlock ().Hash () != head .Hash () {
3830+ t .Fatalf ("Unexpected block hash, want %x, got %x" , head .Hash (), chain .CurrentBlock ().Hash ())
3831+ }
3832+ if chain .CurrentFastBlock ().Hash () != head .Hash () {
3833+ t .Fatalf ("Unexpected fast block hash, want %x, got %x" , head .Hash (), chain .CurrentFastBlock ().Hash ())
3834+ }
3835+ if chain .CurrentHeader ().Hash () != head .Hash () {
3836+ t .Fatalf ("Unexpected head header, want %x, got %x" , head .Hash (), chain .CurrentHeader ().Hash ())
3837+ }
3838+ if ! chain .HasState (head .Root ()) {
3839+ t .Fatalf ("Lost block state %v %x" , head .Number (), head .Hash ())
3840+ }
3841+ }
3842+
3843+ // Switch canonical chain to forkB if necessary
3844+ if len (forkA ) < len (forkB ) {
3845+ verify (forkB [len (forkB )- 1 ])
3846+ } else {
3847+ verify (forkA [len (forkA )- 1 ])
3848+ chain .SetCanonical (forkB [len (forkB )- 1 ])
3849+ verify (forkB [len (forkB )- 1 ])
3850+ }
3851+
3852+ // Ensure all hash markers are updated correctly
3853+ for i := 0 ; i < len (forkB ); i ++ {
3854+ block := forkB [i ]
3855+ hash := chain .GetCanonicalHash (block .NumberU64 ())
3856+ if hash != block .Hash () {
3857+ t .Fatalf ("Unexpected canonical hash %d" , block .NumberU64 ())
3858+ }
3859+ }
3860+ if c .forkA > c .forkB {
3861+ for i := uint64 (c .forkB ) + 1 ; i <= uint64 (c .forkA ); i ++ {
3862+ hash := chain .GetCanonicalHash (i )
3863+ if hash != (common.Hash {}) {
3864+ t .Fatalf ("Unexpected canonical hash %d" , i )
3865+ }
3866+ }
3867+ }
3868+ }
3869+ }
0 commit comments