Skip to content

Commit 31fef69

Browse files
committed
Merge bitcoin/bitcoin#22047: index, rpc: Coinstatsindex follow-ups
779e638 coinstats: Add comments for new coinstatsindex values (Fabian Jahr) 5b3d4e7 Index: Improve logging in coinstatsindex (Fabian Jahr) d4356d4 rpc: Block until synced if coinstatsindex is used in gettxoutsetinfo (Fabian Jahr) a5f6791 rpc: Add missing gettxoutsetinfo help docs (Fabian Jahr) 01386bf Index: Return early from failed coinstatsindex init (Fabian Jahr) 1e38423 index: Use batch writing in coinstatsindex WriteBlock (Fabian Jahr) fb65dde scripted-diff: Fix coinstats data member names (Fabian Jahr) 8ea8c92 index: Avoid unnecessary type casts in coinstatsindex (Fabian Jahr) Pull request description: This is a collection of smaller follow-ups to #19521, addressing several post-merge review comments. ACKs for top commit: Sjors: re-utACK 779e638 jonatack: re-ACK 779e638 diff since last review involves doc changes only; rebased to current master and verified clean debug build/no silent conflicts, unit tests, and feature_coinstatsindex functional test laanwj: Code review ACK 779e638 Talkless: re-utACK 779e638 after cosmetic changes. Tree-SHA512: cb0d038d230c582d7fe3041c89b1e04d39971fab3739d540c609cf826754c6c513b12ded08ac92180aec7a9d7a70114ece50357bd1a902de4adaae9f30b8d699
2 parents 5e21382 + 779e638 commit 31fef69

File tree

5 files changed

+150
-140
lines changed

5 files changed

+150
-140
lines changed

src/index/coinstatsindex.cpp

