github.com/ava-labs/subnet-evm@v0.6.4/core/blockchain_test.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  	"os"
    10  	"testing"
    11  
    12  	"github.com/ava-labs/subnet-evm/consensus/dummy"
    13  	"github.com/ava-labs/subnet-evm/core/rawdb"
    14  	"github.com/ava-labs/subnet-evm/core/state"
    15  	"github.com/ava-labs/subnet-evm/core/state/pruner"
    16  	"github.com/ava-labs/subnet-evm/core/types"
    17  	"github.com/ava-labs/subnet-evm/core/vm"
    18  	"github.com/ava-labs/subnet-evm/eth/tracers/logger"
    19  	"github.com/ava-labs/subnet-evm/params"
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/crypto"
    22  	"github.com/ethereum/go-ethereum/ethdb"
    23  	"github.com/stretchr/testify/require"
    24  )
    25  
    26  var (
    27  	archiveConfig = &CacheConfig{
    28  		TrieCleanLimit:            256,
    29  		TrieDirtyLimit:            256,
    30  		TrieDirtyCommitTarget:     20,
    31  		TriePrefetcherParallelism: 4,
    32  		Pruning:                   false, // Archive mode
    33  		SnapshotLimit:             256,
    34  		AcceptorQueueLimit:        64,
    35  	}
    36  
    37  	pruningConfig = &CacheConfig{
    38  		TrieCleanLimit:            256,
    39  		TrieDirtyLimit:            256,
    40  		TrieDirtyCommitTarget:     20,
    41  		TriePrefetcherParallelism: 4,
    42  		Pruning:                   true, // Enable pruning
    43  		CommitInterval:            4096,
    44  		SnapshotLimit:             256,
    45  		AcceptorQueueLimit:        64,
    46  	}
    47  )
    48  
    49  func newGwei(n int64) *big.Int {
    50  	return new(big.Int).Mul(big.NewInt(n), big.NewInt(params.GWei))
    51  }
    52  
    53  func createBlockChain(
    54  	db ethdb.Database,
    55  	cacheConfig *CacheConfig,
    56  	gspec *Genesis,
    57  	lastAcceptedHash common.Hash,
    58  ) (*BlockChain, error) {
    59  	// Import the chain. This runs all block validation rules.
    60  	blockchain, err := NewBlockChain(
    61  		db,
    62  		cacheConfig,
    63  		gspec,
    64  		dummy.NewCoinbaseFaker(),
    65  		vm.Config{},
    66  		lastAcceptedHash,
    67  		false,
    68  	)
    69  	return blockchain, err
    70  }
    71  
    72  func TestArchiveBlockChain(t *testing.T) {
    73  	createArchiveBlockChain := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
    74  		return createBlockChain(db, archiveConfig, gspec, lastAcceptedHash)
    75  	}
    76  	for _, tt := range tests {
    77  		t.Run(tt.Name, func(t *testing.T) {
    78  			tt.testFunc(t, createArchiveBlockChain)
    79  		})
    80  	}
    81  }
    82  
    83  func TestArchiveBlockChainSnapsDisabled(t *testing.T) {
    84  	create := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
    85  		return createBlockChain(
    86  			db,
    87  			&CacheConfig{
    88  				TrieCleanLimit:            256,
    89  				TrieDirtyLimit:            256,
    90  				TrieDirtyCommitTarget:     20,
    91  				TriePrefetcherParallelism: 4,
    92  				Pruning:                   false, // Archive mode
    93  				SnapshotLimit:             0,     // Disable snapshots
    94  				AcceptorQueueLimit:        64,
    95  			},
    96  			gspec,
    97  			lastAcceptedHash,
    98  		)
    99  	}
   100  	for _, tt := range tests {
   101  		t.Run(tt.Name, func(t *testing.T) {
   102  			tt.testFunc(t, create)
   103  		})
   104  	}
   105  }
   106  
   107  func TestPruningBlockChain(t *testing.T) {
   108  	createPruningBlockChain := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   109  		return createBlockChain(db, pruningConfig, gspec, lastAcceptedHash)
   110  	}
   111  	for _, tt := range tests {
   112  		t.Run(tt.Name, func(t *testing.T) {
   113  			tt.testFunc(t, createPruningBlockChain)
   114  		})
   115  	}
   116  }
   117  
   118  func TestPruningBlockChainSnapsDisabled(t *testing.T) {
   119  	create := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   120  		return createBlockChain(
   121  			db,
   122  			&CacheConfig{
   123  				TrieCleanLimit:            256,
   124  				TrieDirtyLimit:            256,
   125  				TrieDirtyCommitTarget:     20,
   126  				TriePrefetcherParallelism: 4,
   127  				Pruning:                   true, // Enable pruning
   128  				CommitInterval:            4096,
   129  				SnapshotLimit:             0, // Disable snapshots
   130  				AcceptorQueueLimit:        64,
   131  			},
   132  			gspec,
   133  			lastAcceptedHash,
   134  		)
   135  	}
   136  	for _, tt := range tests {
   137  		t.Run(tt.Name, func(t *testing.T) {
   138  			tt.testFunc(t, create)
   139  		})
   140  	}
   141  }
   142  
   143  type wrappedStateManager struct {
   144  	TrieWriter
   145  }
   146  
   147  func (w *wrappedStateManager) Shutdown() error { return nil }
   148  
   149  func TestPruningBlockChainUngracefulShutdown(t *testing.T) {
   150  	create := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   151  		blockchain, err := createBlockChain(db, pruningConfig, gspec, lastAcceptedHash)
   152  		if err != nil {
   153  			return nil, err
   154  		}
   155  
   156  		// Overwrite state manager, so that Shutdown is not called.
   157  		// This tests to ensure that the state manager handles an ungraceful shutdown correctly.
   158  		blockchain.stateManager = &wrappedStateManager{TrieWriter: blockchain.stateManager}
   159  		return blockchain, err
   160  	}
   161  	for _, tt := range tests {
   162  		t.Run(tt.Name, func(t *testing.T) {
   163  			tt.testFunc(t, create)
   164  		})
   165  	}
   166  }
   167  
   168  func TestPruningBlockChainUngracefulShutdownSnapsDisabled(t *testing.T) {
   169  	create := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   170  		blockchain, err := createBlockChain(
   171  			db,
   172  			&CacheConfig{
   173  				TrieCleanLimit:            256,
   174  				TrieDirtyLimit:            256,
   175  				TrieDirtyCommitTarget:     20,
   176  				TriePrefetcherParallelism: 4,
   177  				Pruning:                   true, // Enable pruning
   178  				CommitInterval:            4096,
   179  				SnapshotLimit:             0, // Disable snapshots
   180  				AcceptorQueueLimit:        64,
   181  			},
   182  			gspec,
   183  			lastAcceptedHash,
   184  		)
   185  		if err != nil {
   186  			return nil, err
   187  		}
   188  
   189  		// Overwrite state manager, so that Shutdown is not called.
   190  		// This tests to ensure that the state manager handles an ungraceful shutdown correctly.
   191  		blockchain.stateManager = &wrappedStateManager{TrieWriter: blockchain.stateManager}
   192  		return blockchain, err
   193  	}
   194  	for _, tt := range tests {
   195  		t.Run(tt.Name, func(t *testing.T) {
   196  			tt.testFunc(t, create)
   197  		})
   198  	}
   199  }
   200  
   201  func TestEnableSnapshots(t *testing.T) {
   202  	// Set snapshots to be disabled the first time, and then enable them on the restart
   203  	snapLimit := 0
   204  	create := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   205  		// Import the chain. This runs all block validation rules.
   206  		blockchain, err := createBlockChain(
   207  			db,
   208  			&CacheConfig{
   209  				TrieCleanLimit:            256,
   210  				TrieDirtyLimit:            256,
   211  				TrieDirtyCommitTarget:     20,
   212  				TriePrefetcherParallelism: 4,
   213  				Pruning:                   true, // Enable pruning
   214  				CommitInterval:            4096,
   215  				SnapshotLimit:             snapLimit,
   216  				AcceptorQueueLimit:        64,
   217  			},
   218  			gspec,
   219  			lastAcceptedHash,
   220  		)
   221  		if err != nil {
   222  			return nil, err
   223  		}
   224  		snapLimit = 256
   225  
   226  		return blockchain, err
   227  	}
   228  	for _, tt := range tests {
   229  		t.Run(tt.Name, func(t *testing.T) {
   230  			tt.testFunc(t, create)
   231  		})
   232  	}
   233  }
   234  
   235  func TestCorruptSnapshots(t *testing.T) {
   236  	create := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   237  		// Delete the snapshot block hash and state root to ensure that if we die in between writing a snapshot
   238  		// diff layer to disk at any point, we can still recover on restart.
   239  		rawdb.DeleteSnapshotBlockHash(db)
   240  		rawdb.DeleteSnapshotRoot(db)
   241  
   242  		return createBlockChain(db, pruningConfig, gspec, lastAcceptedHash)
   243  	}
   244  	for _, tt := range tests {
   245  		t.Run(tt.Name, func(t *testing.T) {
   246  			tt.testFunc(t, create)
   247  		})
   248  	}
   249  }
   250  
   251  func TestBlockChainOfflinePruningUngracefulShutdown(t *testing.T) {
   252  	create := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   253  		// Import the chain. This runs all block validation rules.
   254  		blockchain, err := createBlockChain(db, pruningConfig, gspec, lastAcceptedHash)
   255  		if err != nil {
   256  			return nil, err
   257  		}
   258  
   259  		// Overwrite state manager, so that Shutdown is not called.
   260  		// This tests to ensure that the state manager handles an ungraceful shutdown correctly.
   261  		blockchain.stateManager = &wrappedStateManager{TrieWriter: blockchain.stateManager}
   262  
   263  		if lastAcceptedHash == (common.Hash{}) {
   264  			return blockchain, nil
   265  		}
   266  
   267  		if err := blockchain.CleanBlockRootsAboveLastAccepted(); err != nil {
   268  			return nil, err
   269  		}
   270  		// get the target root to prune to before stopping the blockchain
   271  		targetRoot := blockchain.LastAcceptedBlock().Root()
   272  		if targetRoot == types.EmptyRootHash {
   273  			return blockchain, nil
   274  		}
   275  		blockchain.Stop()
   276  
   277  		tempDir := t.TempDir()
   278  		prunerConfig := pruner.Config{
   279  			Datadir:   tempDir,
   280  			BloomSize: 256,
   281  		}
   282  
   283  		pruner, err := pruner.NewPruner(db, prunerConfig)
   284  		if err != nil {
   285  			return nil, fmt.Errorf("offline pruning failed (%s, %d): %w", tempDir, 256, err)
   286  		}
   287  
   288  		if err := pruner.Prune(targetRoot); err != nil {
   289  			return nil, fmt.Errorf("failed to prune blockchain with target root: %s due to: %w", targetRoot, err)
   290  		}
   291  		// Re-initialize the blockchain after pruning
   292  		return createBlockChain(db, pruningConfig, gspec, lastAcceptedHash)
   293  	}
   294  	for _, tt := range tests {
   295  		tt := tt
   296  		t.Run(tt.Name, func(t *testing.T) {
   297  			t.Parallel()
   298  			tt.testFunc(t, create)
   299  		})
   300  	}
   301  }
   302  
   303  func testRepopulateMissingTriesParallel(t *testing.T, parallelism int) {
   304  	var (
   305  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   306  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   307  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   308  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   309  		chainDB = rawdb.NewMemoryDatabase()
   310  	)
   311  
   312  	// Ensure that key1 has some funds in the genesis block.
   313  	genesisBalance := big.NewInt(1000000)
   314  	gspec := &Genesis{
   315  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int), FeeConfig: params.DefaultFeeConfig},
   316  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   317  	}
   318  
   319  	blockchain, err := createBlockChain(chainDB, pruningConfig, gspec, common.Hash{})
   320  	if err != nil {
   321  		t.Fatal(err)
   322  	}
   323  	defer blockchain.Stop()
   324  
   325  	// This call generates a chain of 3 blocks.
   326  	signer := types.HomesteadSigner{}
   327  	_, chain, _, err := GenerateChainWithGenesis(gspec, blockchain.engine, 10, 10, func(i int, gen *BlockGen) {
   328  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   329  		gen.AddTx(tx)
   330  	})
   331  	if err != nil {
   332  		t.Fatal(err)
   333  	}
   334  
   335  	if _, err := blockchain.InsertChain(chain); err != nil {
   336  		t.Fatal(err)
   337  	}
   338  	for _, block := range chain {
   339  		if err := blockchain.Accept(block); err != nil {
   340  			t.Fatal(err)
   341  		}
   342  	}
   343  	blockchain.DrainAcceptorQueue()
   344  
   345  	lastAcceptedHash := blockchain.LastConsensusAcceptedBlock().Hash()
   346  	blockchain.Stop()
   347  
   348  	blockchain, err = createBlockChain(chainDB, pruningConfig, gspec, lastAcceptedHash)
   349  	if err != nil {
   350  		t.Fatal(err)
   351  	}
   352  
   353  	// Confirm that the node does not have the state for intermediate nodes (exclude the last accepted block)
   354  	for _, block := range chain[:len(chain)-1] {
   355  		if blockchain.HasState(block.Root()) {
   356  			t.Fatalf("Expected blockchain to be missing state for intermediate block %d with pruning enabled", block.NumberU64())
   357  		}
   358  	}
   359  	blockchain.Stop()
   360  
   361  	startHeight := uint64(1)
   362  	// Create a node in archival mode and re-populate the trie history.
   363  	blockchain, err = createBlockChain(
   364  		chainDB,
   365  		&CacheConfig{
   366  			TrieCleanLimit:                  256,
   367  			TrieDirtyLimit:                  256,
   368  			TrieDirtyCommitTarget:           20,
   369  			TriePrefetcherParallelism:       4,
   370  			Pruning:                         false, // Archive mode
   371  			SnapshotLimit:                   256,
   372  			PopulateMissingTries:            &startHeight, // Starting point for re-populating.
   373  			PopulateMissingTriesParallelism: parallelism,
   374  			AcceptorQueueLimit:              64,
   375  		},
   376  		gspec,
   377  		lastAcceptedHash,
   378  	)
   379  	if err != nil {
   380  		t.Fatal(err)
   381  	}
   382  	defer blockchain.Stop()
   383  
   384  	for _, block := range chain {
   385  		if !blockchain.HasState(block.Root()) {
   386  			t.Fatalf("failed to re-generate state for block %d", block.NumberU64())
   387  		}
   388  	}
   389  }
   390  
   391  func TestRepopulateMissingTries(t *testing.T) {
   392  	// Test with different levels of parallelism as a regression test.
   393  	for _, parallelism := range []int{1, 2, 4, 1024} {
   394  		testRepopulateMissingTriesParallel(t, parallelism)
   395  	}
   396  }
   397  
   398  func TestUngracefulAsyncShutdown(t *testing.T) {
   399  	var (
   400  		create = func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   401  			blockchain, err := createBlockChain(db, &CacheConfig{
   402  				TrieCleanLimit:            256,
   403  				TrieDirtyLimit:            256,
   404  				TrieDirtyCommitTarget:     20,
   405  				TriePrefetcherParallelism: 4,
   406  				Pruning:                   true,
   407  				CommitInterval:            4096,
   408  				SnapshotLimit:             256,
   409  				SnapshotNoBuild:           true, // Ensure the test errors if snapshot initialization fails
   410  				AcceptorQueueLimit:        1000, // ensure channel doesn't block
   411  			}, gspec, lastAcceptedHash)
   412  			if err != nil {
   413  				return nil, err
   414  			}
   415  			return blockchain, nil
   416  		}
   417  
   418  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   419  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   420  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   421  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   422  		chainDB = rawdb.NewMemoryDatabase()
   423  	)
   424  
   425  	// Ensure that key1 has some funds in the genesis block.
   426  	genesisBalance := big.NewInt(1000000)
   427  	gspec := &Genesis{
   428  		Config: &params.ChainConfig{HomesteadBlock: new(big.Int), FeeConfig: params.DefaultFeeConfig},
   429  		Alloc:  GenesisAlloc{addr1: {Balance: genesisBalance}},
   430  	}
   431  
   432  	blockchain, err := create(chainDB, gspec, common.Hash{})
   433  	if err != nil {
   434  		t.Fatal(err)
   435  	}
   436  	defer blockchain.Stop()
   437  
   438  	// This call generates a chain of 10 blocks.
   439  	signer := types.HomesteadSigner{}
   440  	_, chain, _, err := GenerateChainWithGenesis(gspec, blockchain.engine, 10, 10, func(i int, gen *BlockGen) {
   441  		tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   442  		gen.AddTx(tx)
   443  	})
   444  	if err != nil {
   445  		t.Fatal(err)
   446  	}
   447  
   448  	// Insert three blocks into the chain and accept only the first block.
   449  	if _, err := blockchain.InsertChain(chain); err != nil {
   450  		t.Fatal(err)
   451  	}
   452  
   453  	foundTxs := []common.Hash{}
   454  	missingTxs := []common.Hash{}
   455  	for i, block := range chain {
   456  		if err := blockchain.Accept(block); err != nil {
   457  			t.Fatal(err)
   458  		}
   459  
   460  		if i == 3 {
   461  			// At height 3, kill the async accepted block processor to force an
   462  			// ungraceful recovery
   463  			blockchain.stopAcceptor()
   464  			blockchain.acceptorQueue = nil
   465  		}
   466  
   467  		if i <= 3 {
   468  			// If <= height 3, all txs should be accessible on lookup
   469  			for _, tx := range block.Transactions() {
   470  				foundTxs = append(foundTxs, tx.Hash())
   471  			}
   472  		} else {
   473  			// If > 3, all txs should be accessible on lookup
   474  			for _, tx := range block.Transactions() {
   475  				missingTxs = append(missingTxs, tx.Hash())
   476  			}
   477  		}
   478  	}
   479  
   480  	// After inserting all blocks, we should confirm that txs added after the
   481  	// async worker shutdown cannot be found.
   482  	for _, tx := range foundTxs {
   483  		txLookup := blockchain.GetTransactionLookup(tx)
   484  		if txLookup == nil {
   485  			t.Fatalf("missing transaction: %v", tx)
   486  		}
   487  	}
   488  	for _, tx := range missingTxs {
   489  		txLookup := blockchain.GetTransactionLookup(tx)
   490  		if txLookup != nil {
   491  			t.Fatalf("transaction should be missing: %v", tx)
   492  		}
   493  	}
   494  
   495  	// check the state of the last accepted block
   496  	checkState := func(sdb *state.StateDB) error {
   497  		nonce := sdb.GetNonce(addr1)
   498  		if nonce != 10 {
   499  			return fmt.Errorf("expected nonce addr1: 10, found nonce: %d", nonce)
   500  		}
   501  		transferredFunds := big.NewInt(100000)
   502  		balance1 := sdb.GetBalance(addr1)
   503  		expectedBalance1 := new(big.Int).Sub(genesisBalance, transferredFunds)
   504  		if balance1.Cmp(expectedBalance1) != 0 {
   505  			return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance1, balance1)
   506  		}
   507  
   508  		balance2 := sdb.GetBalance(addr2)
   509  		expectedBalance2 := transferredFunds
   510  		if balance2.Cmp(expectedBalance2) != 0 {
   511  			return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2)
   512  		}
   513  
   514  		nonce = sdb.GetNonce(addr2)
   515  		if nonce != 0 {
   516  			return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce)
   517  		}
   518  		return nil
   519  	}
   520  
   521  	_, newChain, restartedChain := checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState)
   522  
   523  	allTxs := append(foundTxs, missingTxs...)
   524  	for _, bc := range []*BlockChain{newChain, restartedChain} {
   525  		// We should confirm that snapshots were properly initialized
   526  		if bc.snaps == nil {
   527  			t.Fatal("snapshot initialization failed")
   528  		}
   529  
   530  		// We should confirm all transactions can now be queried
   531  		for _, tx := range allTxs {
   532  			txLookup := bc.GetTransactionLookup(tx)
   533  			if txLookup == nil {
   534  				t.Fatalf("missing transaction: %v", tx)
   535  			}
   536  		}
   537  	}
   538  }
   539  
   540  func TestTransactionIndices(t *testing.T) {
   541  	// Configure and generate a sample block chain
   542  	require := require.New(t)
   543  	var (
   544  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   545  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   546  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   547  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   548  		funds   = big.NewInt(10000000000000)
   549  		gspec   = &Genesis{
   550  			Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   551  			Alloc:  GenesisAlloc{addr1: {Balance: funds}},
   552  		}
   553  		signer = types.LatestSigner(gspec.Config)
   554  	)
   555  	genDb, blocks, _, err := GenerateChainWithGenesis(gspec, dummy.NewFaker(), 128, 10, func(i int, block *BlockGen) {
   556  		tx, err := types.SignTx(types.NewTransaction(block.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   557  		require.NoError(err)
   558  		block.AddTx(tx)
   559  	})
   560  	require.NoError(err)
   561  
   562  	blocks2, _, err := GenerateChain(gspec.Config, blocks[len(blocks)-1], dummy.NewFaker(), genDb, 10, 10, func(i int, block *BlockGen) {
   563  		tx, err := types.SignTx(types.NewTransaction(block.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   564  		require.NoError(err)
   565  		block.AddTx(tx)
   566  	})
   567  	require.NoError(err)
   568  
   569  	conf := &CacheConfig{
   570  		TrieCleanLimit:            256,
   571  		TrieDirtyLimit:            256,
   572  		TrieDirtyCommitTarget:     20,
   573  		TriePrefetcherParallelism: 4,
   574  		Pruning:                   true,
   575  		CommitInterval:            4096,
   576  		SnapshotLimit:             256,
   577  		SnapshotNoBuild:           true, // Ensure the test errors if snapshot initialization fails
   578  		AcceptorQueueLimit:        64,
   579  	}
   580  
   581  	// Init block chain and check all needed indices has been indexed.
   582  	chainDB := rawdb.NewMemoryDatabase()
   583  	chain, err := createBlockChain(chainDB, conf, gspec, common.Hash{})
   584  	require.NoError(err)
   585  
   586  	_, err = chain.InsertChain(blocks)
   587  	require.NoError(err)
   588  
   589  	for _, block := range blocks {
   590  		err := chain.Accept(block)
   591  		require.NoError(err)
   592  	}
   593  	chain.DrainAcceptorQueue()
   594  
   595  	lastAcceptedBlock := blocks[len(blocks)-1]
   596  	require.Equal(lastAcceptedBlock.Hash(), chain.CurrentHeader().Hash())
   597  
   598  	CheckTxIndices(t, nil, lastAcceptedBlock.NumberU64(), chain.db, false) // check all indices has been indexed
   599  	chain.Stop()
   600  
   601  	// Reconstruct a block chain which only reserves limited tx indices
   602  	// 128 blocks were previously indexed. Now we add a new block at each test step.
   603  	limits := []uint64{
   604  		0,   /* tip: 129 reserve all (don't run) */
   605  		131, /* tip: 130 reserve all */
   606  		140, /* tip: 131 reserve all */
   607  		64,  /* tip: 132, limit:64 */
   608  		32,  /* tip: 133, limit:32  */
   609  	}
   610  	for i, l := range limits {
   611  		t.Run(fmt.Sprintf("test-%d, limit: %d", i+1, l), func(t *testing.T) {
   612  			conf.TxLookupLimit = l
   613  
   614  			chain, err := createBlockChain(chainDB, conf, gspec, lastAcceptedBlock.Hash())
   615  			require.NoError(err)
   616  
   617  			tail := getTail(l, lastAcceptedBlock.NumberU64())
   618  			// check if startup indices are correct
   619  			CheckTxIndices(t, tail, lastAcceptedBlock.NumberU64(), chain.db, false)
   620  
   621  			newBlks := blocks2[i : i+1]
   622  			_, err = chain.InsertChain(newBlks) // Feed chain a higher block to trigger indices updater.
   623  			require.NoError(err)
   624  
   625  			lastAcceptedBlock = newBlks[0]
   626  			err = chain.Accept(lastAcceptedBlock) // Accept the block to trigger indices updater.
   627  			require.NoError(err)
   628  			chain.DrainAcceptorQueue()
   629  
   630  			tail = getTail(l, lastAcceptedBlock.NumberU64())
   631  			// check if indices are updated correctly
   632  			CheckTxIndices(t, tail, lastAcceptedBlock.NumberU64(), chain.db, false)
   633  			chain.Stop()
   634  		})
   635  	}
   636  }
   637  
   638  func getTail(limit uint64, lastAccepted uint64) *uint64 {
   639  	if limit == 0 {
   640  		return nil
   641  	}
   642  	var tail uint64
   643  	if lastAccepted > limit {
   644  		// tail should be the oldest block number which is indexed
   645  		// i.e the first block number that's in the lookup range
   646  		tail = lastAccepted - limit + 1
   647  	}
   648  	return &tail
   649  }
   650  
   651  func TestTransactionSkipIndexing(t *testing.T) {
   652  	// Configure and generate a sample block chain
   653  	require := require.New(t)
   654  	var (
   655  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   656  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
   657  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
   658  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
   659  		funds   = big.NewInt(10000000000000)
   660  		gspec   = &Genesis{
   661  			Config: &params.ChainConfig{HomesteadBlock: new(big.Int)},
   662  			Alloc:  GenesisAlloc{addr1: {Balance: funds}},
   663  		}
   664  		signer = types.LatestSigner(gspec.Config)
   665  	)
   666  	genDb, blocks, _, err := GenerateChainWithGenesis(gspec, dummy.NewCoinbaseFaker(), 5, 10, func(i int, block *BlockGen) {
   667  		tx, err := types.SignTx(types.NewTransaction(block.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   668  		require.NoError(err)
   669  		block.AddTx(tx)
   670  	})
   671  	require.NoError(err)
   672  
   673  	blocks2, _, err := GenerateChain(gspec.Config, blocks[len(blocks)-1], dummy.NewCoinbaseFaker(), genDb, 5, 10, func(i int, block *BlockGen) {
   674  		tx, err := types.SignTx(types.NewTransaction(block.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
   675  		require.NoError(err)
   676  		block.AddTx(tx)
   677  	})
   678  	require.NoError(err)
   679  
   680  	conf := &CacheConfig{
   681  		TrieCleanLimit:            256,
   682  		TrieDirtyLimit:            256,
   683  		TrieDirtyCommitTarget:     20,
   684  		TriePrefetcherParallelism: 4,
   685  		Pruning:                   true,
   686  		CommitInterval:            4096,
   687  		SnapshotLimit:             256,
   688  		SnapshotNoBuild:           true, // Ensure the test errors if snapshot initialization fails
   689  		AcceptorQueueLimit:        64,
   690  		SkipTxIndexing:            true,
   691  	}
   692  
   693  	// test1: Init block chain and check all indices has been skipped.
   694  	chainDB := rawdb.NewMemoryDatabase()
   695  	chain, err := createAndInsertChain(chainDB, conf, gspec, blocks, common.Hash{},
   696  		func(b *types.Block) {
   697  			bNumber := b.NumberU64()
   698  			checkTxIndicesHelper(t, nil, bNumber+1, bNumber+1, bNumber, chainDB, false) // check all indices has been skipped
   699  		})
   700  	require.NoError(err)
   701  	chain.Stop()
   702  
   703  	// test2: specify lookuplimit with tx index skipping enabled. Blocks should not be indexed but tail should be updated.
   704  	conf.TxLookupLimit = 2
   705  	chainDB = rawdb.NewMemoryDatabase()
   706  	chain, err = createAndInsertChain(chainDB, conf, gspec, blocks, common.Hash{},
   707  		func(b *types.Block) {
   708  			bNumber := b.NumberU64()
   709  			tail := bNumber - conf.TxLookupLimit + 1
   710  			checkTxIndicesHelper(t, &tail, bNumber+1, bNumber+1, bNumber, chainDB, false) // check all indices has been skipped
   711  		})
   712  	require.NoError(err)
   713  	chain.Stop()
   714  
   715  	// test3: tx index skipping and unindexer disabled. Blocks should be indexed and tail should be updated.
   716  	conf.TxLookupLimit = 0
   717  	conf.SkipTxIndexing = false
   718  	chainDB = rawdb.NewMemoryDatabase()
   719  	chain, err = createAndInsertChain(chainDB, conf, gspec, blocks, common.Hash{},
   720  		func(b *types.Block) {
   721  			bNumber := b.NumberU64()
   722  			checkTxIndicesHelper(t, nil, 0, bNumber, bNumber, chainDB, false) // check all indices has been indexed
   723  		})
   724  	require.NoError(err)
   725  	chain.Stop()
   726  
   727  	// now change tx index skipping to true and check that the indices are skipped for the last block
   728  	// and old indices are removed up to the tail, but [tail, current) indices are still there.
   729  	conf.TxLookupLimit = 2
   730  	conf.SkipTxIndexing = true
   731  	chain, err = createAndInsertChain(chainDB, conf, gspec, blocks2[0:1], chain.CurrentHeader().Hash(),
   732  		func(b *types.Block) {
   733  			bNumber := b.NumberU64()
   734  			tail := bNumber - conf.TxLookupLimit + 1
   735  			checkTxIndicesHelper(t, &tail, tail, bNumber-1, bNumber, chainDB, false)
   736  		})
   737  	require.NoError(err)
   738  	chain.Stop()
   739  }
   740  
   741  // TestCanonicalHashMarker tests all the canonical hash markers are updated/deleted
   742  // correctly in case reorg is called.
   743  func TestCanonicalHashMarker(t *testing.T) {
   744  	testCanonicalHashMarker(t, rawdb.HashScheme)
   745  	testCanonicalHashMarker(t, rawdb.PathScheme)
   746  }
   747  
   748  func testCanonicalHashMarker(t *testing.T, scheme string) {
   749  	var cases = []struct {
   750  		forkA int
   751  		forkB int
   752  	}{
   753  		// ForkA: 10 blocks
   754  		// ForkB: 1 blocks
   755  		//
   756  		// reorged:
   757  		//      markers [2, 10] should be deleted
   758  		//      markers [1] should be updated
   759  		{10, 1},
   760  
   761  		// ForkA: 10 blocks
   762  		// ForkB: 2 blocks
   763  		//
   764  		// reorged:
   765  		//      markers [3, 10] should be deleted
   766  		//      markers [1, 2] should be updated
   767  		{10, 2},
   768  
   769  		// ForkA: 10 blocks
   770  		// ForkB: 10 blocks
   771  		//
   772  		// reorged:
   773  		//      markers [1, 10] should be updated
   774  		{10, 10},
   775  
   776  		// ForkA: 10 blocks
   777  		// ForkB: 11 blocks
   778  		//
   779  		// reorged:
   780  		//      markers [1, 11] should be updated
   781  		{10, 11},
   782  	}
   783  	for _, c := range cases {
   784  		var (
   785  			gspec = &Genesis{
   786  				Config:  params.TestChainConfig,
   787  				Alloc:   GenesisAlloc{},
   788  				BaseFee: big.NewInt(params.TestInitialBaseFee),
   789  			}
   790  			engine = dummy.NewCoinbaseFaker()
   791  		)
   792  		_, forkA, _, err := GenerateChainWithGenesis(gspec, engine, c.forkA, 10, func(i int, gen *BlockGen) {})
   793  		if err != nil {
   794  			t.Fatal(err)
   795  		}
   796  		_, forkB, _, err := GenerateChainWithGenesis(gspec, engine, c.forkB, 10, func(i int, gen *BlockGen) {})
   797  		if err != nil {
   798  			t.Fatal(err)
   799  		}
   800  
   801  		// Initialize test chain
   802  		chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, engine, vm.Config{}, common.Hash{}, false)
   803  		if err != nil {
   804  			t.Fatalf("failed to create tester chain: %v", err)
   805  		}
   806  		// Insert forkA and forkB, the canonical should on forkA still
   807  		if n, err := chain.InsertChain(forkA); err != nil {
   808  			t.Fatalf("block %d: failed to insert into chain: %v", n, err)
   809  		}
   810  		if n, err := chain.InsertChain(forkB); err != nil {
   811  			t.Fatalf("block %d: failed to insert into chain: %v", n, err)
   812  		}
   813  
   814  		verify := func(head *types.Block) {
   815  			if chain.CurrentBlock().Hash() != head.Hash() {
   816  				t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash())
   817  			}
   818  			if chain.CurrentHeader().Hash() != head.Hash() {
   819  				t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash())
   820  			}
   821  			if !chain.HasState(head.Root()) {
   822  				t.Fatalf("Lost block state %v %x", head.Number(), head.Hash())
   823  			}
   824  		}
   825  
   826  		// Switch canonical chain to forkB if necessary
   827  		if len(forkA) < len(forkB) {
   828  			verify(forkB[len(forkB)-1])
   829  		} else {
   830  			verify(forkA[len(forkA)-1])
   831  			if err := chain.SetPreference(forkB[len(forkB)-1]); err != nil {
   832  				t.Fatal(err)
   833  			}
   834  			verify(forkB[len(forkB)-1])
   835  		}
   836  
   837  		// Ensure all hash markers are updated correctly
   838  		for i := 0; i < len(forkB); i++ {
   839  			block := forkB[i]
   840  			hash := chain.GetCanonicalHash(block.NumberU64())
   841  			if hash != block.Hash() {
   842  				t.Fatalf("Unexpected canonical hash %d", block.NumberU64())
   843  			}
   844  		}
   845  		if c.forkA > c.forkB {
   846  			for i := uint64(c.forkB) + 1; i <= uint64(c.forkA); i++ {
   847  				hash := chain.GetCanonicalHash(i)
   848  				if hash != (common.Hash{}) {
   849  					t.Fatalf("Unexpected canonical hash %d", i)
   850  				}
   851  			}
   852  		}
   853  		chain.Stop()
   854  	}
   855  }
   856  
   857  func TestTxLookupBlockChain(t *testing.T) {
   858  	cacheConf := &CacheConfig{
   859  		TrieCleanLimit:            256,
   860  		TrieDirtyLimit:            256,
   861  		TrieDirtyCommitTarget:     20,
   862  		TriePrefetcherParallelism: 4,
   863  		Pruning:                   true,
   864  		CommitInterval:            4096,
   865  		SnapshotLimit:             256,
   866  		SnapshotNoBuild:           true, // Ensure the test errors if snapshot initialization fails
   867  		AcceptorQueueLimit:        64,   // ensure channel doesn't block
   868  		TxLookupLimit:             5,
   869  	}
   870  	createTxLookupBlockChain := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   871  		return createBlockChain(db, cacheConf, gspec, lastAcceptedHash)
   872  	}
   873  	for _, tt := range tests {
   874  		t.Run(tt.Name, func(t *testing.T) {
   875  			tt.testFunc(t, createTxLookupBlockChain)
   876  		})
   877  	}
   878  }
   879  
   880  func TestTxLookupSkipIndexingBlockChain(t *testing.T) {
   881  	cacheConf := &CacheConfig{
   882  		TrieCleanLimit:            256,
   883  		TrieDirtyLimit:            256,
   884  		TrieDirtyCommitTarget:     20,
   885  		TriePrefetcherParallelism: 4,
   886  		Pruning:                   true,
   887  		CommitInterval:            4096,
   888  		SnapshotLimit:             256,
   889  		SnapshotNoBuild:           true, // Ensure the test errors if snapshot initialization fails
   890  		AcceptorQueueLimit:        64,   // ensure channel doesn't block
   891  		TxLookupLimit:             5,
   892  		SkipTxIndexing:            true,
   893  	}
   894  	createTxLookupBlockChain := func(db ethdb.Database, gspec *Genesis, lastAcceptedHash common.Hash) (*BlockChain, error) {
   895  		return createBlockChain(db, cacheConf, gspec, lastAcceptedHash)
   896  	}
   897  	for _, tt := range tests {
   898  		t.Run(tt.Name, func(t *testing.T) {
   899  			tt.testFunc(t, createTxLookupBlockChain)
   900  		})
   901  	}
   902  }
   903  
   904  func TestCreateThenDeletePreByzantium(t *testing.T) {
   905  	// We want to use pre-byzantium rules where we have intermediate state roots
   906  	// between transactions.
   907  	config := *params.TestPreSubnetEVMConfig
   908  	config.ByzantiumBlock = nil
   909  	config.ConstantinopleBlock = nil
   910  	config.PetersburgBlock = nil
   911  	config.IstanbulBlock = nil
   912  	config.MuirGlacierBlock = nil
   913  	testCreateThenDelete(t, &config)
   914  }
   915  func TestCreateThenDeletePostByzantium(t *testing.T) {
   916  	testCreateThenDelete(t, params.TestChainConfig)
   917  }
   918  
   919  // testCreateThenDelete tests a creation and subsequent deletion of a contract, happening
   920  // within the same block.
   921  func testCreateThenDelete(t *testing.T, config *params.ChainConfig) {
   922  	var (
   923  		engine = dummy.NewFaker()
   924  		// A sender who makes transactions, has some funds
   925  		key, _      = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   926  		address     = crypto.PubkeyToAddress(key.PublicKey)
   927  		destAddress = crypto.CreateAddress(address, 0)
   928  		funds       = big.NewInt(params.Ether) // Note: additional funds are provided here compared to go-ethereum so test completes.
   929  	)
   930  
   931  	// runtime code is 	0x60ffff : PUSH1 0xFF SELFDESTRUCT, a.k.a SELFDESTRUCT(0xFF)
   932  	code := append([]byte{0x60, 0xff, 0xff}, make([]byte, 32-3)...)
   933  	initCode := []byte{
   934  		// SSTORE 1:1
   935  		byte(vm.PUSH1), 0x1,
   936  		byte(vm.PUSH1), 0x1,
   937  		byte(vm.SSTORE),
   938  		// Get the runtime-code on the stack
   939  		byte(vm.PUSH32)}
   940  	initCode = append(initCode, code...)
   941  	initCode = append(initCode, []byte{
   942  		byte(vm.PUSH1), 0x0, // offset
   943  		byte(vm.MSTORE),
   944  		byte(vm.PUSH1), 0x3, // size
   945  		byte(vm.PUSH1), 0x0, // offset
   946  		byte(vm.RETURN), // return 3 bytes of zero-code
   947  	}...)
   948  	gspec := &Genesis{
   949  		Config: config,
   950  		Alloc: GenesisAlloc{
   951  			address: {Balance: funds},
   952  		},
   953  	}
   954  	nonce := uint64(0)
   955  	signer := types.HomesteadSigner{}
   956  	_, blocks, _, _ := GenerateChainWithGenesis(gspec, engine, 2, 10, func(i int, b *BlockGen) {
   957  		fee := big.NewInt(1)
   958  		if b.header.BaseFee != nil {
   959  			fee = b.header.BaseFee
   960  		}
   961  		b.SetCoinbase(common.Address{1})
   962  		tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{
   963  			Nonce:    nonce,
   964  			GasPrice: new(big.Int).Set(fee),
   965  			Gas:      100000,
   966  			Data:     initCode,
   967  		})
   968  		nonce++
   969  		b.AddTx(tx)
   970  		tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{
   971  			Nonce:    nonce,
   972  			GasPrice: new(big.Int).Set(fee),
   973  			Gas:      100000,
   974  			To:       &destAddress,
   975  		})
   976  		b.AddTx(tx)
   977  		nonce++
   978  	})
   979  	// Import the canonical chain
   980  	chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfig, gspec, engine, vm.Config{
   981  		//Debug:  true,
   982  		//Tracer: logger.NewJSONLogger(nil, os.Stdout),
   983  	}, common.Hash{}, false)
   984  	if err != nil {
   985  		t.Fatalf("failed to create tester chain: %v", err)
   986  	}
   987  	defer chain.Stop()
   988  	// Import the blocks
   989  	for _, block := range blocks {
   990  		if _, err := chain.InsertChain([]*types.Block{block}); err != nil {
   991  			t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
   992  		}
   993  	}
   994  }
   995  
   996  func TestDeleteThenCreate(t *testing.T) {
   997  	var (
   998  		engine      = dummy.NewFaker()
   999  		key, _      = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1000  		address     = crypto.PubkeyToAddress(key.PublicKey)
  1001  		factoryAddr = crypto.CreateAddress(address, 0)
  1002  		funds       = big.NewInt(params.Ether) // Note: additional funds are provided here compared to go-ethereum so test completes.
  1003  	)
  1004  	/*
  1005  		contract Factory {
  1006  		  function deploy(bytes memory code) public {
  1007  			address addr;
  1008  			assembly {
  1009  			  addr := create2(0, add(code, 0x20), mload(code), 0)
  1010  			  if iszero(extcodesize(addr)) {
  1011  				revert(0, 0)
  1012  			  }
  1013  			}
  1014  		  }
  1015  		}
  1016  	*/
  1017  	factoryBIN := common.Hex2Bytes("608060405234801561001057600080fd5b50610241806100206000396000f3fe608060405234801561001057600080fd5b506004361061002a5760003560e01c80627743601461002f575b600080fd5b610049600480360381019061004491906100d8565b61004b565b005b6000808251602084016000f59050803b61006457600080fd5b5050565b600061007b61007684610146565b610121565b905082815260208101848484011115610097576100966101eb565b5b6100a2848285610177565b509392505050565b600082601f8301126100bf576100be6101e6565b5b81356100cf848260208601610068565b91505092915050565b6000602082840312156100ee576100ed6101f5565b5b600082013567ffffffffffffffff81111561010c5761010b6101f0565b5b610118848285016100aa565b91505092915050565b600061012b61013c565b90506101378282610186565b919050565b6000604051905090565b600067ffffffffffffffff821115610161576101606101b7565b5b61016a826101fa565b9050602081019050919050565b82818337600083830152505050565b61018f826101fa565b810181811067ffffffffffffffff821117156101ae576101ad6101b7565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f830116905091905056fea2646970667358221220ea8b35ed310d03b6b3deef166941140b4d9e90ea2c92f6b41eb441daf49a59c364736f6c63430008070033")
  1018  
  1019  	/*
  1020  		contract C {
  1021  			uint256 value;
  1022  			constructor() {
  1023  				value = 100;
  1024  			}
  1025  			function destruct() public payable {
  1026  				selfdestruct(payable(msg.sender));
  1027  			}
  1028  			receive() payable external {}
  1029  		}
  1030  	*/
  1031  	contractABI := common.Hex2Bytes("6080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c63430008070033")
  1032  	contractAddr := crypto.CreateAddress2(factoryAddr, [32]byte{}, crypto.Keccak256(contractABI))
  1033  
  1034  	gspec := &Genesis{
  1035  		Config: params.TestChainConfig,
  1036  		Alloc: GenesisAlloc{
  1037  			address: {Balance: funds},
  1038  		},
  1039  	}
  1040  	nonce := uint64(0)
  1041  	signer := types.HomesteadSigner{}
  1042  	_, blocks, _, err := GenerateChainWithGenesis(gspec, engine, 2, 10, func(i int, b *BlockGen) {
  1043  		fee := big.NewInt(1)
  1044  		if b.header.BaseFee != nil {
  1045  			fee = b.header.BaseFee
  1046  		}
  1047  		b.SetCoinbase(common.Address{1})
  1048  
  1049  		// Block 1
  1050  		if i == 0 {
  1051  			tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{
  1052  				Nonce:    nonce,
  1053  				GasPrice: new(big.Int).Set(fee),
  1054  				Gas:      500000,
  1055  				Data:     factoryBIN,
  1056  			})
  1057  			nonce++
  1058  			b.AddTx(tx)
  1059  
  1060  			data := common.Hex2Bytes("00774360000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a76080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c6343000807003300000000000000000000000000000000000000000000000000")
  1061  			tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{
  1062  				Nonce:    nonce,
  1063  				GasPrice: new(big.Int).Set(fee),
  1064  				Gas:      500000,
  1065  				To:       &factoryAddr,
  1066  				Data:     data,
  1067  			})
  1068  			b.AddTx(tx)
  1069  			nonce++
  1070  		} else {
  1071  			// Block 2
  1072  			tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{
  1073  				Nonce:    nonce,
  1074  				GasPrice: new(big.Int).Set(fee),
  1075  				Gas:      500000,
  1076  				To:       &contractAddr,
  1077  				Data:     common.Hex2Bytes("2b68b9c6"), // destruct
  1078  			})
  1079  			nonce++
  1080  			b.AddTx(tx)
  1081  
  1082  			data := common.Hex2Bytes("00774360000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a76080604052348015600f57600080fd5b5060646000819055506081806100266000396000f3fe608060405260043610601f5760003560e01c80632b68b9c614602a576025565b36602557005b600080fd5b60306032565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220ab749f5ed1fcb87bda03a74d476af3f074bba24d57cb5a355e8162062ad9a4e664736f6c6343000807003300000000000000000000000000000000000000000000000000")
  1083  			tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{
  1084  				Nonce:    nonce,
  1085  				GasPrice: new(big.Int).Set(fee),
  1086  				Gas:      500000,
  1087  				To:       &factoryAddr, // re-creation
  1088  				Data:     data,
  1089  			})
  1090  			b.AddTx(tx)
  1091  			nonce++
  1092  		}
  1093  	})
  1094  	if err != nil {
  1095  		t.Fatal(err)
  1096  	}
  1097  	// Import the canonical chain
  1098  	chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfig, gspec, engine, vm.Config{}, common.Hash{}, false)
  1099  	if err != nil {
  1100  		t.Fatalf("failed to create tester chain: %v", err)
  1101  	}
  1102  	defer chain.Stop()
  1103  	for _, block := range blocks {
  1104  		if _, err := chain.InsertChain([]*types.Block{block}); err != nil {
  1105  			t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
  1106  		}
  1107  	}
  1108  }
  1109  
  1110  // TestTransientStorageReset ensures the transient storage is wiped correctly
  1111  // between transactions.
  1112  func TestTransientStorageReset(t *testing.T) {
  1113  	var (
  1114  		engine      = dummy.NewFaker()
  1115  		key, _      = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1116  		address     = crypto.PubkeyToAddress(key.PublicKey)
  1117  		destAddress = crypto.CreateAddress(address, 0)
  1118  		funds       = big.NewInt(params.Ether) // Note: additional funds are provided here compared to go-ethereum so test completes.
  1119  		vmConfig    = vm.Config{
  1120  			ExtraEips: []int{1153}, // Enable transient storage EIP
  1121  		}
  1122  	)
  1123  	code := append([]byte{
  1124  		// TLoad value with location 1
  1125  		byte(vm.PUSH1), 0x1,
  1126  		byte(vm.TLOAD),
  1127  
  1128  		// PUSH location
  1129  		byte(vm.PUSH1), 0x1,
  1130  
  1131  		// SStore location:value
  1132  		byte(vm.SSTORE),
  1133  	}, make([]byte, 32-6)...)
  1134  	initCode := []byte{
  1135  		// TSTORE 1:1
  1136  		byte(vm.PUSH1), 0x1,
  1137  		byte(vm.PUSH1), 0x1,
  1138  		byte(vm.TSTORE),
  1139  
  1140  		// Get the runtime-code on the stack
  1141  		byte(vm.PUSH32)}
  1142  	initCode = append(initCode, code...)
  1143  	initCode = append(initCode, []byte{
  1144  		byte(vm.PUSH1), 0x0, // offset
  1145  		byte(vm.MSTORE),
  1146  		byte(vm.PUSH1), 0x6, // size
  1147  		byte(vm.PUSH1), 0x0, // offset
  1148  		byte(vm.RETURN), // return 6 bytes of zero-code
  1149  	}...)
  1150  	gspec := &Genesis{
  1151  		Config: params.TestChainConfig,
  1152  		Alloc: GenesisAlloc{
  1153  			address: {Balance: funds},
  1154  		},
  1155  	}
  1156  	nonce := uint64(0)
  1157  	signer := types.HomesteadSigner{}
  1158  	_, blocks, _, _ := GenerateChainWithGenesis(gspec, engine, 1, 10, func(i int, b *BlockGen) {
  1159  		fee := big.NewInt(1)
  1160  		if b.header.BaseFee != nil {
  1161  			fee = b.header.BaseFee
  1162  		}
  1163  		b.SetCoinbase(common.Address{1})
  1164  		tx, _ := types.SignNewTx(key, signer, &types.LegacyTx{
  1165  			Nonce:    nonce,
  1166  			GasPrice: new(big.Int).Set(fee),
  1167  			Gas:      100000,
  1168  			Data:     initCode,
  1169  		})
  1170  		nonce++
  1171  		b.AddTxWithVMConfig(tx, vmConfig)
  1172  
  1173  		tx, _ = types.SignNewTx(key, signer, &types.LegacyTx{
  1174  			Nonce:    nonce,
  1175  			GasPrice: new(big.Int).Set(fee),
  1176  			Gas:      100000,
  1177  			To:       &destAddress,
  1178  		})
  1179  		b.AddTxWithVMConfig(tx, vmConfig)
  1180  		nonce++
  1181  	})
  1182  
  1183  	// Initialize the blockchain with 1153 enabled.
  1184  	chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfig, gspec, engine, vmConfig, common.Hash{}, false)
  1185  	if err != nil {
  1186  		t.Fatalf("failed to create tester chain: %v", err)
  1187  	}
  1188  	defer chain.Stop()
  1189  	// Import the blocks
  1190  	if _, err := chain.InsertChain(blocks); err != nil {
  1191  		t.Fatalf("failed to insert into chain: %v", err)
  1192  	}
  1193  	// Check the storage
  1194  	state, err := chain.StateAt(chain.CurrentHeader().Root)
  1195  	if err != nil {
  1196  		t.Fatalf("Failed to load state %v", err)
  1197  	}
  1198  	loc := common.BytesToHash([]byte{1})
  1199  	slot := state.GetState(destAddress, loc)
  1200  	if slot != (common.Hash{}) {
  1201  		t.Fatalf("Unexpected dirty storage slot")
  1202  	}
  1203  }
  1204  
  1205  func TestEIP3651(t *testing.T) {
  1206  	var (
  1207  		aa     = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
  1208  		bb     = common.HexToAddress("0x000000000000000000000000000000000000bbbb")
  1209  		engine = dummy.NewCoinbaseFaker()
  1210  
  1211  		// A sender who makes transactions, has some funds
  1212  		key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  1213  		key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  1214  		addr1   = crypto.PubkeyToAddress(key1.PublicKey)
  1215  		addr2   = crypto.PubkeyToAddress(key2.PublicKey)
  1216  		funds   = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
  1217  		gspec   = &Genesis{
  1218  			Config:    params.TestChainConfig,
  1219  			Timestamp: uint64(params.DefaultGenesisTime.Unix()),
  1220  			Alloc: GenesisAlloc{
  1221  				addr1: {Balance: funds},
  1222  				addr2: {Balance: funds},
  1223  				// The address 0xAAAA sloads 0x00 and 0x01
  1224  				aa: {
  1225  					Code: []byte{
  1226  						byte(vm.PC),
  1227  						byte(vm.PC),
  1228  						byte(vm.SLOAD),
  1229  						byte(vm.SLOAD),
  1230  					},
  1231  					Nonce:   0,
  1232  					Balance: big.NewInt(0),
  1233  				},
  1234  				// The address 0xBBBB calls 0xAAAA
  1235  				bb: {
  1236  					Code: []byte{
  1237  						byte(vm.PUSH1), 0, // out size
  1238  						byte(vm.DUP1),  // out offset
  1239  						byte(vm.DUP1),  // out insize
  1240  						byte(vm.DUP1),  // in offset
  1241  						byte(vm.PUSH2), // address
  1242  						byte(0xaa),
  1243  						byte(0xaa),
  1244  						byte(vm.GAS), // gas
  1245  						byte(vm.DELEGATECALL),
  1246  					},
  1247  					Nonce:   0,
  1248  					Balance: big.NewInt(0),
  1249  				},
  1250  			},
  1251  		}
  1252  	)
  1253  
  1254  	signer := types.LatestSigner(gspec.Config)
  1255  
  1256  	_, blocks, _, _ := GenerateChainWithGenesis(gspec, engine, 1, 10, func(i int, b *BlockGen) {
  1257  		b.SetCoinbase(aa)
  1258  		// One transaction to Coinbase
  1259  		txdata := &types.DynamicFeeTx{
  1260  			ChainID:    gspec.Config.ChainID,
  1261  			Nonce:      0,
  1262  			To:         &bb,
  1263  			Gas:        500000,
  1264  			GasFeeCap:  newGwei(225),
  1265  			GasTipCap:  big.NewInt(2),
  1266  			AccessList: nil,
  1267  			Data:       []byte{},
  1268  		}
  1269  		tx := types.NewTx(txdata)
  1270  		tx, _ = types.SignTx(tx, signer, key1)
  1271  
  1272  		b.AddTx(tx)
  1273  	})
  1274  	chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfig, gspec, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr)}, common.Hash{}, false)
  1275  	if err != nil {
  1276  		t.Fatalf("failed to create tester chain: %v", err)
  1277  	}
  1278  	defer chain.Stop()
  1279  	if n, err := chain.InsertChain(blocks); err != nil {
  1280  		t.Fatalf("block %d: failed to insert into chain: %v", n, err)
  1281  	}
  1282  
  1283  	block := chain.GetBlockByNumber(1)
  1284  
  1285  	// 1+2: Ensure EIP-1559 access lists are accounted for via gas usage.
  1286  	innerGas := vm.GasQuickStep*2 + params.ColdSloadCostEIP2929*2
  1287  	expectedGas := params.TxGas + 5*vm.GasFastestStep + vm.GasQuickStep + 100 + innerGas // 100 because 0xaaaa is in access list
  1288  	if block.GasUsed() != expectedGas {
  1289  		t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGas, block.GasUsed())
  1290  	}
  1291  
  1292  	state, _ := chain.State()
  1293  
  1294  	// 3: Ensure that miner received the gasUsed * (block baseFee + effectiveGasTip).
  1295  	// Note this differs from go-ethereum where the miner receives the gasUsed * block baseFee,
  1296  	// as our handling of the coinbase payment is different.
  1297  	// Note we use block.GasUsed() here as there is only one tx.
  1298  	actual := state.GetBalance(block.Coinbase())
  1299  	tx := block.Transactions()[0]
  1300  	gasPrice := new(big.Int).Add(block.BaseFee(), tx.EffectiveGasTipValue(block.BaseFee()))
  1301  	expected := new(big.Int).SetUint64(block.GasUsed() * gasPrice.Uint64())
  1302  	if actual.Cmp(expected) != 0 {
  1303  		t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
  1304  	}
  1305  
  1306  	// 4: Ensure the tx sender paid for the gasUsed * (block baseFee + effectiveGasTip).
  1307  	// Note this differs from go-ethereum where the miner receives the gasUsed * block baseFee,
  1308  	// as our handling of the coinbase payment is different.
  1309  	actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
  1310  	if actual.Cmp(expected) != 0 {
  1311  		t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
  1312  	}
  1313  }
  1314  
  1315  func createAndInsertChain(db ethdb.Database, cacheConfig *CacheConfig, gspec *Genesis, blocks types.Blocks, lastAcceptedHash common.Hash, accepted func(*types.Block)) (*BlockChain, error) {
  1316  	chain, err := createBlockChain(db, cacheConfig, gspec, lastAcceptedHash)
  1317  	if err != nil {
  1318  		return nil, err
  1319  	}
  1320  	_, err = chain.InsertChain(blocks)
  1321  	if err != nil {
  1322  		return nil, err
  1323  	}
  1324  	for _, block := range blocks {
  1325  		err := chain.Accept(block)
  1326  		if err != nil {
  1327  			return nil, err
  1328  		}
  1329  		chain.DrainAcceptorQueue()
  1330  		if accepted != nil {
  1331  			accepted(block)
  1332  		}
  1333  	}
  1334  
  1335  	return chain, nil
  1336  }