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 }