Branch data Line data Source code
1 : : // Copyright (c) 2019-2022 The Bitcoin Core developers 2 : : // Distributed under the MIT software license, see the accompanying 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : : 5 : : #include <test/util/mining.h> 6 : : 7 : : #include <chainparams.h> 8 : : #include <consensus/merkle.h> 9 : : #include <consensus/validation.h> 10 : : #include <key_io.h> 11 [ + - ]: 173 : #include <node/context.h> 12 [ + - ]: 173 : #include <pow.h> 13 : 173 : #include <primitives/transaction.h> 14 [ + - ]: 173 : #include <test/util/script.h> 15 [ + - + - : 173 : #include <util/check.h> + - ] 16 : : #include <validation.h> 17 [ + - ]: 173 : #include <validationinterface.h> 18 [ + - ]: 173 : #include <versionbits.h> 19 : : 20 : : using node::BlockAssembler; 21 : : using node::NodeContext; 22 : : 23 : 0 : COutPoint generatetoaddress(const NodeContext& node, const std::string& address) 24 : : { 25 : 0 : const auto dest = DecodeDestination(address); 26 [ # # # # ]: 0 : assert(IsValidDestination(dest)); 27 [ # # ]: 0 : const auto coinbase_script = GetScriptForDestination(dest); 28 : : 29 [ # # ]: 0 : return MineBlock(node, coinbase_script); 30 : 0 : } 31 : : 32 : 1 : std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params) 33 : : { 34 [ + - ]: 1 : std::vector<std::shared_ptr<CBlock>> ret{total_height}; 35 [ + - ]: 1 : auto time{params.GenesisBlock().nTime}; 36 [ + + ]: 201 : for (size_t height{0}; height < total_height; ++height) { 37 [ + - + - ]: 200 : CBlock& block{*(ret.at(height) = std::make_shared<CBlock>())}; 38 : : 39 [ + - ]: 200 : CMutableTransaction coinbase_tx; 40 [ + - ]: 200 : coinbase_tx.vin.resize(1); 41 [ + - ]: 200 : coinbase_tx.vin[0].prevout.SetNull(); 42 [ + - ]: 200 : coinbase_tx.vout.resize(1); 43 [ + - ]: 200 : coinbase_tx.vout[0].scriptPubKey = P2WSH_OP_TRUE; 44 [ + - + - ]: 200 : coinbase_tx.vout[0].nValue = GetBlockSubsidy(height + 1, params.GetConsensus()); 45 [ + - + - : 200 : coinbase_tx.vin[0].scriptSig = CScript() << (height + 1) << OP_0; + - + - ] 46 [ + - + - ]: 200 : block.vtx = {MakeTransactionRef(std::move(coinbase_tx))}; 47 : : 48 : 200 : block.nVersion = VERSIONBITS_LAST_OLD_BLOCK_VERSION; 49 [ + + + - : 200 : block.hashPrevBlock = (height >= 1 ? *ret.at(height - 1) : params.GenesisBlock()).GetHash(); + - + - ] 50 [ + - ]: 200 : block.hashMerkleRoot = BlockMerkleRoot(block); 51 : 200 : block.nTime = ++time; 52 [ + - ]: 200 : block.nBits = params.GenesisBlock().nBits; 53 : 200 : block.nNonce = 0; 54 : : 55 [ + - + - : 415 : while (!CheckProofOfWork(block.GetHash(), block.nBits, params.GetConsensus())) { + - + + ] 56 : 215 : ++block.nNonce; 57 [ + - ]: 215 : assert(block.nNonce); 58 : : } 59 : 200 : } 60 : 1 : return ret; 61 [ + - ]: 1 : } 62 : : 63 : 1000 : COutPoint MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) 64 : : { 65 : 1000 : auto block = PrepareBlock(node, coinbase_scriptPubKey); 66 [ + - ]: 1000 : auto valid = MineBlock(node, block); 67 [ + - + - ]: 1000 : assert(!valid.IsNull()); 68 : : return valid; 69 : 1000 : } 70 : : 71 : : struct BlockValidationStateCatcher : public CValidationInterface { 72 : : const uint256 m_hash; 73 : : std::optional<BlockValidationState> m_state; 74 : 173 : 75 : 50094 : BlockValidationStateCatcher(const uint256& hash) 76 : 50094 : : m_hash{hash}, 77 : 100188 : m_state{} {} 78 : : 79 : : protected: 80 : 50094 : void BlockChecked(const CBlock& block, const BlockValidationState& state) override 81 : : { 82 [ - + ]: 50094 : if (block.GetHash() != m_hash) return; 83 : 50094 : m_state = state; 84 : 50094 : } 85 : : }; 86 : : 87 : 50094 : COutPoint MineBlock(const NodeContext& node, std::shared_ptr<CBlock>& block) 88 : : { 89 [ + + ]: 100479 : while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { 90 : 50385 : ++block->nNonce; 91 [ + - ]: 50385 : assert(block->nNonce); 92 : : } 93 : : 94 : 50094 : auto& chainman{*Assert(node.chainman)}; 95 [ + - ]: 100188 : const auto old_height = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight()); 96 : : bool new_block; 97 : 50094 : BlockValidationStateCatcher bvsc{block->GetHash()}; 98 [ + - ]: 50094 : RegisterValidationInterface(&bvsc); 99 [ + - ]: 50094 : const bool processed{chainman.ProcessNewBlock(block, true, true, &new_block)}; 100 [ + + ]: 50094 : const bool duplicate{!new_block && processed}; 101 [ + - ]: 50094 : assert(!duplicate); 102 [ + - ]: 50094 : UnregisterValidationInterface(&bvsc); 103 [ + - ]: 50094 : SyncWithValidationInterfaceQueue(); 104 [ + - + - : 100188 : const bool was_valid{bvsc.m_state && bvsc.m_state->IsValid()}; + - ] 105 [ + - + - : 100188 : assert(old_height + was_valid == WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight())); + - - + + - ] 106 : : 107 [ + + + - : 50094 : if (was_valid) return {block->vtx[0]->GetHash(), 0}; + - ] 108 [ + - ]: 9547 : return {}; 109 : 50094 : } 110 : : 111 : 51318 : std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey, 112 : : const BlockAssembler::Options& assembler_options) 113 : : { 114 [ - + ]: 51318 : auto block = std::make_shared<CBlock>( 115 : 51318 : BlockAssembler{Assert(node.chainman)->ActiveChainstate(), Assert(node.mempool.get()), assembler_options} 116 [ + - ]: 51318 : .CreateNewBlock(coinbase_scriptPubKey) 117 : 51318 : ->block); 118 : : 119 [ + - + - ]: 51318 : LOCK(cs_main); 120 [ + - + - : 51318 : block->nTime = Assert(node.chainman)->ActiveChain().Tip()->GetMedianTimePast() + 1; + - + - ] 121 [ + - ]: 51318 : block->hashMerkleRoot = BlockMerkleRoot(*block); 122 : : 123 : 51318 : return block; 124 [ + - ]: 51318 : } 125 : 51318 : std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) 126 : : { 127 : 51318 : BlockAssembler::Options assembler_options; 128 : 51318 : ApplyArgsManOptions(*node.args, assembler_options); 129 : 51318 : return PrepareBlock(node, coinbase_scriptPubKey, assembler_options); 130 : : }