mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 14:53:43 +01:00
Merge bitcoin/bitcoin#32467: checkqueue: make the queue non-optional for CCheckQueueControl and drop legacy locking macro usage
fd290730f5validation: clean up and clarify CheckInputScripts logic (Cory Fields)1a37507895validation: use a lock for CCheckQueueControl (Cory Fields)c3b0e6c7f4validation: make CCheckQueueControl's CCheckQueue non-optional (Cory Fields)4c8c90b556validation: only create a CCheckQueueControl if it's actually going to be used (Cory Fields)11fed833b3threading: add LOCK_ARGS macro (Cory Fields) Pull request description: As part of an effort to cleanup our threading primitives and add safe `SharedMutex`/`SharedLock` impls, I'd like to get rid of the last of our legacy `ENTER_CRITICAL_SECTION`/`LEAVE_CRITICAL_SECTION` usage. This, along with a follow-up [after fixing REVERSE_LOCK](https://github.com/bitcoin/bitcoin/pull/32465) will allow us to do that. This replaces the old macros with an RAII lock, while simplifying `CCheckQueueControl`. It now requires a `CCheckQueue`, and optionality is handled externally. In the case of validation, it is wrapped in a `std::optional`. It also adds an `LOCK_ARGS` macro for `UniqueLock` initialization which may be helpful elsewhere. ACKs for top commit: fjahr: re-ACKfd290730f5ryanofsky: Code review ACKfd290730f5, just removing assert since last review. Thanks for considering all the comments and feedback! TheCharlatan: Re-ACKfd290730f5Tree-SHA512: 54b9db604ee1bda7d11bce1653a88d3dcbc4f525eed6a85abdd4d6409138674af4bb8b00afa4e0d3d29dadd045a3a39de253a45f0ef9c05f56cba1aac5b59303
This commit is contained in:
@@ -2421,7 +2421,6 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||
|
||||
uint256 block_hash{block.GetHash()};
|
||||
assert(*pindex->phashBlock == block_hash);
|
||||
const bool parallel_script_checks{m_chainman.GetCheckQueue().HasThreads()};
|
||||
|
||||
const auto time_start{SteadyClock::now()};
|
||||
const CChainParams& params{m_chainman.GetParams()};
|
||||
@@ -2611,7 +2610,9 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||
// in multiple threads). Preallocate the vector size so a new allocation
|
||||
// doesn't invalidate pointers into the vector, and keep txsdata in scope
|
||||
// for as long as `control`.
|
||||
CCheckQueueControl<CScriptCheck> control(fScriptChecks && parallel_script_checks ? &m_chainman.GetCheckQueue() : nullptr);
|
||||
std::optional<CCheckQueueControl<CScriptCheck>> control;
|
||||
if (auto& queue = m_chainman.GetCheckQueue(); queue.HasThreads() && fScriptChecks) control.emplace(queue);
|
||||
|
||||
std::vector<PrecomputedTransactionData> txsdata(block.vtx.size());
|
||||
|
||||
std::vector<int> prevheights;
|
||||
@@ -2669,18 +2670,26 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tx.IsCoinBase())
|
||||
if (!tx.IsCoinBase() && fScriptChecks)
|
||||
{
|
||||
std::vector<CScriptCheck> vChecks;
|
||||
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
|
||||
bool tx_ok;
|
||||
TxValidationState tx_state;
|
||||
if (fScriptChecks && !CheckInputScripts(tx, tx_state, view, flags, fCacheResults, fCacheResults, txsdata[i], m_chainman.m_validation_cache, parallel_script_checks ? &vChecks : nullptr)) {
|
||||
// If CheckInputScripts is called with a pointer to a checks vector, the resulting checks are appended to it. In that case
|
||||
// they need to be added to control which runs them asynchronously. Otherwise, CheckInputScripts runs the checks before returning.
|
||||
if (control) {
|
||||
std::vector<CScriptCheck> vChecks;
|
||||
tx_ok = CheckInputScripts(tx, tx_state, view, flags, fCacheResults, fCacheResults, txsdata[i], m_chainman.m_validation_cache, &vChecks);
|
||||
if (tx_ok) control->Add(std::move(vChecks));
|
||||
} else {
|
||||
tx_ok = CheckInputScripts(tx, tx_state, view, flags, fCacheResults, fCacheResults, txsdata[i], m_chainman.m_validation_cache);
|
||||
}
|
||||
if (!tx_ok) {
|
||||
// Any transaction validation failure in ConnectBlock is a block consensus failure
|
||||
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS,
|
||||
tx_state.GetRejectReason(), tx_state.GetDebugMessage());
|
||||
break;
|
||||
}
|
||||
control.Add(std::move(vChecks));
|
||||
}
|
||||
|
||||
CTxUndo undoDummy;
|
||||
@@ -2702,10 +2711,11 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
|
||||
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cb-amount",
|
||||
strprintf("coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0]->GetValueOut(), blockReward));
|
||||
}
|
||||
|
||||
auto parallel_result = control.Complete();
|
||||
if (parallel_result.has_value() && state.IsValid()) {
|
||||
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(parallel_result->first)), parallel_result->second);
|
||||
if (control) {
|
||||
auto parallel_result = control->Complete();
|
||||
if (parallel_result.has_value() && state.IsValid()) {
|
||||
state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(parallel_result->first)), parallel_result->second);
|
||||
}
|
||||
}
|
||||
if (!state.IsValid()) {
|
||||
LogInfo("Block validation error: %s", state.ToString());
|
||||
|
||||
Reference in New Issue
Block a user