github.com/ethereum/go-ethereum@v1.16.1/core/chain_makers.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/consensus"
    25  	"github.com/ethereum/go-ethereum/consensus/misc"
    26  	"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
    27  	"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
    28  	"github.com/ethereum/go-ethereum/core/rawdb"
    29  	"github.com/ethereum/go-ethereum/core/state"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/ethereum/go-ethereum/core/vm"
    32  	"github.com/ethereum/go-ethereum/ethdb"
    33  	"github.com/ethereum/go-ethereum/params"
    34  	"github.com/ethereum/go-ethereum/triedb"
    35  	"github.com/ethereum/go-verkle"
    36  	"github.com/holiman/uint256"
    37  )
    38  
    39  // BlockGen creates blocks for testing.
    40  // See GenerateChain for a detailed explanation.
    41  type BlockGen struct {
    42  	i       int
    43  	cm      *chainMaker
    44  	parent  *types.Block
    45  	header  *types.Header
    46  	statedb *state.StateDB
    47  
    48  	gasPool     *GasPool
    49  	txs         []*types.Transaction
    50  	receipts    []*types.Receipt
    51  	uncles      []*types.Header
    52  	withdrawals []*types.Withdrawal
    53  
    54  	engine consensus.Engine
    55  }
    56  
    57  // SetCoinbase sets the coinbase of the generated block.
    58  // It can be called at most once.
    59  func (b *BlockGen) SetCoinbase(addr common.Address) {
    60  	if b.gasPool != nil {
    61  		if len(b.txs) > 0 {
    62  			panic("coinbase must be set before adding transactions")
    63  		}
    64  		panic("coinbase can only be set once")
    65  	}
    66  	b.header.Coinbase = addr
    67  	b.gasPool = new(GasPool).AddGas(b.header.GasLimit)
    68  }
    69  
    70  // SetExtra sets the extra data field of the generated block.
    71  func (b *BlockGen) SetExtra(data []byte) {
    72  	b.header.Extra = data
    73  }
    74  
    75  // SetNonce sets the nonce field of the generated block.
    76  func (b *BlockGen) SetNonce(nonce types.BlockNonce) {
    77  	b.header.Nonce = nonce
    78  }
    79  
    80  // SetDifficulty sets the difficulty field of the generated block. This method is
    81  // useful for Clique tests where the difficulty does not depend on time. For the
    82  // ethash tests, please use OffsetTime, which implicitly recalculates the diff.
    83  func (b *BlockGen) SetDifficulty(diff *big.Int) {
    84  	b.header.Difficulty = diff
    85  }
    86  
    87  // SetPoS makes the header a PoS-header (0 difficulty)
    88  func (b *BlockGen) SetPoS() {
    89  	b.header.Difficulty = new(big.Int)
    90  }
    91  
    92  // Difficulty returns the currently calculated difficulty of the block.
    93  func (b *BlockGen) Difficulty() *big.Int {
    94  	return new(big.Int).Set(b.header.Difficulty)
    95  }
    96  
    97  // SetParentBeaconRoot sets the parent beacon root field of the generated
    98  // block.
    99  func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
   100  	b.header.ParentBeaconRoot = &root
   101  	blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
   102  	ProcessBeaconBlockRoot(root, vm.NewEVM(blockContext, b.statedb, b.cm.config, vm.Config{}))
   103  }
   104  
   105  // addTx adds a transaction to the generated block. If no coinbase has
   106  // been set, the block's coinbase is set to the zero address.
   107  //
   108  // There are a few options can be passed as well in order to run some
   109  // customized rules.
   110  // - bc:       enables the ability to query historical block hashes for BLOCKHASH
   111  // - vmConfig: extends the flexibility for customizing evm rules, e.g. enable extra EIPs
   112  func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transaction) {
   113  	if b.gasPool == nil {
   114  		b.SetCoinbase(common.Address{})
   115  	}
   116  	var (
   117  		blockContext = NewEVMBlockContext(b.header, bc, &b.header.Coinbase)
   118  		evm          = vm.NewEVM(blockContext, b.statedb, b.cm.config, vmConfig)
   119  	)
   120  	b.statedb.SetTxContext(tx.Hash(), len(b.txs))
   121  	receipt, err := ApplyTransaction(evm, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed)
   122  	if err != nil {
   123  		panic(err)
   124  	}
   125  	// Merge the tx-local access event into the "block-local" one, in order to collect
   126  	// all values, so that the witness can be built.
   127  	if b.statedb.Database().TrieDB().IsVerkle() {
   128  		b.statedb.AccessEvents().Merge(evm.AccessEvents)
   129  	}
   130  	b.txs = append(b.txs, tx)
   131  	b.receipts = append(b.receipts, receipt)
   132  	if b.header.BlobGasUsed != nil {
   133  		*b.header.BlobGasUsed += receipt.BlobGasUsed
   134  	}
   135  }
   136  
   137  // AddTx adds a transaction to the generated block. If no coinbase has
   138  // been set, the block's coinbase is set to the zero address.
   139  //
   140  // AddTx panics if the transaction cannot be executed. In addition to the protocol-imposed
   141  // limitations (gas limit, etc.), there are some further limitations on the content of
   142  // transactions that can be added. Notably, contract code relying on the BLOCKHASH
   143  // instruction will panic during execution if it attempts to access a block number outside
   144  // of the range created by GenerateChain.
   145  func (b *BlockGen) AddTx(tx *types.Transaction) {
   146  	// Wrap the chain config in an empty BlockChain object to satisfy ChainContext.
   147  	bc := &BlockChain{chainConfig: b.cm.config}
   148  	b.addTx(bc, vm.Config{}, tx)
   149  }
   150  
   151  // AddTxWithChain adds a transaction to the generated block. If no coinbase has
   152  // been set, the block's coinbase is set to the zero address.
   153  //
   154  // AddTxWithChain panics if the transaction cannot be executed. In addition to the
   155  // protocol-imposed limitations (gas limit, etc.), there are some further limitations on
   156  // the content of transactions that can be added. If contract code relies on the BLOCKHASH
   157  // instruction, the block in chain will be returned.
   158  func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
   159  	b.addTx(bc, vm.Config{}, tx)
   160  }
   161  
   162  // AddTxWithVMConfig adds a transaction to the generated block. If no coinbase has
   163  // been set, the block's coinbase is set to the zero address.
   164  // The evm interpreter can be customized with the provided vm config.
   165  func (b *BlockGen) AddTxWithVMConfig(tx *types.Transaction, config vm.Config) {
   166  	b.addTx(nil, config, tx)
   167  }
   168  
   169  // GetBalance returns the balance of the given address at the generated block.
   170  func (b *BlockGen) GetBalance(addr common.Address) *uint256.Int {
   171  	return b.statedb.GetBalance(addr)
   172  }
   173  
   174  // AddUncheckedTx forcefully adds a transaction to the block without any validation.
   175  //
   176  // AddUncheckedTx will cause consensus failures when used during real
   177  // chain processing. This is best used in conjunction with raw block insertion.
   178  func (b *BlockGen) AddUncheckedTx(tx *types.Transaction) {
   179  	b.txs = append(b.txs, tx)
   180  }
   181  
   182  // Number returns the block number of the block being generated.
   183  func (b *BlockGen) Number() *big.Int {
   184  	return new(big.Int).Set(b.header.Number)
   185  }
   186  
   187  // Timestamp returns the timestamp of the block being generated.
   188  func (b *BlockGen) Timestamp() uint64 {
   189  	return b.header.Time
   190  }
   191  
   192  // BaseFee returns the EIP-1559 base fee of the block being generated.
   193  func (b *BlockGen) BaseFee() *big.Int {
   194  	return new(big.Int).Set(b.header.BaseFee)
   195  }
   196  
   197  // Gas returns the amount of gas left in the current block.
   198  func (b *BlockGen) Gas() uint64 {
   199  	return b.header.GasLimit - b.header.GasUsed
   200  }
   201  
   202  // Signer returns a valid signer instance for the current block.
   203  func (b *BlockGen) Signer() types.Signer {
   204  	return types.MakeSigner(b.cm.config, b.header.Number, b.header.Time)
   205  }
   206  
   207  // AddUncheckedReceipt forcefully adds a receipts to the block without a
   208  // backing transaction.
   209  //
   210  // AddUncheckedReceipt will cause consensus failures when used during real
   211  // chain processing. This is best used in conjunction with raw block insertion.
   212  func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) {
   213  	b.receipts = append(b.receipts, receipt)
   214  }
   215  
   216  // TxNonce returns the next valid transaction nonce for the
   217  // account at addr. It panics if the account does not exist.
   218  func (b *BlockGen) TxNonce(addr common.Address) uint64 {
   219  	if !b.statedb.Exist(addr) {
   220  		panic("account does not exist")
   221  	}
   222  	return b.statedb.GetNonce(addr)
   223  }
   224  
   225  // AddUncle adds an uncle header to the generated block.
   226  func (b *BlockGen) AddUncle(h *types.Header) {
   227  	// The uncle will have the same timestamp and auto-generated difficulty
   228  	h.Time = b.header.Time
   229  
   230  	var parent *types.Header
   231  	for i := b.i - 1; i >= 0; i-- {
   232  		if b.cm.chain[i].Hash() == h.ParentHash {
   233  			parent = b.cm.chain[i].Header()
   234  			break
   235  		}
   236  	}
   237  	h.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, parent)
   238  
   239  	// The gas limit and price should be derived from the parent
   240  	h.GasLimit = parent.GasLimit
   241  	if b.cm.config.IsLondon(h.Number) {
   242  		h.BaseFee = eip1559.CalcBaseFee(b.cm.config, parent)
   243  		if !b.cm.config.IsLondon(parent.Number) {
   244  			parentGasLimit := parent.GasLimit * b.cm.config.ElasticityMultiplier()
   245  			h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
   246  		}
   247  	}
   248  	b.uncles = append(b.uncles, h)
   249  }
   250  
   251  // AddWithdrawal adds a withdrawal to the generated block.
   252  // It returns the withdrawal index.
   253  func (b *BlockGen) AddWithdrawal(w *types.Withdrawal) uint64 {
   254  	cpy := *w
   255  	cpy.Index = b.nextWithdrawalIndex()
   256  	b.withdrawals = append(b.withdrawals, &cpy)
   257  	return cpy.Index
   258  }
   259  
   260  // nextWithdrawalIndex computes the index of the next withdrawal.
   261  func (b *BlockGen) nextWithdrawalIndex() uint64 {
   262  	if len(b.withdrawals) != 0 {
   263  		return b.withdrawals[len(b.withdrawals)-1].Index + 1
   264  	}
   265  	for i := b.i - 1; i >= 0; i-- {
   266  		if wd := b.cm.chain[i].Withdrawals(); len(wd) != 0 {
   267  			return wd[len(wd)-1].Index + 1
   268  		}
   269  		if i == 0 {
   270  			// Correctly set the index if no parent had withdrawals.
   271  			if wd := b.cm.bottom.Withdrawals(); len(wd) != 0 {
   272  				return wd[len(wd)-1].Index + 1
   273  			}
   274  		}
   275  	}
   276  	return 0
   277  }
   278  
   279  // PrevBlock returns a previously generated block by number. It panics if
   280  // num is greater or equal to the number of the block being generated.
   281  // For index -1, PrevBlock returns the parent block given to GenerateChain.
   282  func (b *BlockGen) PrevBlock(index int) *types.Block {
   283  	if index >= b.i {
   284  		panic(fmt.Errorf("block index %d out of range (%d,%d)", index, -1, b.i))
   285  	}
   286  	if index == -1 {
   287  		return b.cm.bottom
   288  	}
   289  	return b.cm.chain[index]
   290  }
   291  
   292  // OffsetTime modifies the time instance of a block, implicitly changing its
   293  // associated difficulty. It's useful to test scenarios where forking is not
   294  // tied to chain length directly.
   295  func (b *BlockGen) OffsetTime(seconds int64) {
   296  	b.header.Time += uint64(seconds)
   297  	if b.header.Time <= b.cm.bottom.Header().Time {
   298  		panic("block time out of range")
   299  	}
   300  	b.header.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, b.parent.Header())
   301  }
   302  
   303  // ConsensusLayerRequests returns the EIP-7685 requests which have accumulated so far.
   304  func (b *BlockGen) ConsensusLayerRequests() [][]byte {
   305  	return b.collectRequests(true)
   306  }
   307  
   308  func (b *BlockGen) collectRequests(readonly bool) (requests [][]byte) {
   309  	statedb := b.statedb
   310  	if readonly {
   311  		// The system contracts clear themselves on a system-initiated read.
   312  		// When reading the requests mid-block, we don't want this behavior, so fork
   313  		// off the statedb before executing the system calls.
   314  		statedb = statedb.Copy()
   315  	}
   316  
   317  	if b.cm.config.IsPrague(b.header.Number, b.header.Time) {
   318  		requests = [][]byte{}
   319  		// EIP-6110 deposits
   320  		var blockLogs []*types.Log
   321  		for _, r := range b.receipts {
   322  			blockLogs = append(blockLogs, r.Logs...)
   323  		}
   324  		if err := ParseDepositLogs(&requests, blockLogs, b.cm.config); err != nil {
   325  			panic(fmt.Sprintf("failed to parse deposit log: %v", err))
   326  		}
   327  		// create EVM for system calls
   328  		blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
   329  		evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{})
   330  		// EIP-7002
   331  		if err := ProcessWithdrawalQueue(&requests, evm); err != nil {
   332  			panic(fmt.Sprintf("could not process withdrawal requests: %v", err))
   333  		}
   334  		// EIP-7251
   335  		if err := ProcessConsolidationQueue(&requests, evm); err != nil {
   336  			panic(fmt.Sprintf("could not process consolidation requests: %v", err))
   337  		}
   338  	}
   339  	return requests
   340  }
   341  
   342  // GenerateChain creates a chain of n blocks. The first block's
   343  // parent will be the provided parent. db is used to store
   344  // intermediate states and should contain the parent's state trie.
   345  //
   346  // The generator function is called with a new block generator for
   347  // every block. Any transactions and uncles added to the generator
   348  // become part of the block. If gen is nil, the blocks will be empty
   349  // and their coinbase will be the zero address.
   350  //
   351  // Blocks created by GenerateChain do not contain valid proof of work
   352  // values. Inserting them into BlockChain requires use of FakePow or
   353  // a similar non-validating proof of work implementation.
   354  func GenerateChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
   355  	if config == nil {
   356  		config = params.TestChainConfig
   357  	}
   358  	if engine == nil {
   359  		panic("nil consensus engine")
   360  	}
   361  	cm := newChainMaker(parent, config, engine)
   362  
   363  	genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
   364  		b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine}
   365  		b.header = cm.makeHeader(parent, statedb, b.engine)
   366  
   367  		// Set the difficulty for clique block. The chain maker doesn't have access
   368  		// to a chain, so the difficulty will be left unset (nil). Set it here to the
   369  		// correct value.
   370  		if b.header.Difficulty == nil {
   371  			if config.TerminalTotalDifficulty == nil {
   372  				// Clique chain
   373  				b.header.Difficulty = big.NewInt(2)
   374  			} else {
   375  				// Post-merge chain
   376  				b.header.Difficulty = big.NewInt(0)
   377  			}
   378  		}
   379  
   380  		// Mutate the state and block according to any hard-fork specs
   381  		if daoBlock := config.DAOForkBlock; daoBlock != nil {
   382  			limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
   383  			if b.header.Number.Cmp(daoBlock) >= 0 && b.header.Number.Cmp(limit) < 0 {
   384  				if config.DAOForkSupport {
   385  					b.header.Extra = common.CopyBytes(params.DAOForkBlockExtra)
   386  				}
   387  			}
   388  		}
   389  		if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 {
   390  			misc.ApplyDAOHardFork(statedb)
   391  		}
   392  
   393  		if config.IsPrague(b.header.Number, b.header.Time) || config.IsVerkle(b.header.Number, b.header.Time) {
   394  			// EIP-2935
   395  			blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
   396  			blockContext.Random = &common.Hash{} // enable post-merge instruction set
   397  			evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
   398  			ProcessParentBlockHash(b.header.ParentHash, evm)
   399  		}
   400  
   401  		// Execute any user modifications to the block
   402  		if gen != nil {
   403  			gen(i, b)
   404  		}
   405  
   406  		requests := b.collectRequests(false)
   407  		if requests != nil {
   408  			reqHash := types.CalcRequestsHash(requests)
   409  			b.header.RequestsHash = &reqHash
   410  		}
   411  
   412  		body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals}
   413  		block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
   414  		if err != nil {
   415  			panic(err)
   416  		}
   417  
   418  		// Write state changes to db
   419  		root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number), config.IsCancun(b.header.Number, b.header.Time))
   420  		if err != nil {
   421  			panic(fmt.Sprintf("state write error: %v", err))
   422  		}
   423  		if err = triedb.Commit(root, false); err != nil {
   424  			panic(fmt.Sprintf("trie write error: %v", err))
   425  		}
   426  		return block, b.receipts
   427  	}
   428  
   429  	// Forcibly use hash-based state scheme for retaining all nodes in disk.
   430  	triedb := triedb.NewDatabase(db, triedb.HashDefaults)
   431  	defer triedb.Close()
   432  
   433  	for i := 0; i < n; i++ {
   434  		statedb, err := state.New(parent.Root(), state.NewDatabase(triedb, nil))
   435  		if err != nil {
   436  			panic(err)
   437  		}
   438  		block, receipts := genblock(i, parent, triedb, statedb)
   439  
   440  		// Post-process the receipts.
   441  		// Here we assign the final block hash and other info into the receipt.
   442  		// In order for DeriveFields to work, the transaction and receipt lists need to be
   443  		// of equal length. If AddUncheckedTx or AddUncheckedReceipt are used, there will be
   444  		// extra ones, so we just trim the lists here.
   445  		receiptsCount := len(receipts)
   446  		txs := block.Transactions()
   447  		if len(receipts) > len(txs) {
   448  			receipts = receipts[:len(txs)]
   449  		} else if len(receipts) < len(txs) {
   450  			txs = txs[:len(receipts)]
   451  		}
   452  		var blobGasPrice *big.Int
   453  		if block.ExcessBlobGas() != nil {
   454  			blobGasPrice = eip4844.CalcBlobFee(cm.config, block.Header())
   455  		}
   456  		if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
   457  			panic(err)
   458  		}
   459  
   460  		// Re-expand to ensure all receipts are returned.
   461  		receipts = receipts[:receiptsCount]
   462  
   463  		// Advance the chain.
   464  		cm.add(block, receipts)
   465  		parent = block
   466  	}
   467  	return cm.chain, cm.receipts
   468  }
   469  
   470  // GenerateChainWithGenesis is a wrapper of GenerateChain which will initialize
   471  // genesis block to database first according to the provided genesis specification
   472  // then generate chain on top.
   473  func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) {
   474  	db := rawdb.NewMemoryDatabase()
   475  	triedb := triedb.NewDatabase(db, triedb.HashDefaults)
   476  	defer triedb.Close()
   477  	_, err := genesis.Commit(db, triedb)
   478  	if err != nil {
   479  		panic(err)
   480  	}
   481  	blocks, receipts := GenerateChain(genesis.Config, genesis.ToBlock(), engine, db, n, gen)
   482  	return db, blocks, receipts
   483  }
   484  
   485  func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, trdb *triedb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) {
   486  	if config == nil {
   487  		config = params.TestChainConfig
   488  	}
   489  	proofs := make([]*verkle.VerkleProof, 0, n)
   490  	keyvals := make([]verkle.StateDiff, 0, n)
   491  	cm := newChainMaker(parent, config, engine)
   492  
   493  	genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) {
   494  		b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine}
   495  		b.header = cm.makeHeader(parent, statedb, b.engine)
   496  
   497  		// TODO uncomment when proof generation is merged
   498  		// Save pre state for proof generation
   499  		// preState := statedb.Copy()
   500  
   501  		// EIP-2935 / 7709
   502  		blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
   503  		blockContext.Random = &common.Hash{} // enable post-merge instruction set
   504  		evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
   505  		ProcessParentBlockHash(b.header.ParentHash, evm)
   506  
   507  		// Execute any user modifications to the block.
   508  		if gen != nil {
   509  			gen(i, b)
   510  		}
   511  
   512  		requests := b.collectRequests(false)
   513  		if requests != nil {
   514  			reqHash := types.CalcRequestsHash(requests)
   515  			b.header.RequestsHash = &reqHash
   516  		}
   517  
   518  		body := &types.Body{
   519  			Transactions: b.txs,
   520  			Uncles:       b.uncles,
   521  			Withdrawals:  b.withdrawals,
   522  		}
   523  		block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, body, b.receipts)
   524  		if err != nil {
   525  			panic(err)
   526  		}
   527  
   528  		// Write state changes to DB.
   529  		root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number), config.IsCancun(b.header.Number, b.header.Time))
   530  		if err != nil {
   531  			panic(fmt.Sprintf("state write error: %v", err))
   532  		}
   533  		if err = triedb.Commit(root, false); err != nil {
   534  			panic(fmt.Sprintf("trie write error: %v", err))
   535  		}
   536  
   537  		proofs = append(proofs, block.ExecutionWitness().VerkleProof)
   538  		keyvals = append(keyvals, block.ExecutionWitness().StateDiff)
   539  
   540  		return block, b.receipts
   541  	}
   542  
   543  	for i := 0; i < n; i++ {
   544  		statedb, err := state.New(parent.Root(), state.NewDatabase(trdb, nil))
   545  		if err != nil {
   546  			panic(err)
   547  		}
   548  		block, receipts := genblock(i, parent, trdb, statedb)
   549  
   550  		// Post-process the receipts.
   551  		// Here we assign the final block hash and other info into the receipt.
   552  		// In order for DeriveFields to work, the transaction and receipt lists need to be
   553  		// of equal length. If AddUncheckedTx or AddUncheckedReceipt are used, there will be
   554  		// extra ones, so we just trim the lists here.
   555  		receiptsCount := len(receipts)
   556  		txs := block.Transactions()
   557  		if len(receipts) > len(txs) {
   558  			receipts = receipts[:len(txs)]
   559  		} else if len(receipts) < len(txs) {
   560  			txs = txs[:len(receipts)]
   561  		}
   562  		var blobGasPrice *big.Int
   563  		if block.ExcessBlobGas() != nil {
   564  			blobGasPrice = eip4844.CalcBlobFee(cm.config, block.Header())
   565  		}
   566  		if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil {
   567  			panic(err)
   568  		}
   569  
   570  		// Re-expand to ensure all receipts are returned.
   571  		receipts = receipts[:receiptsCount]
   572  
   573  		// Advance the chain.
   574  		cm.add(block, receipts)
   575  		parent = block
   576  	}
   577  	return cm.chain, cm.receipts, proofs, keyvals
   578  }
   579  
   580  func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (common.Hash, ethdb.Database, []*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) {
   581  	db := rawdb.NewMemoryDatabase()
   582  	cacheConfig := DefaultConfig().WithStateScheme(rawdb.PathScheme)
   583  	cacheConfig.SnapshotLimit = 0
   584  	triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
   585  	defer triedb.Close()
   586  	genesisBlock, err := genesis.Commit(db, triedb)
   587  	if err != nil {
   588  		panic(err)
   589  	}
   590  	blocks, receipts, proofs, keyvals := GenerateVerkleChain(genesis.Config, genesisBlock, engine, db, triedb, n, gen)
   591  	return genesisBlock.Hash(), db, blocks, receipts, proofs, keyvals
   592  }
   593  
   594  func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header {
   595  	time := parent.Time() + 10 // block time is fixed at 10 seconds
   596  	parentHeader := parent.Header()
   597  	header := &types.Header{
   598  		Root:       state.IntermediateRoot(cm.config.IsEIP158(parent.Number())),
   599  		ParentHash: parent.Hash(),
   600  		Coinbase:   parent.Coinbase(),
   601  		Difficulty: engine.CalcDifficulty(cm, time, parentHeader),
   602  		GasLimit:   parent.GasLimit(),
   603  		Number:     new(big.Int).Add(parent.Number(), common.Big1),
   604  		Time:       time,
   605  	}
   606  
   607  	if cm.config.IsLondon(header.Number) {
   608  		header.BaseFee = eip1559.CalcBaseFee(cm.config, parentHeader)
   609  		if !cm.config.IsLondon(parent.Number()) {
   610  			parentGasLimit := parent.GasLimit() * cm.config.ElasticityMultiplier()
   611  			header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
   612  		}
   613  	}
   614  	if cm.config.IsCancun(header.Number, header.Time) {
   615  		excessBlobGas := eip4844.CalcExcessBlobGas(cm.config, parentHeader, time)
   616  		header.ExcessBlobGas = &excessBlobGas
   617  		header.BlobGasUsed = new(uint64)
   618  		header.ParentBeaconRoot = new(common.Hash)
   619  	}
   620  	return header
   621  }
   622  
   623  // makeHeaderChain creates a deterministic chain of headers rooted at parent.
   624  func makeHeaderChain(chainConfig *params.ChainConfig, parent *types.Header, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Header {
   625  	blocks := makeBlockChain(chainConfig, types.NewBlockWithHeader(parent), n, engine, db, seed)
   626  	headers := make([]*types.Header, len(blocks))
   627  	for i, block := range blocks {
   628  		headers[i] = block.Header()
   629  	}
   630  	return headers
   631  }
   632  
   633  // makeHeaderChainWithGenesis creates a deterministic chain of headers from genesis.
   634  func makeHeaderChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine, seed int) (ethdb.Database, []*types.Header) {
   635  	db, blocks := makeBlockChainWithGenesis(genesis, n, engine, seed)
   636  	headers := make([]*types.Header, len(blocks))
   637  	for i, block := range blocks {
   638  		headers[i] = block.Header()
   639  	}
   640  	return db, headers
   641  }
   642  
   643  // makeBlockChain creates a deterministic chain of blocks rooted at parent.
   644  func makeBlockChain(chainConfig *params.ChainConfig, parent *types.Block, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Block {
   645  	blocks, _ := GenerateChain(chainConfig, parent, engine, db, n, func(i int, b *BlockGen) {
   646  		b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
   647  	})
   648  	return blocks
   649  }
   650  
   651  // makeBlockChainWithGenesis creates a deterministic chain of blocks from genesis
   652  func makeBlockChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine, seed int) (ethdb.Database, []*types.Block) {
   653  	db, blocks, _ := GenerateChainWithGenesis(genesis, engine, n, func(i int, b *BlockGen) {
   654  		b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
   655  	})
   656  	return db, blocks
   657  }
   658  
   659  // chainMaker contains the state of chain generation.
   660  type chainMaker struct {
   661  	bottom      *types.Block
   662  	engine      consensus.Engine
   663  	config      *params.ChainConfig
   664  	chain       []*types.Block
   665  	chainByHash map[common.Hash]*types.Block
   666  	receipts    []types.Receipts
   667  }
   668  
   669  func newChainMaker(bottom *types.Block, config *params.ChainConfig, engine consensus.Engine) *chainMaker {
   670  	return &chainMaker{
   671  		bottom:      bottom,
   672  		config:      config,
   673  		engine:      engine,
   674  		chainByHash: make(map[common.Hash]*types.Block),
   675  	}
   676  }
   677  
   678  func (cm *chainMaker) add(b *types.Block, r []*types.Receipt) {
   679  	cm.chain = append(cm.chain, b)
   680  	cm.chainByHash[b.Hash()] = b
   681  	cm.receipts = append(cm.receipts, r)
   682  }
   683  
   684  func (cm *chainMaker) blockByNumber(number uint64) *types.Block {
   685  	if number == cm.bottom.NumberU64() {
   686  		return cm.bottom
   687  	}
   688  	cur := cm.CurrentHeader().Number.Uint64()
   689  	lowest := cm.bottom.NumberU64() + 1
   690  	if number < lowest || number > cur {
   691  		return nil
   692  	}
   693  	return cm.chain[number-lowest]
   694  }
   695  
   696  // ChainReader/ChainContext implementation
   697  
   698  // Config returns the chain configuration (for consensus.ChainReader).
   699  func (cm *chainMaker) Config() *params.ChainConfig {
   700  	return cm.config
   701  }
   702  
   703  // Engine returns the consensus engine (for ChainContext).
   704  func (cm *chainMaker) Engine() consensus.Engine {
   705  	return cm.engine
   706  }
   707  
   708  func (cm *chainMaker) CurrentHeader() *types.Header {
   709  	if len(cm.chain) == 0 {
   710  		return cm.bottom.Header()
   711  	}
   712  	return cm.chain[len(cm.chain)-1].Header()
   713  }
   714  
   715  func (cm *chainMaker) GetHeaderByNumber(number uint64) *types.Header {
   716  	b := cm.blockByNumber(number)
   717  	if b == nil {
   718  		return nil
   719  	}
   720  	return b.Header()
   721  }
   722  
   723  func (cm *chainMaker) GetHeaderByHash(hash common.Hash) *types.Header {
   724  	b := cm.chainByHash[hash]
   725  	if b == nil {
   726  		return nil
   727  	}
   728  	return b.Header()
   729  }
   730  
   731  func (cm *chainMaker) GetHeader(hash common.Hash, number uint64) *types.Header {
   732  	return cm.GetHeaderByNumber(number)
   733  }
   734  
   735  func (cm *chainMaker) GetBlock(hash common.Hash, number uint64) *types.Block {
   736  	return cm.blockByNumber(number)
   737  }