github.com/MetalBlockchain/subnet-evm@v0.4.9/core/chain_makers.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2015 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package core
    28  
    29  import (
    30  	"fmt"
    31  	"math/big"
    32  
    33  	"github.com/MetalBlockchain/subnet-evm/commontype"
    34  	"github.com/MetalBlockchain/subnet-evm/consensus"
    35  	"github.com/MetalBlockchain/subnet-evm/consensus/dummy"
    36  	"github.com/MetalBlockchain/subnet-evm/constants"
    37  	"github.com/MetalBlockchain/subnet-evm/core/state"
    38  	"github.com/MetalBlockchain/subnet-evm/core/types"
    39  	"github.com/MetalBlockchain/subnet-evm/core/vm"
    40  	"github.com/MetalBlockchain/subnet-evm/ethdb"
    41  	"github.com/MetalBlockchain/subnet-evm/params"
    42  	"github.com/ethereum/go-ethereum/common"
    43  )
    44  
    45  // BlockGen creates blocks for testing.
    46  // See GenerateChain for a detailed explanation.
    47  type BlockGen struct {
    48  	i       int
    49  	parent  *types.Block
    50  	chain   []*types.Block
    51  	header  *types.Header
    52  	statedb *state.StateDB
    53  
    54  	gasPool  *GasPool
    55  	txs      []*types.Transaction
    56  	receipts []*types.Receipt
    57  	uncles   []*types.Header
    58  
    59  	config           *params.ChainConfig
    60  	engine           consensus.Engine
    61  	onBlockGenerated func(*types.Block)
    62  }
    63  
    64  // SetCoinbase sets the coinbase of the generated block.
    65  // It can be called at most once.
    66  func (b *BlockGen) SetCoinbase(addr common.Address) {
    67  	if b.gasPool != nil {
    68  		if len(b.txs) > 0 {
    69  			panic("coinbase must be set before adding transactions")
    70  		}
    71  		panic("coinbase can only be set once")
    72  	}
    73  	b.header.Coinbase = addr
    74  	b.gasPool = new(GasPool).AddGas(b.header.GasLimit)
    75  }
    76  
    77  // SetExtra sets the extra data field of the generated block.
    78  func (b *BlockGen) SetExtra(data []byte) {
    79  	b.header.Extra = data
    80  }
    81  
    82  // SetNonce sets the nonce field of the generated block.
    83  func (b *BlockGen) SetNonce(nonce types.BlockNonce) {
    84  	b.header.Nonce = nonce
    85  }
    86  
    87  // SetDifficulty sets the difficulty field of the generated block. This method is
    88  // useful for Clique tests where the difficulty does not depend on time. For the
    89  // ethash tests, please use OffsetTime, which implicitly recalculates the diff.
    90  func (b *BlockGen) SetDifficulty(diff *big.Int) {
    91  	b.header.Difficulty = diff
    92  }
    93  
    94  // AddTx adds a transaction to the generated block. If no coinbase has
    95  // been set, the block's coinbase is set to the zero address.
    96  //
    97  // AddTx panics if the transaction cannot be executed. In addition to
    98  // the protocol-imposed limitations (gas limit, etc.), there are some
    99  // further limitations on the content of transactions that can be
   100  // added. Notably, contract code relying on the BLOCKHASH instruction
   101  // will panic during execution.
   102  func (b *BlockGen) AddTx(tx *types.Transaction) {
   103  	b.AddTxWithChain(nil, tx)
   104  }
   105  
   106  // AddTxWithChain adds a transaction to the generated block. If no coinbase has
   107  // been set, the block's coinbase is set to the zero address.
   108  //
   109  // AddTxWithChain panics if the transaction cannot be executed. In addition to
   110  // the protocol-imposed limitations (gas limit, etc.), there are some
   111  // further limitations on the content of transactions that can be
   112  // added. If contract code relies on the BLOCKHASH instruction,
   113  // the block in chain will be returned.
   114  func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
   115  	if b.gasPool == nil {
   116  		b.SetCoinbase(common.Address{})
   117  	}
   118  	b.statedb.Prepare(tx.Hash(), len(b.txs))
   119  	receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{})
   120  	if err != nil {
   121  		panic(err)
   122  	}
   123  	b.txs = append(b.txs, tx)
   124  	b.receipts = append(b.receipts, receipt)
   125  }
   126  
   127  // GetBalance returns the balance of the given address at the generated block.
   128  func (b *BlockGen) GetBalance(addr common.Address) *big.Int {
   129  	return b.statedb.GetBalance(addr)
   130  }
   131  
   132  // AddUncheckedTx forcefully adds a transaction to the block without any
   133  // validation.
   134  //
   135  // AddUncheckedTx will cause consensus failures when used during real
   136  // chain processing. This is best used in conjunction with raw block insertion.
   137  func (b *BlockGen) AddUncheckedTx(tx *types.Transaction) {
   138  	b.txs = append(b.txs, tx)
   139  }
   140  
   141  // Number returns the block number of the block being generated.
   142  func (b *BlockGen) Number() *big.Int {
   143  	return new(big.Int).Set(b.header.Number)
   144  }
   145  
   146  // BaseFee returns the EIP-1559 base fee of the block being generated.
   147  func (b *BlockGen) BaseFee() *big.Int {
   148  	return new(big.Int).Set(b.header.BaseFee)
   149  }
   150  
   151  // AddUncheckedReceipt forcefully adds a receipts to the block without a
   152  // backing transaction.
   153  //
   154  // AddUncheckedReceipt will cause consensus failures when used during real
   155  // chain processing. This is best used in conjunction with raw block insertion.
   156  func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) {
   157  	b.receipts = append(b.receipts, receipt)
   158  }
   159  
   160  // TxNonce returns the next valid transaction nonce for the
   161  // account at addr. It panics if the account does not exist.
   162  func (b *BlockGen) TxNonce(addr common.Address) uint64 {
   163  	if !b.statedb.Exist(addr) {
   164  		panic("account does not exist")
   165  	}
   166  	return b.statedb.GetNonce(addr)
   167  }
   168  
   169  // AddUncle adds an uncle header to the generated block.
   170  func (b *BlockGen) AddUncle(h *types.Header) {
   171  	b.uncles = append(b.uncles, h)
   172  }
   173  
   174  // PrevBlock returns a previously generated block by number. It panics if
   175  // num is greater or equal to the number of the block being generated.
   176  // For index -1, PrevBlock returns the parent block given to GenerateChain.
   177  func (b *BlockGen) PrevBlock(index int) *types.Block {
   178  	if index >= b.i {
   179  		panic(fmt.Errorf("block index %d out of range (%d,%d)", index, -1, b.i))
   180  	}
   181  	if index == -1 {
   182  		return b.parent
   183  	}
   184  	return b.chain[index]
   185  }
   186  
   187  // OffsetTime modifies the time instance of a block, implicitly changing its
   188  // associated difficulty. It's useful to test scenarios where forking is not
   189  // tied to chain length directly.
   190  func (b *BlockGen) OffsetTime(seconds int64) {
   191  	b.header.Time += uint64(seconds)
   192  	if b.header.Time <= b.parent.Header().Time {
   193  		panic("block time out of range")
   194  	}
   195  	chainreader := &fakeChainReader{config: b.config}
   196  	b.header.Difficulty = b.engine.CalcDifficulty(chainreader, b.header.Time, b.parent.Header())
   197  }
   198  
   199  // SetOnBlockGenerated sets a callback function to be invoked after each block is generated
   200  func (b *BlockGen) SetOnBlockGenerated(onBlockGenerated func(*types.Block)) {
   201  	b.onBlockGenerated = onBlockGenerated
   202  }
   203  
   204  // GenerateChain creates a chain of n blocks. The first block's
   205  // parent will be the provided parent. db is used to store
   206  // intermediate states and should contain the parent's state trie.
   207  //
   208  // The generator function is called with a new block generator for
   209  // every block. Any transactions and uncles added to the generator
   210  // become part of the block. If gen is nil, the blocks will be empty
   211  // and their coinbase will be the zero address.
   212  //
   213  // Blocks created by GenerateChain do not contain valid proof of work
   214  // values. Inserting them into BlockChain requires use of FakePow or
   215  // a similar non-validating proof of work implementation.
   216  func GenerateChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, n int, gap uint64, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts, error) {
   217  	if config == nil {
   218  		config = params.TestChainConfig
   219  	}
   220  	blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
   221  	chainreader := &fakeChainReader{config: config}
   222  	genblock := func(i int, parent *types.Block, statedb *state.StateDB) (*types.Block, types.Receipts, error) {
   223  		b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine}
   224  		b.header = makeHeader(chainreader, config, parent, gap, statedb, b.engine)
   225  
   226  		// Execute any user modifications to the block
   227  		if gen != nil {
   228  			gen(i, b)
   229  		}
   230  		if b.engine != nil {
   231  			// Finalize and seal the block
   232  			block, err := b.engine.FinalizeAndAssemble(chainreader, b.header, parent.Header(), statedb, b.txs, b.uncles, b.receipts)
   233  			if err != nil {
   234  				return nil, nil, fmt.Errorf("Failed to finalize and assemble block at index %d: %w", i, err)
   235  			}
   236  
   237  			// Write state changes to db
   238  			root, err := statedb.Commit(config.IsEIP158(b.header.Number), false)
   239  			if err != nil {
   240  				panic(fmt.Sprintf("state write error: %v", err))
   241  			}
   242  			if err := statedb.Database().TrieDB().Commit(root, false, nil); err != nil {
   243  				panic(fmt.Sprintf("trie write error: %v", err))
   244  			}
   245  			if b.onBlockGenerated != nil {
   246  				b.onBlockGenerated(block)
   247  			}
   248  			return block, b.receipts, nil
   249  		}
   250  		return nil, nil, nil
   251  	}
   252  	for i := 0; i < n; i++ {
   253  		statedb, err := state.New(parent.Root(), state.NewDatabase(db), nil)
   254  		if err != nil {
   255  			return nil, nil, err
   256  		}
   257  		block, receipt, err := genblock(i, parent, statedb)
   258  		if err != nil {
   259  			return nil, nil, err
   260  		}
   261  		blocks[i] = block
   262  		receipts[i] = receipt
   263  		parent = block
   264  	}
   265  	return blocks, receipts, nil
   266  }
   267  
   268  func makeHeader(chain consensus.ChainReader, config *params.ChainConfig, parent *types.Block, gap uint64, state *state.StateDB, engine consensus.Engine) *types.Header {
   269  	var time uint64
   270  	if parent.Time() == 0 {
   271  		time = gap
   272  	} else {
   273  		time = parent.Time() + gap
   274  	}
   275  
   276  	header := &types.Header{
   277  		Root:       state.IntermediateRoot(chain.Config().IsEIP158(parent.Number())),
   278  		ParentHash: parent.Hash(),
   279  		Coinbase:   parent.Coinbase(),
   280  		Difficulty: engine.CalcDifficulty(chain, time, &types.Header{
   281  			Number:     parent.Number(),
   282  			Time:       time - gap,
   283  			Difficulty: parent.Difficulty(),
   284  			UncleHash:  parent.UncleHash(),
   285  		}),
   286  		Number: new(big.Int).Add(parent.Number(), common.Big1),
   287  		Time:   time,
   288  	}
   289  
   290  	timestamp := new(big.Int).SetUint64(time)
   291  	if chain.Config().IsSubnetEVM(timestamp) {
   292  		feeConfig, _, err := chain.GetFeeConfigAt(parent.Header())
   293  		if err != nil {
   294  			panic(err)
   295  		}
   296  
   297  		header.GasLimit = feeConfig.GasLimit.Uint64()
   298  		header.Extra, header.BaseFee, err = dummy.CalcBaseFee(chain.Config(), feeConfig, parent.Header(), time)
   299  		if err != nil {
   300  			panic(err)
   301  		}
   302  	} else {
   303  		header.GasLimit = CalcGasLimit(parent.GasUsed(), parent.GasLimit(), parent.GasLimit(), parent.GasLimit())
   304  	}
   305  	return header
   306  }
   307  
   308  type fakeChainReader struct {
   309  	config *params.ChainConfig
   310  }
   311  
   312  // Config returns the chain configuration.
   313  func (cr *fakeChainReader) Config() *params.ChainConfig {
   314  	return cr.config
   315  }
   316  
   317  func (cr *fakeChainReader) CurrentHeader() *types.Header                            { return nil }
   318  func (cr *fakeChainReader) GetHeaderByNumber(number uint64) *types.Header           { return nil }
   319  func (cr *fakeChainReader) GetHeaderByHash(hash common.Hash) *types.Header          { return nil }
   320  func (cr *fakeChainReader) GetHeader(hash common.Hash, number uint64) *types.Header { return nil }
   321  func (cr *fakeChainReader) GetBlock(hash common.Hash, number uint64) *types.Block   { return nil }
   322  func (cr *fakeChainReader) GetFeeConfigAt(parent *types.Header) (commontype.FeeConfig, *big.Int, error) {
   323  	return cr.config.FeeConfig, nil, nil
   324  }
   325  
   326  func (cr *fakeChainReader) GetCoinbaseAt(parent *types.Header) (common.Address, bool, error) {
   327  	return constants.BlackholeAddr, cr.config.AllowFeeRecipients, nil
   328  }