diff options
Diffstat (limited to 'src/test/util/mining.cpp')
-rw-r--r-- | src/test/util/mining.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp new file mode 100644 index 0000000000..5ed8598e8e --- /dev/null +++ b/src/test/util/mining.cpp @@ -0,0 +1,89 @@ +// Copyright (c) 2019-2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/util/mining.h> + +#include <chainparams.h> +#include <consensus/merkle.h> +#include <key_io.h> +#include <node/context.h> +#include <node/miner.h> +#include <pow.h> +#include <script/standard.h> +#include <test/util/script.h> +#include <util/check.h> +#include <validation.h> +#include <versionbits.h> + +using node::BlockAssembler; +using node::NodeContext; + +CTxIn generatetoaddress(const NodeContext& node, const std::string& address) +{ + const auto dest = DecodeDestination(address); + assert(IsValidDestination(dest)); + const auto coinbase_script = GetScriptForDestination(dest); + + return MineBlock(node, coinbase_script); +} + +std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params) +{ + std::vector<std::shared_ptr<CBlock>> ret{total_height}; + auto time{params.GenesisBlock().nTime}; + for (size_t height{0}; height < total_height; ++height) { + CBlock& block{*(ret.at(height) = std::make_shared<CBlock>())}; + + CMutableTransaction coinbase_tx; + coinbase_tx.vin.resize(1); + coinbase_tx.vin[0].prevout.SetNull(); + coinbase_tx.vout.resize(1); + coinbase_tx.vout[0].scriptPubKey = P2WSH_OP_TRUE; + coinbase_tx.vout[0].nValue = GetBlockSubsidy(height + 1, params.GetConsensus()); + coinbase_tx.vin[0].scriptSig = CScript() << (height + 1) << OP_0; + block.vtx = {MakeTransactionRef(std::move(coinbase_tx))}; + + block.nVersion = VERSIONBITS_LAST_OLD_BLOCK_VERSION; + block.hashPrevBlock = (height >= 1 ? *ret.at(height - 1) : params.GenesisBlock()).GetHash(); + block.hashMerkleRoot = BlockMerkleRoot(block); + block.nTime = ++time; + block.nBits = params.GenesisBlock().nBits; + block.nNonce = 0; + + while (!CheckProofOfWork(block.GetHash(), block.nBits, params.GetConsensus())) { + ++block.nNonce; + assert(block.nNonce); + } + } + return ret; +} + +CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) +{ + auto block = PrepareBlock(node, coinbase_scriptPubKey); + + while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { + ++block->nNonce; + assert(block->nNonce); + } + + bool processed{Assert(node.chainman)->ProcessNewBlock(Params(), block, true, nullptr)}; + assert(processed); + + return CTxIn{block->vtx[0]->GetHash(), 0}; +} + +std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) +{ + auto block = std::make_shared<CBlock>( + BlockAssembler{Assert(node.chainman)->ActiveChainstate(), *Assert(node.mempool), Params()} + .CreateNewBlock(coinbase_scriptPubKey) + ->block); + + LOCK(cs_main); + block->nTime = Assert(node.chainman)->ActiveChain().Tip()->GetMedianTimePast() + 1; + block->hashMerkleRoot = BlockMerkleRoot(*block); + + return block; +} |