github.com/MetalBlockchain/subnet-evm@v0.4.9/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  	"strings"
    10  	"testing"
    11  
    12  	"github.com/MetalBlockchain/subnet-evm/commontype"
    13  	"github.com/MetalBlockchain/subnet-evm/consensus/dummy"
    14  	"github.com/MetalBlockchain/subnet-evm/core/rawdb"
    15  	"github.com/MetalBlockchain/subnet-evm/core/state"
    16  	"github.com/MetalBlockchain/subnet-evm/core/types"
    17  	"github.com/MetalBlockchain/subnet-evm/ethdb"
    18  	"github.com/MetalBlockchain/subnet-evm/params"
    19  	"github.com/MetalBlockchain/subnet-evm/precompile"
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/crypto"
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  type ChainTest struct {
    26  	Name     string
    27  	testFunc func(
    28  		t *testing.T,
    29  		create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error),
    30  	)
    31  }
    32  
    33  var tests = []ChainTest{
    34  	{
    35  		"InsertChainAcceptSingleBlock",
    36  		TestInsertChainAcceptSingleBlock,
    37  	},
    38  	{
    39  		"InsertForkedChain",
    40  		TestInsertLongForkedChain,
    41  	},
    42  	{
    43  		"AcceptNonCanonicalBlock",
    44  		TestAcceptNonCanonicalBlock,
    45  	},
    46  	{
    47  		"SetPreferenceRewind",
    48  		TestSetPreferenceRewind,
    49  	},
    50  	{
    51  		"BuildOnVariousStages",
    52  		TestBuildOnVariousStages,
    53  	},
    54  	{
    55  		"EmptyBlocks",
    56  		TestEmptyBlocks,
    57  	},
    58  	{
    59  		"AcceptBlockIdenticalStateRoot",
    60  		TestAcceptBlockIdenticalStateRoot,
    61  	},
    62  	{
    63  		"ReprocessAcceptBlockIdenticalStateRoot",
    64  		TestReprocessAcceptBlockIdenticalStateRoot,
    65  	},
    66  	{
    67  		"GenerateChainInvalidBlockFee",
    68  		TestGenerateChainInvalidBlockFee,
    69  	},
    70  	{
    71  		"InsertChainInvalidBlockFee",
    72  		TestInsertChainInvalidBlockFee,
    73  	},
    74  	{
    75  		"InsertChainValidBlockFee",
    76  		TestInsertChainValidBlockFee,
    77  	},
    78  	{
    79  		"TestStatefulPrecompiles",
    80  		TestStatefulPrecompiles,
    81  	},
    82  }
    83  
    84  func copyMemDB(db ethdb.Database) (ethdb.Database, error) {
    85  	newDB := rawdb.NewMemoryDatabase()
    86  	iter := db.NewIterator(nil, nil)
    87  	defer iter.Release()
    88  	for iter.Next() {
    89  		if err := newDB.Put(iter.Key(), iter.Value()); err != nil {
    90  			return nil, err
    91  		}
    92  	}
    93  
    94  	return newDB, nil
    95  }
    96  
    97  // checkBlockChainState creates a new BlockChain instance and checks that exporting each block from
    98  // genesis to last accepted from the original instance yields the same last accepted block and state
    99  // root.
   100  // Additionally, create another BlockChain instance from [originalDB] to ensure that BlockChain is
   101  // persisted correctly through a restart.
   102  func checkBlockChainState(
   103  	t *testing.T,
   104  	bc *BlockChain,
   105  	genesis *Genesis,
   106  	originalDB ethdb.Database,
   107  	create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error),
   108  	checkState func(sdb *state.StateDB) error,
   109  ) (*BlockChain, *BlockChain, *BlockChain) {
   110  	var (
   111  		chainConfig       = bc.Config()
   112  		lastAcceptedBlock = bc.LastConsensusAcceptedBlock()
   113  		newDB             = rawdb.NewMemoryDatabase()
   114  	)
   115  
   116  	acceptedState, err := bc.StateAt(lastAcceptedBlock.Root())
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  	if err := checkState(acceptedState); err != nil {
   121  		t.Fatalf("Check state failed for original blockchain due to: %s", err)
   122  	}
   123  
   124  	_ = genesis.MustCommit(newDB)
   125  
   126  	newBlockChain, err := create(newDB, chainConfig, common.Hash{})
   127  	if err != nil {
   128  		t.Fatalf("Failed to create new blockchain instance: %s", err)
   129  	}
   130  
   131  	for i := uint64(1); i <= lastAcceptedBlock.NumberU64(); i++ {
   132  		block := bc.GetBlockByNumber(i)
   133  		if block == nil {
   134  			t.Fatalf("Failed to retrieve block by number %d from original chain", i)
   135  		}
   136  		if err := newBlockChain.InsertBlock(block); err != nil {
   137  			t.Fatalf("Failed to insert block %s:%d due to %s", block.Hash().Hex(), block.NumberU64(), err)
   138  		}
   139  		if err := newBlockChain.Accept(block); err != nil {
   140  			t.Fatalf("Failed to accept block %s:%d due to %s", block.Hash().Hex(), block.NumberU64(), err)
   141  		}
   142  	}
   143  	newBlockChain.DrainAcceptorQueue()
   144  
   145  	newLastAcceptedBlock := newBlockChain.LastConsensusAcceptedBlock()
   146  	if newLastAcceptedBlock.Hash() != lastAcceptedBlock.Hash() {
   147  		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())
   148  	}
   149  
   150  	// Check that the state of [newBlockChain] passes the check
   151  	acceptedState, err = newBlockChain.StateAt(lastAcceptedBlock.Root())
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  	if err := checkState(acceptedState); err != nil {
   156  		t.Fatalf("Check state failed for newly generated blockchain due to: %s", err)
   157  	}
   158  
   159  	// Copy the database over to prevent any issues when re-using [originalDB] after this call.
   160  	originalDB, err = copyMemDB(originalDB)
   161  	if err != nil {
   162  		t.Fatal(err)
   163  	}
   164  	restartedChain, err := create(originalDB, chainConfig, lastAcceptedBlock.Hash())
   165  	if err != nil {
   166  		t.Fatal(err)
   167  	}
   168  	defer restartedChain.Stop()
   169  	if currentBlock := restartedChain.CurrentBlock(); currentBlock.Hash() != lastAcceptedBlock.Hash() {
   170  		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())
   171  	}
   172  	if restartedLastAcceptedBlock := restartedChain.LastConsensusAcceptedBlock(); restartedLastAcceptedBlock.Hash() != lastAcceptedBlock.Hash() {
   173  		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())
   174  	}
   175  
   176  	// Check that the state of [restartedChain] passes the check
   177  	acceptedState, err = restartedChain.StateAt(lastAcceptedBlock.Root())
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  	if err := checkState(acceptedState); err != nil {
   182  		t.Fatalf("Check state failed for restarted blockchain due to: %s", err)
   183  	}
   184  
   185  	return bc, newBlockChain, restartedChain
   186  }
   187  
   188  func TestInsertChainAcceptSingleBlock(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   189  	var (
   190  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   191  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   192  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   193  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   194  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   195  		// database.
   196  		genDB   = rawdb.NewMemoryDatabase()
   197  		chainDB = rawdb.NewMemoryDatabase()
   198  	)
   199  
   200  	// Ensure that key1 has some funds in the genesis block.
   201  	genesisBalance := big.NewInt(1000000)
   202  	gspec := &Genesis{
   203  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   204  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   205  	}
   206  	genesis := gspec.MustCommit(genDB)
   207  	_ = gspec.MustCommit(chainDB)
   208  
   209  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   210  	if err != nil {
   211  		t.Fatal(err)
   212  	}
   213  	defer blockchain.Stop()
   214  
   215  	// This call generates a chain of 3 blocks.
   216  	signer := types.HomesteadSigner{}
   217  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   218  	// to the BlockChain's database while generating blocks.
   219  	chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 10, func(i int, gen *BlockGen) {
   220  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   221  		gen.AddTx(tx)
   222  	})
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  
   227  	// Insert three blocks into the chain and accept only the first block.
   228  	if _, err := blockchain.InsertChain(chain); err != nil {
   229  		t.Fatal(err)
   230  	}
   231  	if err := blockchain.Accept(chain[0]); err != nil {
   232  		t.Fatal(err)
   233  	}
   234  	blockchain.DrainAcceptorQueue()
   235  
   236  	// check the state of the last accepted block
   237  	checkState := func(sdb *state.StateDB) error {
   238  		nonce := sdb.GetNonce(addr1)
   239  		if nonce != 1 {
   240  			return fmt.Errorf("expected nonce addr1: 1, found nonce: %d", nonce)
   241  		}
   242  		transferredFunds := big.NewInt(10000)
   243  		balance1 := sdb.GetBalance(addr1)
   244  		expectedBalance1 := new(big.Int).Sub(genesisBalance, transferredFunds)
   245  		if balance1.Cmp(expectedBalance1) != 0 {
   246  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance1, balance1)
   247  		}
   248  
   249  		balance2 := sdb.GetBalance(addr2)
   250  		expectedBalance2 := transferredFunds
   251  		if balance2.Cmp(expectedBalance2) != 0 {
   252  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2)
   253  		}
   254  
   255  		nonce = sdb.GetNonce(addr2)
   256  		if nonce != 0 {
   257  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce)
   258  		}
   259  		return nil
   260  	}
   261  
   262  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   263  }
   264  
   265  func TestInsertLongForkedChain(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   266  	var (
   267  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   268  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   269  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   270  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   271  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   272  		// database.
   273  		genDB   = rawdb.NewMemoryDatabase()
   274  		chainDB = rawdb.NewMemoryDatabase()
   275  	)
   276  
   277  	// Ensure that key1 has some funds in the genesis block.
   278  	genesisBalance := big.NewInt(1000000000)
   279  	gspec := &Genesis{
   280  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   281  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   282  	}
   283  	genesis := gspec.MustCommit(genDB)
   284  	_ = gspec.MustCommit(chainDB)
   285  
   286  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   287  	if err != nil {
   288  		t.Fatal(err)
   289  	}
   290  	defer blockchain.Stop()
   291  
   292  	numBlocks := 129
   293  	signer := types.HomesteadSigner{}
   294  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   295  	// to the BlockChain's database while generating blocks.
   296  	chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) {
   297  		// Generate a transaction to create a unique block
   298  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   299  		gen.AddTx(tx)
   300  	})
   301  	if err != nil {
   302  		t.Fatal(err)
   303  	}
   304  	// Generate the forked chain to be longer than the original chain to check for a regression where
   305  	// a longer chain can trigger a reorg.
   306  	chain2, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks+1, 10, func(i int, gen *BlockGen) {
   307  		// Generate a transaction with a different amount to ensure [chain2] is different than [chain1].
   308  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(5000), params.TxGas, nil, nil), signer, key1)
   309  		gen.AddTx(tx)
   310  	})
   311  	if err != nil {
   312  		t.Fatal(err)
   313  	}
   314  
   315  	if blockchain.snaps != nil {
   316  		if want, got := 1, blockchain.snaps.NumBlockLayers(); got != want {
   317  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   318  		}
   319  	}
   320  
   321  	// Insert both chains.
   322  	if _, err := blockchain.InsertChain(chain1); err != nil {
   323  		t.Fatal(err)
   324  	}
   325  
   326  	if blockchain.snaps != nil {
   327  		if want, got := 1+len(chain1), blockchain.snaps.NumBlockLayers(); got != want {
   328  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   329  		}
   330  	}
   331  
   332  	if _, err := blockchain.InsertChain(chain2); err != nil {
   333  		t.Fatal(err)
   334  	}
   335  
   336  	if blockchain.snaps != nil {
   337  		if want, got := 1+len(chain1)+len(chain2), blockchain.snaps.NumBlockLayers(); got != want {
   338  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   339  		}
   340  	}
   341  
   342  	currentBlock := blockchain.CurrentBlock()
   343  	expectedCurrentBlock := chain1[len(chain1)-1]
   344  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
   345  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
   346  	}
   347  
   348  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   349  		t.Fatal(err)
   350  	}
   351  
   352  	// Accept the first block in [chain1], reject all blocks in [chain2] to
   353  	// mimic the order that the consensus engine will call Accept/Reject in
   354  	// and then Accept the rest of the blocks in [chain1].
   355  	if err := blockchain.Accept(chain1[0]); err != nil {
   356  		t.Fatal(err)
   357  	}
   358  	blockchain.DrainAcceptorQueue()
   359  
   360  	if blockchain.snaps != nil {
   361  		// Snap layer count should be 1 fewer
   362  		if want, got := len(chain1)+len(chain2), blockchain.snaps.NumBlockLayers(); got != want {
   363  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   364  		}
   365  	}
   366  
   367  	for i := 0; i < len(chain2); i++ {
   368  		if err := blockchain.Reject(chain2[i]); err != nil {
   369  			t.Fatal(err)
   370  		}
   371  
   372  		if blockchain.snaps != nil {
   373  			// Snap layer count should decrease by 1 per Reject
   374  			if want, got := len(chain1)+len(chain2)-i-1, blockchain.snaps.NumBlockLayers(); got != want {
   375  				t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   376  			}
   377  		}
   378  	}
   379  
   380  	if blockchain.snaps != nil {
   381  		if want, got := len(chain1), blockchain.snaps.NumBlockLayers(); got != want {
   382  			t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   383  		}
   384  	}
   385  
   386  	for i := 1; i < len(chain1); i++ {
   387  		if err := blockchain.Accept(chain1[i]); err != nil {
   388  			t.Fatal(err)
   389  		}
   390  		blockchain.DrainAcceptorQueue()
   391  
   392  		if blockchain.snaps != nil {
   393  			// Snap layer count should decrease by 1 per Accept
   394  			if want, got := len(chain1)-i, blockchain.snaps.NumBlockLayers(); got != want {
   395  				t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want)
   396  			}
   397  		}
   398  	}
   399  
   400  	lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock()
   401  	expectedLastAcceptedBlock := chain1[len(chain1)-1]
   402  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
   403  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
   404  	}
   405  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   406  		t.Fatal(err)
   407  	}
   408  
   409  	// check the state of the last accepted block
   410  	checkState := func(sdb *state.StateDB) error {
   411  		nonce1 := sdb.GetNonce(addr1)
   412  		if nonce1 != 129 {
   413  			return fmt.Errorf("expected addr1 nonce: 129, found nonce %d", nonce1)
   414  		}
   415  		balance1 := sdb.GetBalance(addr1)
   416  		transferredFunds := new(big.Int).Mul(big.NewInt(129), big.NewInt(10000))
   417  		expectedBalance := new(big.Int).Sub(genesisBalance, transferredFunds)
   418  		if balance1.Cmp(expectedBalance) != 0 {
   419  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance, balance1)
   420  		}
   421  		nonce2 := sdb.GetNonce(addr2)
   422  		if nonce2 != 0 {
   423  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce2)
   424  		}
   425  		balance2 := sdb.GetBalance(addr2)
   426  		if balance2.Cmp(transferredFunds) != 0 {
   427  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", transferredFunds, balance2)
   428  		}
   429  		return nil
   430  	}
   431  
   432  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   433  }
   434  
   435  func TestAcceptNonCanonicalBlock(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   436  	var (
   437  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   438  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   439  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   440  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   441  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   442  		// database.
   443  		genDB   = rawdb.NewMemoryDatabase()
   444  		chainDB = rawdb.NewMemoryDatabase()
   445  	)
   446  
   447  	// Ensure that key1 has some funds in the genesis block.
   448  	genesisBalance := big.NewInt(1000000000)
   449  	gspec := &Genesis{
   450  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   451  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   452  	}
   453  	genesis := gspec.MustCommit(genDB)
   454  	_ = gspec.MustCommit(chainDB)
   455  
   456  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   457  	if err != nil {
   458  		t.Fatal(err)
   459  	}
   460  	defer blockchain.Stop()
   461  
   462  	numBlocks := 3
   463  	signer := types.HomesteadSigner{}
   464  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   465  	// to the BlockChain's database while generating blocks.
   466  	chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) {
   467  		// Generate a transaction to create a unique block
   468  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   469  		gen.AddTx(tx)
   470  	})
   471  	if err != nil {
   472  		t.Fatal(err)
   473  	}
   474  	chain2, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) {
   475  		// Generate a transaction with a different amount to create a chain of blocks different from [chain1]
   476  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(5000), params.TxGas, nil, nil), signer, key1)
   477  		gen.AddTx(tx)
   478  	})
   479  	if err != nil {
   480  		t.Fatal(err)
   481  	}
   482  
   483  	// Insert three blocks into the chain and accept only the first.
   484  	if _, err := blockchain.InsertChain(chain1); err != nil {
   485  		t.Fatal(err)
   486  	}
   487  	if _, err := blockchain.InsertChain(chain2); err != nil {
   488  		t.Fatal(err)
   489  	}
   490  
   491  	currentBlock := blockchain.CurrentBlock()
   492  	expectedCurrentBlock := chain1[len(chain1)-1]
   493  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
   494  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
   495  	}
   496  
   497  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   498  		t.Fatal(err)
   499  	}
   500  
   501  	// Accept the first block in [chain2], reject all blocks in [chain1] to
   502  	// mimic the order that the consensus engine will call Accept/Reject in.
   503  	if err := blockchain.Accept(chain2[0]); err != nil {
   504  		t.Fatal(err)
   505  	}
   506  	blockchain.DrainAcceptorQueue()
   507  
   508  	for i := 0; i < len(chain1); i++ {
   509  		if err := blockchain.Reject(chain1[i]); err != nil {
   510  			t.Fatal(err)
   511  		}
   512  	}
   513  
   514  	lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock()
   515  	expectedLastAcceptedBlock := chain2[0]
   516  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
   517  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
   518  	}
   519  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   520  		t.Fatal(err)
   521  	}
   522  
   523  	// check the state of the last accepted block
   524  	checkState := func(sdb *state.StateDB) error {
   525  		nonce1 := sdb.GetNonce(addr1)
   526  		if nonce1 != 1 {
   527  			return fmt.Errorf("expected addr1 nonce: 1, found nonce: %d", nonce1)
   528  		}
   529  		balance1 := sdb.GetBalance(addr1)
   530  		transferredFunds := big.NewInt(5000)
   531  		expectedBalance := new(big.Int).Sub(genesisBalance, transferredFunds)
   532  		if balance1.Cmp(expectedBalance) != 0 {
   533  			return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1)
   534  		}
   535  		nonce2 := sdb.GetNonce(addr2)
   536  		if nonce2 != 0 {
   537  			return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2)
   538  		}
   539  		balance2 := sdb.GetBalance(addr2)
   540  		if balance2.Cmp(transferredFunds) != 0 {
   541  			return fmt.Errorf("expected balance2: %d, found %d", transferredFunds, balance2)
   542  		}
   543  		return nil
   544  	}
   545  
   546  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   547  }
   548  
   549  func TestSetPreferenceRewind(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   550  	var (
   551  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   552  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   553  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   554  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   555  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   556  		// database.
   557  		genDB   = rawdb.NewMemoryDatabase()
   558  		chainDB = rawdb.NewMemoryDatabase()
   559  	)
   560  
   561  	// Ensure that key1 has some funds in the genesis block.
   562  	genesisBalance := big.NewInt(1000000000)
   563  	gspec := &Genesis{
   564  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   565  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   566  	}
   567  	genesis := gspec.MustCommit(genDB)
   568  	_ = gspec.MustCommit(chainDB)
   569  
   570  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   571  	if err != nil {
   572  		t.Fatal(err)
   573  	}
   574  	defer blockchain.Stop()
   575  
   576  	numBlocks := 3
   577  	signer := types.HomesteadSigner{}
   578  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   579  	// to the BlockChain's database while generating blocks.
   580  	chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) {
   581  		// Generate a transaction to create a unique block
   582  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   583  		gen.AddTx(tx)
   584  	})
   585  	if err != nil {
   586  		t.Fatal(err)
   587  	}
   588  
   589  	// Insert three blocks into the chain and accept only the first.
   590  	if _, err := blockchain.InsertChain(chain); err != nil {
   591  		t.Fatal(err)
   592  	}
   593  
   594  	currentBlock := blockchain.CurrentBlock()
   595  	expectedCurrentBlock := chain[len(chain)-1]
   596  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
   597  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
   598  	}
   599  
   600  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   601  		t.Fatal(err)
   602  	}
   603  
   604  	// SetPreference to an ancestor of the currently preferred block. Test that this unlikely, but possible behavior
   605  	// is handled correctly.
   606  	if err := blockchain.SetPreference(chain[0]); err != nil {
   607  		t.Fatal(err)
   608  	}
   609  
   610  	currentBlock = blockchain.CurrentBlock()
   611  	expectedCurrentBlock = chain[0]
   612  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
   613  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
   614  	}
   615  
   616  	lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock()
   617  	expectedLastAcceptedBlock := blockchain.Genesis()
   618  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
   619  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
   620  	}
   621  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   622  		t.Fatal(err)
   623  	}
   624  	// check the state of the last accepted block
   625  	checkGenesisState := func(sdb *state.StateDB) error {
   626  		nonce1 := sdb.GetNonce(addr1)
   627  		if nonce1 != 0 {
   628  			return fmt.Errorf("expected addr1 nonce: 0, found nonce: %d", nonce1)
   629  		}
   630  		balance1 := sdb.GetBalance(addr1)
   631  		if balance1.Cmp(genesisBalance) != 0 {
   632  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", genesisBalance, balance1)
   633  		}
   634  		nonce2 := sdb.GetNonce(addr2)
   635  		if nonce2 != 0 {
   636  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce2)
   637  		}
   638  		balance2 := sdb.GetBalance(addr2)
   639  		if balance2.Cmp(big.NewInt(0)) != 0 {
   640  			return fmt.Errorf("expected addr2 balance: 0, found balance %d", balance2)
   641  		}
   642  		return nil
   643  	}
   644  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkGenesisState)
   645  
   646  	if err := blockchain.Accept(chain[0]); err != nil {
   647  		t.Fatal(err)
   648  	}
   649  	blockchain.DrainAcceptorQueue()
   650  
   651  	lastAcceptedBlock = blockchain.LastConsensusAcceptedBlock()
   652  	expectedLastAcceptedBlock = chain[0]
   653  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
   654  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
   655  	}
   656  	if err := blockchain.ValidateCanonicalChain(); err != nil {
   657  		t.Fatal(err)
   658  	}
   659  	checkUpdatedState := func(sdb *state.StateDB) error {
   660  		nonce := sdb.GetNonce(addr1)
   661  		if nonce != 1 {
   662  			return fmt.Errorf("expected addr1 nonce: 1, found nonce: %d", nonce)
   663  		}
   664  		transferredFunds := big.NewInt(10000)
   665  		balance1 := sdb.GetBalance(addr1)
   666  		expectedBalance1 := new(big.Int).Sub(genesisBalance, transferredFunds)
   667  		if balance1.Cmp(expectedBalance1) != 0 {
   668  			return fmt.Errorf("expected addr1 balance: %d, found balance %d", expectedBalance1, balance1)
   669  		}
   670  
   671  		balance2 := sdb.GetBalance(addr2)
   672  		expectedBalance2 := transferredFunds
   673  		if balance2.Cmp(expectedBalance2) != 0 {
   674  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2)
   675  		}
   676  
   677  		nonce = sdb.GetNonce(addr2)
   678  		if nonce != 0 {
   679  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce)
   680  		}
   681  		return nil
   682  	}
   683  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkUpdatedState)
   684  }
   685  
   686  func TestBuildOnVariousStages(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   687  	var (
   688  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   689  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   690  		key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
   691  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   692  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   693  		addr3   = crypto.PubkeyToAddress(key3.PublicKey)
   694  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   695  		// database.
   696  		genDB   = rawdb.NewMemoryDatabase()
   697  		chainDB = rawdb.NewMemoryDatabase()
   698  	)
   699  
   700  	// Ensure that key1 has some funds in the genesis block.
   701  	genesisBalance := big.NewInt(1000000)
   702  	gspec := &Genesis{
   703  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   704  		Alloc: GenesisAlloc{
   705  			addr1: {Balance: genesisBalance},
   706  			addr3: {Balance: genesisBalance},
   707  		},
   708  	}
   709  	genesis := gspec.MustCommit(genDB)
   710  	_ = gspec.MustCommit(chainDB)
   711  
   712  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   713  	if err != nil {
   714  		t.Fatal(err)
   715  	}
   716  	defer blockchain.Stop()
   717  
   718  	// This call generates a chain of 3 blocks.
   719  	signer := types.HomesteadSigner{}
   720  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   721  	// to the BlockChain's database while generating blocks.
   722  	chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 20, 10, func(i int, gen *BlockGen) {
   723  		// Send all funds back and forth between the two accounts
   724  		if i%2 == 0 {
   725  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, genesisBalance, params.TxGas, nil, nil), signer, key1)
   726  			gen.AddTx(tx)
   727  		} else {
   728  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr1, genesisBalance, params.TxGas, nil, nil), signer, key2)
   729  			gen.AddTx(tx)
   730  		}
   731  	})
   732  	if err != nil {
   733  		t.Fatal(err)
   734  	}
   735  	// Build second chain forked off of the 10th block in [chain1]
   736  	chain2, _, err := GenerateChain(gspec.Config, chain1[9], blockchain.engine, genDB, 10, 10, func(i int, gen *BlockGen) {
   737  		// Send all funds back and forth between the two accounts
   738  		if i%2 == 0 {
   739  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr2, genesisBalance, params.TxGas, nil, nil), signer, key3)
   740  			gen.AddTx(tx)
   741  		} else {
   742  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, genesisBalance, params.TxGas, nil, nil), signer, key2)
   743  			gen.AddTx(tx)
   744  		}
   745  	})
   746  	if err != nil {
   747  		t.Fatal(err)
   748  	}
   749  	// Build third chain forked off of the 5th block in [chain1].
   750  	// The parent of this chain will be accepted before this fork
   751  	// is inserted.
   752  	chain3, _, err := GenerateChain(gspec.Config, chain1[4], blockchain.engine, genDB, 10, 10, func(i int, gen *BlockGen) {
   753  		// Send all funds back and forth between accounts 2 and 3.
   754  		if i%2 == 0 {
   755  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, genesisBalance, params.TxGas, nil, nil), signer, key2)
   756  			gen.AddTx(tx)
   757  		} else {
   758  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr2, genesisBalance, params.TxGas, nil, nil), signer, key3)
   759  			gen.AddTx(tx)
   760  		}
   761  	})
   762  	if err != nil {
   763  		t.Fatal(err)
   764  	}
   765  
   766  	// Insert first 10 blocks from [chain1]
   767  	if _, err := blockchain.InsertChain(chain1); err != nil {
   768  		t.Fatal(err)
   769  	}
   770  	// Accept the first 5 blocks
   771  	for _, block := range chain1[0:5] {
   772  		if err := blockchain.Accept(block); err != nil {
   773  			t.Fatal(err)
   774  		}
   775  	}
   776  	blockchain.DrainAcceptorQueue()
   777  
   778  	// Insert the forked chain [chain2] which starts at the 10th
   779  	// block in [chain1] ie. a block that is still in processing.
   780  	if _, err := blockchain.InsertChain(chain2); err != nil {
   781  		t.Fatal(err)
   782  	}
   783  	// Insert another forked chain starting at the last accepted
   784  	// block from [chain1].
   785  	if _, err := blockchain.InsertChain(chain3); err != nil {
   786  		t.Fatal(err)
   787  	}
   788  	// Accept the next block in [chain1] and then reject all
   789  	// of the blocks in [chain3], which would then be rejected.
   790  	if err := blockchain.Accept(chain1[5]); err != nil {
   791  		t.Fatal(err)
   792  	}
   793  	blockchain.DrainAcceptorQueue()
   794  	for _, block := range chain3 {
   795  		if err := blockchain.Reject(block); err != nil {
   796  			t.Fatal(err)
   797  		}
   798  	}
   799  	// Accept the rest of the blocks in [chain1]
   800  	for _, block := range chain1[6:10] {
   801  		if err := blockchain.Accept(block); err != nil {
   802  			t.Fatal(err)
   803  		}
   804  	}
   805  	blockchain.DrainAcceptorQueue()
   806  
   807  	// Accept the first block in [chain2] and reject the
   808  	// subsequent blocks in [chain1] which would then be rejected.
   809  	if err := blockchain.Accept(chain2[0]); err != nil {
   810  		t.Fatal(err)
   811  	}
   812  	blockchain.DrainAcceptorQueue()
   813  
   814  	for _, block := range chain1[10:] {
   815  		if err := blockchain.Reject(block); err != nil {
   816  			t.Fatal(err)
   817  		}
   818  	}
   819  
   820  	// check the state of the last accepted block
   821  	checkState := func(sdb *state.StateDB) error {
   822  		nonce := sdb.GetNonce(addr1)
   823  		if nonce != 5 {
   824  			return fmt.Errorf("expected nonce addr1: 5, found nonce: %d", nonce)
   825  		}
   826  		balance1 := sdb.GetBalance(addr1)
   827  		expectedBalance1 := genesisBalance
   828  		if balance1.Cmp(expectedBalance1) != 0 {
   829  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance1, balance1)
   830  		}
   831  
   832  		balance2 := sdb.GetBalance(addr2)
   833  		expectedBalance2 := genesisBalance
   834  		if balance2.Cmp(expectedBalance2) != 0 {
   835  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2)
   836  		}
   837  
   838  		nonce = sdb.GetNonce(addr2)
   839  		if nonce != 5 {
   840  			return fmt.Errorf("expected addr2 nonce: 5, found nonce: %d", nonce)
   841  		}
   842  
   843  		balance3 := sdb.GetBalance(addr3)
   844  		expectedBalance3 := common.Big0
   845  		if balance3.Cmp(expectedBalance3) != 0 {
   846  			return fmt.Errorf("expected addr3 balance: %d, found balance: %d", expectedBalance3, balance3)
   847  		}
   848  
   849  		nonce = sdb.GetNonce(addr3)
   850  		if nonce != 1 {
   851  			return fmt.Errorf("expected addr3 nonce: 1, found nonce: %d", nonce)
   852  		}
   853  		return nil
   854  	}
   855  
   856  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   857  }
   858  
   859  func TestEmptyBlocks(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   860  	var (
   861  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   862  		// database.
   863  		genDB   = rawdb.NewMemoryDatabase()
   864  		chainDB = rawdb.NewMemoryDatabase()
   865  	)
   866  
   867  	// Ensure that key1 has some funds in the genesis block.
   868  	gspec := &Genesis{
   869  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   870  		Alloc:  GenesisAlloc{},
   871  	}
   872  	genesis := gspec.MustCommit(genDB)
   873  	_ = gspec.MustCommit(chainDB)
   874  
   875  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   876  	if err != nil {
   877  		t.Fatal(err)
   878  	}
   879  	defer blockchain.Stop()
   880  
   881  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
   882  	// to the BlockChain's database while generating blocks.
   883  	chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 10, func(i int, gen *BlockGen) {})
   884  	if err != nil {
   885  		t.Fatal(err)
   886  	}
   887  
   888  	// Insert three blocks into the chain and accept only the first block.
   889  	if _, err := blockchain.InsertChain(chain); err != nil {
   890  		t.Fatal(err)
   891  	}
   892  	for _, block := range chain {
   893  		if err := blockchain.Accept(block); err != nil {
   894  			t.Fatal(err)
   895  		}
   896  	}
   897  	blockchain.DrainAcceptorQueue()
   898  
   899  	// Nothing to assert about the state
   900  	checkState := func(sdb *state.StateDB) error {
   901  		return nil
   902  	}
   903  
   904  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   905  }
   906  
   907  func TestReorgReInsert(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
   908  	var (
   909  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   910  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   911  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   912  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   913  		// We use two separate databases since GenerateChain commits the state roots to its underlying
   914  		// database.
   915  		genDB   = rawdb.NewMemoryDatabase()
   916  		chainDB = rawdb.NewMemoryDatabase()
   917  	)
   918  
   919  	// Ensure that key1 has some funds in the genesis block.
   920  	genesisBalance := big.NewInt(1000000000)
   921  	gspec := &Genesis{
   922  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   923  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   924  	}
   925  	genesis := gspec.MustCommit(genDB)
   926  	_ = gspec.MustCommit(chainDB)
   927  
   928  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
   929  	if err != nil {
   930  		t.Fatal(err)
   931  	}
   932  	defer blockchain.Stop()
   933  
   934  	signer := types.HomesteadSigner{}
   935  	numBlocks := 3
   936  	chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) {
   937  		// Generate a transaction to create a unique block
   938  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   939  		gen.AddTx(tx)
   940  	})
   941  	if err != nil {
   942  		t.Fatal(err)
   943  	}
   944  
   945  	// Insert and accept first block
   946  	if err := blockchain.InsertBlock(chain[0]); err != nil {
   947  		t.Fatal(err)
   948  	}
   949  	if err := blockchain.Accept(chain[0]); err != nil {
   950  		t.Fatal(err)
   951  	}
   952  
   953  	// Insert block and then set preference back (rewind) to last accepted blck
   954  	if err := blockchain.InsertBlock(chain[1]); err != nil {
   955  		t.Fatal(err)
   956  	}
   957  	if err := blockchain.SetPreference(chain[0]); err != nil {
   958  		t.Fatal(err)
   959  	}
   960  
   961  	// Re-insert and accept block
   962  	if err := blockchain.InsertBlock(chain[1]); err != nil {
   963  		t.Fatal(err)
   964  	}
   965  	if err := blockchain.Accept(chain[1]); err != nil {
   966  		t.Fatal(err)
   967  	}
   968  
   969  	// Build on top of the re-inserted block and accept
   970  	if err := blockchain.InsertBlock(chain[2]); err != nil {
   971  		t.Fatal(err)
   972  	}
   973  	if err := blockchain.Accept(chain[2]); err != nil {
   974  		t.Fatal(err)
   975  	}
   976  	blockchain.DrainAcceptorQueue()
   977  
   978  	// Nothing to assert about the state
   979  	checkState := func(sdb *state.StateDB) error {
   980  		nonce1 := sdb.GetNonce(addr1)
   981  		if nonce1 != 3 {
   982  			return fmt.Errorf("expected addr1 nonce: 3, found nonce: %d", nonce1)
   983  		}
   984  		balance1 := sdb.GetBalance(addr1)
   985  		transferredFunds := big.NewInt(30000)
   986  		expectedBalance := new(big.Int).Sub(genesisBalance, transferredFunds)
   987  		if balance1.Cmp(expectedBalance) != 0 {
   988  			return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1)
   989  		}
   990  		nonce2 := sdb.GetNonce(addr2)
   991  		if nonce2 != 0 {
   992  			return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2)
   993  		}
   994  		balance2 := sdb.GetBalance(addr2)
   995  		if balance2.Cmp(transferredFunds) != 0 {
   996  			return fmt.Errorf("expected balance2: %d, found %d", transferredFunds, balance2)
   997  		}
   998  		return nil
   999  	}
  1000  
  1001  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
  1002  }
  1003  
  1004  // Insert two different chains that result in the identical state root.
  1005  // Once we accept one of the chains, we insert and accept A3 on top of the shared
  1006  // state root
  1007  //   G   (genesis)
  1008  //  / \
  1009  // A1  B1
  1010  // |   |
  1011  // A2  B2 (A2 and B2 represent two different paths to the identical state trie)
  1012  // |
  1013  // A3
  1014  func TestAcceptBlockIdenticalStateRoot(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
  1015  	var (
  1016  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1017  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  1018  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
  1019  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
  1020  		// We use two separate databases since GenerateChain commits the state roots to its underlying
  1021  		// database.
  1022  		genDB   = rawdb.NewMemoryDatabase()
  1023  		chainDB = rawdb.NewMemoryDatabase()
  1024  	)
  1025  
  1026  	// Ensure that key1 has some funds in the genesis block.
  1027  	genesisBalance := big.NewInt(1000000000)
  1028  	gspec := &Genesis{
  1029  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
  1030  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
  1031  	}
  1032  	genesis := gspec.MustCommit(genDB)
  1033  	_ = gspec.MustCommit(chainDB)
  1034  
  1035  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
  1036  	if err != nil {
  1037  		t.Fatal(err)
  1038  	}
  1039  	defer blockchain.Stop()
  1040  
  1041  	signer := types.HomesteadSigner{}
  1042  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
  1043  	// to the BlockChain's database while generating blocks.
  1044  	chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 10, func(i int, gen *BlockGen) {
  1045  		if i < 2 {
  1046  			// Send half the funds from addr1 to addr2 in one transaction per each of the two blocks in [chain1]
  1047  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(500000000), params.TxGas, nil, nil), signer, key1)
  1048  			gen.AddTx(tx)
  1049  		}
  1050  		// Allow the third block to be empty.
  1051  	})
  1052  	if err != nil {
  1053  		t.Fatal(err)
  1054  	}
  1055  	chain2, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 2, 10, func(i int, gen *BlockGen) {
  1056  		// 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
  1057  		// root in the second block of [chain2] as is present in the second block of [chain1].
  1058  		if i == 0 {
  1059  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(250000000), params.TxGas, nil, nil), signer, key1)
  1060  			gen.AddTx(tx)
  1061  		} else {
  1062  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(750000000), params.TxGas, nil, nil), signer, key1)
  1063  			gen.AddTx(tx)
  1064  		}
  1065  	})
  1066  	if err != nil {
  1067  		t.Fatal(err)
  1068  	}
  1069  
  1070  	// Assert that the block root of the second block in both chains is identical
  1071  	if chain1[1].Root() != chain2[1].Root() {
  1072  		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())
  1073  	}
  1074  
  1075  	// Insert first two blocks of [chain1] and both blocks in [chain2]
  1076  	// This leaves us one additional block to insert on top of [chain1]
  1077  	// after testing that the state roots are handled correctly.
  1078  	if _, err := blockchain.InsertChain(chain1[:2]); err != nil {
  1079  		t.Fatal(err)
  1080  	}
  1081  	if _, err := blockchain.InsertChain(chain2); err != nil {
  1082  		t.Fatal(err)
  1083  	}
  1084  
  1085  	currentBlock := blockchain.CurrentBlock()
  1086  	expectedCurrentBlock := chain1[1]
  1087  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
  1088  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
  1089  	}
  1090  
  1091  	// Accept the first block in [chain1] and reject all of [chain2]
  1092  	if err := blockchain.Accept(chain1[0]); err != nil {
  1093  		t.Fatal(err)
  1094  	}
  1095  	blockchain.DrainAcceptorQueue()
  1096  
  1097  	for _, block := range chain2 {
  1098  		if err := blockchain.Reject(block); err != nil {
  1099  			t.Fatal(err)
  1100  		}
  1101  	}
  1102  
  1103  	// Accept the last two blocks in [chain1]. This is a regression test to ensure
  1104  	// that we do not discard a snapshot difflayer that is still in use by a
  1105  	// processing block, when a different block with the same root is rejected.
  1106  	if err := blockchain.Accept(chain1[1]); err != nil {
  1107  		t.Fatal(err)
  1108  	}
  1109  	blockchain.DrainAcceptorQueue()
  1110  
  1111  	lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock()
  1112  	expectedLastAcceptedBlock := chain1[1]
  1113  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
  1114  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
  1115  	}
  1116  
  1117  	if err := blockchain.InsertBlock(chain1[2]); err != nil {
  1118  		t.Fatal(err)
  1119  	}
  1120  	if err := blockchain.Accept(chain1[2]); err != nil {
  1121  		t.Fatal(err)
  1122  	}
  1123  	blockchain.DrainAcceptorQueue()
  1124  
  1125  	// check the state of the last accepted block
  1126  	checkState := func(sdb *state.StateDB) error {
  1127  		nonce1 := sdb.GetNonce(addr1)
  1128  		if nonce1 != 2 {
  1129  			return fmt.Errorf("expected addr1 nonce: 2, found nonce: %d", nonce1)
  1130  		}
  1131  		balance1 := sdb.GetBalance(addr1)
  1132  		expectedBalance := common.Big0
  1133  		if balance1.Cmp(expectedBalance) != 0 {
  1134  			return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1)
  1135  		}
  1136  		nonce2 := sdb.GetNonce(addr2)
  1137  		if nonce2 != 0 {
  1138  			return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2)
  1139  		}
  1140  		balance2 := sdb.GetBalance(addr2)
  1141  		if balance2.Cmp(genesisBalance) != 0 {
  1142  			return fmt.Errorf("expected balance2: %d, found %d", genesisBalance, balance2)
  1143  		}
  1144  		return nil
  1145  	}
  1146  
  1147  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
  1148  }
  1149  
  1150  // Insert two different chains that result in the identical state root.
  1151  // Once we insert both of the chains, we restart, insert both the chains again,
  1152  // and then we accept one of the chains and accept A3 on top of the shared state
  1153  // root
  1154  //   G   (genesis)
  1155  //  / \
  1156  // A1  B1
  1157  // |   |
  1158  // A2  B2 (A2 and B2 represent two different paths to the identical state trie)
  1159  // |
  1160  // A3
  1161  func TestReprocessAcceptBlockIdenticalStateRoot(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
  1162  	var (
  1163  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1164  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  1165  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
  1166  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
  1167  		// We use two separate databases since GenerateChain commits the state roots to its underlying
  1168  		// database.
  1169  		genDB   = rawdb.NewMemoryDatabase()
  1170  		chainDB = rawdb.NewMemoryDatabase()
  1171  	)
  1172  
  1173  	// Ensure that key1 has some funds in the genesis block.
  1174  	genesisBalance := big.NewInt(1000000000)
  1175  	gspec := &Genesis{
  1176  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
  1177  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
  1178  	}
  1179  	genesis := gspec.MustCommit(genDB)
  1180  	_ = gspec.MustCommit(chainDB)
  1181  
  1182  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
  1183  	if err != nil {
  1184  		t.Fatal(err)
  1185  	}
  1186  
  1187  	signer := types.HomesteadSigner{}
  1188  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
  1189  	// to the BlockChain's database while generating blocks.
  1190  	chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 10, func(i int, gen *BlockGen) {
  1191  		if i < 2 {
  1192  			// Send half the funds from addr1 to addr2 in one transaction per each of the two blocks in [chain1]
  1193  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(500000000), params.TxGas, nil, nil), signer, key1)
  1194  			gen.AddTx(tx)
  1195  		}
  1196  		// Allow the third block to be empty.
  1197  	})
  1198  	if err != nil {
  1199  		t.Fatal(err)
  1200  	}
  1201  	chain2, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 2, 10, func(i int, gen *BlockGen) {
  1202  		// 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
  1203  		// root in the second block of [chain2] as is present in the second block of [chain1].
  1204  		if i == 0 {
  1205  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(250000000), params.TxGas, nil, nil), signer, key1)
  1206  			gen.AddTx(tx)
  1207  		} else {
  1208  			tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(750000000), params.TxGas, nil, nil), signer, key1)
  1209  			gen.AddTx(tx)
  1210  		}
  1211  	})
  1212  	if err != nil {
  1213  		t.Fatal(err)
  1214  	}
  1215  
  1216  	// Assert that the block root of the second block in both chains is identical
  1217  	if chain1[1].Root() != chain2[1].Root() {
  1218  		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())
  1219  	}
  1220  
  1221  	// Insert first two blocks of [chain1] and both blocks in [chain2]
  1222  	// This leaves us one additional block to insert on top of [chain1]
  1223  	// after testing that the state roots are handled correctly.
  1224  	if _, err := blockchain.InsertChain(chain1[:2]); err != nil {
  1225  		t.Fatal(err)
  1226  	}
  1227  	if _, err := blockchain.InsertChain(chain2); err != nil {
  1228  		t.Fatal(err)
  1229  	}
  1230  
  1231  	currentBlock := blockchain.CurrentBlock()
  1232  	expectedCurrentBlock := chain1[1]
  1233  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
  1234  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
  1235  	}
  1236  
  1237  	blockchain.Stop()
  1238  
  1239  	blockchain, err = create(chainDB, gspec.Config, common.Hash{})
  1240  	if err != nil {
  1241  		t.Fatal(err)
  1242  	}
  1243  	defer blockchain.Stop()
  1244  
  1245  	// Insert first two blocks of [chain1] and both blocks in [chain2]
  1246  	// This leaves us one additional block to insert on top of [chain1]
  1247  	// after testing that the state roots are handled correctly.
  1248  	if _, err := blockchain.InsertChain(chain1[:2]); err != nil {
  1249  		t.Fatal(err)
  1250  	}
  1251  	if _, err := blockchain.InsertChain(chain2); err != nil {
  1252  		t.Fatal(err)
  1253  	}
  1254  
  1255  	currentBlock = blockchain.CurrentBlock()
  1256  	expectedCurrentBlock = chain1[1]
  1257  	if currentBlock.Hash() != expectedCurrentBlock.Hash() {
  1258  		t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64())
  1259  	}
  1260  
  1261  	// Accept the first block in [chain1] and reject all of [chain2]
  1262  	if err := blockchain.Accept(chain1[0]); err != nil {
  1263  		t.Fatal(err)
  1264  	}
  1265  	blockchain.DrainAcceptorQueue()
  1266  
  1267  	for _, block := range chain2 {
  1268  		if err := blockchain.Reject(block); err != nil {
  1269  			t.Fatal(err)
  1270  		}
  1271  	}
  1272  
  1273  	// Accept the last two blocks in [chain1]. This is a regression test to ensure
  1274  	// that we do not discard a snapshot difflayer that is still in use by a
  1275  	// processing block, when a different block with the same root is rejected.
  1276  	if err := blockchain.Accept(chain1[1]); err != nil {
  1277  		t.Fatal(err)
  1278  	}
  1279  	blockchain.DrainAcceptorQueue()
  1280  
  1281  	lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock()
  1282  	expectedLastAcceptedBlock := chain1[1]
  1283  	if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() {
  1284  		t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64())
  1285  	}
  1286  
  1287  	if err := blockchain.InsertBlock(chain1[2]); err != nil {
  1288  		t.Fatal(err)
  1289  	}
  1290  	if err := blockchain.Accept(chain1[2]); err != nil {
  1291  		t.Fatal(err)
  1292  	}
  1293  	blockchain.DrainAcceptorQueue()
  1294  
  1295  	// check the state of the last accepted block
  1296  	checkState := func(sdb *state.StateDB) error {
  1297  		nonce1 := sdb.GetNonce(addr1)
  1298  		if nonce1 != 2 {
  1299  			return fmt.Errorf("expected addr1 nonce: 2, found nonce: %d", nonce1)
  1300  		}
  1301  		balance1 := sdb.GetBalance(addr1)
  1302  		expectedBalance := common.Big0
  1303  		if balance1.Cmp(expectedBalance) != 0 {
  1304  			return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1)
  1305  		}
  1306  		nonce2 := sdb.GetNonce(addr2)
  1307  		if nonce2 != 0 {
  1308  			return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2)
  1309  		}
  1310  		balance2 := sdb.GetBalance(addr2)
  1311  		if balance2.Cmp(genesisBalance) != 0 {
  1312  			return fmt.Errorf("expected balance2: %d, found %d", genesisBalance, balance2)
  1313  		}
  1314  		return nil
  1315  	}
  1316  
  1317  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
  1318  }
  1319  
  1320  func TestGenerateChainInvalidBlockFee(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
  1321  	var (
  1322  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1323  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  1324  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
  1325  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
  1326  		// We use two separate databases since GenerateChain commits the state roots to its underlying
  1327  		// database.
  1328  		genDB   = rawdb.NewMemoryDatabase()
  1329  		chainDB = rawdb.NewMemoryDatabase()
  1330  	)
  1331  
  1332  	// Ensure that key1 has some funds in the genesis block.
  1333  	genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether))
  1334  	gspec := &Genesis{
  1335  		Config: params.TestChainConfig,
  1336  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
  1337  	}
  1338  	genesis := gspec.MustCommit(genDB)
  1339  	_ = gspec.MustCommit(chainDB)
  1340  
  1341  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
  1342  	if err != nil {
  1343  		t.Fatal(err)
  1344  	}
  1345  	defer blockchain.Stop()
  1346  
  1347  	// This call generates a chain of 3 blocks.
  1348  	signer := types.LatestSigner(params.TestChainConfig)
  1349  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
  1350  	// to the BlockChain's database while generating blocks.
  1351  	_, _, err = GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 0, func(i int, gen *BlockGen) {
  1352  		tx := types.NewTx(&types.DynamicFeeTx{
  1353  			ChainID:   params.TestChainConfig.ChainID,
  1354  			Nonce:     gen.TxNonce(addr1),
  1355  			To:        &addr2,
  1356  			Gas:       params.TxGas,
  1357  			GasFeeCap: gen.BaseFee(),
  1358  			GasTipCap: big.NewInt(0),
  1359  			Data:      []byte{},
  1360  		})
  1361  
  1362  		signedTx, err := types.SignTx(tx, signer, key1)
  1363  		if err != nil {
  1364  			t.Fatal(err)
  1365  		}
  1366  		gen.AddTx(signedTx)
  1367  	})
  1368  	if err == nil {
  1369  		t.Fatal("should not have been able to build a block because of insufficient block fee")
  1370  	}
  1371  	if !strings.Contains(err.Error(), "insufficient gas (0) to cover the block cost (400000)") {
  1372  		t.Fatalf("should have gotten insufficient block fee error but got %v instead", err)
  1373  	}
  1374  }
  1375  
  1376  func TestInsertChainInvalidBlockFee(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
  1377  	var (
  1378  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1379  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  1380  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
  1381  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
  1382  		// We use two separate databases since GenerateChain commits the state roots to its underlying
  1383  		// database.
  1384  		genDB   = rawdb.NewMemoryDatabase()
  1385  		chainDB = rawdb.NewMemoryDatabase()
  1386  	)
  1387  
  1388  	// Ensure that key1 has some funds in the genesis block.
  1389  	genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether))
  1390  	gspec := &Genesis{
  1391  		Config: params.TestChainConfig,
  1392  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
  1393  	}
  1394  	genesis := gspec.MustCommit(genDB)
  1395  	_ = gspec.MustCommit(chainDB)
  1396  
  1397  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
  1398  	if err != nil {
  1399  		t.Fatal(err)
  1400  	}
  1401  	defer blockchain.Stop()
  1402  
  1403  	// This call generates a chain of 3 blocks.
  1404  	signer := types.LatestSigner(params.TestChainConfig)
  1405  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
  1406  	// to the BlockChain's database while generating blocks.
  1407  	chain, _, err := GenerateChain(params.TestChainConfig, genesis, dummy.NewETHFaker(), genDB, 3, 0, func(i int, gen *BlockGen) {
  1408  		tx := types.NewTx(&types.DynamicFeeTx{
  1409  			ChainID:   params.TestChainConfig.ChainID,
  1410  			Nonce:     gen.TxNonce(addr1),
  1411  			To:        &addr2,
  1412  			Gas:       params.TxGas,
  1413  			GasFeeCap: gen.BaseFee(),
  1414  			GasTipCap: big.NewInt(0),
  1415  			Data:      []byte{},
  1416  		})
  1417  
  1418  		signedTx, err := types.SignTx(tx, signer, key1)
  1419  		if err != nil {
  1420  			t.Fatal(err)
  1421  		}
  1422  		gen.AddTx(signedTx)
  1423  	})
  1424  	if err != nil {
  1425  		t.Fatal(err)
  1426  	}
  1427  	_, err = blockchain.InsertChain(chain)
  1428  	if err == nil {
  1429  		t.Fatal("should not have been able to build a block because of insufficient block fee")
  1430  	}
  1431  	if !strings.Contains(err.Error(), "insufficient gas (0) to cover the block cost (400000)") {
  1432  		t.Fatalf("should have gotten insufficient block fee error but got %v instead", err)
  1433  	}
  1434  }
  1435  
  1436  func TestInsertChainValidBlockFee(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
  1437  	var (
  1438  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1439  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  1440  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
  1441  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
  1442  		// We use two separate databases since GenerateChain commits the state roots to its underlying
  1443  		// database.
  1444  		genDB   = rawdb.NewMemoryDatabase()
  1445  		chainDB = rawdb.NewMemoryDatabase()
  1446  	)
  1447  
  1448  	// Ensure that key1 has some funds in the genesis block.
  1449  	genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether))
  1450  	gspec := &Genesis{
  1451  		Config: params.TestChainConfig,
  1452  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
  1453  	}
  1454  	genesis := gspec.MustCommit(genDB)
  1455  	_ = gspec.MustCommit(chainDB)
  1456  
  1457  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
  1458  	if err != nil {
  1459  		t.Fatal(err)
  1460  	}
  1461  	defer blockchain.Stop()
  1462  
  1463  	// This call generates a chain of 3 blocks.
  1464  	signer := types.LatestSigner(params.TestChainConfig)
  1465  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
  1466  	// to the BlockChain's database while generating blocks.
  1467  	tip := big.NewInt(50000 * params.GWei)
  1468  	transfer := big.NewInt(10000)
  1469  	chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 0, func(i int, gen *BlockGen) {
  1470  		feeCap := new(big.Int).Add(gen.BaseFee(), tip)
  1471  		tx := types.NewTx(&types.DynamicFeeTx{
  1472  			ChainID:   params.TestChainConfig.ChainID,
  1473  			Nonce:     gen.TxNonce(addr1),
  1474  			To:        &addr2,
  1475  			Gas:       params.TxGas,
  1476  			Value:     transfer,
  1477  			GasFeeCap: feeCap,
  1478  			GasTipCap: tip,
  1479  			Data:      []byte{},
  1480  		})
  1481  
  1482  		signedTx, err := types.SignTx(tx, signer, key1)
  1483  		if err != nil {
  1484  			t.Fatal(err)
  1485  		}
  1486  		gen.AddTx(signedTx)
  1487  	})
  1488  	if err != nil {
  1489  		t.Fatal(err)
  1490  	}
  1491  
  1492  	// Insert three blocks into the chain and accept only the first block.
  1493  	if _, err := blockchain.InsertChain(chain); err != nil {
  1494  		t.Fatal(err)
  1495  	}
  1496  	if err := blockchain.Accept(chain[0]); err != nil {
  1497  		t.Fatal(err)
  1498  	}
  1499  	blockchain.DrainAcceptorQueue()
  1500  
  1501  	// check the state of the last accepted block
  1502  	checkState := func(sdb *state.StateDB) error {
  1503  		nonce := sdb.GetNonce(addr1)
  1504  		if nonce != 1 {
  1505  			return fmt.Errorf("expected nonce addr1: 1, found nonce: %d", nonce)
  1506  		}
  1507  		balance1 := sdb.GetBalance(addr1)
  1508  		expectedBalance1 := new(big.Int).Sub(genesisBalance, transfer)
  1509  		baseFee := params.DefaultFeeConfig.MinBaseFee
  1510  		feeSpend := new(big.Int).Mul(new(big.Int).Add(baseFee, tip), new(big.Int).SetUint64(params.TxGas))
  1511  		expectedBalance1.Sub(expectedBalance1, feeSpend)
  1512  		if balance1.Cmp(expectedBalance1) != 0 {
  1513  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance1, balance1)
  1514  		}
  1515  
  1516  		balance2 := sdb.GetBalance(addr2)
  1517  		expectedBalance2 := transfer
  1518  		if balance2.Cmp(expectedBalance2) != 0 {
  1519  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2)
  1520  		}
  1521  
  1522  		nonce = sdb.GetNonce(addr2)
  1523  		if nonce != 0 {
  1524  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce)
  1525  		}
  1526  		return nil
  1527  	}
  1528  
  1529  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
  1530  }
  1531  
  1532  // TestStatefulPrecompiles provides a testing framework to ensure that processing transactions interacting with the stateful precompiles work as expected.
  1533  func TestStatefulPrecompiles(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) {
  1534  	var (
  1535  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1536  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  1537  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
  1538  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
  1539  		// We use two separate databases since GenerateChain commits the state roots to its underlying
  1540  		// database.
  1541  		genDB   = rawdb.NewMemoryDatabase()
  1542  		chainDB = rawdb.NewMemoryDatabase()
  1543  	)
  1544  
  1545  	// Ensure that key1 has sufficient funds in the genesis block for all of the tests.
  1546  	genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether))
  1547  	config := *params.TestChainConfig
  1548  	// Set all of the required config parameters
  1549  	config.ContractDeployerAllowListConfig = precompile.NewContractDeployerAllowListConfig(big.NewInt(0), []common.Address{addr1}, nil)
  1550  	config.FeeManagerConfig = precompile.NewFeeManagerConfig(big.NewInt(0), []common.Address{addr1}, nil, nil)
  1551  	gspec := &Genesis{
  1552  		Config: &config,
  1553  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
  1554  	}
  1555  	genesis := gspec.MustCommit(genDB)
  1556  	_ = gspec.MustCommit(chainDB)
  1557  
  1558  	blockchain, err := create(chainDB, gspec.Config, common.Hash{})
  1559  	if err != nil {
  1560  		t.Fatal(err)
  1561  	}
  1562  	defer blockchain.Stop()
  1563  
  1564  	signer := types.LatestSigner(params.TestChainConfig)
  1565  	tip := big.NewInt(50000 * params.GWei)
  1566  
  1567  	// Simple framework to add a test that the stateful precompile works as expected
  1568  	type test struct {
  1569  		addTx         func(gen *BlockGen)
  1570  		verifyGenesis func(sdb *state.StateDB)
  1571  		verifyState   func(sdb *state.StateDB) error
  1572  	}
  1573  	testFeeConfig := commontype.FeeConfig{
  1574  		GasLimit:        big.NewInt(11_000_000),
  1575  		TargetBlockRate: 5, // in seconds
  1576  
  1577  		MinBaseFee:               big.NewInt(28_000_000_000),
  1578  		TargetGas:                big.NewInt(18_000_000),
  1579  		BaseFeeChangeDenominator: big.NewInt(3396),
  1580  
  1581  		MinBlockGasCost:  big.NewInt(0),
  1582  		MaxBlockGasCost:  big.NewInt(4_000_000),
  1583  		BlockGasCostStep: big.NewInt(500_000),
  1584  	}
  1585  	assert := assert.New(t)
  1586  	tests := map[string]test{
  1587  		"allow list": {
  1588  			addTx: func(gen *BlockGen) {
  1589  				feeCap := new(big.Int).Add(gen.BaseFee(), tip)
  1590  				input, err := precompile.PackModifyAllowList(addr2, precompile.AllowListAdmin)
  1591  				if err != nil {
  1592  					t.Fatal(err)
  1593  				}
  1594  				tx := types.NewTx(&types.DynamicFeeTx{
  1595  					ChainID:   params.TestChainConfig.ChainID,
  1596  					Nonce:     gen.TxNonce(addr1),
  1597  					To:        &precompile.ContractDeployerAllowListAddress,
  1598  					Gas:       3_000_000,
  1599  					Value:     common.Big0,
  1600  					GasFeeCap: feeCap,
  1601  					GasTipCap: tip,
  1602  					Data:      input,
  1603  				})
  1604  
  1605  				signedTx, err := types.SignTx(tx, signer, key1)
  1606  				if err != nil {
  1607  					t.Fatal(err)
  1608  				}
  1609  				gen.AddTx(signedTx)
  1610  			},
  1611  			verifyState: func(sdb *state.StateDB) error {
  1612  				res := precompile.GetContractDeployerAllowListStatus(sdb, addr1)
  1613  				if precompile.AllowListAdmin != res {
  1614  					return fmt.Errorf("unexpected allow list status for addr1 %s, expected %s", res, precompile.AllowListAdmin)
  1615  				}
  1616  				res = precompile.GetContractDeployerAllowListStatus(sdb, addr2)
  1617  				if precompile.AllowListAdmin != res {
  1618  					return fmt.Errorf("unexpected allow list status for addr2 %s, expected %s", res, precompile.AllowListAdmin)
  1619  				}
  1620  				return nil
  1621  			},
  1622  			verifyGenesis: func(sdb *state.StateDB) {
  1623  				res := precompile.GetContractDeployerAllowListStatus(sdb, addr1)
  1624  				if precompile.AllowListAdmin != res {
  1625  					t.Fatalf("unexpected allow list status for addr1 %s, expected %s", res, precompile.AllowListAdmin)
  1626  				}
  1627  				res = precompile.GetContractDeployerAllowListStatus(sdb, addr2)
  1628  				if precompile.AllowListNoRole != res {
  1629  					t.Fatalf("unexpected allow list status for addr2 %s, expected %s", res, precompile.AllowListNoRole)
  1630  				}
  1631  			},
  1632  		},
  1633  		"fee manager set config": {
  1634  			addTx: func(gen *BlockGen) {
  1635  				feeCap := new(big.Int).Add(gen.BaseFee(), tip)
  1636  				input, err := precompile.PackSetFeeConfig(testFeeConfig)
  1637  				if err != nil {
  1638  					t.Fatal(err)
  1639  				}
  1640  				tx := types.NewTx(&types.DynamicFeeTx{
  1641  					ChainID:   params.TestChainConfig.ChainID,
  1642  					Nonce:     gen.TxNonce(addr1),
  1643  					To:        &precompile.FeeConfigManagerAddress,
  1644  					Gas:       3_000_000,
  1645  					Value:     common.Big0,
  1646  					GasFeeCap: feeCap,
  1647  					GasTipCap: tip,
  1648  					Data:      input,
  1649  				})
  1650  
  1651  				signedTx, err := types.SignTx(tx, signer, key1)
  1652  				if err != nil {
  1653  					t.Fatal(err)
  1654  				}
  1655  				gen.AddTx(signedTx)
  1656  			},
  1657  			verifyState: func(sdb *state.StateDB) error {
  1658  				res := precompile.GetFeeConfigManagerStatus(sdb, addr1)
  1659  				assert.Equal(precompile.AllowListAdmin, res)
  1660  
  1661  				storedConfig := precompile.GetStoredFeeConfig(sdb)
  1662  				assert.EqualValues(testFeeConfig, storedConfig)
  1663  
  1664  				feeConfig, _, err := blockchain.GetFeeConfigAt(blockchain.CurrentHeader())
  1665  				assert.NoError(err)
  1666  				assert.EqualValues(testFeeConfig, feeConfig)
  1667  				return nil
  1668  			},
  1669  			verifyGenesis: func(sdb *state.StateDB) {
  1670  				res := precompile.GetFeeConfigManagerStatus(sdb, addr1)
  1671  				assert.Equal(precompile.AllowListAdmin, res)
  1672  
  1673  				feeConfig, _, err := blockchain.GetFeeConfigAt(blockchain.Genesis().Header())
  1674  				assert.NoError(err)
  1675  				assert.EqualValues(config.FeeConfig, feeConfig)
  1676  			},
  1677  		},
  1678  	}
  1679  
  1680  	// Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing
  1681  	// to the BlockChain's database while generating blocks.
  1682  	chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 1, 0, func(i int, gen *BlockGen) {
  1683  		for _, test := range tests {
  1684  			test.addTx(gen)
  1685  		}
  1686  	})
  1687  	if err != nil {
  1688  		t.Fatal(err)
  1689  	}
  1690  
  1691  	// Insert three blocks into the chain and accept only the first block.
  1692  	if _, err := blockchain.InsertChain(chain); err != nil {
  1693  		t.Fatal(err)
  1694  	}
  1695  	if err := blockchain.Accept(chain[0]); err != nil {
  1696  		t.Fatal(err)
  1697  	}
  1698  	blockchain.DrainAcceptorQueue()
  1699  
  1700  	genesisState, err := blockchain.StateAt(blockchain.Genesis().Root())
  1701  	if err != nil {
  1702  		t.Fatal(err)
  1703  	}
  1704  	for _, test := range tests {
  1705  		if test.verifyGenesis == nil {
  1706  			continue
  1707  		}
  1708  		test.verifyGenesis(genesisState)
  1709  	}
  1710  
  1711  	// Run all of the necessary state verification
  1712  	checkState := func(sdb *state.StateDB) error {
  1713  		for _, test := range tests {
  1714  			if err := test.verifyState(sdb); err != nil {
  1715  				return err
  1716  			}
  1717  		}
  1718  		return nil
  1719  	}
  1720  
  1721  	// This tests that the precompiles work as expected when they are enabled
  1722  	checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
  1723  }