@@ -3676,3 +3676,85 @@ func TestEIP1559Transition(t *testing.T) {
36763676 t .Fatalf ("sender balance incorrect: expected %d, got %d" , expected , actual )
36773677 }
36783678}
3679+
3680+ // Tests the scenario the chain is requested to another point with the missing state.
3681+ // It expects the state is recovered and all relevant chain markers are set correctly.
3682+ func TestSetCanonical (t * testing.T ) {
3683+ //log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
3684+
3685+ var (
3686+ db = rawdb .NewMemoryDatabase ()
3687+ key , _ = crypto .HexToECDSA ("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291" )
3688+ address = crypto .PubkeyToAddress (key .PublicKey )
3689+ funds = big .NewInt (100000000000000000 )
3690+ gspec = & Genesis {
3691+ Config : params .TestChainConfig ,
3692+ Alloc : GenesisAlloc {address : {Balance : funds }},
3693+ BaseFee : big .NewInt (params .InitialBaseFee ),
3694+ }
3695+ genesis = gspec .MustCommit (db )
3696+ signer = types .LatestSigner (gspec .Config )
3697+ engine = ethash .NewFaker ()
3698+ )
3699+ // Generate and import the canonical chain
3700+ canon , _ := GenerateChain (params .TestChainConfig , genesis , engine , db , 2 * TriesInMemory , func (i int , gen * BlockGen ) {
3701+ tx , err := types .SignTx (types .NewTransaction (gen .TxNonce (address ), common.Address {0x00 }, big .NewInt (1000 ), params .TxGas , gen .header .BaseFee , nil ), signer , key )
3702+ if err != nil {
3703+ panic (err )
3704+ }
3705+ gen .AddTx (tx )
3706+ })
3707+ diskdb := rawdb .NewMemoryDatabase ()
3708+ gspec .MustCommit (diskdb )
3709+
3710+ chain , err := NewBlockChain (diskdb , nil , params .TestChainConfig , engine , vm.Config {}, nil , nil )
3711+ if err != nil {
3712+ t .Fatalf ("failed to create tester chain: %v" , err )
3713+ }
3714+ if n , err := chain .InsertChain (canon ); err != nil {
3715+ t .Fatalf ("block %d: failed to insert into chain: %v" , n , err )
3716+ }
3717+
3718+ // Generate the side chain and import them
3719+ side , _ := GenerateChain (params .TestChainConfig , genesis , engine , db , 2 * TriesInMemory , func (i int , gen * BlockGen ) {
3720+ tx , err := types .SignTx (types .NewTransaction (gen .TxNonce (address ), common.Address {0x00 }, big .NewInt (1 ), params .TxGas , gen .header .BaseFee , nil ), signer , key )
3721+ if err != nil {
3722+ panic (err )
3723+ }
3724+ gen .AddTx (tx )
3725+ })
3726+ for _ , block := range side {
3727+ err := chain .InsertBlockWithoutSetHead (block )
3728+ if err != nil {
3729+ t .Fatalf ("Failed to insert into chain: %v" , err )
3730+ }
3731+ }
3732+ for _ , block := range side {
3733+ got := chain .GetBlockByHash (block .Hash ())
3734+ if got == nil {
3735+ t .Fatalf ("Lost the inserted block" )
3736+ }
3737+ }
3738+
3739+ // Set the chain head to the side chain, ensure all the relevant markers are updated.
3740+ verify := func (head * types.Block ) {
3741+ if chain .CurrentBlock ().Hash () != head .Hash () {
3742+ t .Fatalf ("Unexpected block hash, want %x, got %x" , head .Hash (), chain .CurrentBlock ().Hash ())
3743+ }
3744+ if chain .CurrentFastBlock ().Hash () != head .Hash () {
3745+ t .Fatalf ("Unexpected fast block hash, want %x, got %x" , head .Hash (), chain .CurrentFastBlock ().Hash ())
3746+ }
3747+ if chain .CurrentHeader ().Hash () != head .Hash () {
3748+ t .Fatalf ("Unexpected head header, want %x, got %x" , head .Hash (), chain .CurrentHeader ().Hash ())
3749+ }
3750+ if ! chain .HasState (head .Root ()) {
3751+ t .Fatalf ("Lost block state %v %x" , head .Number (), head .Hash ())
3752+ }
3753+ }
3754+ chain .SetCanonical (side [len (side )- 1 ])
3755+ verify (side [len (side )- 1 ])
3756+
3757+ // Reset the chain head to original chain
3758+ chain .SetCanonical (canon [TriesInMemory - 1 ])
3759+ verify (canon [TriesInMemory - 1 ])
3760+ }
0 commit comments