Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Copyright (c) 2017 The Bitcoin developers | // Copyright (c) 2017-2018 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include "validation.h" | #include "validation.h" | ||||
#include "arith_uint256.h" | #include "arith_uint256.h" | ||||
#include "chainparams.h" | #include "chainparams.h" | ||||
#include "checkpoints.h" | #include "checkpoints.h" | ||||
▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Lines | |||||
static bool FlushStateToDisk(const CChainParams &chainParams, | static bool FlushStateToDisk(const CChainParams &chainParams, | ||||
CValidationState &state, FlushStateMode mode, | CValidationState &state, FlushStateMode mode, | ||||
int nManualPruneHeight = 0); | int nManualPruneHeight = 0); | ||||
static void FindFilesToPruneManual(std::set<int> &setFilesToPrune, | static void FindFilesToPruneManual(std::set<int> &setFilesToPrune, | ||||
int nManualPruneHeight); | int nManualPruneHeight); | ||||
static void FindFilesToPrune(std::set<int> &setFilesToPrune, | static void FindFilesToPrune(std::set<int> &setFilesToPrune, | ||||
uint64_t nPruneAfterHeight); | uint64_t nPruneAfterHeight); | ||||
static FILE *OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); | static FILE *OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); | ||||
static uint32_t GetBlockScriptFlags(const CBlockIndex *pindex, | uint32_t GetBlockScriptFlags(const Config &config, | ||||
const Config &config); | const CBlockIndex *pindex); | ||||
static bool IsFinalTx(const CTransaction &tx, int nBlockHeight, | static bool IsFinalTx(const CTransaction &tx, int nBlockHeight, | ||||
int64_t nBlockTime) { | int64_t nBlockTime) { | ||||
if (tx.nLockTime == 0) { | if (tx.nLockTime == 0) { | ||||
return true; | return true; | ||||
} | } | ||||
int64_t lockTime = tx.nLockTime; | int64_t lockTime = tx.nLockTime; | ||||
▲ Show 20 Lines • Show All 756 Lines • ▼ Show 20 Lines | // Check for conflicts with in-memory transactions | ||||
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); | ||||
} | } | ||||
// Check against previous transactions. This is done last to help | |||||
// prevent CPU exhaustion denial-of-service attacks. | |||||
PrecomputedTransactionData txdata(tx); | |||||
if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, false, | |||||
txdata)) { | |||||
// State filled in by CheckInputs. | |||||
return false; | |||||
} | |||||
// Check again against the current block tip's script verification flags | // Check again against the current block tip's script verification flags | ||||
// to cache our script execution flags. This is, of course, useless if | // to cache our script execution flags. This is, of course, useless if | ||||
// the next block has different script flags from the previous one, but | // the next block has different script flags from the previous one, but | ||||
// because the cache tracks script flags for us it will auto-invalidate | // because the cache tracks script flags for us it will auto-invalidate | ||||
// and we'll just have a few blocks of extra misses on soft-fork | // and we'll just have a few blocks of extra misses on soft-fork | ||||
// activation. | // activation. | ||||
// | // | ||||
// This is also useful in case of bugs in the standard flags that cause | // This is also useful in case of bugs in the standard flags that cause | ||||
// transactions to pass as valid when they're actually invalid. For | // transactions to pass as valid when they're actually invalid. For | ||||
// instance the STRICTENC flag was incorrectly allowing certain CHECKSIG | // instance the STRICTENC flag was incorrectly allowing certain CHECKSIG | ||||
// NOT scripts to pass, even though they were invalid. | // NOT scripts to pass, even though they were invalid. | ||||
// | // | ||||
// There is a similar check in CreateNewBlock() to prevent creating | // There is a similar check in CreateNewBlock() to prevent creating | ||||
// invalid blocks (using TestBlockValidity), however allowing such | // invalid blocks (using TestBlockValidity), however allowing such | ||||
// transactions into the mempool can be exploited as a DoS attack. | // transactions into the mempool can be exploited as a DoS attack. | ||||
uint32_t currentBlockScriptVerifyFlags = | uint32_t currentBlockScriptVerifyFlags = | ||||
GetBlockScriptFlags(chainActive.Tip(), config); | GetBlockScriptFlags(config, chainActive.Tip()); | ||||
scriptVerifyFlags |= currentBlockScriptVerifyFlags; | |||||
// Check against previous transactions. This is done last to help | |||||
// prevent CPU exhaustion denial-of-service attacks. | |||||
PrecomputedTransactionData txdata(tx); | |||||
if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, false, | |||||
txdata)) { | |||||
// State filled in by CheckInputs. | |||||
return false; | |||||
} | |||||
if (!CheckInputsFromMempoolAndCache(tx, state, view, pool, | if (!CheckInputsFromMempoolAndCache(tx, state, view, pool, | ||||
currentBlockScriptVerifyFlags, true, | currentBlockScriptVerifyFlags, true, | ||||
txdata)) { | txdata)) { | ||||
// If we're using promiscuousmempoolflags, we may hit this normally. | // If we're using promiscuousmempoolflags, we may hit this normally. | ||||
// Check if current block has some flags that scriptVerifyFlags does | // Check if current block has some flags that scriptVerifyFlags does | ||||
// not before printing an ominous warning. | // not before printing an ominous warning. | ||||
if (!(~scriptVerifyFlags & currentBlockScriptVerifyFlags)) { | if (!(~scriptVerifyFlags & currentBlockScriptVerifyFlags)) { | ||||
return error( | return error( | ||||
▲ Show 20 Lines • Show All 529 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < tx.vin.size(); i++) { | ||||
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()))); | ||||
} | } | ||||
} | } | ||||
if (!(flags & SCRIPT_ENABLE_OPCODES_MONOLITH)) { | |||||
// Check whether the failure was caused by an opcode used in | |||||
// the monolith fork deployment. We do not want to trigger DoS | |||||
// protection and cause a network split if so. | |||||
CScriptCheck check2(scriptPubKey, amount, tx, i, | |||||
flags & | |||||
SCRIPT_ENABLE_OPCODES_MONOLITH, | |||||
sigCacheStore, txdata); | |||||
if (!check2()) { | |||||
return state.DoS( | |||||
100, false, REJECT_INVALID, | |||||
movrcx: The comment for this branch isn't matching up with the current ban score so it'll need to be… | |||||
movrcxUnsubmitted Not Done Inline ActionsActually nevermind.. I think this impacts mostly ConnectBlock() as the p2p transaction relay tests are running appropriately. movrcx: Actually nevermind.. I think this impacts mostly ConnectBlock() as the p2p transaction relay… | |||||
strprintf("monolith-fork-script-failure (%s)", | |||||
ScriptErrorString(check.GetScriptError()))); | |||||
} | |||||
} | |||||
// Failures of other flags indicate a transaction that is invalid in | // Failures of other flags indicate a transaction that is invalid in | ||||
// new blocks, e.g. a invalid P2SH. We DoS ban such nodes as they | // new blocks, e.g. a invalid P2SH. We DoS ban such nodes as they | ||||
// are not following the protocol. That said during an upgrade | // are not following the protocol. That said during an upgrade | ||||
// careful thought should be taken as to the correct behavior - we | // careful thought should be taken as to the correct behavior - we | ||||
// may want to continue peering with non-upgraded nodes even after | // may want to continue peering with non-upgraded nodes even after | ||||
// soft-fork super-majority signaling has occurred. | // soft-fork super-majority signaling has occurred. | ||||
return state.DoS( | return state.DoS( | ||||
100, false, REJECT_INVALID, | 100, false, REJECT_INVALID, | ||||
▲ Show 20 Lines • Show All 292 Lines • ▼ Show 20 Lines | bool Condition(const CBlockIndex *pindex, | ||||
((ComputeBlockVersion(pindex->pprev, params) >> bit) & 1) == 0; | ((ComputeBlockVersion(pindex->pprev, params) >> bit) & 1) == 0; | ||||
} | } | ||||
}; | }; | ||||
// Protected by cs_main | // Protected by cs_main | ||||
static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS]; | static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS]; | ||||
// Returns the script flags which should be checked for a given block | // Returns the script flags which should be checked for a given block | ||||
static uint32_t GetBlockScriptFlags(const CBlockIndex *pindex, | uint32_t GetBlockScriptFlags(const Config &config, | ||||
const Config &config) { | const CBlockIndex *pindex) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
const Consensus::Params &consensusparams = | const Consensus::Params &consensusparams = | ||||
config.GetChainParams().GetConsensus(); | config.GetChainParams().GetConsensus(); | ||||
// BIP16 didn't become active until Apr 1 2012 | // BIP16 didn't become active until Apr 1 2012 | ||||
int64_t nBIP16SwitchTime = 1333238400; | int64_t nBIP16SwitchTime = 1333238400; | ||||
bool fStrictPayToScriptHash = (pindex->GetBlockTime() >= nBIP16SwitchTime); | bool fStrictPayToScriptHash = (pindex->GetBlockTime() >= nBIP16SwitchTime); | ||||
uint32_t flags = | uint32_t flags = | ||||
fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE; | fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE; | ||||
// Start enforcing the DERSIG (BIP66) rule | // Start enforcing the DERSIG (BIP66) rule | ||||
if (pindex->nHeight >= consensusparams.BIP66Height) { | if (pindex->nHeight >= consensusparams.BIP66Height) { | ||||
flags |= SCRIPT_VERIFY_DERSIG; | flags |= SCRIPT_VERIFY_DERSIG; | ||||
} | } | ||||
// Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule | // Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule | ||||
if (pindex->nHeight >= consensusparams.BIP65Height) { | if (pindex->nHeight >= consensusparams.BIP65Height) { | ||||
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; | flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; | ||||
} | } | ||||
// Start enforcing BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic. | // Start enforcing BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic. | ||||
if (VersionBitsState(pindex->pprev, consensusparams, | if (VersionBitsState(pindex->pprev, consensusparams, Consensus::DEPLOYMENT_CSV, | ||||
Consensus::DEPLOYMENT_CSV, | |||||
versionbitscache) == THRESHOLD_ACTIVE) { | versionbitscache) == THRESHOLD_ACTIVE) { | ||||
flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; | flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; | ||||
} | } | ||||
// If the UAHF is enabled, we start accepting replay protected txns | // If the UAHF is enabled, we start accepting replay protected txns | ||||
if (IsUAHFenabled(config, pindex->pprev)) { | if (IsUAHFenabled(config, pindex->pprev)) { | ||||
flags |= SCRIPT_VERIFY_STRICTENC; | flags |= SCRIPT_VERIFY_STRICTENC; | ||||
flags |= SCRIPT_ENABLE_SIGHASH_FORKID; | flags |= SCRIPT_ENABLE_SIGHASH_FORKID; | ||||
} | } | ||||
// If the DAA HF is enabled, we start rejecting transaction that use a high | // If the DAA HF is enabled, we start rejecting transaction that use a high | ||||
// s in their signature. We also make sure that signature that are supposed | // s in their signature. We also make sure that signature that are supposed | ||||
// to fail (for instance in multisig or other forms of smart contracts) are | // to fail (for instance in multisig or other forms of smart contracts) are | ||||
// null. | // null. | ||||
if (IsDAAEnabled(config, pindex->pprev)) { | if (IsDAAEnabled(config, pindex->pprev)) { | ||||
flags |= SCRIPT_VERIFY_LOW_S; | flags |= SCRIPT_VERIFY_LOW_S; | ||||
flags |= SCRIPT_VERIFY_NULLFAIL; | flags |= SCRIPT_VERIFY_NULLFAIL; | ||||
} | } | ||||
if (IsMonolithEnabled(config, pindex)) { | |||||
// When the May 15, 2018 HF is enabled, activate new opcodes. | |||||
flags |= SCRIPT_ENABLE_OPCODES_MONOLITH; | |||||
} | |||||
return flags; | return flags; | ||||
} | } | ||||
static int64_t nTimeCheck = 0; | static int64_t nTimeCheck = 0; | ||||
static int64_t nTimeForks = 0; | static int64_t nTimeForks = 0; | ||||
static int64_t nTimeVerify = 0; | static int64_t nTimeVerify = 0; | ||||
static int64_t nTimeConnect = 0; | static int64_t nTimeConnect = 0; | ||||
static int64_t nTimeIndex = 0; | static int64_t nTimeIndex = 0; | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | static bool ConnectBlock(const Config &config, const CBlock &block, | ||||
// Start enforcing BIP68 (sequence locks) using versionbits logic. | // Start enforcing BIP68 (sequence locks) using versionbits logic. | ||||
int nLockTimeFlags = 0; | int nLockTimeFlags = 0; | ||||
if (VersionBitsState(pindex->pprev, consensusParams, | if (VersionBitsState(pindex->pprev, consensusParams, | ||||
Consensus::DEPLOYMENT_CSV, | Consensus::DEPLOYMENT_CSV, | ||||
versionbitscache) == THRESHOLD_ACTIVE) { | versionbitscache) == THRESHOLD_ACTIVE) { | ||||
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; | nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; | ||||
} | } | ||||
uint32_t flags = GetBlockScriptFlags(pindex, config); | uint32_t flags = GetBlockScriptFlags(config, pindex); | ||||
int64_t nTime2 = GetTimeMicros(); | int64_t nTime2 = GetTimeMicros(); | ||||
nTimeForks += nTime2 - nTime1; | nTimeForks += nTime2 - nTime1; | ||||
LogPrint(BCLog::BENCH, " - Fork checks: %.2fms [%.2fs]\n", | LogPrint(BCLog::BENCH, " - Fork checks: %.2fms [%.2fs]\n", | ||||
0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); | 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); | ||||
CBlockUndo blockundo; | CBlockUndo blockundo; | ||||
▲ Show 20 Lines • Show All 328 Lines • ▼ Show 20 Lines | |||||
void PruneAndFlush() { | void PruneAndFlush() { | ||||
CValidationState state; | CValidationState state; | ||||
fCheckForPruning = true; | fCheckForPruning = true; | ||||
const CChainParams &chainparams = Params(); | const CChainParams &chainparams = Params(); | ||||
FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); | FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); | ||||
} | } | ||||
/** | /** | ||||
* Update chainActive and related internal data structures when adding a new block to the chain tip. | * Update chainActive and related internal data structures when adding a new | ||||
* block to the chain tip. | |||||
*/ | */ | ||||
static void UpdateTip(const Config &config, CBlockIndex *pindexNew) { | static void UpdateTip(const Config &config, CBlockIndex *pindexNew) { | ||||
const Consensus::Params &consensusParams = | const Consensus::Params &consensusParams = | ||||
config.GetChainParams().GetConsensus(); | config.GetChainParams().GetConsensus(); | ||||
chainActive.SetTip(pindexNew); | chainActive.SetTip(pindexNew); | ||||
// New best block | // New best block | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | LogPrint(BCLog::BENCH, "- Disconnect block: %.2fms\n", | ||||
(GetTimeMicros() - nStart) * 0.001); | (GetTimeMicros() - nStart) * 0.001); | ||||
// Write the chain state to disk, if necessary. | // Write the chain state to disk, if necessary. | ||||
if (!FlushStateToDisk(config.GetChainParams(), state, | if (!FlushStateToDisk(config.GetChainParams(), state, | ||||
FLUSH_STATE_IF_NEEDED)) { | FLUSH_STATE_IF_NEEDED)) { | ||||
return false; | return false; | ||||
} | } | ||||
// If this block was activating the monolith opcodes, then we need to | |||||
// remove any transactions that use the monolith opcodes from the mempool. | |||||
// There is 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. | |||||
if (IsMonolithEnabled(config, pindexDelete) && | |||||
!IsMonolithEnabled(config, pindexDelete->pprev)) { | |||||
mempool.clear(); | |||||
} | |||||
if (disconnectpool) { | if (disconnectpool) { | ||||
// Save transactions to re-add to mempool at end of reorg | // Save transactions to re-add to mempool at end of reorg | ||||
for (const auto &tx : boost::adaptors::reverse(block.vtx)) { | for (const auto &tx : boost::adaptors::reverse(block.vtx)) { | ||||
disconnectpool->addTransaction(tx); | disconnectpool->addTransaction(tx); | ||||
} | } | ||||
while (disconnectpool->DynamicMemoryUsage() > | while (disconnectpool->DynamicMemoryUsage() > | ||||
MAX_DISCONNECTED_TX_POOL_SIZE) { | MAX_DISCONNECTED_TX_POOL_SIZE) { | ||||
// Drop the earliest entry, and remove its children from the | // Drop the earliest entry, and remove its children from the | ||||
▲ Show 20 Lines • Show All 1,039 Lines • ▼ Show 20 Lines | static bool ContextualCheckBlock(const Config &config, const CBlock &block, | ||||
int nLockTimeFlags = 0; | int nLockTimeFlags = 0; | ||||
if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV, | if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV, | ||||
versionbitscache) == THRESHOLD_ACTIVE) { | versionbitscache) == THRESHOLD_ACTIVE) { | ||||
nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST; | nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST; | ||||
} | } | ||||
if (!IsMonolithEnabled(config, pindexPrev)) { | if (!IsMonolithEnabled(config, pindexPrev)) { | ||||
// When the May 15, 2018 HF is not enabled, block cannot be bigger | // When the May 15, 2018 HF is not enabled, block cannot be bigger | ||||
// than 8MB . | // than 8MB. | ||||
const uint64_t currentBlockSize = | const uint64_t currentBlockSize = | ||||
::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); | ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); | ||||
if (currentBlockSize > 8 * ONE_MEGABYTE) { | if (currentBlockSize > 8 * ONE_MEGABYTE) { | ||||
return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", | return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", | ||||
false, "size limits failed"); | false, "size limits failed"); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,759 Lines • Show Last 20 Lines |
The comment for this branch isn't matching up with the current ban score so it'll need to be changed. What's the intended ban score?