Lines changed: 97 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ struct DBVal {
2424
uint64_t bogo_size;
2525
CAmount total_amount;
2626
CAmount total_subsidy;
27-
CAmount block_unspendable_amount;
28-
CAmount block_prevout_spent_amount;
29-
CAmount block_new_outputs_ex_coinbase_amount;
30-
CAmount block_coinbase_amount;
31-
CAmount unspendables_genesis_block;
32-
CAmount unspendables_bip30;
33-
CAmount unspendables_scripts;
34-
CAmount unspendables_unclaimed_rewards;
27+
CAmount total_unspendable_amount;
28+
CAmount total_prevout_spent_amount;
29+
CAmount total_new_outputs_ex_coinbase_amount;
30+
CAmount total_coinbase_amount;
31+
CAmount total_unspendables_genesis_block;
32+
CAmount total_unspendables_bip30;
33+
CAmount total_unspendables_scripts;
34+
CAmount total_unspendables_unclaimed_rewards;
3535

3636
SERIALIZE_METHODS(DBVal, obj)
3737
{
@@ -40,14 +40,14 @@ struct DBVal {
4040
READWRITE(obj.bogo_size);
4141
READWRITE(obj.total_amount);
4242
READWRITE(obj.total_subsidy);
43-
READWRITE(obj.block_unspendable_amount);
44-
READWRITE(obj.block_prevout_spent_amount);
45-
READWRITE(obj.block_new_outputs_ex_coinbase_amount);
46-
READWRITE(obj.block_coinbase_amount);
47-
READWRITE(obj.unspendables_genesis_block);
48-
READWRITE(obj.unspendables_bip30);
49-
READWRITE(obj.unspendables_scripts);
50-
READWRITE(obj.unspendables_unclaimed_rewards);
43+
READWRITE(obj.total_unspendable_amount);
44+
READWRITE(obj.total_prevout_spent_amount);
45+
READWRITE(obj.total_new_outputs_ex_coinbase_amount);
46+
READWRITE(obj.total_coinbase_amount);
47+
READWRITE(obj.total_unspendables_genesis_block);
48+
READWRITE(obj.total_unspendables_bip30);
49+
READWRITE(obj.total_unspendables_scripts);
50+
READWRITE(obj.total_unspendables_unclaimed_rewards);
5151
}
5252
};
5353

@@ -122,9 +122,12 @@ bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
122122

123123
uint256 expected_block_hash{pindex->pprev->GetBlockHash()};
124124
if (read_out.first != expected_block_hash) {
125+
LogPrintf("WARNING: previous block header belongs to unexpected block %s; expected %s\n",
126+
read_out.first.ToString(), expected_block_hash.ToString());
127+
125128
if (!m_db->Read(DBHashKey(expected_block_hash), read_out)) {
126-
return error("%s: previous block header belongs to unexpected block %s; expected %s",
127-
__func__, read_out.first.ToString(), expected_block_hash.ToString());
129+
return error("%s: previous block header not found; expected %s",
130+
__func__, expected_block_hash.ToString());
128131
}
129132
}
130133

@@ -138,29 +141,29 @@ bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
138141

139142
// Skip duplicate txid coinbase transactions (BIP30).
140143
if (is_bip30_block && tx->IsCoinBase()) {
141-
m_block_unspendable_amount += block_subsidy;
142-
m_unspendables_bip30 += block_subsidy;
144+
m_total_unspendable_amount += block_subsidy;
145+
m_total_unspendables_bip30 += block_subsidy;
143146
continue;
144147
}
145148

146-
for (size_t j = 0; j < tx->vout.size(); ++j) {
149+
for (uint32_t j = 0; j < tx->vout.size(); ++j) {
147150
const CTxOut& out{tx->vout[j]};
148151
Coin coin{out, pindex->nHeight, tx->IsCoinBase()};
149-
COutPoint outpoint{tx->GetHash(), static_cast<uint32_t>(j)};
152+
COutPoint outpoint{tx->GetHash(), j};
150153

151154
// Skip unspendable coins
152155
if (coin.out.scriptPubKey.IsUnspendable()) {
153-
m_block_unspendable_amount += coin.out.nValue;
154-
m_unspendables_scripts += coin.out.nValue;
156+
m_total_unspendable_amount += coin.out.nValue;
157+
m_total_unspendables_scripts += coin.out.nValue;
155158
continue;
156159
}
157160

158161
m_muhash.Insert(MakeUCharSpan(TxOutSer(outpoint, coin)));
159162

160163
if (tx->IsCoinBase()) {
161-
m_block_coinbase_amount += coin.out.nValue;
164+
m_total_coinbase_amount += coin.out.nValue;
162165
} else {
163-
m_block_new_outputs_ex_coinbase_amount += coin.out.nValue;
166+
m_total_new_outputs_ex_coinbase_amount += coin.out.nValue;
164167
}
165168

166169
++m_transaction_output_count;
@@ -178,7 +181,7 @@ bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
178181

179182
m_muhash.Remove(MakeUCharSpan(TxOutSer(outpoint, coin)));
180183

181-
m_block_prevout_spent_amount += coin.out.nValue;
184+
m_total_prevout_spent_amount += coin.out.nValue;
182185

183186
--m_transaction_output_count;
184187
m_total_amount -= coin.out.nValue;
@@ -188,38 +191,41 @@ bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
188191
}
189192
} else {
190193
// genesis block
191-
m_block_unspendable_amount += block_subsidy;
192-
m_unspendables_genesis_block += block_subsidy;
194+
m_total_unspendable_amount += block_subsidy;
195+
m_total_unspendables_genesis_block += block_subsidy;
193196
}
194197

195198
// If spent prevouts + block subsidy are still a higher amount than
196199
// new outputs + coinbase + current unspendable amount this means
197200
// the miner did not claim the full block reward. Unclaimed block
198201
// rewards are also unspendable.
199-
const CAmount unclaimed_rewards{(m_block_prevout_spent_amount + m_total_subsidy) - (m_block_new_outputs_ex_coinbase_amount + m_block_coinbase_amount + m_block_unspendable_amount)};
200-
m_block_unspendable_amount += unclaimed_rewards;
201-
m_unspendables_unclaimed_rewards += unclaimed_rewards;
202+
const CAmount unclaimed_rewards{(m_total_prevout_spent_amount + m_total_subsidy) - (m_total_new_outputs_ex_coinbase_amount + m_total_coinbase_amount + m_total_unspendable_amount)};
203+
m_total_unspendable_amount += unclaimed_rewards;
204+
m_total_unspendables_unclaimed_rewards += unclaimed_rewards;
202205

203206
std::pair<uint256, DBVal> value;
204207
value.first = pindex->GetBlockHash();
205208
value.second.transaction_output_count = m_transaction_output_count;
206209
value.second.bogo_size = m_bogo_size;
207210
value.second.total_amount = m_total_amount;
208211
value.second.total_subsidy = m_total_subsidy;
209-
value.second.block_unspendable_amount = m_block_unspendable_amount;
210-
value.second.block_prevout_spent_amount = m_block_prevout_spent_amount;
211-
value.second.block_new_outputs_ex_coinbase_amount = m_block_new_outputs_ex_coinbase_amount;
212-
value.second.block_coinbase_amount = m_block_coinbase_amount;
213-
value.second.unspendables_genesis_block = m_unspendables_genesis_block;
214-
value.second.unspendables_bip30 = m_unspendables_bip30;
215-
value.second.unspendables_scripts = m_unspendables_scripts;
216-
value.second.unspendables_unclaimed_rewards = m_unspendables_unclaimed_rewards;
212+
value.second.total_unspendable_amount = m_total_unspendable_amount;
213+
value.second.total_prevout_spent_amount = m_total_prevout_spent_amount;
214+
value.second.total_new_outputs_ex_coinbase_amount = m_total_new_outputs_ex_coinbase_amount;
215+
value.second.total_coinbase_amount = m_total_coinbase_amount;
216+
value.second.total_unspendables_genesis_block = m_total_unspendables_genesis_block;
217+
value.second.total_unspendables_bip30 = m_total_unspendables_bip30;
218+
value.second.total_unspendables_scripts = m_total_unspendables_scripts;
219+
value.second.total_unspendables_unclaimed_rewards = m_total_unspendables_unclaimed_rewards;
217220

218221
uint256 out;
219222
m_muhash.Finalize(out);
220223
value.second.muhash = out;
221224

222-
return m_db->Write(DBHeightKey(pindex->nHeight), value) && m_db->Write(DB_MUHASH, m_muhash);
225+
CDBBatch batch(*m_db);
226+
batch.Write(DBHeightKey(pindex->nHeight), value);
227+
batch.Write(DB_MUHASH, m_muhash);
228+
return m_db->WriteBatch(batch);
223229
}
224230

