Line data Source code
1 : // Copyright (c) 2019-2021 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 <evo/evodb.h> 11 : #include <key_io.h> 12 : #include <node/context.h> 13 : #include <node/miner.h> 14 : #include <pow.h> 15 : #include <primitives/transaction.h> 16 : #include <script/standard.h> 17 : #include <test/util/script.h> 18 : #include <util/check.h> 19 : #include <validation.h> 20 : #include <validationinterface.h> 21 : #include <versionbits.h> 22 : 23 : using node::BlockAssembler; 24 : using node::NodeContext; 25 : 26 0 : COutPoint generatetoaddress(const NodeContext& node, const std::string& address) 27 : { 28 0 : const auto dest = DecodeDestination(address); 29 0 : assert(IsValidDestination(dest)); 30 0 : const auto coinbase_script = GetScriptForDestination(dest); 31 : 32 0 : return MineBlock(node, coinbase_script); 33 0 : } 34 : 35 0 : std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params) 36 : { 37 0 : std::vector<std::shared_ptr<CBlock>> ret{total_height}; 38 0 : auto time{params.GenesisBlock().nTime}; 39 0 : for (size_t height{0}; height < total_height; ++height) { 40 0 : CBlock& block{*(ret.at(height) = std::make_shared<CBlock>())}; 41 : 42 0 : CMutableTransaction coinbase_tx; 43 0 : coinbase_tx.vin.resize(1); 44 0 : coinbase_tx.vin[0].prevout.SetNull(); 45 0 : coinbase_tx.vout.resize(1); 46 0 : coinbase_tx.vout[0].scriptPubKey = P2SH_OP_TRUE; 47 0 : coinbase_tx.vout[0].nValue = GetBlockSubsidyInner(params.GenesisBlock().nBits, height, params.GetConsensus(), false); 48 0 : coinbase_tx.vin[0].scriptSig = CScript() << (height + 1) << OP_0; 49 0 : block.vtx = {MakeTransactionRef(std::move(coinbase_tx))}; 50 : 51 0 : block.nVersion = VERSIONBITS_LAST_OLD_BLOCK_VERSION; 52 0 : block.hashPrevBlock = (height >= 1 ? *ret.at(height - 1) : params.GenesisBlock()).GetHash(); 53 0 : block.hashMerkleRoot = BlockMerkleRoot(block); 54 0 : block.nTime = ++time; 55 0 : block.nBits = params.GenesisBlock().nBits; 56 0 : block.nNonce = 0; 57 : 58 0 : while (!CheckProofOfWork(block.GetHash(), block.nBits, params.GetConsensus())) { 59 0 : ++block.nNonce; 60 0 : assert(block.nNonce); 61 : } 62 0 : } 63 0 : return ret; 64 0 : } 65 : 66 0 : COutPoint MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) 67 : { 68 0 : auto block = PrepareBlock(node, coinbase_scriptPubKey); 69 : 70 0 : while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { 71 0 : ++block->nNonce; 72 0 : assert(block->nNonce); 73 : } 74 : 75 0 : bool processed{Assert(node.chainman)->ProcessNewBlock(block, true, nullptr)}; 76 0 : assert(processed); 77 : 78 0 : return {block->vtx[0]->GetHash(), 0}; 79 0 : } 80 : 81 0 : std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) 82 : { 83 0 : assert(node.mempool); 84 0 : auto block = std::make_shared<CBlock>( 85 0 : BlockAssembler{node.chainman->ActiveChainstate(), node, Assert(node.mempool.get()), Params()} 86 0 : .CreateNewBlock(coinbase_scriptPubKey) 87 0 : ->block); 88 : 89 0 : block->nTime = Assert(node.chainman)->ActiveChain().Tip()->GetMedianTimePast() + 1; 90 0 : block->hashMerkleRoot = BlockMerkleRoot(*block); 91 : 92 0 : return block; 93 0 : } 94 : 95 : struct BlockValidationStateCatcher : public CValidationInterface { 96 : const uint256 m_hash; 97 : std::optional<BlockValidationState> m_state; 98 : 99 0 : BlockValidationStateCatcher(const uint256& hash) 100 0 : : m_hash{hash}, 101 0 : m_state{} {} 102 : 103 : protected: 104 0 : void BlockChecked(const CBlock& block, const BlockValidationState& state) override 105 : { 106 0 : if (block.GetHash() != m_hash) return; 107 0 : m_state = state; 108 0 : } 109 : }; 110 : 111 0 : COutPoint MineBlock(const NodeContext& node, std::shared_ptr<CBlock>& block) 112 : { 113 0 : while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { 114 0 : ++block->nNonce; 115 0 : assert(block->nNonce); 116 : } 117 : 118 0 : auto& chainman{*Assert(node.chainman)}; 119 0 : const auto old_height = WITH_LOCK(::cs_main, return chainman.ActiveHeight()); 120 : bool new_block; 121 0 : BlockValidationStateCatcher bvsc{block->GetHash()}; 122 0 : RegisterValidationInterface(&bvsc); 123 0 : const bool processed{chainman.ProcessNewBlock(block, true, &new_block)}; 124 0 : const bool duplicate{!new_block && processed}; 125 0 : assert(!duplicate); 126 0 : UnregisterValidationInterface(&bvsc); 127 0 : SyncWithValidationInterfaceQueue(); 128 0 : const bool was_valid{bvsc.m_state && bvsc.m_state->IsValid()}; 129 0 : assert(old_height + was_valid == WITH_LOCK(::cs_main, return chainman.ActiveHeight())); 130 : 131 0 : if (was_valid) return {block->vtx[0]->GetHash(), 0}; 132 0 : return {}; 133 0 : }