@@ -2568,171 +2568,10 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
25682568 m_prev_script_checks_logged = fScriptChecks ;
25692569 }
25702570
2571- CBlockUndo blockundo;
2572-
2573- // Precomputed transaction data pointers must not be invalidated
2574- // until after `control` has run the script checks (potentially
2575- // in multiple threads). Preallocate the vector size so a new allocation
2576- // doesn't invalidate pointers into the vector, and keep txsdata in scope
2577- // for as long as `control`.
2578- std::optional<CCheckQueueControl<CScriptCheck>> control;
2579- if (auto & queue = m_chainman.GetCheckQueue (); queue.HasThreads () && fScriptChecks ) control.emplace (queue);
2580-
2581- std::vector<PrecomputedTransactionData> txsdata (block.vtx .size ());
2582-
2583- std::vector<int > prevheights;
2584- CAmount nFees = 0 ;
2585- int nInputs = 0 ;
2586- int64_t nSigOpsCost = 0 ;
2587- blockundo.vtxundo .reserve (block.vtx .size () - 1 );
2588- for (unsigned int i = 0 ; i < block.vtx .size (); i++)
2589- {
2590- if (!state.IsValid ()) break ;
2591- const CTransaction &tx = *(block.vtx [i]);
2592-
2593- nInputs += tx.vin .size ();
2594-
2595- if (!tx.IsCoinBase ())
2596- {
2597- CAmount txfee = 0 ;
2598- TxValidationState tx_state;
2599- if (!Consensus::CheckTxInputs (tx, tx_state, view, pindex->nHeight , txfee)) {
2600- // Any transaction validation failure in ConnectBlock is a block consensus failure
2601- state.Invalid (BlockValidationResult::BLOCK_CONSENSUS,
2602- tx_state.GetRejectReason (),
2603- tx_state.GetDebugMessage () + " in transaction " + tx.GetHash ().ToString ());
2604- break ;
2605- }
2606- nFees += txfee;
2607- if (!MoneyRange (nFees)) {
2608- state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-txns-accumulated-fee-outofrange" ,
2609- " accumulated fee in the block out of range" );
2610- break ;
2611- }
2612-
2613- // Check that transaction is BIP68 final
2614- // BIP68 lock checks (as opposed to nLockTime checks) must
2615- // be in ConnectBlock because they require the UTXO set
2616- prevheights.resize (tx.vin .size ());
2617- for (size_t j = 0 ; j < tx.vin .size (); j++) {
2618- prevheights[j] = view.AccessCoin (tx.vin [j].prevout ).nHeight ;
2619- }
2620-
2621- if (!SequenceLocks (tx, nLockTimeFlags, prevheights, *pindex)) {
2622- state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-txns-nonfinal" ,
2623- " contains a non-BIP68-final transaction " + tx.GetHash ().ToString ());
2624- break ;
2625- }
2626- }
2627-
2628- // GetTransactionSigOpCost counts 3 types of sigops:
2629- // * legacy (always)
2630- // * p2sh (when P2SH enabled in flags and excludes coinbase)
2631- // * witness (when witness enabled in flags and excludes coinbase)
2632- nSigOpsCost += GetTransactionSigOpCost (tx, view, flags);
2633- if (nSigOpsCost > MAX_BLOCK_SIGOPS_COST) {
2634- state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-blk-sigops" , " too many sigops" );
2635- break ;
2636- }
2637-
2638- if (!tx.IsCoinBase () && fScriptChecks )
2639- {
2640- bool fCacheResults = fJustCheck ; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
2641- bool tx_ok;
2642- TxValidationState tx_state;
2643- // If CheckInputScripts is called with a pointer to a checks vector, the resulting checks are appended to it. In that case
2644- // they need to be added to control which runs them asynchronously. Otherwise, CheckInputScripts runs the checks before returning.
2645- if (control) {
2646- std::vector<CScriptCheck> vChecks;
2647- tx_ok = CheckInputScripts (tx, tx_state, view, flags, fCacheResults , fCacheResults , txsdata[i], m_chainman.m_validation_cache , &vChecks);
2648- if (tx_ok) control->Add (std::move (vChecks));
2649- } else {
2650- tx_ok = CheckInputScripts (tx, tx_state, view, flags, fCacheResults , fCacheResults , txsdata[i], m_chainman.m_validation_cache );
2651- }
2652- if (!tx_ok) {
2653- // Any transaction validation failure in ConnectBlock is a block consensus failure
2654- state.Invalid (BlockValidationResult::BLOCK_CONSENSUS,
2655- tx_state.GetRejectReason (), tx_state.GetDebugMessage ());
2656- break ;
2657- }
2658- }
2659-
2660- CTxUndo undoDummy;
2661- if (i > 0 ) {
2662- blockundo.vtxundo .emplace_back ();
2663- }
2664- UpdateCoins (tx, view, i == 0 ? undoDummy : blockundo.vtxundo .back (), pindex->nHeight );
2665- }
2666- const auto time_3{SteadyClock::now ()};
2667- m_chainman.time_connect += time_3 - time_2;
2668- LogDebug (BCLog::BENCH, " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n " , (unsigned )block.vtx .size (),
2669- Ticks<MillisecondsDouble>(time_3 - time_2), Ticks<MillisecondsDouble>(time_3 - time_2) / block.vtx .size (),
2670- nInputs <= 1 ? 0 : Ticks<MillisecondsDouble>(time_3 - time_2) / (nInputs - 1 ),
2671- Ticks<SecondsDouble>(m_chainman.time_connect ),
2672- Ticks<MillisecondsDouble>(m_chainman.time_connect ) / m_chainman.num_blocks_total );
2673-
2674- CAmount blockReward = nFees + GetBlockSubsidy (pindex->nHeight , params.GetConsensus ());
2675- if (block.vtx [0 ]->GetValueOut () > blockReward && state.IsValid ()) {
2676- state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-cb-amount" ,
2677- strprintf (" coinbase pays too much (actual=%d vs limit=%d)" , block.vtx [0 ]->GetValueOut (), blockReward));
2678- }
2679- if (control) {
2680- auto parallel_result = control->Complete ();
2681- if (parallel_result.has_value () && state.IsValid ()) {
2682- state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, strprintf (" block-script-verify-flag-failed (%s)" , ScriptErrorString (parallel_result->first )), parallel_result->second );
2683- }
2684- }
2685- if (!state.IsValid ()) {
2686- LogInfo (" Block validation error: %s" , state.ToString ());
2687- return false ;
2688- }
2689- const auto time_4{SteadyClock::now ()};
2690- m_chainman.time_verify += time_4 - time_2;
2691- LogDebug (BCLog::BENCH, " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs (%.2fms/blk)]\n " , nInputs - 1 ,
2692- Ticks<MillisecondsDouble>(time_4 - time_2),
2693- nInputs <= 1 ? 0 : Ticks<MillisecondsDouble>(time_4 - time_2) / (nInputs - 1 ),
2694- Ticks<SecondsDouble>(m_chainman.time_verify ),
2695- Ticks<MillisecondsDouble>(m_chainman.time_verify ) / m_chainman.num_blocks_total );
2696-
2697- if (fJustCheck ) {
2698- return true ;
2699- }
2700-
2701- if (!m_blockman.WriteBlockUndo (blockundo, state, *pindex)) {
2702- return false ;
2703- }
2704-
2705- const auto time_5{SteadyClock::now ()};
2706- m_chainman.time_undo += time_5 - time_4;
2707- LogDebug (BCLog::BENCH, " - Write undo data: %.2fms [%.2fs (%.2fms/blk)]\n " ,
2708- Ticks<MillisecondsDouble>(time_5 - time_4),
2709- Ticks<SecondsDouble>(m_chainman.time_undo ),
2710- Ticks<MillisecondsDouble>(m_chainman.time_undo ) / m_chainman.num_blocks_total );
2711-
2712- if (!pindex->IsValid (BLOCK_VALID_SCRIPTS)) {
2713- pindex->RaiseValidity (BLOCK_VALID_SCRIPTS);
2714- m_blockman.m_dirty_blockindex .insert (pindex);
2715- }
27162571
27172572 // add this block to the view's block chain
27182573 view.SetBestBlock (pindex->GetBlockHash ());
27192574
2720- const auto time_6{SteadyClock::now ()};
2721- m_chainman.time_index += time_6 - time_5;
2722- LogDebug (BCLog::BENCH, " - Index writing: %.2fms [%.2fs (%.2fms/blk)]\n " ,
2723- Ticks<MillisecondsDouble>(time_6 - time_5),
2724- Ticks<SecondsDouble>(m_chainman.time_index ),
2725- Ticks<MillisecondsDouble>(m_chainman.time_index ) / m_chainman.num_blocks_total );
2726-
2727- TRACEPOINT (validation, block_connected,
2728- block_hash.data (),
2729- pindex->nHeight ,
2730- block.vtx .size (),
2731- nInputs,
2732- nSigOpsCost,
2733- Ticks<std::chrono::nanoseconds>(time_5 - time_start)
2734- );
2735-
27362575 return true ;
27372576}
27382577
0 commit comments