github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/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 "fmt" 21 "math/big" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/consensus" 25 "github.com/ethereum/go-ethereum/consensus/misc" 26 "github.com/ethereum/go-ethereum/consensus/misc/eip1559" 27 "github.com/ethereum/go-ethereum/consensus/misc/eip4844" 28 "github.com/ethereum/go-ethereum/core/rawdb" 29 "github.com/ethereum/go-ethereum/core/state" 30 "github.com/ethereum/go-ethereum/core/types" 31 "github.com/ethereum/go-ethereum/core/vm" 32 "github.com/ethereum/go-ethereum/ethdb" 33 "github.com/ethereum/go-ethereum/params" 34 "github.com/ethereum/go-ethereum/triedb" 35 "github.com/gballet/go-verkle" 36 "github.com/holiman/uint256" 37 ) 38 39 // BlockGen creates blocks for testing. 40 // See GenerateChain for a detailed explanation. 41 type BlockGen struct { 42 i int 43 cm *chainMaker 44 parent *types.Block 45 header *types.Header 46 statedb *state.StateDB 47 48 gasPool *GasPool 49 txs []*types.Transaction 50 receipts []*types.Receipt 51 uncles []*types.Header 52 withdrawals []*types.Withdrawal 53 54 engine consensus.Engine 55 } 56 57 // SetCoinbase sets the coinbase of the generated block. 58 // It can be called at most once. 59 func (b *BlockGen) SetCoinbase(addr common.Address) { 60 if b.gasPool != nil { 61 if len(b.txs) > 0 { 62 panic("coinbase must be set before adding transactions") 63 } 64 panic("coinbase can only be set once") 65 } 66 b.header.Coinbase = addr 67 b.gasPool = new(GasPool).AddGas(b.header.GasLimit) 68 } 69 70 // SetExtra sets the extra data field of the generated block. 71 func (b *BlockGen) SetExtra(data []byte) { 72 b.header.Extra = data 73 } 74 75 // SetNonce sets the nonce field of the generated block. 76 func (b *BlockGen) SetNonce(nonce types.BlockNonce) { 77 b.header.Nonce = nonce 78 } 79 80 // SetDifficulty sets the difficulty field of the generated block. This method is 81 // useful for Clique tests where the difficulty does not depend on time. For the 82 // ethash tests, please use OffsetTime, which implicitly recalculates the diff. 83 func (b *BlockGen) SetDifficulty(diff *big.Int) { 84 b.header.Difficulty = diff 85 } 86 87 // SetPoS makes the header a PoS-header (0 difficulty) 88 func (b *BlockGen) SetPoS() { 89 b.header.Difficulty = new(big.Int) 90 } 91 92 // Difficulty returns the currently calculated difficulty of the block. 93 func (b *BlockGen) Difficulty() *big.Int { 94 return new(big.Int).Set(b.header.Difficulty) 95 } 96 97 // SetParentBeaconRoot sets the parent beacon root field of the generated 98 // block. 99 func (b *BlockGen) SetParentBeaconRoot(root common.Hash) { 100 b.header.ParentBeaconRoot = &root 101 var ( 102 blockContext = NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase) 103 vmenv = vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.cm.config, vm.Config{}) 104 ) 105 ProcessBeaconBlockRoot(root, vmenv, b.statedb) 106 } 107 108 // addTx adds a transaction to the generated block. If no coinbase has 109 // been set, the block's coinbase is set to the zero address. 110 // 111 // There are a few options can be passed as well in order to run some 112 // customized rules. 113 // - bc: enables the ability to query historical block hashes for BLOCKHASH 114 // - vmConfig: extends the flexibility for customizing evm rules, e.g. enable extra EIPs 115 func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transaction) { 116 if b.gasPool == nil { 117 b.SetCoinbase(common.Address{}) 118 } 119 b.statedb.SetTxContext(tx.Hash(), len(b.txs)) 120 receipt, err := ApplyTransaction(b.cm.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig) 121 if err != nil { 122 panic(err) 123 } 124 b.txs = append(b.txs, tx) 125 b.receipts = append(b.receipts, receipt) 126 if b.header.BlobGasUsed != nil { 127 *b.header.BlobGasUsed += receipt.BlobGasUsed 128 } 129 } 130 131 // AddTx adds a transaction to the generated block. If no coinbase has 132 // been set, the block's coinbase is set to the zero address. 133 // 134 // AddTx panics if the transaction cannot be executed. In addition to the protocol-imposed 135 // limitations (gas limit, etc.), there are some further limitations on the content of 136 // transactions that can be added. Notably, contract code relying on the BLOCKHASH 137 // instruction will panic during execution if it attempts to access a block number outside 138 // of the range created by GenerateChain. 139 func (b *BlockGen) AddTx(tx *types.Transaction) { 140 b.addTx(nil, vm.Config{}, tx) 141 } 142 143 // AddTxWithChain adds a transaction to the generated block. If no coinbase has 144 // been set, the block's coinbase is set to the zero address. 145 // 146 // AddTxWithChain panics if the transaction cannot be executed. In addition to the 147 // protocol-imposed limitations (gas limit, etc.), there are some further limitations on 148 // the content of transactions that can be added. If contract code relies on the BLOCKHASH 149 // instruction, the block in chain will be returned. 150 func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { 151 b.addTx(bc, vm.Config{}, tx) 152 } 153 154 // AddTxWithVMConfig adds a transaction to the generated block. If no coinbase has 155 // been set, the block's coinbase is set to the zero address. 156 // The evm interpreter can be customized with the provided vm config. 157 func (b *BlockGen) AddTxWithVMConfig(tx *types.Transaction, config vm.Config) { 158 b.addTx(nil, config, tx) 159 } 160 161 // GetBalance returns the balance of the given address at the generated block. 162 func (b *BlockGen) GetBalance(addr common.Address) *uint256.Int { 163 return b.statedb.GetBalance(addr) 164 } 165 166 // AddUncheckedTx forcefully adds a transaction to the block without any validation. 167 // 168 // AddUncheckedTx will cause consensus failures when used during real 169 // chain processing. This is best used in conjunction with raw block insertion. 170 func (b *BlockGen) AddUncheckedTx(tx *types.Transaction) { 171 b.txs = append(b.txs, tx) 172 } 173 174 // Number returns the block number of the block being generated. 175 func (b *BlockGen) Number() *big.Int { 176 return new(big.Int).Set(b.header.Number) 177 } 178 179 // Timestamp returns the timestamp of the block being generated. 180 func (b *BlockGen) Timestamp() uint64 { 181 return b.header.Time 182 } 183 184 // BaseFee returns the EIP-1559 base fee of the block being generated. 185 func (b *BlockGen) BaseFee() *big.Int { 186 return new(big.Int).Set(b.header.BaseFee) 187 } 188 189 // Gas returns the amount of gas left in the current block. 190 func (b *BlockGen) Gas() uint64 { 191 return b.header.GasLimit - b.header.GasUsed 192 } 193 194 // Signer returns a valid signer instance for the current block. 195 func (b *BlockGen) Signer() types.Signer { 196 return types.MakeSigner(b.cm.config, b.header.Number, b.header.Time) 197 } 198 199 // AddUncheckedReceipt forcefully adds a receipts to the block without a 200 // backing transaction. 201 // 202 // AddUncheckedReceipt will cause consensus failures when used during real 203 // chain processing. This is best used in conjunction with raw block insertion. 204 func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) { 205 b.receipts = append(b.receipts, receipt) 206 } 207 208 // TxNonce returns the next valid transaction nonce for the 209 // account at addr. It panics if the account does not exist. 210 func (b *BlockGen) TxNonce(addr common.Address) uint64 { 211 if !b.statedb.Exist(addr) { 212 panic("account does not exist") 213 } 214 return b.statedb.GetNonce(addr) 215 } 216 217 // AddUncle adds an uncle header to the generated block. 218 func (b *BlockGen) AddUncle(h *types.Header) { 219 // The uncle will have the same timestamp and auto-generated difficulty 220 h.Time = b.header.Time 221 222 var parent *types.Header 223 for i := b.i - 1; i >= 0; i-- { 224 if b.cm.chain[i].Hash() == h.ParentHash { 225 parent = b.cm.chain[i].Header() 226 break 227 } 228 } 229 h.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, parent) 230 231 // The gas limit and price should be derived from the parent 232 h.GasLimit = parent.GasLimit 233 if b.cm.config.IsLondon(h.Number) { 234 h.BaseFee = eip1559.CalcBaseFee(b.cm.config, parent) 235 if !b.cm.config.IsLondon(parent.Number) { 236 parentGasLimit := parent.GasLimit * b.cm.config.ElasticityMultiplier() 237 h.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit) 238 } 239 } 240 b.uncles = append(b.uncles, h) 241 } 242 243 // AddWithdrawal adds a withdrawal to the generated block. 244 // It returns the withdrawal index. 245 func (b *BlockGen) AddWithdrawal(w *types.Withdrawal) uint64 { 246 cpy := *w 247 cpy.Index = b.nextWithdrawalIndex() 248 b.withdrawals = append(b.withdrawals, &cpy) 249 return cpy.Index 250 } 251 252 // nextWithdrawalIndex computes the index of the next withdrawal. 253 func (b *BlockGen) nextWithdrawalIndex() uint64 { 254 if len(b.withdrawals) != 0 { 255 return b.withdrawals[len(b.withdrawals)-1].Index + 1 256 } 257 for i := b.i - 1; i >= 0; i-- { 258 if wd := b.cm.chain[i].Withdrawals(); len(wd) != 0 { 259 return wd[len(wd)-1].Index + 1 260 } 261 if i == 0 { 262 // Correctly set the index if no parent had withdrawals. 263 if wd := b.cm.bottom.Withdrawals(); len(wd) != 0 { 264 return wd[len(wd)-1].Index + 1 265 } 266 } 267 } 268 return 0 269 } 270 271 // PrevBlock returns a previously generated block by number. It panics if 272 // num is greater or equal to the number of the block being generated. 273 // For index -1, PrevBlock returns the parent block given to GenerateChain. 274 func (b *BlockGen) PrevBlock(index int) *types.Block { 275 if index >= b.i { 276 panic(fmt.Errorf("block index %d out of range (%d,%d)", index, -1, b.i)) 277 } 278 if index == -1 { 279 return b.cm.bottom 280 } 281 return b.cm.chain[index] 282 } 283 284 // OffsetTime modifies the time instance of a block, implicitly changing its 285 // associated difficulty. It's useful to test scenarios where forking is not 286 // tied to chain length directly. 287 func (b *BlockGen) OffsetTime(seconds int64) { 288 b.header.Time += uint64(seconds) 289 if b.header.Time <= b.cm.bottom.Header().Time { 290 panic("block time out of range") 291 } 292 b.header.Difficulty = b.engine.CalcDifficulty(b.cm, b.header.Time, b.parent.Header()) 293 } 294 295 // GenerateChain creates a chain of n blocks. The first block's 296 // parent will be the provided parent. db is used to store 297 // intermediate states and should contain the parent's state trie. 298 // 299 // The generator function is called with a new block generator for 300 // every block. Any transactions and uncles added to the generator 301 // become part of the block. If gen is nil, the blocks will be empty 302 // and their coinbase will be the zero address. 303 // 304 // Blocks created by GenerateChain do not contain valid proof of work 305 // values. Inserting them into BlockChain requires use of FakePow or 306 // a similar non-validating proof of work implementation. 307 func GenerateChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) { 308 if config == nil { 309 config = params.TestChainConfig 310 } 311 if engine == nil { 312 panic("nil consensus engine") 313 } 314 cm := newChainMaker(parent, config, engine) 315 316 genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) { 317 b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine} 318 b.header = cm.makeHeader(parent, statedb, b.engine) 319 320 // Set the difficulty for clique block. The chain maker doesn't have access 321 // to a chain, so the difficulty will be left unset (nil). Set it here to the 322 // correct value. 323 if b.header.Difficulty == nil { 324 if config.TerminalTotalDifficulty == nil { 325 // Clique chain 326 b.header.Difficulty = big.NewInt(2) 327 } else { 328 // Post-merge chain 329 b.header.Difficulty = big.NewInt(0) 330 } 331 } 332 // Mutate the state and block according to any hard-fork specs 333 if daoBlock := config.DAOForkBlock; daoBlock != nil { 334 limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange) 335 if b.header.Number.Cmp(daoBlock) >= 0 && b.header.Number.Cmp(limit) < 0 { 336 if config.DAOForkSupport { 337 b.header.Extra = common.CopyBytes(params.DAOForkBlockExtra) 338 } 339 } 340 } 341 if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 { 342 misc.ApplyDAOHardFork(statedb) 343 } 344 // Execute any user modifications to the block 345 if gen != nil { 346 gen(i, b) 347 } 348 349 body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals} 350 block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts) 351 if err != nil { 352 panic(err) 353 } 354 355 // Write state changes to db 356 root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number)) 357 if err != nil { 358 panic(fmt.Sprintf("state write error: %v", err)) 359 } 360 if err = triedb.Commit(root, false); err != nil { 361 panic(fmt.Sprintf("trie write error: %v", err)) 362 } 363 return block, b.receipts 364 } 365 366 // Forcibly use hash-based state scheme for retaining all nodes in disk. 367 triedb := triedb.NewDatabase(db, triedb.HashDefaults) 368 defer triedb.Close() 369 370 for i := 0; i < n; i++ { 371 statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, triedb), nil) 372 if err != nil { 373 panic(err) 374 } 375 block, receipts := genblock(i, parent, triedb, statedb) 376 377 // Post-process the receipts. 378 // Here we assign the final block hash and other info into the receipt. 379 // In order for DeriveFields to work, the transaction and receipt lists need to be 380 // of equal length. If AddUncheckedTx or AddUncheckedReceipt are used, there will be 381 // extra ones, so we just trim the lists here. 382 receiptsCount := len(receipts) 383 txs := block.Transactions() 384 if len(receipts) > len(txs) { 385 receipts = receipts[:len(txs)] 386 } else if len(receipts) < len(txs) { 387 txs = txs[:len(receipts)] 388 } 389 var blobGasPrice *big.Int 390 if block.ExcessBlobGas() != nil { 391 blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas()) 392 } 393 if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil { 394 panic(err) 395 } 396 397 // Re-expand to ensure all receipts are returned. 398 receipts = receipts[:receiptsCount] 399 400 // Advance the chain. 401 cm.add(block, receipts) 402 parent = block 403 } 404 return cm.chain, cm.receipts 405 } 406 407 // GenerateChainWithGenesis is a wrapper of GenerateChain which will initialize 408 // genesis block to database first according to the provided genesis specification 409 // then generate chain on top. 410 func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) { 411 db := rawdb.NewMemoryDatabase() 412 triedb := triedb.NewDatabase(db, triedb.HashDefaults) 413 defer triedb.Close() 414 _, err := genesis.Commit(db, triedb) 415 if err != nil { 416 panic(err) 417 } 418 blocks, receipts := GenerateChain(genesis.Config, genesis.ToBlock(), engine, db, n, gen) 419 return db, blocks, receipts 420 } 421 422 func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db ethdb.Database, trdb *triedb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) { 423 if config == nil { 424 config = params.TestChainConfig 425 } 426 proofs := make([]*verkle.VerkleProof, 0, n) 427 keyvals := make([]verkle.StateDiff, 0, n) 428 cm := newChainMaker(parent, config, engine) 429 430 genblock := func(i int, parent *types.Block, triedb *triedb.Database, statedb *state.StateDB) (*types.Block, types.Receipts) { 431 b := &BlockGen{i: i, cm: cm, parent: parent, statedb: statedb, engine: engine} 432 b.header = cm.makeHeader(parent, statedb, b.engine) 433 434 // TODO uncomment when proof generation is merged 435 // Save pre state for proof generation 436 // preState := statedb.Copy() 437 438 // TODO uncomment when the 2935 PR is merged 439 // if config.IsPrague(b.header.Number, b.header.Time) { 440 // if !config.IsPrague(b.parent.Number(), b.parent.Time()) { 441 // Transition case: insert all 256 ancestors 442 // InsertBlockHashHistoryAtEip2935Fork(statedb, b.header.Number.Uint64()-1, b.header.ParentHash, chainreader) 443 // } else { 444 // ProcessParentBlockHash(statedb, b.header.Number.Uint64()-1, b.header.ParentHash) 445 // } 446 // } 447 // Execute any user modifications to the block 448 if gen != nil { 449 gen(i, b) 450 } 451 body := &types.Body{ 452 Transactions: b.txs, 453 Uncles: b.uncles, 454 Withdrawals: b.withdrawals, 455 } 456 block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, body, b.receipts) 457 if err != nil { 458 panic(err) 459 } 460 461 // Write state changes to db 462 root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number)) 463 if err != nil { 464 panic(fmt.Sprintf("state write error: %v", err)) 465 } 466 if err = triedb.Commit(root, false); err != nil { 467 panic(fmt.Sprintf("trie write error: %v", err)) 468 } 469 470 // TODO uncomment when proof generation is merged 471 // proofs = append(proofs, block.ExecutionWitness().VerkleProof) 472 // keyvals = append(keyvals, block.ExecutionWitness().StateDiff) 473 474 return block, b.receipts 475 } 476 477 for i := 0; i < n; i++ { 478 statedb, err := state.New(parent.Root(), state.NewDatabaseWithNodeDB(db, trdb), nil) 479 if err != nil { 480 panic(err) 481 } 482 block, receipts := genblock(i, parent, trdb, statedb) 483 484 // Post-process the receipts. 485 // Here we assign the final block hash and other info into the receipt. 486 // In order for DeriveFields to work, the transaction and receipt lists need to be 487 // of equal length. If AddUncheckedTx or AddUncheckedReceipt are used, there will be 488 // extra ones, so we just trim the lists here. 489 receiptsCount := len(receipts) 490 txs := block.Transactions() 491 if len(receipts) > len(txs) { 492 receipts = receipts[:len(txs)] 493 } else if len(receipts) < len(txs) { 494 txs = txs[:len(receipts)] 495 } 496 var blobGasPrice *big.Int 497 if block.ExcessBlobGas() != nil { 498 blobGasPrice = eip4844.CalcBlobFee(*block.ExcessBlobGas()) 499 } 500 if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.BaseFee(), blobGasPrice, txs); err != nil { 501 panic(err) 502 } 503 504 // Re-expand to ensure all receipts are returned. 505 receipts = receipts[:receiptsCount] 506 507 // Advance the chain. 508 cm.add(block, receipts) 509 parent = block 510 } 511 return cm.chain, cm.receipts, proofs, keyvals 512 } 513 514 func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) { 515 db := rawdb.NewMemoryDatabase() 516 cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme) 517 cacheConfig.SnapshotLimit = 0 518 triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true)) 519 defer triedb.Close() 520 genesisBlock, err := genesis.Commit(db, triedb) 521 if err != nil { 522 panic(err) 523 } 524 blocks, receipts, proofs, keyvals := GenerateVerkleChain(genesis.Config, genesisBlock, engine, db, triedb, n, gen) 525 return db, blocks, receipts, proofs, keyvals 526 } 527 528 func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header { 529 time := parent.Time() + 10 // block time is fixed at 10 seconds 530 header := &types.Header{ 531 Root: state.IntermediateRoot(cm.config.IsEIP158(parent.Number())), 532 ParentHash: parent.Hash(), 533 Coinbase: parent.Coinbase(), 534 Difficulty: engine.CalcDifficulty(cm, time, parent.Header()), 535 GasLimit: parent.GasLimit(), 536 Number: new(big.Int).Add(parent.Number(), common.Big1), 537 Time: time, 538 } 539 540 if cm.config.IsLondon(header.Number) { 541 header.BaseFee = eip1559.CalcBaseFee(cm.config, parent.Header()) 542 if !cm.config.IsLondon(parent.Number()) { 543 parentGasLimit := parent.GasLimit() * cm.config.ElasticityMultiplier() 544 header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit) 545 } 546 } 547 if cm.config.IsCancun(header.Number, header.Time) { 548 var ( 549 parentExcessBlobGas uint64 550 parentBlobGasUsed uint64 551 ) 552 if parent.ExcessBlobGas() != nil { 553 parentExcessBlobGas = *parent.ExcessBlobGas() 554 parentBlobGasUsed = *parent.BlobGasUsed() 555 } 556 excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed) 557 header.ExcessBlobGas = &excessBlobGas 558 header.BlobGasUsed = new(uint64) 559 header.ParentBeaconRoot = new(common.Hash) 560 } 561 return header 562 } 563 564 // makeHeaderChain creates a deterministic chain of headers rooted at parent. 565 func makeHeaderChain(chainConfig *params.ChainConfig, parent *types.Header, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Header { 566 blocks := makeBlockChain(chainConfig, types.NewBlockWithHeader(parent), n, engine, db, seed) 567 headers := make([]*types.Header, len(blocks)) 568 for i, block := range blocks { 569 headers[i] = block.Header() 570 } 571 return headers 572 } 573 574 // makeHeaderChainWithGenesis creates a deterministic chain of headers from genesis. 575 func makeHeaderChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine, seed int) (ethdb.Database, []*types.Header) { 576 db, blocks := makeBlockChainWithGenesis(genesis, n, engine, seed) 577 headers := make([]*types.Header, len(blocks)) 578 for i, block := range blocks { 579 headers[i] = block.Header() 580 } 581 return db, headers 582 } 583 584 // makeBlockChain creates a deterministic chain of blocks rooted at parent. 585 func makeBlockChain(chainConfig *params.ChainConfig, parent *types.Block, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Block { 586 blocks, _ := GenerateChain(chainConfig, parent, engine, db, n, func(i int, b *BlockGen) { 587 b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) 588 }) 589 return blocks 590 } 591 592 // makeBlockChainWithGenesis creates a deterministic chain of blocks from genesis 593 func makeBlockChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine, seed int) (ethdb.Database, []*types.Block) { 594 db, blocks, _ := GenerateChainWithGenesis(genesis, engine, n, func(i int, b *BlockGen) { 595 b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) 596 }) 597 return db, blocks 598 } 599 600 // chainMaker contains the state of chain generation. 601 type chainMaker struct { 602 bottom *types.Block 603 engine consensus.Engine 604 config *params.ChainConfig 605 chain []*types.Block 606 chainByHash map[common.Hash]*types.Block 607 receipts []types.Receipts 608 } 609 610 func newChainMaker(bottom *types.Block, config *params.ChainConfig, engine consensus.Engine) *chainMaker { 611 return &chainMaker{ 612 bottom: bottom, 613 config: config, 614 engine: engine, 615 chainByHash: make(map[common.Hash]*types.Block), 616 } 617 } 618 619 func (cm *chainMaker) add(b *types.Block, r []*types.Receipt) { 620 cm.chain = append(cm.chain, b) 621 cm.chainByHash[b.Hash()] = b 622 cm.receipts = append(cm.receipts, r) 623 } 624 625 func (cm *chainMaker) blockByNumber(number uint64) *types.Block { 626 if number == cm.bottom.NumberU64() { 627 return cm.bottom 628 } 629 cur := cm.CurrentHeader().Number.Uint64() 630 lowest := cm.bottom.NumberU64() + 1 631 if number < lowest || number > cur { 632 return nil 633 } 634 return cm.chain[number-lowest] 635 } 636 637 // ChainReader/ChainContext implementation 638 639 // Config returns the chain configuration (for consensus.ChainReader). 640 func (cm *chainMaker) Config() *params.ChainConfig { 641 return cm.config 642 } 643 644 // Engine returns the consensus engine (for ChainContext). 645 func (cm *chainMaker) Engine() consensus.Engine { 646 return cm.engine 647 } 648 649 func (cm *chainMaker) CurrentHeader() *types.Header { 650 if len(cm.chain) == 0 { 651 return cm.bottom.Header() 652 } 653 return cm.chain[len(cm.chain)-1].Header() 654 } 655 656 func (cm *chainMaker) GetHeaderByNumber(number uint64) *types.Header { 657 b := cm.blockByNumber(number) 658 if b == nil { 659 return nil 660 } 661 return b.Header() 662 } 663 664 func (cm *chainMaker) GetHeaderByHash(hash common.Hash) *types.Header { 665 b := cm.chainByHash[hash] 666 if b == nil { 667 return nil 668 } 669 return b.Header() 670 } 671 672 func (cm *chainMaker) GetHeader(hash common.Hash, number uint64) *types.Header { 673 return cm.GetHeaderByNumber(number) 674 } 675 676 func (cm *chainMaker) GetBlock(hash common.Hash, number uint64) *types.Block { 677 return cm.blockByNumber(number) 678 } 679 680 func (cm *chainMaker) GetTd(hash common.Hash, number uint64) *big.Int { 681 return nil // not supported 682 }