| 41 | } |
| 42 | |
| 43 | std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params) |
| 44 | { |
| 45 | std::vector<std::shared_ptr<CBlock>> ret{total_height}; |
| 46 | auto time{params.GenesisBlock().nTime}; |
| 47 | // NOTE: here `height` does not correspond to the block height but the block height - 1. |
| 48 | for (size_t height{0}; height < total_height; ++height) { |
| 49 | CBlock& block{*(ret.at(height) = std::make_shared<CBlock>())}; |
| 50 | |
| 51 | CMutableTransaction coinbase_tx; |
| 52 | coinbase_tx.nLockTime = static_cast<uint32_t>(height); |
| 53 | coinbase_tx.vin.resize(1); |
| 54 | coinbase_tx.vin[0].prevout.SetNull(); |
| 55 | coinbase_tx.vin[0].nSequence = CTxIn::MAX_SEQUENCE_NONFINAL; // Make sure timelock is enforced. |
| 56 | coinbase_tx.vout.resize(1); |
| 57 | coinbase_tx.vout[0].scriptPubKey = P2WSH_OP_TRUE; |
| 58 | coinbase_tx.vout[0].nValue = GetBlockSubsidy(height + 1, params.GetConsensus()); |
| 59 | // Always include OP_0 as a dummy extraNonce. |
| 60 | coinbase_tx.vin[0].scriptSig = CScript() << (height + 1) << OP_0; |
| 61 | block.vtx = {MakeTransactionRef(std::move(coinbase_tx))}; |
| 62 | |
| 63 | block.nVersion = VERSIONBITS_LAST_OLD_BLOCK_VERSION; |
| 64 | block.hashPrevBlock = (height >= 1 ? *ret.at(height - 1) : params.GenesisBlock()).GetHash(); |
| 65 | block.hashMerkleRoot = BlockMerkleRoot(block); |
| 66 | block.nTime = ++time; |
| 67 | block.nBits = params.GenesisBlock().nBits; |
| 68 | block.nNonce = 0; |
| 69 | |
| 70 | while (!CheckProofOfWork(block.GetHash(), block.nBits, params.GetConsensus())) { |
| 71 | ++block.nNonce; |
| 72 | assert(block.nNonce); |
| 73 | } |
| 74 | } |
| 75 | return ret; |
| 76 | } |
| 77 | |
| 78 | COutPoint MineBlock(const NodeContext& node, const node::BlockCreateOptions& assembler_options) |
| 79 | { |
no test coverage detected