Repository navigation
Expand file tree
/
Copy pathminer.cpp
More file actions
367 lines (314 loc) · 13.9 KB
/
Copy pathminer.cpp
File metadata and controls
367 lines (314 loc) · 13.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-present 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 <node/miner.h>
#include <chain.h>
#include <chainparams.h>
#include <common/args.h>
#include <consensus/amount.h>
#include <consensus/consensus.h>
#include <consensus/merkle.h>
#include <consensus/params.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <node/blockstorage.h>
#include <node/mining_args.h>
#include <node/mining_types.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <pow.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <script/script.h>
#include <sync.h>
#include <tinyformat.h>
#include <txgraph.h>
#include <txmempool.h>
#include <uint256.h>
#include <util/check.h>
#include <util/feefrac.h>
#include <util/log.h>
#include <util/result.h>
#include <util/time.h>
#include <util/translation.h>
#include <validation.h>
#include <versionbits.h>
#include <algorithm>
#include <cstddef>
#include <functional>
#include <span>
#include <stdexcept>
#include <string>
#include <utility>
namespace node {
int64_t GetMinimumTime(const CBlockIndex* pindexPrev, const int64_t difficulty_adjustment_interval)
{
int64_t min_time{pindexPrev->GetMedianTimePast() + 1};
// Height of block to be mined.
const int height{pindexPrev->nHeight + 1};
// Account for BIP94 timewarp rule on all networks. This makes future
// activation safer.
if (height % difficulty_adjustment_interval == 0) {
min_time = std::max<int64_t>(min_time, pindexPrev->GetBlockTime() - MAX_TIMEWARP);
}
// Account for the BIP54 Murch-Zawy rule on all networks: the last block of
// a difficulty adjustment period may not be earlier than its first block.
if (height % difficulty_adjustment_interval == difficulty_adjustment_interval - 1) {
const int first_height{height - static_cast<int>(difficulty_adjustment_interval) + 1};
const CBlockIndex* first_block{Assert(pindexPrev->GetAncestor(first_height))};
min_time = std::max<int64_t>(min_time, first_block->GetBlockTime());
}
return min_time;
}
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
{
int64_t nOldTime = pblock->nTime;
int64_t nNewTime{std::max<int64_t>(GetMinimumTime(pindexPrev, consensusParams.DifficultyAdjustmentInterval()),
TicksSinceEpoch<std::chrono::seconds>(NodeClock::now()))};
if (nOldTime < nNewTime) {
pblock->nTime = nNewTime;
}
// Updating time can change work required on testnet:
if (consensusParams.fPowAllowMinDifficultyBlocks) {
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
}
return nNewTime - nOldTime;
}
void RegenerateCommitments(CBlock& block, ChainstateManager& chainman)
{
CMutableTransaction tx{*block.vtx.at(0)};
tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block));
block.vtx.at(0) = MakeTransactionRef(tx);
const CBlockIndex* prev_block = WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock));
chainman.GenerateCoinbaseCommitment(block, prev_block);
block.hashMerkleRoot = BlockMerkleRoot(block);
}
BlockAssembler::BlockAssembler(Chainstate& chainstate,
const CTxMemPool* mempool,
BlockCreateOptions options)
: chainparams{chainstate.m_chainman.GetParams()},
m_mempool{options.use_mempool ? mempool : nullptr},
m_chainstate{chainstate},
m_options{[&] {
if (auto result{CheckMiningOptions(options, /*use_argnames=*/false)}; !result) {
throw std::runtime_error(util::ErrorString(result).original);
}
return FlattenMiningOptions(std::move(options));
}()}
{
}
void BlockAssembler::resetBlock()
{
// Reserve space for fixed-size block header, txs count, and coinbase tx.
nBlockWeight = *Assert(m_options.block_reserved_weight);
nBlockSigOpsCost = m_options.coinbase_output_max_additional_sigops;
// These counters do not include coinbase tx
nBlockTx = 0;
nFees = 0;
}
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock()
{
const auto time_start{SteadyClock::now()};
resetBlock();
pblocktemplate.reset(new CBlockTemplate());
CBlock* const pblock = &pblocktemplate->block; // pointer for convenience
// Add dummy coinbase tx as first transaction. It is skipped by the
// getblocktemplate RPC and mining interface consumers must not use it.
pblock->vtx.emplace_back();
LOCK(::cs_main);
CBlockIndex* pindexPrev = m_chainstate.m_chain.Tip();
assert(pindexPrev != nullptr);
nHeight = pindexPrev->nHeight + 1;
pblock->nVersion = m_chainstate.m_chainman.m_versionbitscache.ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
// -regtest only: allow overriding block.nVersion with
// -blockversion=N to test forking scenarios
if (chainparams.MineBlocksOnDemand()) {
pblock->nVersion = gArgs.GetIntArg("-blockversion", pblock->nVersion);
}
pblock->nTime = TicksSinceEpoch<std::chrono::seconds>(NodeClock::now());
m_lock_time_cutoff = pindexPrev->GetMedianTimePast();
if (m_mempool) {
LOCK(m_mempool->cs);
m_mempool->StartBlockBuilding();
addChunks();
m_mempool->StopBlockBuilding();
}
const auto time_1{SteadyClock::now()};
m_last_block_num_txs = nBlockTx;
m_last_block_weight = nBlockWeight;
// Create coinbase transaction.
CMutableTransaction coinbaseTx;
// Construct coinbase transaction struct in parallel
CoinbaseTx& coinbase_tx{pblocktemplate->m_coinbase_tx};
coinbase_tx.version = coinbaseTx.version;
coinbaseTx.vin.resize(1);
coinbaseTx.vin[0].prevout.SetNull();
coinbaseTx.vin[0].nSequence = CTxIn::MAX_SEQUENCE_NONFINAL; // Make sure timelock is enforced.
coinbase_tx.sequence = coinbaseTx.vin[0].nSequence;
// Add an output that spends the full coinbase reward.
coinbaseTx.vout.resize(1);
coinbaseTx.vout[0].scriptPubKey = m_options.coinbase_output_script;
// Block subsidy + fees
const CAmount block_reward{nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus())};
coinbaseTx.vout[0].nValue = block_reward;
coinbase_tx.block_reward_remaining = block_reward;
// Start the coinbase scriptSig with the block height as required by BIP34.
// Mining clients are expected to append extra data to this prefix, so
// increasing its length would reduce the space they can use and may break
// existing clients.
coinbaseTx.vin[0].scriptSig = CScript() << nHeight;
// Set script_sig_prefix here, so IPC mining clients are not affected by
// the optional scriptSig padding below. They provide their own extraNonce,
// and in a typical setup a pool name or realistic extraNonce already makes
// the scriptSig long enough.
coinbase_tx.script_sig_prefix = coinbaseTx.vin[0].scriptSig;
if (nHeight <= 16) {
// For blocks at heights <= 16, the BIP34-encoded height alone is only
// one byte. Consensus requires coinbase scriptSigs to be at least two
// bytes long (bad-cb-length), so an OP_0 is always appended at those
// heights.
coinbaseTx.vin[0].scriptSig << OP_0;
}
Assert(nHeight > 0);
coinbaseTx.nLockTime = static_cast<uint32_t>(nHeight - 1);
coinbase_tx.lock_time = coinbaseTx.nLockTime;
pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
m_chainstate.m_chainman.GenerateCoinbaseCommitment(*pblock, pindexPrev);
const CTransactionRef& final_coinbase{pblock->vtx[0]};
if (final_coinbase->HasWitness()) {
const auto& witness_stack{final_coinbase->vin[0].scriptWitness.stack};
// Consensus requires the coinbase witness stack to have exactly one
// element of 32 bytes.
Assert(witness_stack.size() == 1 && witness_stack[0].size() == 32);
coinbase_tx.witness = uint256(witness_stack[0]);
}
if (const int witness_index = GetWitnessCommitmentIndex(*pblock); witness_index != NO_WITNESS_COMMITMENT) {
Assert(witness_index >= 0 && static_cast<size_t>(witness_index) < final_coinbase->vout.size());
coinbase_tx.required_outputs.push_back(final_coinbase->vout[witness_index]);
}
LogDebug(BCLog::MINING, "CreateNewBlock(): block weight: %u txs: %u fees: %ld sigops %d\n", GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost);
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
pblock->nNonce = 0;
if (m_options.test_block_validity) {
if (BlockValidationState state{TestBlockValidity(m_chainstate, *pblock, /*check_pow=*/false, /*check_merkle_root=*/false)}; !state.IsValid()) {
throw std::runtime_error(strprintf("TestBlockValidity failed: %s", state.ToString()));
}
}
const auto time_2{SteadyClock::now()};
LogDebug(BCLog::BENCH, "CreateNewBlock() chunks: %.2fms, validity: %.2fms (total %.2fms)\n",
Ticks<MillisecondsDouble>(time_1 - time_start),
Ticks<MillisecondsDouble>(time_2 - time_1),
Ticks<MillisecondsDouble>(time_2 - time_start));
return std::move(pblocktemplate);
}
bool BlockAssembler::TestChunkBlockLimits(int64_t chunk_weight, int64_t chunk_sigops_cost) const
{
// block_max_weight has been flattened before block assembly limit checks.
Assert(m_options.block_max_weight);
if (nBlockWeight + chunk_weight >= m_options.block_max_weight) {
return false;
}
if (nBlockSigOpsCost + chunk_sigops_cost >= MAX_BLOCK_SIGOPS_COST) {
return false;
}
return true;
}
// Perform transaction-level checks before adding to block:
// - transaction finality (locktime)
bool BlockAssembler::TestChunkTransactions(const std::vector<CTxMemPoolEntryRef>& txs) const
{
for (const auto tx : txs) {
if (!IsFinalTx(tx.get().GetTx(), nHeight, m_lock_time_cutoff)) {
return false;
}
}
return true;
}
void BlockAssembler::AddToBlock(const CTxMemPoolEntry& entry)
{
pblocktemplate->block.vtx.emplace_back(entry.GetSharedTx());
pblocktemplate->vTxFees.push_back(entry.GetFee());
pblocktemplate->vTxSigOpsCost.push_back(entry.GetSigOpCost());
nBlockWeight += entry.GetTxWeight();
++nBlockTx;
nBlockSigOpsCost += entry.GetSigOpCost();
nFees += entry.GetFee();
if (*m_options.print_modified_fee) {
LogInfo("fee rate %s txid %s\n",
CFeeRate(entry.GetModifiedFee(), entry.GetTxSize()).ToString(),
entry.GetTx().GetHash().ToString());
}
}
void BlockAssembler::addChunks()
{
// Limit the number of attempts to add transactions to the block when it is
// close to full; this is just a simple heuristic to finish quickly if the
// mempool has a lot of entries.
const int64_t MAX_CONSECUTIVE_FAILURES = 1000;
constexpr int32_t BLOCK_FULL_ENOUGH_WEIGHT_DELTA = 4000;
int64_t nConsecutiveFailed = 0;
std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef> selected_transactions;
selected_transactions.reserve(MAX_CLUSTER_COUNT_LIMIT);
FeePerWeight chunk_feerate;
// This fills selected_transactions
chunk_feerate = m_mempool->GetBlockBuilderChunk(selected_transactions);
FeePerVSize chunk_feerate_vsize = ToFeePerVSize(chunk_feerate);
while (selected_transactions.size() > 0) {
// Check to see if min fee rate is still respected.
if (ByRatio{chunk_feerate_vsize} < ByRatio{m_options.block_min_fee_rate->GetFeePerVSize()}) {
// Everything else we might consider has a lower feerate
return;
}
int64_t chunk_sig_ops = 0;
int64_t chunk_weight = 0;
for (const auto& tx : selected_transactions) {
chunk_sig_ops += tx.get().GetSigOpCost();
chunk_weight += tx.get().GetTxWeight();
}
// Check to see if this chunk will fit.
if (!TestChunkBlockLimits(chunk_weight, chunk_sig_ops) || !TestChunkTransactions(selected_transactions)) {
// This chunk won't fit, so we skip it and will try the next best one.
m_mempool->SkipBuilderChunk();
++nConsecutiveFailed;
// block_max_weight has been flattened before block assembly limit checks.
Assert(m_options.block_max_weight);
if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight +
BLOCK_FULL_ENOUGH_WEIGHT_DELTA > *m_options.block_max_weight) {
// Give up if we're close to full and haven't succeeded in a while
return;
}
} else {
m_mempool->IncludeBuilderChunk();
// This chunk will fit, so add it to the block.
nConsecutiveFailed = 0;
for (const auto& tx : selected_transactions) {
AddToBlock(tx);
}
pblocktemplate->m_package_feerates.emplace_back(chunk_feerate_vsize);
}
selected_transactions.clear();
chunk_feerate = m_mempool->GetBlockBuilderChunk(selected_transactions);
chunk_feerate_vsize = ToFeePerVSize(chunk_feerate);
}
}
void AddMerkleRootAndCoinbase(CBlock& block, CTransactionRef coinbase, uint32_t version, uint32_t timestamp, uint32_t nonce)
{
if (block.vtx.size() == 0) {
block.vtx.emplace_back(coinbase);
} else {
block.vtx[0] = coinbase;
}
block.nVersion = version;
block.nTime = timestamp;
block.nNonce = nonce;
block.hashMerkleRoot = BlockMerkleRoot(block);
// Reset cached checks
block.m_checked_witness_commitment = false;
block.m_checked_merkle_root = false;
block.fChecked = false;
}
} // namespace node