/root/bitcoin/src/test/util/mining.cpp
Line | Count | Source |
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 <addresstype.h> |
8 | | #include <chain.h> |
9 | | #include <chainparams.h> |
10 | | #include <consensus/merkle.h> |
11 | | #include <consensus/validation.h> |
12 | | #include <interfaces/mining.h> |
13 | | #include <key_io.h> |
14 | | #include <node/context.h> |
15 | | #include <pow.h> |
16 | | #include <primitives/block.h> |
17 | | #include <primitives/transaction.h> |
18 | | #include <script/script.h> |
19 | | #include <sync.h> |
20 | | #include <test/util/script.h> |
21 | | #include <uint256.h> |
22 | | #include <util/check.h> |
23 | | #include <validation.h> |
24 | | #include <validationinterface.h> |
25 | | #include <versionbits.h> |
26 | | |
27 | | #include <cstdint> |
28 | | #include <memory> |
29 | | #include <optional> |
30 | | #include <utility> |
31 | | |
32 | | using node::NodeContext; |
33 | | |
34 | | COutPoint generatetoaddress(const NodeContext& node, const std::string& address) |
35 | 0 | { |
36 | 0 | const auto dest = DecodeDestination(address); |
37 | 0 | assert(IsValidDestination(dest)); Branch (37:5): [True: 0, False: 0]
|
38 | 0 | return MineBlock(node, { |
39 | 0 | .coinbase_output_script = GetScriptForDestination(dest), |
40 | 0 | }); |
41 | 0 | } |
42 | | |
43 | | std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params) |
44 | 0 | { |
45 | 0 | std::vector<std::shared_ptr<CBlock>> ret{total_height}; |
46 | 0 | auto time{params.GenesisBlock().nTime}; |
47 | | // NOTE: here `height` does not correspond to the block height but the block height - 1. |
48 | 0 | for (size_t height{0}; height < total_height; ++height) { Branch (48:28): [True: 0, False: 0]
|
49 | 0 | CBlock& block{*(ret.at(height) = std::make_shared<CBlock>())}; |
50 | |
|
51 | 0 | CMutableTransaction coinbase_tx; |
52 | 0 | coinbase_tx.nLockTime = static_cast<uint32_t>(height); |
53 | 0 | coinbase_tx.vin.resize(1); |
54 | 0 | coinbase_tx.vin[0].prevout.SetNull(); |
55 | 0 | coinbase_tx.vin[0].nSequence = CTxIn::MAX_SEQUENCE_NONFINAL; // Make sure timelock is enforced. |
56 | 0 | coinbase_tx.vout.resize(1); |
57 | 0 | coinbase_tx.vout[0].scriptPubKey = P2WSH_OP_TRUE; |
58 | 0 | coinbase_tx.vout[0].nValue = GetBlockSubsidy(height + 1, params.GetConsensus()); |
59 | | // Always include OP_0 as a dummy extraNonce. |
60 | 0 | coinbase_tx.vin[0].scriptSig = CScript() << (height + 1) << OP_0; |
61 | 0 | block.vtx = {MakeTransactionRef(std::move(coinbase_tx))}; |
62 | |
|
63 | 0 | block.nVersion = VERSIONBITS_LAST_OLD_BLOCK_VERSION; |
64 | 0 | block.hashPrevBlock = (height >= 1 ? *ret.at(height - 1) : params.GenesisBlock()).GetHash(); Branch (64:32): [True: 0, False: 0]
|
65 | 0 | block.hashMerkleRoot = BlockMerkleRoot(block); |
66 | 0 | block.nTime = ++time; |
67 | 0 | block.nBits = params.GenesisBlock().nBits; |
68 | 0 | block.nNonce = 0; |
69 | |
|
70 | 0 | while (!CheckProofOfWork(block.GetHash(), block.nBits, params.GetConsensus())) { Branch (70:16): [True: 0, False: 0]
|
71 | 0 | ++block.nNonce; |
72 | 0 | assert(block.nNonce); Branch (72:13): [True: 0, False: 0]
|
73 | 0 | } |
74 | 0 | } |
75 | 0 | return ret; |
76 | 0 | } |
77 | | |
78 | | bool BuildChain(const NodeContext& node, const CBlockIndex* pindex, |
79 | | const CScript& coinbase_script_pub_key, |
80 | | size_t length, |
81 | | std::vector<std::shared_ptr<CBlock>>& chain) |
82 | 0 | { |
83 | 0 | auto mining{interfaces::MakeMining(node)}; |
84 | 0 | const Consensus::Params& consensus{Assert(node.chainman)->GetConsensus()}; |
85 | |
|
86 | 0 | chain.resize(length); |
87 | 0 | for (auto& chain_block : chain) { Branch (87:28): [True: 0, False: 0]
|
88 | 0 | auto block_template{mining->createNewBlock({ |
89 | 0 | .use_mempool = false, |
90 | 0 | .coinbase_output_script = coinbase_script_pub_key, |
91 | 0 | }, /*cooldown=*/false)}; |
92 | 0 | CBlock block{Assert(block_template)->getBlock()}; |
93 | | |
94 | | // The template is built on the active tip, so repoint it at pindex and |
95 | | // redo the fields that depend on the predecessor. |
96 | 0 | block.hashPrevBlock = pindex->GetBlockHash(); |
97 | 0 | block.nTime = pindex->nTime + 1; |
98 | 0 | { |
99 | 0 | CMutableTransaction tx_coinbase{*block.vtx.at(0)}; |
100 | 0 | tx_coinbase.nLockTime = static_cast<uint32_t>(pindex->nHeight); |
101 | 0 | tx_coinbase.vin.at(0).scriptSig = CScript{} << pindex->nHeight + 1; |
102 | 0 | block.vtx.at(0) = MakeTransactionRef(std::move(tx_coinbase)); |
103 | 0 | block.hashMerkleRoot = BlockMerkleRoot(block); |
104 | 0 | } |
105 | |
|
106 | 0 | while (!CheckProofOfWork(block.GetHash(), block.nBits, consensus)) ++block.nNonce; Branch (106:16): [True: 0, False: 0]
|
107 | |
|
108 | 0 | chain_block = std::make_shared<CBlock>(std::move(block)); |
109 | |
|
110 | 0 | BlockValidationState state; |
111 | 0 | if (!Assert(node.chainman)->ProcessNewBlockHeaders({{*chain_block}}, true, state, &pindex)) { Branch (111:13): [True: 0, False: 0]
|
112 | 0 | return false; |
113 | 0 | } |
114 | 0 | } |
115 | | |
116 | 0 | return true; |
117 | 0 | } |
118 | | |
119 | | COutPoint MineBlock(const NodeContext& node, const node::BlockCreateOptions& assembler_options) |
120 | 334k | { |
121 | 334k | auto block = PrepareBlock(node, assembler_options); |
122 | 334k | auto valid = MineBlock(node, block); |
123 | 334k | assert(!valid.IsNull()); Branch (123:5): [True: 334k, False: 0]
|
124 | 334k | return valid; |
125 | 334k | } |
126 | | |
127 | | struct BlockValidationStateCatcher : public CValidationInterface { |
128 | | const uint256 m_hash; |
129 | | std::optional<BlockValidationState> m_state; |
130 | | |
131 | | BlockValidationStateCatcher(const uint256& hash) |
132 | 519k | : m_hash{hash}, |
133 | 519k | m_state{} {} |
134 | | |
135 | | protected: |
136 | | void BlockChecked(const std::shared_ptr<const CBlock>& block, const BlockValidationState& state) override |
137 | 519k | { |
138 | 519k | if (block->GetHash() != m_hash) return; Branch (138:13): [True: 0, False: 519k]
|
139 | 519k | m_state = state; |
140 | 519k | } |
141 | | }; |
142 | | |
143 | | COutPoint MineBlock(const NodeContext& node, std::shared_ptr<CBlock>& block) |
144 | 519k | { |
145 | 977k | while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { Branch (145:12): [True: 457k, False: 519k]
|
146 | 457k | ++block->nNonce; |
147 | 457k | assert(block->nNonce); Branch (147:9): [True: 457k, False: 0]
|
148 | 457k | } |
149 | | |
150 | 519k | return ProcessBlock(node, block); |
151 | 519k | } |
152 | | |
153 | | COutPoint ProcessBlock(const NodeContext& node, const std::shared_ptr<CBlock>& block) |
154 | 519k | { |
155 | 519k | auto& chainman{*Assert(node.chainman)}; |
156 | 519k | const auto old_height = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight()); |
157 | 519k | bool new_block; |
158 | 519k | BlockValidationStateCatcher bvsc{block->GetHash()}; |
159 | 519k | node.validation_signals->RegisterValidationInterface(&bvsc); |
160 | 519k | const bool processed{chainman.ProcessNewBlock(block, true, true, &new_block)}; |
161 | 519k | const bool duplicate{!new_block && processed}; Branch (161:26): [True: 32.2k, False: 487k]
Branch (161:40): [True: 0, False: 32.2k]
|
162 | 519k | assert(!duplicate); Branch (162:5): [True: 519k, False: 0]
|
163 | 519k | node.validation_signals->UnregisterValidationInterface(&bvsc); |
164 | 519k | node.validation_signals->SyncWithValidationInterfaceQueue(); |
165 | 519k | const bool was_valid{bvsc.m_state && bvsc.m_state->IsValid()}; Branch (165:26): [True: 519k, False: 0]
Branch (165:42): [True: 474k, False: 45.6k]
|
166 | 519k | assert(old_height + was_valid == WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight())); Branch (166:5): [True: 519k, False: 0]
|
167 | | |
168 | 519k | if (was_valid) return {block->vtx[0]->GetHash(), 0}; Branch (168:9): [True: 474k, False: 45.6k]
|
169 | 45.6k | return {}; |
170 | 519k | } |
171 | | |
172 | | std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, |
173 | | const node::BlockCreateOptions& assembler_options) |
174 | 523k | { |
175 | 523k | auto mining = interfaces::MakeMining(node); |
176 | 523k | auto block_template = mining->createNewBlock(assembler_options, /*cooldown=*/false); |
177 | 523k | auto block = std::make_shared<CBlock>(Assert(block_template)->getBlock()); |
178 | | |
179 | 523k | LOCK(cs_main); |
180 | 523k | block->nTime = Assert(node.chainman)->ActiveChain().Tip()->GetMedianTimePast() + 1; |
181 | 523k | block->hashMerkleRoot = BlockMerkleRoot(*block); |
182 | | |
183 | 523k | return block; |
184 | 523k | } |