github.com/m3shine/gochain@v2.2.26+incompatible/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  	"context"
    21  	"fmt"
    22  	"math/big"
    23  
    24  	"github.com/gochain-io/gochain/common"
    25  	"github.com/gochain-io/gochain/consensus"
    26  	"github.com/gochain-io/gochain/core/state"
    27  	"github.com/gochain-io/gochain/core/types"
    28  	"github.com/gochain-io/gochain/core/vm"
    29  	"github.com/gochain-io/gochain/params"
    30  )
    31  
    32  // BlockGen creates blocks for testing.
    33  // See GenerateChain for a detailed explanation.
    34  type BlockGen struct {
    35  	i           int
    36  	parent      *types.Block
    37  	chain       []*types.Block
    38  	chainReader consensus.ChainReader
    39  	header      *types.Header
    40  	statedb     *state.StateDB
    41  
    42  	gasPool  *GasPool
    43  	txs      []*types.Transaction
    44  	receipts []*types.Receipt
    45  	uncles   []*types.Header
    46  
    47  	config *params.ChainConfig
    48  	engine consensus.Engine
    49  }
    50  
    51  // SetCoinbase sets the coinbase of the generated block.
    52  // It can be called at most once.
    53  func (b *BlockGen) SetCoinbase(addr common.Address) {
    54  	if b.gasPool != nil {
    55  		if len(b.txs) > 0 {
    56  			panic("coinbase must be set before adding transactions")
    57  		}
    58  		panic("coinbase can only be set once")
    59  	}
    60  	b.header.Coinbase = addr
    61  	b.gasPool = new(GasPool).AddGas(b.header.GasLimit)
    62  }
    63  
    64  // SetExtra sets the extra data field of the generated block.
    65  func (b *BlockGen) SetExtra(data []byte) {
    66  	b.header.Extra = data
    67  }
    68  
    69  // AddTx adds a transaction to the generated block. If no coinbase has
    70  // been set, the block's coinbase is set to the zero address.
    71  //
    72  // AddTx panics if the transaction cannot be executed. In addition to
    73  // the protocol-imposed limitations (gas limit, etc.), there are some
    74  // further limitations on the content of transactions that can be
    75  // added. Notably, contract code relying on the BLOCKHASH instruction
    76  // will panic during execution.
    77  func (b *BlockGen) AddTx(ctx context.Context, tx *types.Transaction) {
    78  	if b.gasPool == nil {
    79  		b.SetCoinbase(common.Address{})
    80  	}
    81  	b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
    82  	signer := types.MakeSigner(b.config, b.header.Number)
    83  	// Create a new emv context and environment.
    84  	evmContext := NewEVMContextLite(b.header, nil, &b.header.Coinbase)
    85  	vmenv := vm.NewEVM(evmContext, b.statedb, b.config, vm.Config{})
    86  	receipt, _, err := ApplyTransaction(ctx, vmenv, b.config, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, signer)
    87  	if err != nil {
    88  		panic(err)
    89  	}
    90  	b.txs = append(b.txs, tx)
    91  	b.receipts = append(b.receipts, receipt)
    92  }
    93  
    94  // Number returns the block number of the block being generated.
    95  func (b *BlockGen) Number() *big.Int {
    96  	return new(big.Int).Set(b.header.Number)
    97  }
    98  
    99  // AddUncheckedReceipt forcefully adds a receipts to the block without a
   100  // backing transaction.
   101  //
   102  // AddUncheckedReceipt will cause consensus failures when used during real
   103  // chain processing. This is best used in conjunction with raw block insertion.
   104  func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) {
   105  	b.receipts = append(b.receipts, receipt)
   106  }
   107  
   108  // TxNonce returns the next valid transaction nonce for the
   109  // account at addr. It panics if the account does not exist.
   110  func (b *BlockGen) TxNonce(addr common.Address) uint64 {
   111  	if !b.statedb.Exist(addr) {
   112  		panic("account does not exist")
   113  	}
   114  	return b.statedb.GetNonce(addr)
   115  }
   116  
   117  // PrevBlock returns a previously generated block by number. It panics if
   118  // num is greater or equal to the number of the block being generated.
   119  // For index -1, PrevBlock returns the parent block given to GenerateChain.
   120  func (b *BlockGen) PrevBlock(index int) *types.Block {
   121  	if index >= b.i {
   122  		panic("block index out of range")
   123  	}
   124  	if index == -1 {
   125  		return b.parent
   126  	}
   127  	return b.chain[index]
   128  }
   129  
   130  func (b *BlockGen) SetDifficulty(amt uint64) {
   131  	b.header.Difficulty = new(big.Int).SetUint64(amt)
   132  }
   133  
   134  // GenerateChain creates a chain of n blocks. The first block's
   135  // parent will be the provided parent. db is used to store
   136  // intermediate states and should contain the parent's state trie.
   137  //
   138  // The generator function is called with a new block generator for
   139  // every block. Any transactions and uncles added to the generator
   140  // become part of the block. If gen is nil, the blocks will be empty
   141  // and their coinbase will be the zero address.
   142  //
   143  // Blocks created by GenerateChain do not contain valid proof of work
   144  // values. Inserting them into BlockChain requires use of FakePow or
   145  // a similar non-validating proof of work implementation.
   146  func GenerateChain(ctx context.Context, config *params.ChainConfig, first *types.Block, engine consensus.Engine, db common.Database, n int, gen func(context.Context, int, *BlockGen)) ([]*types.Block, []types.Receipts) {
   147  	if config == nil {
   148  		config = params.TestChainConfig
   149  	}
   150  	blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
   151  
   152  	genblock := func(i int, parent *types.Block, statedb *state.StateDB) (*types.Block, types.Receipts) {
   153  		// TODO(karalabe): This is needed for clique, which depends on multiple blocks.
   154  		// It's nonetheless ugly to spin up a blockchain here. Get rid of this somehow.
   155  		blockchain, _ := NewBlockChain(ctx, db, nil, config, engine, vm.Config{})
   156  		defer blockchain.Stop()
   157  		b := &BlockGen{i: i, parent: parent, chain: blocks, chainReader: blockchain, statedb: statedb, config: config, engine: engine}
   158  
   159  		b.header = &types.Header{
   160  			Root:       statedb.IntermediateRoot(b.config.IsEIP158(parent.Number())),
   161  			ParentHash: parent.Hash(),
   162  			GasLimit:   CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit()),
   163  			Number:     new(big.Int).Add(parent.Number(), common.Big1),
   164  			Signers:    parent.Signers(),
   165  			Voters:     parent.Voters(),
   166  			Time:       new(big.Int).Add(parent.Time(), new(big.Int).SetUint64(config.Clique.Period)),
   167  		}
   168  
   169  		// Execute any user modifications to the block and finalize it
   170  		if gen != nil {
   171  			gen(ctx, i, b)
   172  		}
   173  
   174  		if b.engine != nil {
   175  			if err := b.engine.Prepare(ctx, b.chainReader, b.header); err != nil {
   176  				panic(fmt.Sprintf("failed to prepare %d: %v", b.header.Number.Uint64(), err))
   177  			}
   178  			block := b.engine.Finalize(ctx, b.chainReader, b.header, statedb, b.txs, b.receipts, true)
   179  
   180  			stop := make(chan struct{})
   181  			block, _, err := b.engine.Seal(ctx, b.chainReader, block, stop)
   182  			close(stop)
   183  			if err != nil {
   184  				panic(fmt.Sprintf("block seal error: %v", err))
   185  			}
   186  			// Write state changes to db
   187  			root, err := statedb.Commit(config.IsEIP158(b.header.Number))
   188  			if err != nil {
   189  				panic(fmt.Sprintf("state write error: %v", err))
   190  			}
   191  			if err := statedb.Database().TrieDB().Commit(root, false); err != nil {
   192  				panic(fmt.Sprintf("trie write error: %v", err))
   193  			}
   194  			return block, b.receipts
   195  		}
   196  		return nil, nil
   197  	}
   198  	parent := first
   199  	for i := 0; i < n; i++ {
   200  		statedb, err := state.New(parent.Root(), state.NewDatabase(db))
   201  		if err != nil {
   202  			panic(err)
   203  		}
   204  		block, receipt := genblock(i, parent, statedb)
   205  		blocks[i] = block
   206  		receipts[i] = receipt
   207  		parent = block
   208  	}
   209  	return blocks, receipts
   210  }
   211  
   212  // makeHeaderChain creates a deterministic chain of headers rooted at parent.
   213  func makeHeaderChain(ctx context.Context, parent *types.Header, n int, engine consensus.Engine, db common.Database, seed int) []*types.Header {
   214  	blocks := makeBlockChain(ctx, types.NewBlockWithHeader(parent), n, engine, db, seed)
   215  	headers := make([]*types.Header, len(blocks))
   216  	for i, block := range blocks {
   217  		headers[i] = block.Header()
   218  	}
   219  	return headers
   220  }
   221  
   222  // makeBlockChain creates a deterministic chain of blocks rooted at parent.
   223  func makeBlockChain(ctx context.Context, parent *types.Block, n int, engine consensus.Engine, db common.Database, seed int) []*types.Block {
   224  	blocks, _ := GenerateChain(ctx, params.TestChainConfig, parent, engine, db, n, func(ctx context.Context, i int, b *BlockGen) {
   225  		b.SetExtra([]byte{0: byte(seed)})
   226  	})
   227  	return blocks
   228  }