mining.cpp
1 // Copyright (c) 2019-present 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 #include <node/context.h> 12 #include <pow.h> 13 #include <primitives/transaction.h> 14 #include <test/util/script.h> 15 #include <util/check.h> 16 #include <validation.h> 17 #include <validationinterface.h> 18 #include <versionbits.h> 19 20 #include <algorithm> 21 #include <memory> 22 23 using node::BlockAssembler; 24 using node::NodeContext; 25 26 COutPoint generatetoaddress(const NodeContext& node, const std::string& address) 27 { 28 const auto dest = DecodeDestination(address); 29 assert(IsValidDestination(dest)); 30 BlockAssembler::Options assembler_options; 31 assembler_options.coinbase_output_script = GetScriptForDestination(dest); 32 assembler_options.include_dummy_extranonce = true; 33 34 return MineBlock(node, assembler_options); 35 } 36 37 std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params) 38 { 39 std::vector<std::shared_ptr<CBlock>> ret{total_height}; 40 auto time{params.GenesisBlock().nTime}; 41 // NOTE: here `height` does not correspond to the block height but the block height - 1. 42 for (size_t height{0}; height < total_height; ++height) { 43 CBlock& block{*(ret.at(height) = std::make_shared<CBlock>())}; 44 45 CMutableTransaction coinbase_tx; 46 coinbase_tx.nLockTime = static_cast<uint32_t>(height); 47 coinbase_tx.vin.resize(1); 48 coinbase_tx.vin[0].prevout.SetNull(); 49 coinbase_tx.vin[0].nSequence = CTxIn::MAX_SEQUENCE_NONFINAL; // Make sure timelock is enforced. 50 coinbase_tx.vout.resize(1); 51 coinbase_tx.vout[0].scriptPubKey = P2WSH_OP_TRUE; 52 coinbase_tx.vout[0].nValue = GetBlockSubsidy(height + 1, params.GetConsensus()); 53 // Always include OP_0 as a dummy extraNonce. 54 coinbase_tx.vin[0].scriptSig = CScript() << (height + 1) << OP_0; 55 block.vtx = {MakeTransactionRef(std::move(coinbase_tx))}; 56 57 block.nVersion = VERSIONBITS_LAST_OLD_BLOCK_VERSION; 58 block.hashPrevBlock = (height >= 1 ? *ret.at(height - 1) : params.GenesisBlock()).GetHash(); 59 block.hashMerkleRoot = BlockMerkleRoot(block); 60 block.nTime = ++time; 61 block.nBits = params.GenesisBlock().nBits; 62 block.nNonce = 0; 63 64 while (!CheckProofOfWork(block.GetHash(), block.nBits, params.GetConsensus())) { 65 ++block.nNonce; 66 assert(block.nNonce); 67 } 68 } 69 return ret; 70 } 71 72 COutPoint MineBlock(const NodeContext& node, const node::BlockAssembler::Options& assembler_options) 73 { 74 auto block = PrepareBlock(node, assembler_options); 75 auto valid = MineBlock(node, block); 76 assert(!valid.IsNull()); 77 return valid; 78 } 79 80 struct BlockValidationStateCatcher : public CValidationInterface { 81 const uint256 m_hash; 82 std::optional<BlockValidationState> m_state; 83 84 BlockValidationStateCatcher(const uint256& hash) 85 : m_hash{hash}, 86 m_state{} {} 87 88 protected: 89 void BlockChecked(const std::shared_ptr<const CBlock>& block, const BlockValidationState& state) override 90 { 91 if (block->GetHash() != m_hash) return; 92 m_state = state; 93 } 94 }; 95 96 COutPoint MineBlock(const NodeContext& node, std::shared_ptr<CBlock>& block) 97 { 98 while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { 99 ++block->nNonce; 100 assert(block->nNonce); 101 } 102 103 return ProcessBlock(node, block); 104 } 105 106 COutPoint ProcessBlock(const NodeContext& node, const std::shared_ptr<CBlock>& block) 107 { 108 auto& chainman{*Assert(node.chainman)}; 109 const auto old_height = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight()); 110 bool new_block; 111 BlockValidationStateCatcher bvsc{block->GetHash()}; 112 node.validation_signals->RegisterValidationInterface(&bvsc); 113 const bool processed{chainman.ProcessNewBlock(block, true, true, &new_block)}; 114 const bool duplicate{!new_block && processed}; 115 assert(!duplicate); 116 node.validation_signals->UnregisterValidationInterface(&bvsc); 117 node.validation_signals->SyncWithValidationInterfaceQueue(); 118 const bool was_valid{bvsc.m_state && bvsc.m_state->IsValid()}; 119 assert(old_height + was_valid == WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight())); 120 121 if (was_valid) return {block->vtx[0]->GetHash(), 0}; 122 return {}; 123 } 124 125 std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, 126 const BlockAssembler::Options& assembler_options) 127 { 128 auto block = std::make_shared<CBlock>( 129 BlockAssembler{Assert(node.chainman)->ActiveChainstate(), Assert(node.mempool.get()), assembler_options} 130 .CreateNewBlock() 131 ->block); 132 133 LOCK(cs_main); 134 block->nTime = Assert(node.chainman)->ActiveChain().Tip()->GetMedianTimePast() + 1; 135 block->hashMerkleRoot = BlockMerkleRoot(*block); 136 137 return block; 138 } 139 std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) 140 { 141 BlockAssembler::Options assembler_options; 142 assembler_options.coinbase_output_script = coinbase_scriptPubKey; 143 assembler_options.include_dummy_extranonce = true; 144 ApplyArgsManOptions(*node.args, assembler_options); 145 return PrepareBlock(node, assembler_options); 146 }