gitlab.com/flarenetwork/coreth@v0.1.1/core/test_blockchain.go (about)

     1  // (c) 2020-2021, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package core
     5  
     6  import (
     7  	"fmt"
     8  	"math/big"
     9  	"testing"
    10  
    11  	"github.com/ethereum/go-ethereum/common"
    12  	"github.com/ethereum/go-ethereum/crypto"
    13  	"github.com/ethereum/go-ethereum/ethdb"
    14  	"gitlab.com/flarenetwork/coreth/core/rawdb"
    15  	"gitlab.com/flarenetwork/coreth/core/state"
    16  	"gitlab.com/flarenetwork/coreth/core/types"
    17  	"gitlab.com/flarenetwork/coreth/params"
    18  )
    19  
    20  type ChainTest struct {
    21  	Name     string
    22  	testFunc func(
    23  		t *testing.T,
    24  		create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error),
    25  	)
    26  }
    27  
    28  var tests = []ChainTest{
    29  	{
    30  		"InsertChainAcceptSingleBlock",
    31  		TestInsertChainAcceptSingleBlock,
    32  	},
    33  	{
    34  		"InsertForkedChain",
    35  		TestInsertLongForkedChain,
    36  	},
    37  	{
    38  		"AcceptNonCanonicalBlock",
    39  		TestAcceptNonCanonicalBlock,
    40  	},
    41  	{
    42  		"SetPreferenceRewind",
    43  		TestSetPreferenceRewind,
    44  	},
    45  	{
    46  		"BuildOnVariousStages",
    47  		TestBuildOnVariousStages,
    48  	},
    49  	{
    50  		"EmptyBlocks",
    51  		TestEmptyBlocks,
    52  	},
    53  	{
    54  		"AcceptBlockIdenticalStateRoot",
    55  		TestAcceptBlockIdenticalStateRoot,
    56  	},
    57  	{
    58  		"ReprocessAcceptBlockIdenticalStateRoot",
    59  		TestReprocessAcceptBlockIdenticalStateRoot,
    60  	},
    61  }
    62  
    63  func copyMemDB(db ethdb.Database) (ethdb.Database, error) {
    64  	newDB := rawdb.NewMemoryDatabase()
    65  	iter := db.NewIterator(nil, nil)
    66  	defer iter.Release()
    67  	for iter.Next() {
    68  		if err := newDB.Put(iter.Key(), iter.Value()); err != nil {
    69  			return nil, err
    70  		}
    71  	}
    72  
    73  	return newDB, nil
    74  }
    75  
    76  // checkBlockChainState creates a new BlockChain instance and checks that exporting each block from
    77  // genesis to last acceptd from the original instance yields the same last accepted block and state
    78  // root.
    79  // Additionally, create another BlockChain instance from [originalDB] to ensure that BlockChain is
    80  // persisted correctly through a restart.
    81  func checkBlockChainState(
    82  	t *testing.T,
    83  	bc *BlockChain,
    84  	genesis *Genesis,
    85  	originalDB ethdb.Database,
    86  	create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error),
    87  	checkState func(sdb *state.StateDB) error,
    88  ) (*BlockChain, *BlockChain, *BlockChain) {
    89  	var (
    90  		chainConfig       = bc.Config()
    91  		lastAcceptedBlock = bc.LastAcceptedBlock()
    92  		newDB             = rawdb.NewMemoryDatabase()
    93  	)
    94  
    95  	acceptedState, err := bc.StateAt(lastAcceptedBlock.Root())
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  	if err := checkState(acceptedState); err != nil {
   100  		t.Fatalf("Check state failed for original blockchain due to: %s", err)
   101  	}
   102  
   103  	_ = genesis.MustCommit(newDB)
   104  
   105  	newBlockChain, err := create(newDB, chainConfig, common.Hash{})
   106  	if err != nil {
   107  		t.Fatalf("Failed to create new blockchain instance: %s", err)
   108  	}
   109  
   110  	for i := uint64(1); i <= lastAcceptedBlock.NumberU64(); i++ {
   111  		block := bc.GetBlockByNumber(i)
   112  		if block == nil {
   113  			t.Fatalf("Failed to retrieve block by number %d from original chain", i)
   114  		}
   115  		if err := newBlockChain.InsertBlock(block); err != nil {
   116  			t.Fatalf("Failed to insert block %s:%d due to %s", block.Hash().Hex(), block.NumberU64(), err)
   117  		}
   118  		if err := newBlockChain.Accept(block); err != nil {
   119  			t.Fatalf("Failed to accept block %s:%d due to %s", block.Hash().Hex(), block.NumberU64(), err)
   120  		}
   121  	}
   122  
   123  	newLastAcceptedBlock := newBlockChain.LastAcceptedBlock()
   124  	if newLastAcceptedBlock.Hash() != lastAcceptedBlock.Hash() {
   125  		t.Fatalf("Expected new blockchain to have last accepted block %s:%d, but found %s:%d", lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64(), newLastAcceptedBlock.Hash().Hex(), newLastAcceptedBlock.NumberU64())
   126  	}
   127  
   128  	// Check that the state of [newBlockChain] passes the check
   129  	acceptedState, err = newBlockChain.StateAt(lastAcceptedBlock.Root())
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	if err := checkState(acceptedState); err != nil {
   134  		t.Fatalf("Check state failed for newly generated blockchain due to: %s", err)
   135  	}
   136  
   137  	// Copy the database over to prevent any issues when re-using [originalDB] after this call.
   138  	originalDB, err = copyMemDB(originalDB)
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  	restartedChain, err := create(originalDB, chainConfig, lastAcceptedBlock.Hash())
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  	defer restartedChain.Stop()
   147  	if currentBlock := restartedChain.CurrentBlock(); currentBlock.Hash() != lastAcceptedBlock.Hash() {
   148  		t.Fatalf("Expected restarted chain to have current block %s:%d, but found %s:%d", lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
   149  	}
   150  	if restartedLastAcceptedBlock := restartedChain.LastAcceptedBlock(); restartedLastAcceptedBlock.Hash() != lastAcceptedBlock.Hash() {
   151  		t.Fatalf("Expected restarted chain to have current block %s:%d, but found %s:%d", lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64(), restartedLastAcceptedBlock.Hash().Hex(), restartedLastAcceptedBlock.NumberU64())
   152  	}
   153  
   154  	// Check that the state of [restartedChain] passes the check
   155  	acceptedState, err = restartedChain.StateAt(lastAcceptedBlock.Root())
   156  	if err != nil {
   157  		t.Fatal(err)
   158  	}
   159  	if err := checkState(acceptedState); err != nil {
   160  		t.Fatalf("Check state failed for restarted blockchain due to: %s", err)
   161  	}
   162  
   163  	return bc, newBlockChain, restartedChain
   164  }
   165  
   166  func TestInsertChainAcceptSingleBlock(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   167  	var (
   168  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   169  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   170  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   171  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   172  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   173  		// database.
   174  		genDB   = rawdb.NewMemoryDatabase()
   175  		chainDB = rawdb.NewMemoryDatabase()
   176  	)
   177  
   178  	// Ensure that key1 has some funds in the genesis block.
   179  	genesisBalance := big.NewInt(1000000)
   180  	gspec := &Genesis{
   181  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   182  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   183  	}
   184  	genesis := gspec.MustCommit(genDB)
   185  	_ = gspec.MustCommit(chainDB)
   186  
   187  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   188  	if err != nil {
   189  		t.Fatal(err)
   190  	}
   191  	defer blockchain.Stop()
   192  
   193  	// This call generates a chain of 3 blocks.
   194  	signer := types.HomesteadSigner{}
   195  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   196  	// to the BlockChain's database while generating blocks.
   197  	chain, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, func(i int, gen *BlockGen) {
   198  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   199  		gen.AddTx(tx)
   200  	})
   201  
   202  	// Insert three blocks into the chain and accept only the first block.
   203  	if _, err := blockchain.InsertChain(chain); err != nil {
   204  		t.Fatal(err)
   205  	}
   206  	if err := blockchain.Accept(chain[0]); err != nil {
   207  		t.Fatal(err)
   208  	}
   209  
   210  	// check the state of the last accepted block
   211  	checkState := func(sdb *state.StateDB) error {
   212  		nonce := sdb.GetNonce(addr1)
   213  		if nonce != 1 {
   214  			return fmt.Errorf("expected nonce addr1: 1, found nonce: %d", nonce)
   215  		}
   216  		transferredFunds := big.NewInt(10000)
   217  		balance1 := sdb.GetBalance(addr1)
   218  		expectedBalance1 := new(big.Int).Sub(genesisBalance, transferredFunds)
   219  		if balance1.Cmp(expectedBalance1) != 0 {
   220  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance1, balance1)
   221  		}
   222  
   223  		balance2 := sdb.GetBalance(addr2)
   224  		expectedBalance2 := transferredFunds
   225  		if balance2.Cmp(expectedBalance2) != 0 {
   226  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2)
   227  		}
   228  
   229  		nonce = sdb.GetNonce(addr2)
   230  		if nonce != 0 {
   231  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce)
   232  		}
   233  		return nil
   234  	}
   235  
   236  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   237  }
   238  
   239  func TestInsertLongForkedChain(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   240  	var (
   241  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   242  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   243  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   244  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   245  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   246  		// database.
   247  		genDB   = rawdb.NewMemoryDatabase()
   248  		chainDB = rawdb.NewMemoryDatabase()
   249  	)
   250  
   251  	// Ensure that key1 has some funds in the genesis block.
   252  	genesisBalance := big.NewInt(1000000000)
   253  	gspec := &Genesis{
   254  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   255  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   256  	}
   257  	genesis := gspec.MustCommit(genDB)
   258  	_ = gspec.MustCommit(chainDB)
   259  
   260  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   261  	if err != nil {
   262  		t.Fatal(err)
   263  	}
   264  	defer blockchain.Stop()
   265  
   266  	numBlocks := 129
   267  	signer := types.HomesteadSigner{}
   268  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   269  	// to the BlockChain's database while generating blocks.
   270  	chain1, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, func(i int, gen *BlockGen) {
   271  		// Generate a transaction to create a unique block
   272  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   273  		gen.AddTx(tx)
   274  	})
   275  	// Generate the forked chain to be longer than the original chain to check for a regression where
   276  	// a longer chain can trigger a reorg.
   277  	chain2, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks+1, func(i int, gen *BlockGen) {
   278  		// Generate a transaction with a different amount to ensure [chain2] is different than [chain1].
   279  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(5000), params.TxGas, nil, nil), signer, key1)
   280  		gen.AddTx(tx)
   281  	})
   282  
   283  	if blockchain.snaps != nil {
   284  		if want, got := 1, blockchain.snaps.NumBlockLayers(); got != want {
   285  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   286  		}
   287  	}
   288  
   289  	// Insert both chains.
   290  	if _, err := blockchain.InsertChain(chain1); err != nil {
   291  		t.Fatal(err)
   292  	}
   293  
   294  	if blockchain.snaps != nil {
   295  		if want, got := 1+len(chain1), blockchain.snaps.NumBlockLayers(); got != want {
   296  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   297  		}
   298  	}
   299  
   300  	if _, err := blockchain.InsertChain(chain2); err != nil {
   301  		t.Fatal(err)
   302  	}
   303  
   304  	if blockchain.snaps != nil {
   305  		if want, got := 1+len(chain1)+len(chain2), blockchain.snaps.NumBlockLayers(); got != want {
   306  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   307  		}
   308  	}
   309  
   310  	currentBlock := blockchain.CurrentBlock()
   311  	expectedCurrentBlock := chain1[len(chain1)-1]
   312  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
   313  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
   314  	}
   315  
   316  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   317  		t.Fatal(err)
   318  	}
   319  
   320  	// Accept the first block in [chain1], reject all blocks in [chain2] to
   321  	// mimic the order that the consensus engine will call Accept/Reject in
   322  	// and then Accept the rest of the blocks in [chain1].
   323  	if err := blockchain.Accept(chain1[0]); err != nil {
   324  		t.Fatal(err)
   325  	}
   326  
   327  	if blockchain.snaps != nil {
   328  		// Snap layer count should be 1 fewer
   329  		if want, got := len(chain1)+len(chain2), blockchain.snaps.NumBlockLayers(); got != want {
   330  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   331  		}
   332  	}
   333  
   334  	for i := 0; i < len(chain2); i++ {
   335  		if err := blockchain.Reject(chain2[i]); err != nil {
   336  			t.Fatal(err)
   337  		}
   338  
   339  		if blockchain.snaps != nil {
   340  			// Snap layer count should decrease by 1 per Reject
   341  			if want, got := len(chain1)+len(chain2)-i-1, blockchain.snaps.NumBlockLayers(); got != want {
   342  				t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   343  			}
   344  		}
   345  	}
   346  
   347  	if blockchain.snaps != nil {
   348  		if want, got := len(chain1), blockchain.snaps.NumBlockLayers(); got != want {
   349  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   350  		}
   351  	}
   352  
   353  	for i := 1; i < len(chain1); i++ {
   354  		if err := blockchain.Accept(chain1[i]); err != nil {
   355  			t.Fatal(err)
   356  		}
   357  
   358  		if blockchain.snaps != nil {
   359  			// Snap layer count should decrease by 1 per Accept
   360  			if want, got := len(chain1)-i, blockchain.snaps.NumBlockLayers(); got != want {
   361  				t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   362  			}
   363  		}
   364  	}
   365  
   366  	lastAcceptedBlock := blockchain.LastAcceptedBlock()
   367  	expectedLastAcceptedBlock := chain1[len(chain1)-1]
   368  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
   369  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
   370  	}
   371  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   372  		t.Fatal(err)
   373  	}
   374  
   375  	// check the state of the last accepted block
   376  	checkState := func(sdb *state.StateDB) error {
   377  		nonce1 := sdb.GetNonce(addr1)
   378  		if nonce1 != 129 {
   379  			return fmt.Errorf("expected addr1 nonce: 129, found nonce %d", nonce1)
   380  		}
   381  		balance1 := sdb.GetBalance(addr1)
   382  		transferredFunds := new(big.Int).Mul(big.NewInt(129), big.NewInt(10000))
   383  		expectedBalance := new(big.Int).Sub(genesisBalance, transferredFunds)
   384  		if balance1.Cmp(expectedBalance) != 0 {
   385  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance, balance1)
   386  		}
   387  		nonce2 := sdb.GetNonce(addr2)
   388  		if nonce2 != 0 {
   389  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce2)
   390  		}
   391  		balance2 := sdb.GetBalance(addr2)
   392  		if balance2.Cmp(transferredFunds) != 0 {
   393  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", transferredFunds, balance2)
   394  		}
   395  		return nil
   396  	}
   397  
   398  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   399  }
   400  
   401  func TestAcceptNonCanonicalBlock(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   402  	var (
   403  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   404  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   405  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   406  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   407  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   408  		// database.
   409  		genDB   = rawdb.NewMemoryDatabase()
   410  		chainDB = rawdb.NewMemoryDatabase()
   411  	)
   412  
   413  	// Ensure that key1 has some funds in the genesis block.
   414  	genesisBalance := big.NewInt(1000000000)
   415  	gspec := &Genesis{
   416  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   417  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   418  	}
   419  	genesis := gspec.MustCommit(genDB)
   420  	_ = gspec.MustCommit(chainDB)
   421  
   422  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   423  	if err != nil {
   424  		t.Fatal(err)
   425  	}
   426  	defer blockchain.Stop()
   427  
   428  	numBlocks := 3
   429  	signer := types.HomesteadSigner{}
   430  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   431  	// to the BlockChain's database while generating blocks.
   432  	chain1, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, func(i int, gen *BlockGen) {
   433  		// Generate a transaction to create a unique block
   434  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   435  		gen.AddTx(tx)
   436  	})
   437  	chain2, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, func(i int, gen *BlockGen) {
   438  		// Generate a transaction with a different amount to create a chain of blocks different from [chain1]
   439  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(5000), params.TxGas, nil, nil), signer, key1)
   440  		gen.AddTx(tx)
   441  	})
   442  
   443  	// Insert three blocks into the chain and accept only the first.
   444  	if _, err := blockchain.InsertChain(chain1); err != nil {
   445  		t.Fatal(err)
   446  	}
   447  	if _, err := blockchain.InsertChain(chain2); err != nil {
   448  		t.Fatal(err)
   449  	}
   450  
   451  	currentBlock := blockchain.CurrentBlock()
   452  	expectedCurrentBlock := chain1[len(chain1)-1]
   453  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
   454  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
   455  	}
   456  
   457  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   458  		t.Fatal(err)
   459  	}
   460  
   461  	// Accept the first block in [chain2], reject all blocks in [chain1] to
   462  	// mimic the order that the consensus engine will call Accept/Reject in.
   463  	if err := blockchain.Accept(chain2[0]); err != nil {
   464  		t.Fatal(err)
   465  	}
   466  	for i := 0; i < len(chain1); i++ {
   467  		if err := blockchain.Reject(chain1[i]); err != nil {
   468  			t.Fatal(err)
   469  		}
   470  	}
   471  
   472  	lastAcceptedBlock := blockchain.LastAcceptedBlock()
   473  	expectedLastAcceptedBlock := chain2[0]
   474  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
   475  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
   476  	}
   477  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   478  		t.Fatal(err)
   479  	}
   480  
   481  	// check the state of the last accepted block
   482  	checkState := func(sdb *state.StateDB) error {
   483  		nonce1 := sdb.GetNonce(addr1)
   484  		if nonce1 != 1 {
   485  			return fmt.Errorf("expected addr1 nonce: 1, found nonce: %d", nonce1)
   486  		}
   487  		balance1 := sdb.GetBalance(addr1)
   488  		transferredFunds := big.NewInt(5000)
   489  		expectedBalance := new(big.Int).Sub(genesisBalance, transferredFunds)
   490  		if balance1.Cmp(expectedBalance) != 0 {
   491  			return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1)
   492  		}
   493  		nonce2 := sdb.GetNonce(addr2)
   494  		if nonce2 != 0 {
   495  			return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2)
   496  		}
   497  		balance2 := sdb.GetBalance(addr2)
   498  		if balance2.Cmp(transferredFunds) != 0 {
   499  			return fmt.Errorf("expected balance2: %d, found %d", transferredFunds, balance2)
   500  		}
   501  		return nil
   502  	}
   503  
   504  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   505  }
   506  
   507  func TestSetPreferenceRewind(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   508  	var (
   509  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   510  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   511  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   512  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   513  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   514  		// database.
   515  		genDB   = rawdb.NewMemoryDatabase()
   516  		chainDB = rawdb.NewMemoryDatabase()
   517  	)
   518  
   519  	// Ensure that key1 has some funds in the genesis block.
   520  	genesisBalance := big.NewInt(1000000000)
   521  	gspec := &Genesis{
   522  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   523  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   524  	}
   525  	genesis := gspec.MustCommit(genDB)
   526  	_ = gspec.MustCommit(chainDB)
   527  
   528  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   529  	if err != nil {
   530  		t.Fatal(err)
   531  	}
   532  	defer blockchain.Stop()
   533  
   534  	numBlocks := 3
   535  	signer := types.HomesteadSigner{}
   536  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   537  	// to the BlockChain's database while generating blocks.
   538  	chain, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, func(i int, gen *BlockGen) {
   539  		// Generate a transaction to create a unique block
   540  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   541  		gen.AddTx(tx)
   542  	})
   543  
   544  	// Insert three blocks into the chain and accept only the first.
   545  	if _, err := blockchain.InsertChain(chain); err != nil {
   546  		t.Fatal(err)
   547  	}
   548  
   549  	currentBlock := blockchain.CurrentBlock()
   550  	expectedCurrentBlock := chain[len(chain)-1]
   551  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
   552  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
   553  	}
   554  
   555  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   556  		t.Fatal(err)
   557  	}
   558  
   559  	// SetPreference to an ancestor of the currently preferred block. Test that this unlikely, but possible behavior
   560  	// is handled correctly.
   561  	if err := blockchain.SetPreference(chain[0]); err != nil {
   562  		t.Fatal(err)
   563  	}
   564  
   565  	currentBlock = blockchain.CurrentBlock()
   566  	expectedCurrentBlock = chain[0]
   567  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
   568  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
   569  	}
   570  
   571  	lastAcceptedBlock := blockchain.LastAcceptedBlock()
   572  	expectedLastAcceptedBlock := blockchain.Genesis()
   573  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
   574  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
   575  	}
   576  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   577  		t.Fatal(err)
   578  	}
   579  	// check the state of the last accepted block
   580  	checkGenesisState := func(sdb *state.StateDB) error {
   581  		nonce1 := sdb.GetNonce(addr1)
   582  		if nonce1 != 0 {
   583  			return fmt.Errorf("expected addr1 nonce: 0, found nonce: %d", nonce1)
   584  		}
   585  		balance1 := sdb.GetBalance(addr1)
   586  		if balance1.Cmp(genesisBalance) != 0 {
   587  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", genesisBalance, balance1)
   588  		}
   589  		nonce2 := sdb.GetNonce(addr2)
   590  		if nonce2 != 0 {
   591  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce2)
   592  		}
   593  		balance2 := sdb.GetBalance(addr2)
   594  		if balance2.Cmp(big.NewInt(0)) != 0 {
   595  			return fmt.Errorf("expected addr2 balance: 0, found balance %d", balance2)
   596  		}
   597  		return nil
   598  	}
   599  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkGenesisState)
   600  
   601  	if err := blockchain.Accept(chain[0]); err != nil {
   602  		t.Fatal(err)
   603  	}
   604  	lastAcceptedBlock = blockchain.LastAcceptedBlock()
   605  	expectedLastAcceptedBlock = chain[0]
   606  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
   607  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
   608  	}
   609  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   610  		t.Fatal(err)
   611  	}
   612  	checkUpdatedState := func(sdb *state.StateDB) error {
   613  		nonce := sdb.GetNonce(addr1)
   614  		if nonce != 1 {
   615  			return fmt.Errorf("expected addr1 nonce: 1, found nonce: %d", nonce)
   616  		}
   617  		transferredFunds := big.NewInt(10000)
   618  		balance1 := sdb.GetBalance(addr1)
   619  		expectedBalance1 := new(big.Int).Sub(genesisBalance, transferredFunds)
   620  		if balance1.Cmp(expectedBalance1) != 0 {
   621  			return fmt.Errorf("expected addr1 balance: %d, found balance %d", expectedBalance1, balance1)
   622  		}
   623  
   624  		balance2 := sdb.GetBalance(addr2)
   625  		expectedBalance2 := transferredFunds
   626  		if balance2.Cmp(expectedBalance2) != 0 {
   627  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2)
   628  		}
   629  
   630  		nonce = sdb.GetNonce(addr2)
   631  		if nonce != 0 {
   632  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce)
   633  		}
   634  		return nil
   635  	}
   636  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkUpdatedState)
   637  }
   638  
   639  func TestBuildOnVariousStages(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   640  	var (
   641  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   642  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   643  		key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
   644  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   645  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   646  		addr3   = crypto.PubkeyToAddress(key3.PublicKey)
   647  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   648  		// database.
   649  		genDB   = rawdb.NewMemoryDatabase()
   650  		chainDB = rawdb.NewMemoryDatabase()
   651  	)
   652  
   653  	// Ensure that key1 has some funds in the genesis block.
   654  	genesisBalance := big.NewInt(1000000)
   655  	gspec := &Genesis{
   656  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   657  		Alloc: GenesisAlloc{
   658  			addr1: {Balance: genesisBalance},
   659  			addr3: {Balance: genesisBalance},
   660  		},
   661  	}
   662  	genesis := gspec.MustCommit(genDB)
   663  	_ = gspec.MustCommit(chainDB)
   664  
   665  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   666  	if err != nil {
   667  		t.Fatal(err)
   668  	}
   669  	defer blockchain.Stop()
   670  
   671  	// This call generates a chain of 3 blocks.
   672  	signer := types.HomesteadSigner{}
   673  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   674  	// to the BlockChain's database while generating blocks.
   675  	chain1, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 20, func(i int, gen *BlockGen) {
   676  		// Send all funds back and forth between the two accounts
   677  		if i%2 == 0 {
   678  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, genesisBalance, params.TxGas, nil, nil), signer, key1)
   679  			gen.AddTx(tx)
   680  		} else {
   681  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr1, genesisBalance, params.TxGas, nil, nil), signer, key2)
   682  			gen.AddTx(tx)
   683  		}
   684  	})
   685  	// Build second chain forked off of the 10th block in [chain1]
   686  	chain2, _ := GenerateChain(gspec.Config, chain1[9], blockchain.engine, genDB, 10, func(i int, gen *BlockGen) {
   687  		// Send all funds back and forth between the two accounts
   688  		if i%2 == 0 {
   689  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr2, genesisBalance, params.TxGas, nil, nil), signer, key3)
   690  			gen.AddTx(tx)
   691  		} else {
   692  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, genesisBalance, params.TxGas, nil, nil), signer, key2)
   693  			gen.AddTx(tx)
   694  		}
   695  	})
   696  	// Build third chain forked off of the 5th block in [chain1].
   697  	// The parent of this chain will be accepted before this fork
   698  	// is inserted.
   699  	chain3, _ := GenerateChain(gspec.Config, chain1[4], blockchain.engine, genDB, 10, func(i int, gen *BlockGen) {
   700  		// Send all funds back and forth between accounts 2 and 3.
   701  		if i%2 == 0 {
   702  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, genesisBalance, params.TxGas, nil, nil), signer, key2)
   703  			gen.AddTx(tx)
   704  		} else {
   705  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr2, genesisBalance, params.TxGas, nil, nil), signer, key3)
   706  			gen.AddTx(tx)
   707  		}
   708  	})
   709  
   710  	// Insert first 10 blocks from [chain1]
   711  	if _, err := blockchain.InsertChain(chain1); err != nil {
   712  		t.Fatal(err)
   713  	}
   714  	// Accept the first 5 blocks
   715  	for _, block := range chain1[0:5] {
   716  		if err := blockchain.Accept(block); err != nil {
   717  			t.Fatal(err)
   718  		}
   719  	}
   720  	// Insert the forked chain [chain2] which starts at the 10th
   721  	// block in [chain1] ie. a block that is still in processing.
   722  	if _, err := blockchain.InsertChain(chain2); err != nil {
   723  		t.Fatal(err)
   724  	}
   725  	// Insert another forked chain starting at the last accepted
   726  	// block from [chain1].
   727  	if _, err := blockchain.InsertChain(chain3); err != nil {
   728  		t.Fatal(err)
   729  	}
   730  	// Accept the next block in [chain1] and then reject all
   731  	// of the blocks in [chain3], which would then be rejected.
   732  	if err := blockchain.Accept(chain1[5]); err != nil {
   733  		t.Fatal(err)
   734  	}
   735  	for _, block := range chain3 {
   736  		if err := blockchain.Reject(block); err != nil {
   737  			t.Fatal(err)
   738  		}
   739  	}
   740  	// Accept the rest of the blocks in [chain1]
   741  	for _, block := range chain1[6:10] {
   742  		if err := blockchain.Accept(block); err != nil {
   743  			t.Fatal(err)
   744  		}
   745  	}
   746  
   747  	// Accept the first block in [chain2] and reject the
   748  	// subsequent blocks in [chain1] which would then be rejected.
   749  	if err := blockchain.Accept(chain2[0]); err != nil {
   750  		t.Fatal(err)
   751  	}
   752  	for _, block := range chain1[10:] {
   753  		if err := blockchain.Reject(block); err != nil {
   754  			t.Fatal(err)
   755  		}
   756  	}
   757  
   758  	// check the state of the last accepted block
   759  	checkState := func(sdb *state.StateDB) error {
   760  		nonce := sdb.GetNonce(addr1)
   761  		if nonce != 5 {
   762  			return fmt.Errorf("expected nonce addr1: 5, found nonce: %d", nonce)
   763  		}
   764  		balance1 := sdb.GetBalance(addr1)
   765  		expectedBalance1 := genesisBalance
   766  		if balance1.Cmp(expectedBalance1) != 0 {
   767  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance1, balance1)
   768  		}
   769  
   770  		balance2 := sdb.GetBalance(addr2)
   771  		expectedBalance2 := genesisBalance
   772  		if balance2.Cmp(expectedBalance2) != 0 {
   773  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2)
   774  		}
   775  
   776  		nonce = sdb.GetNonce(addr2)
   777  		if nonce != 5 {
   778  			return fmt.Errorf("expected addr2 nonce: 5, found nonce: %d", nonce)
   779  		}
   780  
   781  		balance3 := sdb.GetBalance(addr3)
   782  		expectedBalance3 := common.Big0
   783  		if balance3.Cmp(expectedBalance3) != 0 {
   784  			return fmt.Errorf("expected addr3 balance: %d, found balance: %d", expectedBalance3, balance3)
   785  		}
   786  
   787  		nonce = sdb.GetNonce(addr3)
   788  		if nonce != 1 {
   789  			return fmt.Errorf("expected addr3 nonce: 1, found nonce: %d", nonce)
   790  		}
   791  		return nil
   792  	}
   793  
   794  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   795  }
   796  
   797  func TestEmptyBlocks(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   798  	var (
   799  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   800  		// database.
   801  		genDB   = rawdb.NewMemoryDatabase()
   802  		chainDB = rawdb.NewMemoryDatabase()
   803  	)
   804  
   805  	// Ensure that key1 has some funds in the genesis block.
   806  	gspec := &Genesis{
   807  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   808  		Alloc:  GenesisAlloc{},
   809  	}
   810  	genesis := gspec.MustCommit(genDB)
   811  	_ = gspec.MustCommit(chainDB)
   812  
   813  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   814  	if err != nil {
   815  		t.Fatal(err)
   816  	}
   817  	defer blockchain.Stop()
   818  
   819  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   820  	// to the BlockChain's database while generating blocks.
   821  	chain, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, func(i int, gen *BlockGen) {})
   822  
   823  	// Insert three blocks into the chain and accept only the first block.
   824  	if _, err := blockchain.InsertChain(chain); err != nil {
   825  		t.Fatal(err)
   826  	}
   827  	for _, block := range chain {
   828  		if err := blockchain.Accept(block); err != nil {
   829  			t.Fatal(err)
   830  		}
   831  	}
   832  
   833  	// Nothing to assert about the state
   834  	checkState := func(sdb *state.StateDB) error {
   835  		return nil
   836  	}
   837  
   838  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   839  }
   840  
   841  func TestReorgReInsert(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   842  	var (
   843  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   844  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   845  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   846  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   847  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   848  		// database.
   849  		genDB   = rawdb.NewMemoryDatabase()
   850  		chainDB = rawdb.NewMemoryDatabase()
   851  	)
   852  
   853  	// Ensure that key1 has some funds in the genesis block.
   854  	genesisBalance := big.NewInt(1000000000)
   855  	gspec := &Genesis{
   856  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   857  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   858  	}
   859  	genesis := gspec.MustCommit(genDB)
   860  	_ = gspec.MustCommit(chainDB)
   861  
   862  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   863  	if err != nil {
   864  		t.Fatal(err)
   865  	}
   866  	defer blockchain.Stop()
   867  
   868  	signer := types.HomesteadSigner{}
   869  	numBlocks := 3
   870  	chain, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, func(i int, gen *BlockGen) {
   871  		// Generate a transaction to create a unique block
   872  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   873  		gen.AddTx(tx)
   874  	})
   875  
   876  	// Insert and accept first block
   877  	if err := blockchain.InsertBlock(chain[0]); err != nil {
   878  		t.Fatal(err)
   879  	}
   880  	if err := blockchain.Accept(chain[0]); err != nil {
   881  		t.Fatal(err)
   882  	}
   883  	// Insert block and then set preference back (rewind) to last accepted blck
   884  	if err := blockchain.InsertBlock(chain[1]); err != nil {
   885  		t.Fatal(err)
   886  	}
   887  	if err := blockchain.SetPreference(chain[0]); err != nil {
   888  		t.Fatal(err)
   889  	}
   890  	// Re-insert and accept block
   891  	if err := blockchain.InsertBlock(chain[1]); err != nil {
   892  		t.Fatal(err)
   893  	}
   894  	if err := blockchain.Accept(chain[1]); err != nil {
   895  		t.Fatal(err)
   896  	}
   897  	// Build on top of the re-inserted block and accept
   898  	if err := blockchain.InsertBlock(chain[2]); err != nil {
   899  		t.Fatal(err)
   900  	}
   901  	if err := blockchain.Accept(chain[2]); err != nil {
   902  		t.Fatal(err)
   903  	}
   904  
   905  	// Nothing to assert about the state
   906  	checkState := func(sdb *state.StateDB) error {
   907  		nonce1 := sdb.GetNonce(addr1)
   908  		if nonce1 != 3 {
   909  			return fmt.Errorf("expected addr1 nonce: 3, found nonce: %d", nonce1)
   910  		}
   911  		balance1 := sdb.GetBalance(addr1)
   912  		transferredFunds := big.NewInt(30000)
   913  		expectedBalance := new(big.Int).Sub(genesisBalance, transferredFunds)
   914  		if balance1.Cmp(expectedBalance) != 0 {
   915  			return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1)
   916  		}
   917  		nonce2 := sdb.GetNonce(addr2)
   918  		if nonce2 != 0 {
   919  			return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2)
   920  		}
   921  		balance2 := sdb.GetBalance(addr2)
   922  		if balance2.Cmp(transferredFunds) != 0 {
   923  			return fmt.Errorf("expected balance2: %d, found %d", transferredFunds, balance2)
   924  		}
   925  		return nil
   926  	}
   927  
   928  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   929  }
   930  
   931  // Insert two different chains that result in the identical state root.
   932  // Once we accept one of the chains, we insert and accept A3 on top of the shared
   933  // state root
   934  //   G   (genesis)
   935  //  / \
   936  // A1  B1
   937  // |   |
   938  // A2  B2 (A2 and B2 represent two different paths to the identical state trie)
   939  // |
   940  // A3
   941  func TestAcceptBlockIdenticalStateRoot(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   942  	var (
   943  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   944  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   945  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   946  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   947  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   948  		// database.
   949  		genDB   = rawdb.NewMemoryDatabase()
   950  		chainDB = rawdb.NewMemoryDatabase()
   951  	)
   952  
   953  	// Ensure that key1 has some funds in the genesis block.
   954  	genesisBalance := big.NewInt(1000000000)
   955  	gspec := &Genesis{
   956  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   957  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   958  	}
   959  	genesis := gspec.MustCommit(genDB)
   960  	_ = gspec.MustCommit(chainDB)
   961  
   962  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   963  	if err != nil {
   964  		t.Fatal(err)
   965  	}
   966  	defer blockchain.Stop()
   967  
   968  	signer := types.HomesteadSigner{}
   969  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   970  	// to the BlockChain's database while generating blocks.
   971  	chain1, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, func(i int, gen *BlockGen) {
   972  		if i < 2 {
   973  			// Send half the funds from addr1 to addr2 in one transaction per each of the two blocks in [chain1]
   974  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(500000000), params.TxGas, nil, nil), signer, key1)
   975  			gen.AddTx(tx)
   976  		}
   977  		// Allow the third block to be empty.
   978  	})
   979  	chain2, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 2, func(i int, gen *BlockGen) {
   980  		// Send 1/4 of the funds from addr1 to addr2 in tx1 and 3/4 of the funds in tx2. This will produce the identical state
   981  		// root in the second block of [chain2] as is present in the second block of [chain1].
   982  		if i == 0 {
   983  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(250000000), params.TxGas, nil, nil), signer, key1)
   984  			gen.AddTx(tx)
   985  		} else {
   986  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(750000000), params.TxGas, nil, nil), signer, key1)
   987  			gen.AddTx(tx)
   988  		}
   989  	})
   990  
   991  	// Assert that the block root of the second block in both chains is identical
   992  	if chain1[1].Root() != chain2[1].Root() {
   993  		t.Fatalf("Expected the latter block in both chain1 and chain2 to have identical state root, but found %s and %s", chain1[1].Root(), chain2[1].Root())
   994  	}
   995  
   996  	// Insert first two blocks of [chain1] and both blocks in [chain2]
   997  	// This leaves us one additional block to insert on top of [chain1]
   998  	// after testing that the state roots are handled correctly.
   999  	if _, err := blockchain.InsertChain(chain1[:2]); err != nil {
  1000  		t.Fatal(err)
  1001  	}
  1002  	if _, err := blockchain.InsertChain(chain2); err != nil {
  1003  		t.Fatal(err)
  1004  	}
  1005  
  1006  	currentBlock := blockchain.CurrentBlock()
  1007  	expectedCurrentBlock := chain1[1]
  1008  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
  1009  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
  1010  	}
  1011  
  1012  	// Accept the first block in [chain1] and reject all of [chain2]
  1013  	if err := blockchain.Accept(chain1[0]); err != nil {
  1014  		t.Fatal(err)
  1015  	}
  1016  	for _, block := range chain2 {
  1017  		if err := blockchain.Reject(block); err != nil {
  1018  			t.Fatal(err)
  1019  		}
  1020  	}
  1021  
  1022  	// Accept the last two blocks in [chain1]. This is a regression test to ensure
  1023  	// that we do not discard a snapshot difflayer that is still in use by a
  1024  	// processing block, when a different block with the same root is rejected.
  1025  	if err := blockchain.Accept(chain1[1]); err != nil {
  1026  		t.Fatal(err)
  1027  	}
  1028  
  1029  	lastAcceptedBlock := blockchain.LastAcceptedBlock()
  1030  	expectedLastAcceptedBlock := chain1[1]
  1031  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
  1032  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
  1033  	}
  1034  
  1035  	if err := blockchain.InsertBlock(chain1[2]); err != nil {
  1036  		t.Fatal(err)
  1037  	}
  1038  	if err := blockchain.Accept(chain1[2]); err != nil {
  1039  		t.Fatal(err)
  1040  	}
  1041  
  1042  	// check the state of the last accepted block
  1043  	checkState := func(sdb *state.StateDB) error {
  1044  		nonce1 := sdb.GetNonce(addr1)
  1045  		if nonce1 != 2 {
  1046  			return fmt.Errorf("expected addr1 nonce: 2, found nonce: %d", nonce1)
  1047  		}
  1048  		balance1 := sdb.GetBalance(addr1)
  1049  		expectedBalance := common.Big0
  1050  		if balance1.Cmp(expectedBalance) != 0 {
  1051  			return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1)
  1052  		}
  1053  		nonce2 := sdb.GetNonce(addr2)
  1054  		if nonce2 != 0 {
  1055  			return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2)
  1056  		}
  1057  		balance2 := sdb.GetBalance(addr2)
  1058  		if balance2.Cmp(genesisBalance) != 0 {
  1059  			return fmt.Errorf("expected balance2: %d, found %d", genesisBalance, balance2)
  1060  		}
  1061  		return nil
  1062  	}
  1063  
  1064  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
  1065  }
  1066  
  1067  // Insert two different chains that result in the identical state root.
  1068  // Once we insert both of the chains, we restart, insert both the chains again,
  1069  // and then we accept one of the chains and accept A3 on top of the shared state
  1070  // root
  1071  //   G   (genesis)
  1072  //  / \
  1073  // A1  B1
  1074  // |   |
  1075  // A2  B2 (A2 and B2 represent two different paths to the identical state trie)
  1076  // |
  1077  // A3
  1078  func TestReprocessAcceptBlockIdenticalStateRoot(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
  1079  	var (
  1080  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1081  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  1082  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
  1083  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
  1084  		// We use two separate databases since GenerateChain commits the state roots to its underlying
  1085  		// database.
  1086  		genDB   = rawdb.NewMemoryDatabase()
  1087  		chainDB = rawdb.NewMemoryDatabase()
  1088  	)
  1089  
  1090  	// Ensure that key1 has some funds in the genesis block.
  1091  	genesisBalance := big.NewInt(1000000000)
  1092  	gspec := &Genesis{
  1093  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
  1094  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
  1095  	}
  1096  	genesis := gspec.MustCommit(genDB)
  1097  	_ = gspec.MustCommit(chainDB)
  1098  
  1099  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
  1100  	if err != nil {
  1101  		t.Fatal(err)
  1102  	}
  1103  
  1104  	signer := types.HomesteadSigner{}
  1105  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
  1106  	// to the BlockChain's database while generating blocks.
  1107  	chain1, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, func(i int, gen *BlockGen) {
  1108  		if i < 2 {
  1109  			// Send half the funds from addr1 to addr2 in one transaction per each of the two blocks in [chain1]
  1110  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(500000000), params.TxGas, nil, nil), signer, key1)
  1111  			gen.AddTx(tx)
  1112  		}
  1113  		// Allow the third block to be empty.
  1114  	})
  1115  	chain2, _ := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 2, func(i int, gen *BlockGen) {
  1116  		// Send 1/4 of the funds from addr1 to addr2 in tx1 and 3/4 of the funds in tx2. This will produce the identical state
  1117  		// root in the second block of [chain2] as is present in the second block of [chain1].
  1118  		if i == 0 {
  1119  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(250000000), params.TxGas, nil, nil), signer, key1)
  1120  			gen.AddTx(tx)
  1121  		} else {
  1122  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(750000000), params.TxGas, nil, nil), signer, key1)
  1123  			gen.AddTx(tx)
  1124  		}
  1125  	})
  1126  
  1127  	// Assert that the block root of the second block in both chains is identical
  1128  	if chain1[1].Root() != chain2[1].Root() {
  1129  		t.Fatalf("Expected the latter block in both chain1 and chain2 to have identical state root, but found %s and %s", chain1[1].Root(), chain2[1].Root())
  1130  	}
  1131  
  1132  	// Insert first two blocks of [chain1] and both blocks in [chain2]
  1133  	// This leaves us one additional block to insert on top of [chain1]
  1134  	// after testing that the state roots are handled correctly.
  1135  	if _, err := blockchain.InsertChain(chain1[:2]); err != nil {
  1136  		t.Fatal(err)
  1137  	}
  1138  	if _, err := blockchain.InsertChain(chain2); err != nil {
  1139  		t.Fatal(err)
  1140  	}
  1141  
  1142  	currentBlock := blockchain.CurrentBlock()
  1143  	expectedCurrentBlock := chain1[1]
  1144  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
  1145  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
  1146  	}
  1147  
  1148  	blockchain.Stop()
  1149  
  1150  	blockchain, err = create(chainDB, gspec.Config, common.Hash{})
  1151  	if err != nil {
  1152  		t.Fatal(err)
  1153  	}
  1154  	defer blockchain.Stop()
  1155  
  1156  	// Insert first two blocks of [chain1] and both blocks in [chain2]
  1157  	// This leaves us one additional block to insert on top of [chain1]
  1158  	// after testing that the state roots are handled correctly.
  1159  	if _, err := blockchain.InsertChain(chain1[:2]); err != nil {
  1160  		t.Fatal(err)
  1161  	}
  1162  	if _, err := blockchain.InsertChain(chain2); err != nil {
  1163  		t.Fatal(err)
  1164  	}
  1165  
  1166  	currentBlock = blockchain.CurrentBlock()
  1167  	expectedCurrentBlock = chain1[1]
  1168  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
  1169  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
  1170  	}
  1171  
  1172  	// Accept the first block in [chain1] and reject all of [chain2]
  1173  	if err := blockchain.Accept(chain1[0]); err != nil {
  1174  		t.Fatal(err)
  1175  	}
  1176  	for _, block := range chain2 {
  1177  		if err := blockchain.Reject(block); err != nil {
  1178  			t.Fatal(err)
  1179  		}
  1180  	}
  1181  
  1182  	// Accept the last two blocks in [chain1]. This is a regression test to ensure
  1183  	// that we do not discard a snapshot difflayer that is still in use by a
  1184  	// processing block, when a different block with the same root is rejected.
  1185  	if err := blockchain.Accept(chain1[1]); err != nil {
  1186  		t.Fatal(err)
  1187  	}
  1188  
  1189  	lastAcceptedBlock := blockchain.LastAcceptedBlock()
  1190  	expectedLastAcceptedBlock := chain1[1]
  1191  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
  1192  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
  1193  	}
  1194  
  1195  	if err := blockchain.InsertBlock(chain1[2]); err != nil {
  1196  		t.Fatal(err)
  1197  	}
  1198  	if err := blockchain.Accept(chain1[2]); err != nil {
  1199  		t.Fatal(err)
  1200  	}
  1201  
  1202  	// check the state of the last accepted block
  1203  	checkState := func(sdb *state.StateDB) error {
  1204  		nonce1 := sdb.GetNonce(addr1)
  1205  		if nonce1 != 2 {
  1206  			return fmt.Errorf("expected addr1 nonce: 2, found nonce: %d", nonce1)
  1207  		}
  1208  		balance1 := sdb.GetBalance(addr1)
  1209  		expectedBalance := common.Big0
  1210  		if balance1.Cmp(expectedBalance) != 0 {
  1211  			return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1)
  1212  		}
  1213  		nonce2 := sdb.GetNonce(addr2)
  1214  		if nonce2 != 0 {
  1215  			return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2)
  1216  		}
  1217  		balance2 := sdb.GetBalance(addr2)
  1218  		if balance2.Cmp(genesisBalance) != 0 {
  1219  			return fmt.Errorf("expected balance2: %d, found %d", genesisBalance, balance2)
  1220  		}
  1221  		return nil
  1222  	}
  1223  
  1224  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
  1225  }