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+
20292051std::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