Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 304 Lines • ▼ Show 20 Lines | static bool IsCurrentForFeeEstimation() { | ||||
return true; | return true; | ||||
} | } | ||||
static bool IsMagneticAnomalyEnabledForCurrentBlock(const Config &config) { | static bool IsMagneticAnomalyEnabledForCurrentBlock(const Config &config) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
return IsMagneticAnomalyEnabled(config, chainActive.Tip()); | return IsMagneticAnomalyEnabled(config, chainActive.Tip()); | ||||
} | } | ||||
static bool IsGreatWallEnabledForCurrentBlock(const Config &config) { | |||||
AssertLockHeld(cs_main); | |||||
return IsGreatWallEnabled(config, chainActive.Tip()); | |||||
} | |||||
// Command-line argument "-replayprotectionactivationtime=<timestamp>" will | // Command-line argument "-replayprotectionactivationtime=<timestamp>" will | ||||
// cause the node to switch to replay protected SigHash ForkID value when the | // cause the node to switch to replay protected SigHash ForkID value when the | ||||
// median timestamp of the previous 11 blocks is greater than or equal to | // median timestamp of the previous 11 blocks is greater than or equal to | ||||
// <timestamp>. Defaults to the pre-defined timestamp when not set. | // <timestamp>. Defaults to the pre-defined timestamp when not set. | ||||
static bool IsReplayProtectionEnabled(const Config &config, | static bool IsReplayProtectionEnabled(const Config &config, | ||||
int64_t nMedianTimePast) { | int64_t nMedianTimePast) { | ||||
return nMedianTimePast >= | return nMedianTimePast >= | ||||
gArgs.GetArg( | gArgs.GetArg( | ||||
▲ Show 20 Lines • Show All 309 Lines • ▼ Show 20 Lines | for (const CTxIn &txin : tx.vin) { | ||||
if (IsReplayProtectionEnabledForCurrentBlock(config)) { | if (IsReplayProtectionEnabledForCurrentBlock(config)) { | ||||
extraFlags |= SCRIPT_ENABLE_REPLAY_PROTECTION; | extraFlags |= SCRIPT_ENABLE_REPLAY_PROTECTION; | ||||
} | } | ||||
if (IsMagneticAnomalyEnabledForCurrentBlock(config)) { | if (IsMagneticAnomalyEnabledForCurrentBlock(config)) { | ||||
extraFlags |= SCRIPT_ENABLE_CHECKDATASIG; | extraFlags |= SCRIPT_ENABLE_CHECKDATASIG; | ||||
} | } | ||||
if (IsGreatWallEnabledForCurrentBlock(config)) { | |||||
if (!fRequireStandard) { | |||||
deadalnix: Check that one first, as it is pretty much free. | |||||
markblundebergAuthorUnsubmitted Done Inline ActionsIsGreatWallEnabledForCurrentBlock will end up getting called 100% of the time anyway when combined with schnorr activation. markblundeberg: IsGreatWallEnabledForCurrentBlock will end up getting called 100% of the time anyway when… | |||||
florianUnsubmitted Done Inline ActionsOther activations will make that first conditional be tested every time. florian: Other activations will make that first conditional be tested every time. | |||||
extraFlags |= SCRIPT_ALLOW_SEGWIT_RECOVERY; | |||||
} | |||||
} | |||||
// Check inputs based on the set of flags we activate. | // Check inputs based on the set of flags we activate. | ||||
uint32_t scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS; | uint32_t scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS; | ||||
if (!config.GetChainParams().RequireStandard()) { | if (!config.GetChainParams().RequireStandard()) { | ||||
scriptVerifyFlags = | scriptVerifyFlags = | ||||
SCRIPT_ENABLE_SIGHASH_FORKID | | SCRIPT_ENABLE_SIGHASH_FORKID | | ||||
gArgs.GetArg("-promiscuousmempoolflags", scriptVerifyFlags); | gArgs.GetArg("-promiscuousmempoolflags", scriptVerifyFlags); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 536 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < tx.vin.size(); i++) { | ||||
txdata); | txdata); | ||||
if (pvChecks) { | if (pvChecks) { | ||||
pvChecks->push_back(std::move(check)); | pvChecks->push_back(std::move(check)); | ||||
} else if (!check()) { | } else if (!check()) { | ||||
// Compute flags without the optional standardness flags. | // Compute flags without the optional standardness flags. | ||||
// This differs from MANDATORY_SCRIPT_VERIFY_FLAGS as it contains | // This differs from MANDATORY_SCRIPT_VERIFY_FLAGS as it contains | ||||
// additional upgrade flags (see AcceptToMemoryPoolWorker variable | // additional upgrade flags (see AcceptToMemoryPoolWorker variable | ||||
// extraFlags). | // extraFlags). | ||||
// Even though CLEANSTACK is not mandatory as of yet, it might | |||||
// become in a future revision. Since ALLOW_SEGWIT_RECOVERY | |||||
// allows a more permissive ruleset, we need to manually include | |||||
// it in here to recheck this input under the most permissible set | |||||
// of consensus rules | |||||
uint32_t mandatoryFlags = | uint32_t mandatoryFlags = | ||||
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS; | flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS | | ||||
SCRIPT_ALLOW_SEGWIT_RECOVERY; | |||||
markblundebergAuthorUnsubmitted Done Inline ActionsWould be good to put some parentheses here -- at least speaking for myself, I don't always remember that & has higher operator precedence than |. markblundeberg: Would be good to put some parentheses here -- at least speaking for myself, I don't always… | |||||
deadalnixUnsubmitted Done Inline Actionsdeadalnix: likestamp | |||||
if (flags != mandatoryFlags) { | if (flags != mandatoryFlags) { | ||||
// Check whether the failure was caused by a non-mandatory | // Check whether the failure was caused by a non-mandatory | ||||
// script verification check. If so, don't trigger DoS | // script verification check. If so, don't trigger DoS | ||||
// protection to avoid splitting the network on the basis of | // protection to avoid splitting the network on the basis of | ||||
// relay policy disagreements. | // relay policy disagreements. | ||||
// | |||||
jasonbcoxUnsubmitted Done Inline Actionsremove jasonbcox: remove | |||||
deadalnixUnsubmitted Done Inline ActionsRemove deadalnix: Remove | |||||
CScriptCheck check2(scriptPubKey, amount, tx, i, mandatoryFlags, | CScriptCheck check2(scriptPubKey, amount, tx, i, mandatoryFlags, | ||||
sigCacheStore, txdata); | sigCacheStore, txdata); | ||||
if (check2()) { | if (check2()) { | ||||
return state.Invalid( | return state.Invalid( | ||||
false, REJECT_NONSTANDARD, | false, REJECT_NONSTANDARD, | ||||
strprintf("non-mandatory-script-verify-flag (%s)", | strprintf("non-mandatory-script-verify-flag (%s)", | ||||
ScriptErrorString(check.GetScriptError()))); | ScriptErrorString(check.GetScriptError()))); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 361 Lines • ▼ Show 20 Lines | static uint32_t GetBlockScriptFlags(const Config &config, | ||||
// alternative. We also start enforcing push only signatures and | // alternative. We also start enforcing push only signatures and | ||||
// clean stack. | // clean stack. | ||||
if (IsMagneticAnomalyEnabled(config, pChainTip)) { | if (IsMagneticAnomalyEnabled(config, pChainTip)) { | ||||
flags |= SCRIPT_ENABLE_CHECKDATASIG; | flags |= SCRIPT_ENABLE_CHECKDATASIG; | ||||
flags |= SCRIPT_VERIFY_SIGPUSHONLY; | flags |= SCRIPT_VERIFY_SIGPUSHONLY; | ||||
flags |= SCRIPT_VERIFY_CLEANSTACK; | flags |= SCRIPT_VERIFY_CLEANSTACK; | ||||
} | } | ||||
// If the Great Wall fork is enabled, we start accepting transactions | |||||
// recovering coins sent to segwit addresses | |||||
if (IsGreatWallEnabled(config, pChainTip)) { | |||||
flags |= SCRIPT_ALLOW_SEGWIT_RECOVERY; | |||||
} | |||||
// We make sure this node will have replay protection during the next hard | // We make sure this node will have replay protection during the next hard | ||||
// fork. | // fork. | ||||
if (IsReplayProtectionEnabled(config, pChainTip)) { | if (IsReplayProtectionEnabled(config, pChainTip)) { | ||||
flags |= SCRIPT_ENABLE_REPLAY_PROTECTION; | flags |= SCRIPT_ENABLE_REPLAY_PROTECTION; | ||||
} | } | ||||
return flags; | return flags; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 578 Lines • ▼ Show 20 Lines | |||||
* After calling, the mempool will be in an inconsistent state, with | * After calling, the mempool will be in an inconsistent state, with | ||||
* transactions from disconnected blocks being added to disconnectpool. You | * transactions from disconnected blocks being added to disconnectpool. You | ||||
* should make the mempool consistent again by calling updateMempoolForReorg. | * should make the mempool consistent again by calling updateMempoolForReorg. | ||||
* with cs_main held. | * with cs_main held. | ||||
* | * | ||||
* If disconnectpool is nullptr, then no disconnected transactions are added to | * If disconnectpool is nullptr, then no disconnected transactions are added to | ||||
* disconnectpool (note that the caller is responsible for mempool consistency | * disconnectpool (note that the caller is responsible for mempool consistency | ||||
* in any case). | * in any case). | ||||
* | |||||
* In case of a reorg crossing a fork boundary, i.e. a change in applicable | |||||
* evaluation flags, it queues all mempool transactions in disconnectpool for | |||||
* future reprocessing in updateMempoolForReorg. The mempool is thus emptied. | |||||
*/ | */ | ||||
static bool DisconnectTip(const Config &config, CValidationState &state, | static bool DisconnectTip(const Config &config, CValidationState &state, | ||||
DisconnectedBlockTransactions *disconnectpool) { | DisconnectedBlockTransactions *disconnectpool) { | ||||
CBlockIndex *pindexDelete = chainActive.Tip(); | CBlockIndex *pindexDelete = chainActive.Tip(); | ||||
assert(pindexDelete); | assert(pindexDelete); | ||||
// Read block from disk. | // Read block from disk. | ||||
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | ||||
Show All 24 Lines | if (!FlushStateToDisk(config.GetChainParams(), state, | ||||
FLUSH_STATE_IF_NEEDED)) { | FLUSH_STATE_IF_NEEDED)) { | ||||
return false; | return false; | ||||
} | } | ||||
// If this block was deactivating the replay protection, then we need to | // If this block was deactivating the replay protection, then we need to | ||||
// remove transactions that are replay protected from the mempool. There is | // remove transactions that are replay protected from the mempool. There is | ||||
// no easy way to do this so we'll just discard the whole mempool and then | // no easy way to do this so we'll just discard the whole mempool and then | ||||
// add the transaction of the block we just disconnected back. | // add the transaction of the block we just disconnected back. | ||||
if (IsReplayProtectionEnabled(config, pindexDelete) && | if (IsReplayProtectionEnabled(config, pindexDelete) && | ||||
markblundebergAuthorUnsubmitted Done Inline ActionsSince IsReplayProtectionEnabled involves new flags, this if-block is made redundant by the new code using GetBlockScriptFlags. markblundeberg: Since IsReplayProtectionEnabled involves new flags, this if-block is made redundant by the new… | |||||
!IsReplayProtectionEnabled(config, pindexDelete->pprev)) { | !IsReplayProtectionEnabled(config, pindexDelete->pprev)) { | ||||
LogPrint(BCLog::MEMPOOL, "Clearing mempool for reorg"); | LogPrint(BCLog::MEMPOOL, "Clearing mempool for reorg\n"); | ||||
jasonbcoxUnsubmitted Done Inline ActionsPlease separate this into it's own diff. It sounds silly, but it provides the following benefits for the review process:
jasonbcox: Please separate this into it's own diff. It sounds silly, but it provides the following… | |||||
g_mempool.clear(); | g_mempool.clear(); | ||||
// While not strictly necessary, clearing the disconnect pool is also | // While not strictly necessary, clearing the disconnect pool is also | ||||
// beneficial so we don't try to reuse its content at the end of the | // beneficial so we don't try to reuse its content at the end of the | ||||
// reorg, which we know will fail. | // reorg, which we know will fail. | ||||
if (disconnectpool) { | if (disconnectpool) { | ||||
disconnectpool->clear(); | disconnectpool->clear(); | ||||
} | } | ||||
} | } | ||||
// If this block is deactivating a fork, we enqueue all mempool transactions | |||||
// in front of disconnectpool for future reprocessing | |||||
if (GetBlockScriptFlags(config, pindexDelete) != | |||||
GetBlockScriptFlags(config, pindexDelete->pprev)) { | |||||
LogPrint(BCLog::MEMPOOL, | |||||
"%s mempool for a reorg crossing a fork boundary\n", | |||||
disconnectpool ? "Reprocessing" : "Clearing"); | |||||
if (disconnectpool) { | |||||
disconnectpool->importMempool(); | |||||
} | |||||
g_mempool.clear(); | |||||
} | |||||
jasonbcoxUnsubmitted Done Inline ActionsIs this block necessary for segwit recovery? If not, it really should be it's own diff. jasonbcox: Is this block necessary for segwit recovery? If not, it really should be it's own diff. | |||||
if (disconnectpool) { | if (disconnectpool) { | ||||
disconnectpool->addForBlock(block.vtx); | disconnectpool->addForBlock(block.vtx); | ||||
} | } | ||||
// If the tip is finalized, then undo it. | // If the tip is finalized, then undo it. | ||||
if (pindexFinalized == pindexDelete) { | if (pindexFinalized == pindexDelete) { | ||||
pindexFinalized = pindexDelete->pprev; | pindexFinalized = pindexDelete->pprev; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 3,301 Lines • Show Last 20 Lines |
Check that one first, as it is pretty much free.