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 }