github.com/halybang/go-ethereum@v1.0.5-0.20180325041310-3b262bc1367c/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  	"crypto/ecdsa"
    21  	"fmt"
    22  	"math/big"
    23  
    24  	"github.com/wanchain/go-wanchain/accounts"
    25  	"github.com/wanchain/go-wanchain/common"
    26  	"github.com/wanchain/go-wanchain/consensus"
    27  	"github.com/wanchain/go-wanchain/consensus/ethash"
    28  	"github.com/wanchain/go-wanchain/core/state"
    29  	"github.com/wanchain/go-wanchain/core/types"
    30  	"github.com/wanchain/go-wanchain/core/vm"
    31  	"github.com/wanchain/go-wanchain/crypto"
    32  	"github.com/wanchain/go-wanchain/ethdb"
    33  	"github.com/wanchain/go-wanchain/params"
    34  )
    35  
    36  // So we can deterministically seed different blockchains
    37  var (
    38  	canonicalSeed             = 1
    39  	forkSeed                  = 2
    40  	fakedAddr                 = common.HexToAddress("0xf9b32578b4420a36f132db32b56f3831a7cc1804")
    41  	fakedAccountPrivateKey, _ = crypto.HexToECDSA("f1572f76b75b40a7da72d6f2ee7fda3d1189c2d28f0a2f096347055abe344d7f")
    42  	extraVanity               = 32
    43  	extraSeal                 = 65
    44  )
    45  
    46  func fakeSignerFn(signer accounts.Account, hash []byte) ([]byte, error) {
    47  	return crypto.Sign(hash, fakedAccountPrivateKey)
    48  }
    49  
    50  type ChainEnv struct {
    51  	config       *params.ChainConfig
    52  	genesis      *Genesis
    53  	engine       *ethash.Ethash
    54  	blockChain   *BlockChain
    55  	db           ethdb.Database
    56  	mapSigners   map[common.Address]struct{}
    57  	arraySigners []common.Address
    58  	signerKeys   []*ecdsa.PrivateKey
    59  	//set signers here for testing convenience
    60  	// validSigners
    61  }
    62  
    63  // add for testing permission proof of work
    64  var (
    65  	totalSigner = 20
    66  	signerSet   = make(map[common.Address]*ecdsa.PrivateKey)
    67  	addrSigners = make([]common.Address, 0)
    68  )
    69  
    70  func init() {
    71  	for i := 0; i < totalSigner; i++ {
    72  		private, _ := crypto.GenerateKey()
    73  		addr := crypto.PubkeyToAddress(private.PublicKey)
    74  		signerSet[addr] = private
    75  		addrSigners = append(addrSigners, addr)
    76  	}
    77  }
    78  
    79  func NewChainEnv(config *params.ChainConfig, g *Genesis, engine consensus.Engine, bc *BlockChain, db ethdb.Database) *ChainEnv {
    80  	ce := &ChainEnv{
    81  		config:       config,
    82  		genesis:      g,
    83  		engine:       engine.(*ethash.Ethash),
    84  		blockChain:   bc,
    85  		db:           db,
    86  		mapSigners:   make(map[common.Address]struct{}),
    87  		arraySigners: make([]common.Address, len(g.ExtraData)/common.AddressLength),
    88  	}
    89  
    90  	for i := 0; i < len(ce.arraySigners); i++ {
    91  		copy(ce.arraySigners[i][:], g.ExtraData[i*common.AddressLength:])
    92  	}
    93  	for _, s := range ce.arraySigners {
    94  		ce.mapSigners[s] = struct{}{}
    95  	}
    96  
    97  	return ce
    98  }
    99  
   100  // BlockGen creates blocks for testing.
   101  // See GenerateChain for a detailed explanation.
   102  type BlockGen struct {
   103  	i       int
   104  	parent  *types.Block
   105  	chain   []*types.Block
   106  	header  *types.Header
   107  	statedb *state.StateDB
   108  
   109  	gasPool  *GasPool
   110  	txs      []*types.Transaction
   111  	receipts []*types.Receipt
   112  	uncles   []*types.Header
   113  
   114  	config *params.ChainConfig
   115  }
   116  
   117  // SetCoinbase sets the coinbase of the generated block.
   118  // It can be called at most once.
   119  func (b *BlockGen) SetCoinbase(addr common.Address) {
   120  	if b.gasPool != nil {
   121  		if len(b.txs) > 0 {
   122  			panic("coinbase must be set before adding transactions")
   123  		}
   124  		panic("coinbase can only be set once")
   125  	}
   126  	b.header.Coinbase = addr
   127  	b.gasPool = new(GasPool).AddGas(b.header.GasLimit)
   128  }
   129  
   130  // SetExtra sets the extra data field of the generated block.
   131  func (b *BlockGen) SetExtra(data []byte) {
   132  	// ensure the extra data has all its components
   133  	l := len(data)
   134  	if l > extraVanity {
   135  		fmt.Println("extra data too long")
   136  		return
   137  	}
   138  
   139  	copy(b.header.Extra[extraVanity-l:extraVanity], data)
   140  }
   141  
   142  // AddTx adds a transaction to the generated block. If no coinbase has
   143  // been set, the block's coinbase is set to the zero address.
   144  //
   145  // AddTx panics if the transaction cannot be executed. In addition to
   146  // the protocol-imposed limitations (gas limit, etc.), there are some
   147  // further limitations on the content of transactions that can be
   148  // added. Notably, contract code relying on the BLOCKHASH instruction
   149  // will panic during execution.
   150  func (b *BlockGen) AddTx(tx *types.Transaction) {
   151  	if b.gasPool == nil {
   152  		b.SetCoinbase(b.parent.Coinbase())
   153  	}
   154  	b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
   155  	receipt, _, err := ApplyTransaction(b.config, nil, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
   156  	if err != nil {
   157  		panic(err)
   158  	}
   159  	b.txs = append(b.txs, tx)
   160  	b.receipts = append(b.receipts, receipt)
   161  }
   162  
   163  func (b *BlockGen) AddTxAndCalcGasUsed(tx *types.Transaction) *big.Int {
   164  	if b.gasPool == nil {
   165  		b.SetCoinbase(b.parent.Coinbase())
   166  	}
   167  	b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
   168  	receipt, gasUsed, err := ApplyTransaction(b.config, nil, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
   169  	if err != nil {
   170  		panic(err)
   171  	}
   172  	b.txs = append(b.txs, tx)
   173  	b.receipts = append(b.receipts, receipt)
   174  	return gasUsed
   175  }
   176  
   177  // Number returns the block number of the block being generated.
   178  func (b *BlockGen) Number() *big.Int {
   179  	return new(big.Int).Set(b.header.Number)
   180  }
   181  
   182  // AddUncheckedReceipt forcefully adds a receipts to the block without a
   183  // backing transaction.
   184  //
   185  // AddUncheckedReceipt will cause consensus failures when used during real
   186  // chain processing. This is best used in conjunction with raw block insertion.
   187  func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) {
   188  	b.receipts = append(b.receipts, receipt)
   189  }
   190  
   191  // TxNonce returns the next valid transaction nonce for the
   192  // account at addr. It panics if the account does not exist.
   193  func (b *BlockGen) TxNonce(addr common.Address) uint64 {
   194  	if !b.statedb.Exist(addr) {
   195  		panic("account does not exist")
   196  	}
   197  	return b.statedb.GetNonce(addr)
   198  }
   199  
   200  // AddUncle adds an uncle header to the generated block.
   201  func (b *BlockGen) AddUncle(h *types.Header) {
   202  	b.uncles = append(b.uncles, h)
   203  }
   204  
   205  // PrevBlock returns a previously generated block by number. It panics if
   206  // num is greater or equal to the number of the block being generated.
   207  // For index -1, PrevBlock returns the parent block given to GenerateChain.
   208  func (b *BlockGen) PrevBlock(index int) *types.Block {
   209  	if index >= b.i {
   210  		panic("block index out of range")
   211  	}
   212  	if index == -1 {
   213  		return b.parent
   214  	}
   215  	return b.chain[index]
   216  }
   217  
   218  // OffsetTime modifies the time instance of a block, implicitly changing its
   219  // associated difficulty. It's useful to test scenarios where forking is not
   220  // tied to chain length directly.
   221  func (b *BlockGen) OffsetTime(seconds int64) {
   222  	b.header.Time.Add(b.header.Time, new(big.Int).SetInt64(seconds))
   223  	if b.header.Time.Cmp(b.parent.Header().Time) <= 0 {
   224  		panic("block time out of range")
   225  	}
   226  	b.header.Difficulty = ethash.CalcDifficulty(b.config, b.header.Time.Uint64(), b.parent.Header())
   227  }
   228  
   229  // GenerateChain creates a chain of n blocks. The first block's
   230  // parent will be the provided parent. db is used to store
   231  // intermediate states and should contain the parent's state trie.
   232  //
   233  // The generator function is called with a new block generator for
   234  // every block. Any transactions and uncles added to the generator
   235  // become part of the block. If gen is nil, the blocks will be empty
   236  // and their coinbase will be the zero address.
   237  //
   238  // Blocks created by GenerateChain do not contain valid proof of work
   239  // values. Inserting them into BlockChain requires use of FakePow or
   240  // a similar non-validating proof of work implementation.
   241  func (self *ChainEnv) GenerateChain(parent *types.Block, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
   242  	blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
   243  	genblock := func(i int, h *types.Header, statedb *state.StateDB) (*types.Block, types.Receipts) {
   244  		b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb, config: self.config}
   245  
   246  		// Execute any user modifications to the block and finalize it
   247  		if gen != nil {
   248  			gen(i, b)
   249  		}
   250  
   251  		ethash.AccumulateRewards(self.config, statedb, h, b.uncles)
   252  		root, err := statedb.CommitTo(self.db, true)
   253  		if err != nil {
   254  			panic(fmt.Sprintf("state write error: %v", err))
   255  		}
   256  		h.Root = root
   257  
   258  		self.engine.Authorize(fakedAddr, fakeSignerFn)
   259  		h.Coinbase.Set(fakedAddr)
   260  		rawBlock := types.NewBlock(h, b.txs, b.uncles, b.receipts)
   261  		sealBlock, _ := self.engine.Seal(self.blockChain, rawBlock, nil)
   262  		return sealBlock, b.receipts
   263  	}
   264  	for i := 0; i < n; i++ {
   265  		statedb, err := state.New(parent.Root(), state.NewDatabase(self.db))
   266  		if err != nil {
   267  			panic(err)
   268  		}
   269  		header := makeHeader(self.config, parent, statedb)
   270  		block, receipt := genblock(i, header, statedb)
   271  		blocks[i] = block
   272  		receipts[i] = receipt
   273  		parent = block
   274  	}
   275  	return blocks, receipts
   276  }
   277  
   278  func (self *ChainEnv) GenerateChainMulti(parent *types.Block, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
   279  	blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
   280  	genblock := func(i int, h *types.Header, statedb *state.StateDB) (*types.Block, types.Receipts) {
   281  		b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb, config: self.config}
   282  
   283  		// Execute any user modifications to the block and finalize it
   284  		if gen != nil {
   285  			gen(i, b)
   286  		}
   287  
   288  		ethash.AccumulateRewards(self.config, statedb, h, b.uncles)
   289  		root, err := statedb.CommitTo(self.db, true)
   290  		if err != nil {
   291  			panic(fmt.Sprintf("state write error: %v", err))
   292  		}
   293  		h.Root = root
   294  
   295  		self.engine.Authorize(fakedAddr, fakeSignerFn)
   296  		rawBlock := types.NewBlock(h, b.txs, b.uncles, b.receipts)
   297  		sealBlock, _ := self.engine.Seal(self.blockChain, rawBlock, nil)
   298  		return sealBlock, b.receipts
   299  	}
   300  	for i := 0; i < n; i++ {
   301  		statedb, err := state.New(parent.Root(), state.NewDatabase(self.db))
   302  		if err != nil {
   303  			panic(err)
   304  		}
   305  		header := makeHeader(self.config, parent, statedb)
   306  		block, receipt := genblock(i, header, statedb)
   307  		blocks[i] = block
   308  		receipts[i] = receipt
   309  		parent = block
   310  	}
   311  	return blocks, receipts
   312  }
   313  
   314  func fakeSignerFnEx(signer accounts.Account, hash []byte) ([]byte, error) {
   315  	return crypto.Sign(hash, signerSet[signer.Address])
   316  }
   317  
   318  func (self *ChainEnv) GenerateChainEx(parent *types.Block, signerSequence []int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
   319  	blocks, receipts := make(types.Blocks, len(signerSequence)), make([]types.Receipts, len(signerSequence))
   320  	genblock := func(i int, h *types.Header, statedb *state.StateDB) (*types.Block, types.Receipts) {
   321  		b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb, config: self.config}
   322  
   323  		// Execute any user modifications to the block and finalize it
   324  		if gen != nil {
   325  			gen(i, b)
   326  		}
   327  
   328  		ethash.AccumulateRewards(self.config, statedb, h, b.uncles)
   329  		root, err := statedb.CommitTo(self.db, true)
   330  		if err != nil {
   331  			panic(fmt.Sprintf("state write error: %v", err))
   332  		}
   333  		h.Root = root
   334  
   335  		self.engine.Authorize(addrSigners[i], fakeSignerFnEx)
   336  		h.Coinbase.Set(addrSigners[i])
   337  		rawBlock := types.NewBlock(h, b.txs, b.uncles, b.receipts)
   338  		sealBlock, _ := self.engine.Seal(self.blockChain, rawBlock, nil)
   339  		return sealBlock, b.receipts
   340  	}
   341  	for i := 0; i < len(signerSequence); i++ {
   342  		statedb, err := state.New(parent.Root(), state.NewDatabase(self.db))
   343  		if err != nil {
   344  			panic(err)
   345  		}
   346  		header := makeHeader(self.config, parent, statedb)
   347  		block, receipt := genblock(signerSequence[i], header, statedb)
   348  		blocks[i] = block
   349  		receipts[i] = receipt
   350  		parent = block
   351  	}
   352  	return blocks, receipts
   353  }
   354  
   355  func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.StateDB) *types.Header {
   356  	var time *big.Int
   357  	if parent.Time() == nil {
   358  		time = big.NewInt(10)
   359  	} else {
   360  		time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
   361  	}
   362  
   363  	return &types.Header{
   364  		Root:       state.IntermediateRoot(true /*config.IsEIP158(parent.Number())*/),
   365  		ParentHash: parent.Hash(),
   366  		Coinbase:   parent.Coinbase(),
   367  		Difficulty: ethash.CalcDifficulty(config, time.Uint64(), &types.Header{
   368  			Number:     parent.Number(),
   369  			Time:       new(big.Int).Sub(time, big.NewInt(10)),
   370  			Difficulty: parent.Difficulty(),
   371  			UncleHash:  parent.UncleHash(),
   372  		}),
   373  		GasLimit: CalcGasLimit(parent),
   374  		GasUsed:  new(big.Int),
   375  		Number:   new(big.Int).Add(parent.Number(), common.Big1),
   376  		Time:     time,
   377  		Extra:    make([]byte, 97),
   378  	}
   379  }
   380  
   381  // newCanonical creates a chain database, and injects a deterministic canonical
   382  // chain. Depending on the full flag, if creates either a full block chain or a
   383  // header only chain.
   384  func newCanonical(n int, full bool) (ethdb.Database, *BlockChain, error, *ChainEnv) {
   385  	// Initialize a fresh chain with only a genesis block
   386  	gspec := DefaultPPOWTestingGenesisBlock()
   387  	db, _ := ethdb.NewMemDatabase()
   388  	genesis := gspec.MustCommit(db)
   389  	engine := ethash.NewFaker(db)
   390  
   391  	blockchain, _ := NewBlockChain(db, params.TestChainConfig, engine, vm.Config{})
   392  	chainEnv := NewChainEnv(params.TestChainConfig, gspec, engine, blockchain, db)
   393  	// Create and inject the requested chain
   394  	if n == 0 {
   395  		return db, blockchain, nil, chainEnv
   396  	}
   397  	if full {
   398  		// Full block-chain requested
   399  		blocks := chainEnv.makeBlockChain(genesis, n, canonicalSeed)
   400  		_, err := blockchain.InsertChain(blocks)
   401  		return db, blockchain, err, chainEnv
   402  	}
   403  	// Header-only chain requested
   404  	headers := chainEnv.makeHeaderChain(genesis.Header(), n, canonicalSeed)
   405  	_, err := blockchain.InsertHeaderChain(headers, 1)
   406  	return db, blockchain, err, chainEnv
   407  }
   408  
   409  // makeHeaderChain creates a deterministic chain of headers rooted at parent.
   410  func (self *ChainEnv) makeHeaderChain(parent *types.Header, n int, seed int) []*types.Header {
   411  	blocks := self.makeBlockChain(types.NewBlockWithHeader(parent), n, seed)
   412  	headers := make([]*types.Header, len(blocks))
   413  	for i, block := range blocks {
   414  		headers[i] = block.Header()
   415  	}
   416  	return headers
   417  }
   418  
   419  // makeBlockChain creates a deterministic chain of blocks rooted at parent.
   420  func (self *ChainEnv) makeBlockChain(parent *types.Block, n int, seed int) []*types.Block {
   421  	// blocks, _ := self.GenerateChain(parent, n, func(i int, b *BlockGen) {
   422  	// b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
   423  	// })
   424  	blocks, _ := self.GenerateChain(parent, n, nil)
   425  	return blocks
   426  }
   427  
   428  func (self *ChainEnv) Blockchain() *BlockChain {
   429  	return self.blockChain
   430  }
   431  
   432  func (self *ChainEnv) Database() ethdb.Database {
   433  	return self.blockChain.chainDb
   434  }
   435  
   436  func (self *ChainEnv) Config() *params.ChainConfig {
   437  	return self.config
   438  }