225231
static bool CopyHeightIndexToHashIndex(CDBIterator& db_it, CDBBatch& batch,
@@ -317,14 +323,14 @@ bool CoinStatsIndex::LookUpStats(const CBlockIndex* block_index, CCoinsStats& co
317323
coins_stats.nBogoSize = entry.bogo_size;
318324
coins_stats.nTotalAmount = entry.total_amount;
319325
coins_stats.total_subsidy = entry.total_subsidy;
320-
coins_stats.block_unspendable_amount = entry.block_unspendable_amount;
321-
coins_stats.block_prevout_spent_amount = entry.block_prevout_spent_amount;
322-
coins_stats.block_new_outputs_ex_coinbase_amount = entry.block_new_outputs_ex_coinbase_amount;
323-
coins_stats.block_coinbase_amount = entry.block_coinbase_amount;
324-
coins_stats.unspendables_genesis_block = entry.unspendables_genesis_block;
325-
coins_stats.unspendables_bip30 = entry.unspendables_bip30;
326-
coins_stats.unspendables_scripts = entry.unspendables_scripts;
327-
coins_stats.unspendables_unclaimed_rewards = entry.unspendables_unclaimed_rewards;
326+
coins_stats.total_unspendable_amount = entry.total_unspendable_amount;
327+
coins_stats.total_prevout_spent_amount = entry.total_prevout_spent_amount;
328+
coins_stats.total_new_outputs_ex_coinbase_amount = entry.total_new_outputs_ex_coinbase_amount;
329+
coins_stats.total_coinbase_amount = entry.total_coinbase_amount;
330+
coins_stats.total_unspendables_genesis_block = entry.total_unspendables_genesis_block;
331+
coins_stats.total_unspendables_bip30 = entry.total_unspendables_bip30;
332+
coins_stats.total_unspendables_scripts = entry.total_unspendables_scripts;
333+
coins_stats.total_unspendables_unclaimed_rewards = entry.total_unspendables_unclaimed_rewards;
328334

329335
return true;
330336
}
@@ -341,33 +347,31 @@ bool CoinStatsIndex::Init()
341347
}
342348
}
343349

