Skip to content

Commit b64755f

Browse files
committed
consensus: Use UTXO hints in ConnectBlock
1 parent 9a8a6d4 commit b64755f

1 file changed

Lines changed: 55 additions & 11 deletions

File tree

src/validation.cpp

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <script/script.h>
4545
#include <script/sigcache.h>
4646
#include <signet.h>
47+
#include <swiftsync.h>
4748
#include <tinyformat.h>
4849
#include <txdb.h>
4950
#include <txmempool.h>
@@ -2026,6 +2027,27 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund
20262027
AddCoins(inputs, tx, nHeight);
20272028
}
20282029

2030+
void UpdateCoinsWithHints(const CTransaction& tx, CCoinsViewCache& inputs, const CBlockIndex& pindex, swiftsync::Aggregate& agg, swiftsync::BlockHints& hints)
2031+
{
2032+
const bool is_coinbase = tx.IsCoinBase();
2033+
if (is_coinbase && IsBIP30Unspendable(pindex.GetBlockHash(), pindex.nHeight)) return;
2034+
if (!is_coinbase) {
2035+
for (const CTxIn& txin : tx.vin) {
2036+
agg.Spend(txin.prevout);
2037+
}
2038+
}
2039+
const Txid& txid{tx.GetHash()};
2040+
for (uint64_t index = 0; index < tx.vout.size(); index++) {
2041+
COutPoint outpoint = COutPoint(txid, index);
2042+
if (!hints.IsCurrOutputUnspent() && !tx.vout[index].scriptPubKey.IsUnspendable()) {
2043+
agg.Add(outpoint);
2044+
} else {
2045+
inputs.AddCoin(outpoint, Coin(tx.vout[index], pindex.nHeight, is_coinbase), is_coinbase);
2046+
}
2047+
hints.NextOutput();
2048+
}
2049+
}
2050+
20292051
std::optional<std::pair<ScriptError, std::string>> CScriptCheck::operator()() {
20302052
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
20312053
const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;
@@ -2352,11 +2374,13 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
23522374
// Special case for the genesis block, skipping connection of its transactions
23532375
// (its coinbase is unspendable)
23542376
if (block_hash == params.GetConsensus().hashGenesisBlock) {
2377+
m_swiftsync_ctx.StartingFromGenesis();
23552378
if (!fJustCheck)
23562379
view.SetBestBlock(pindex->GetBlockHash());
23572380
return true;
23582381
}
23592382

2383+
const bool swiftsync_active = m_swiftsync_ctx.AcceleratedSyncPossible();
23602384
const char* script_check_reason;
23612385
if (m_chainman.AssumedValidBlock().IsNull()) {
23622386
script_check_reason = "assumevalid=0 (always verify)";
@@ -2535,14 +2559,18 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
25352559
int nInputs = 0;
25362560
int64_t nSigOpsCost = 0;
25372561
blockundo.vtxundo.reserve(block.vtx.size() - 1);
2562+
std::optional<swiftsync::BlockHints> hints;
2563+
if (swiftsync_active) {
2564+
hints.emplace(m_swiftsync_ctx.ReadBlockHints(pindex->nHeight));
2565+
}
25382566
for (unsigned int i = 0; i < block.vtx.size(); i++)
25392567
{
25402568
if (!state.IsValid()) break;
25412569
const CTransaction &tx = *(block.vtx[i]);
25422570

25432571
nInputs += tx.vin.size();
25442572

2545-
if (!tx.IsCoinBase())
2573+
if (!tx.IsCoinBase() && !swiftsync_active)
25462574
{
25472575
CAmount txfee = 0;
25482576
TxValidationState tx_state;
@@ -2579,13 +2607,15 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
25792607
// * legacy (always)
25802608
// * p2sh (when P2SH enabled in flags and excludes coinbase)
25812609
// * witness (when witness enabled in flags and excludes coinbase)
2582-
nSigOpsCost += GetTransactionSigOpCost(tx, view, flags);
2583-
if (nSigOpsCost > MAX_BLOCK_SIGOPS_COST) {
2584-
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-blk-sigops", "too many sigops");
2585-
break;
2610+
if (!swiftsync_active) {
2611+
nSigOpsCost += GetTransactionSigOpCost(tx, view, flags);
2612+
if (nSigOpsCost > MAX_BLOCK_SIGOPS_COST) {
2613+
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-blk-sigops", "too many sigops");
2614+
break;
2615+
}
25862616
}
25872617

2588-
if (!tx.IsCoinBase() && fScriptChecks)
2618+
if (!tx.IsCoinBase() && fScriptChecks && !swiftsync_active)
25892619
{
25902620
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
25912621
bool tx_ok;
@@ -2611,7 +2641,19 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
26112641
if (i > 0) {
26122642
blockundo.vtxundo.emplace_back();
26132643
}
2614-
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
2644+
if (swiftsync_active) {
2645+
UpdateCoinsWithHints(tx, view, *pindex, m_swiftsync_ctx.m_aggregate, hints.value());
2646+
} else {
2647+
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
2648+
}
2649+
}
2650+
if (swiftsync_active && m_swiftsync_ctx.StopHeight() == (uint32_t)pindex->nHeight) {
2651+
m_swiftsync_ctx.Completed();
2652+
if (m_swiftsync_ctx.m_aggregate.IsZero()) {
2653+
LogInfo("Accelerated IBD succeeded.");
2654+
} else {
2655+
return FatalError(m_chainman.GetNotifications(), state, _("UTXO set check failed indicating a corrupt file. Restart with -reindex or -reindexchainstate to recover."));
2656+
}
26152657
}
26162658
const auto time_3{SteadyClock::now()};
26172659
m_chainman.time_connect += time_3 - time_2;
@@ -2621,10 +2663,12 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
26212663
Ticks<SecondsDouble>(m_chainman.time_connect),
26222664
Ticks<MillisecondsDouble>(m_chainman.time_connect) / m_chainman.num_blocks_total);
26232665

2624-
CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, params.GetConsensus());
2625-
if (block.vtx[0]->GetValueOut() > blockReward && state.IsValid()) {
2626-
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cb-amount",
2666+
if (!swiftsync_active) {
2667+
CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, params.GetConsensus());
2668+
if (block.vtx[0]->GetValueOut() > blockReward && state.IsValid()) {
2669+
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cb-amount",
26272670
strprintf("coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0]->GetValueOut(), blockReward));
2671+
}
26282672
}
26292673
if (control) {
26302674
auto parallel_result = control->Complete();
@@ -2648,7 +2692,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
26482692
return true;
26492693
}
26502694

2651-
if (!m_blockman.WriteBlockUndo(blockundo, state, *pindex)) {
2695+
if (!swiftsync_active && !m_blockman.WriteBlockUndo(blockundo, state, *pindex)) {
26522696
return false;
26532697
}
26542698

0 commit comments

Comments
 (0)