344-
if (BaseIndex::Init()) {
345-
const CBlockIndex* pindex{CurrentIndex()};
350+
if (!BaseIndex::Init()) return false;
346351

347-
if (pindex) {
348-
DBVal entry;
349-
if (!LookUpOne(*m_db, pindex, entry)) {
350-
return false;
351-
}
352+
const CBlockIndex* pindex{CurrentIndex()};
352353

353-
m_transaction_output_count = entry.transaction_output_count;
354-
m_bogo_size = entry.bogo_size;
355-
m_total_amount = entry.total_amount;
356-
m_total_subsidy = entry.total_subsidy;
357-
m_block_unspendable_amount = entry.block_unspendable_amount;
358-
m_block_prevout_spent_amount = entry.block_prevout_spent_amount;
359-
m_block_new_outputs_ex_coinbase_amount = entry.block_new_outputs_ex_coinbase_amount;
360-
m_block_coinbase_amount = entry.block_coinbase_amount;
361-
m_unspendables_genesis_block = entry.unspendables_genesis_block;
362-
m_unspendables_bip30 = entry.unspendables_bip30;
363-
m_unspendables_scripts = entry.unspendables_scripts;
364-
m_unspendables_unclaimed_rewards = entry.unspendables_unclaimed_rewards;
354+
if (pindex) {
355+
DBVal entry;
356+
if (!LookUpOne(*m_db, pindex, entry)) {
357+
return false;
365358
}
366359

367-
return true;
360+
m_transaction_output_count = entry.transaction_output_count;
361+
m_bogo_size = entry.bogo_size;
362+
m_total_amount = entry.total_amount;
363+
m_total_subsidy = entry.total_subsidy;
364+
m_total_unspendable_amount = entry.total_unspendable_amount;
365+
m_total_prevout_spent_amount = entry.total_prevout_spent_amount;
366+
m_total_new_outputs_ex_coinbase_amount = entry.total_new_outputs_ex_coinbase_amount;
367+
m_total_coinbase_amount = entry.total_coinbase_amount;
368+
m_total_unspendables_genesis_block = entry.total_unspendables_genesis_block;
369+
m_total_unspendables_bip30 = entry.total_unspendables_bip30;
370+
m_total_unspendables_scripts = entry.total_unspendables_scripts;
371+
m_total_unspendables_unclaimed_rewards = entry.total_unspendables_unclaimed_rewards;
368372
}
369373

370-
return false;
374+
return true;
371375
}
372376

373377
// Reverse a single block as part of a reorg
@@ -391,9 +395,12 @@ bool CoinStatsIndex::ReverseBlock(const CBlock& block, const CBlockIndex* pindex
391395

392396
uint256 expected_block_hash{pindex->pprev->GetBlockHash()};
393397
if (read_out.first != expected_block_hash) {
398+
LogPrintf("WARNING: previous block header belongs to unexpected block %s; expected %s\n",
399+
read_out.first.ToString(), expected_block_hash.ToString());
400+
394401
if (!m_db->Read(DBHashKey(expected_block_hash), read_out)) {
395-
return error("%s: previous block header belongs to unexpected block %s; expected %s",
396-
__func__, read_out.first.ToString(), expected_block_hash.ToString());
402+
return error("%s: previous block header not found; expected %s",
403+
__func__, expected_block_hash.ToString());
397404
}
398405
}
399406
}
@@ -402,24 +409,24 @@ bool CoinStatsIndex::ReverseBlock(const CBlock& block, const CBlockIndex* pindex
402409
for (size_t i = 0; i < block.vtx.size(); ++i) {
403410
const auto& tx{block.vtx.at(i)};
404411

405-
for (size_t j = 0; j < tx->vout.size(); ++j) {
412+
for (uint32_t j = 0; j < tx->vout.size(); ++j) {
406413
const CTxOut& out{tx->vout[j]};
407-
COutPoint outpoint{tx->GetHash(), static_cast<uint32_t>(j)};
414+
COutPoint outpoint{tx->GetHash(), j};
408415
Coin coin{out, pindex->nHeight, tx->IsCoinBase()};
409416

410417
// Skip unspendable coins
411418
if (coin.out.scriptPubKey.IsUnspendable()) {
412-
m_block_unspendable_amount -= coin.out.nValue;
413-
m_unspendables_scripts -= coin.out.nValue;
419+
m_total_unspendable_amount -= coin.out.nValue;
420+
m_total_unspendables_scripts -= coin.out.nValue;
414421
continue;
415422
}
416423

417424
m_muhash.Remove(MakeUCharSpan(TxOutSer(outpoint, coin)));
418425

419426
if (tx->IsCoinBase()) {
420-
m_block_coinbase_amount -= coin.out.nValue;
427+
m_total_coinbase_amount -= coin.out.nValue;
421428
} else {
422-
m_block_new_outputs_ex_coinbase_amount -= coin.out.nValue;
429+
m_total_new_outputs_ex_coinbase_amount -= coin.out.nValue;
423430
}
424431

425432
--m_transaction_output_count;
@@ -437,7 +444,7 @@ bool CoinStatsIndex::ReverseBlock(const CBlock& block, const CBlockIndex* pindex
437444

438445
m_muhash.Insert(MakeUCharSpan(TxOutSer(outpoint, coin)));
439446

440-
m_block_prevout_spent_amount -= coin.out.nValue;
447+
m_total_prevout_spent_amount -= coin.out.nValue;
441448

442449
m_transaction_output_count++;
443450
m_total_amount += coin.out.nValue;
@@ -446,9 +453,9 @@ bool CoinStatsIndex::ReverseBlock(const CBlock& block, const CBlockIndex* pindex
446453
}
447454
}
448455

449-
const CAmount unclaimed_rewards{(m_block_new_outputs_ex_coinbase_amount + m_block_coinbase_amount + m_block_unspendable_amount) - (m_block_prevout_spent_amount + m_total_subsidy)};
450-
m_block_unspendable_amount -= unclaimed_rewards;
451-
m_unspendables_unclaimed_rewards -= unclaimed_rewards;
456+
const CAmount unclaimed_rewards{(m_total_new_outputs_ex_coinbase_amount + m_total_coinbase_amount + m_total_unspendable_amount) - (m_total_prevout_spent_amount + m_total_subsidy)};
457+
m_total_unspendable_amount -= unclaimed_rewards;
458+
m_total_unspendables_unclaimed_rewards -= unclaimed_rewards;
452459

453460
// Check that the rolled back internal values are consistent with the DB read out
454461
uint256 out;
@@ -459,14 +466,14 @@ bool CoinStatsIndex::ReverseBlock(const CBlock& block, const CBlockIndex* pindex
459466
Assert(m_total_amount == read_out.second.total_amount);
460467
Assert(m_bogo_size == read_out.second.bogo_size);
461468
Assert(m_total_subsidy == read_out.second.total_subsidy);
462-
Assert(m_block_unspendable_amount == read_out.second.block_unspendable_amount);
463-
Assert(m_block_prevout_spent_amount == read_out.second.block_prevout_spent_amount);
464-
Assert(m_block_new_outputs_ex_coinbase_amount == read_out.second.block_new_outputs_ex_coinbase_amount);
465-
Assert(m_block_coinbase_amount == read_out.second.block_coinbase_amount);
466-
Assert(m_unspendables_genesis_block == read_out.second.unspendables_genesis_block);
467-
Assert(m_unspendables_bip30 == read_out.second.unspendables_bip30);
468-
Assert(m_unspendables_scripts == read_out.second.unspendables_scripts);
469-
Assert(m_unspendables_unclaimed_rewards == read_out.second.unspendables_unclaimed_rewards);
469+
Assert(m_total_unspendable_amount == read_out.second.total_unspendable_amount);
470+
Assert(m_total_prevout_spent_amount == read_out.second.total_prevout_spent_amount);
471+
Assert(m_total_new_outputs_ex_coinbase_amount == read_out.second.total_new_outputs_ex_coinbase_amount);
472+
Assert(m_total_coinbase_amount == read_out.second.total_coinbase_amount);
473+
Assert(m_total_unspendables_genesis_block == read_out.second.total_unspendables_genesis_block);
474+
Assert(m_total_unspendables_bip30 == read_out.second.total_unspendables_bip30);
475+
Assert(m_total_unspendables_scripts == read_out.second.total_unspendables_scripts);
476+
Assert(m_total_unspendables_unclaimed_rewards == read_out.second.total_unspendables_unclaimed_rewards);
470477

471478
return m_db->Write(DB_MUHASH, m_muhash);
472479
}

src/index/coinstatsindex.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ class CoinStatsIndex final : public BaseIndex
2525
uint64_t m_bogo_size{0};
2626
CAmount m_total_amount{0};
2727
CAmount m_total_subsidy{0};
28-
CAmount m_block_unspendable_amount{0};
29-
CAmount m_block_prevout_spent_amount{0};
30-
CAmount m_block_new_outputs_ex_coinbase_amount{0};
31-
CAmount m_block_coinbase_amount{0};
32-
CAmount m_unspendables_genesis_block{0};
33-
CAmount m_unspendables_bip30{0};
34-
CAmount m_unspendables_scripts{0};
35-
CAmount m_unspendables_unclaimed_rewards{0};
28+
CAmount m_total_unspendable_amount{0};
29+
CAmount m_total_prevout_spent_amount{0};
30+
CAmount m_total_new_outputs_ex_coinbase_amount{0};
31+
CAmount m_total_coinbase_amount{0};
32+
CAmount m_total_unspendables_genesis_block{0};
33+
CAmount m_total_unspendables_bip30{0};
34+
CAmount m_total_unspendables_scripts{0};
35+
CAmount m_total_unspendables_unclaimed_rewards{0};
3636

3737
bool ReverseBlock(const CBlock& block, const CBlockIndex* pindex);
3838

src/node/coinstats.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,25 @@ struct CCoinsStats
4545
bool index_used{false};
4646

4747
// Following values are only available from coinstats index
48+
49+
//! Total cumulative amount of block subsidies up to and including this block
4850
CAmount total_subsidy{0};
49-
CAmount block_unspendable_amount{0};
50-
CAmount block_prevout_spent_amount{0};
51-
CAmount block_new_outputs_ex_coinbase_amount{0};
52-
CAmount block_coinbase_amount{0};
53-
CAmount unspendables_genesis_block{0};
54-
CAmount unspendables_bip30{0};
55-
CAmount unspendables_scripts{0};
56-
CAmount unspendables_unclaimed_rewards{0};
51+
//! Total cumulative amount of unspendable coins up to and including this block
52+
CAmount total_unspendable_amount{0};
53+
//! Total cumulative amount of prevouts spent up to and including this block
54+
CAmount total_prevout_spent_amount{0};
55+
//! Total cumulative amount of outputs created up to and including this block
56+
CAmount total_new_outputs_ex_coinbase_amount{0};
57+
//! Total cumulative amount of coinbase outputs up to and including this block
58+
CAmount total_coinbase_amount{0};
59+
//! The unspendable coinbase amount from the genesis block
60+
CAmount total_unspendables_genesis_block{0};
61+
//! The two unspendable coinbase outputs total amount caused by BIP30
62+
CAmount total_unspendables_bip30{0};
63+
//! Total cumulative amount of outputs sent to unspendable scripts (OP_RETURN for example) up to and including this block
64+
CAmount total_unspendables_scripts{0};
65+
//! Total cumulative amount of coins lost due to unclaimed miner rewards up to and including this block
66+
CAmount total_unspendables_unclaimed_rewards{0};
5767

5868
CCoinsStats(CoinStatsHashType hash_type) : m_hash_type(hash_type) {}
5969
};

0 commit comments

Comments
 (0)