Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show All 18 Lines | |||||
#include <checkqueue.h> | #include <checkqueue.h> | ||||
#include <config.h> | #include <config.h> | ||||
#include <consensus/activation.h> | #include <consensus/activation.h> | ||||
#include <consensus/amount.h> | #include <consensus/amount.h> | ||||
#include <consensus/merkle.h> | #include <consensus/merkle.h> | ||||
#include <consensus/tx_check.h> | #include <consensus/tx_check.h> | ||||
#include <consensus/tx_verify.h> | #include <consensus/tx_verify.h> | ||||
#include <consensus/validation.h> | #include <consensus/validation.h> | ||||
#include <deploymentstatus.h> | |||||
#include <fs.h> | #include <fs.h> | ||||
#include <hash.h> | #include <hash.h> | ||||
#include <index/blockfilterindex.h> | #include <index/blockfilterindex.h> | ||||
#include <logging.h> | #include <logging.h> | ||||
#include <logging/timer.h> | #include <logging/timer.h> | ||||
#include <minerfund.h> | #include <minerfund.h> | ||||
#include <node/blockstorage.h> | #include <node/blockstorage.h> | ||||
#include <node/coinstats.h> | #include <node/coinstats.h> | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | for (const BlockHash &hash : locator.vHave) { | ||||
if (pindex->GetAncestor(m_chain.Height()) == m_chain.Tip()) { | if (pindex->GetAncestor(m_chain.Height()) == m_chain.Tip()) { | ||||
return m_chain.Tip(); | return m_chain.Tip(); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return m_chain.Genesis(); | return m_chain.Genesis(); | ||||
} | } | ||||
static uint32_t GetNextBlockScriptFlags(const Consensus::Params ¶ms, | static uint32_t GetNextBlockScriptFlags(const CBlockIndex *pindex, | ||||
const CBlockIndex *pindex); | const ChainstateManager &chainman); | ||||
bool CheckSequenceLocksAtTip(CBlockIndex *tip, const CCoinsView &coins_view, | bool CheckSequenceLocksAtTip(CBlockIndex *tip, const CCoinsView &coins_view, | ||||
const CTransaction &tx, LockPoints *lp, | const CTransaction &tx, LockPoints *lp, | ||||
bool useExistingLockPoints) { | bool useExistingLockPoints) { | ||||
assert(tip != nullptr); | assert(tip != nullptr); | ||||
CBlockIndex index; | CBlockIndex index; | ||||
index.pprev = tip; | index.pprev = tip; | ||||
▲ Show 20 Lines • Show All 645 Lines • ▼ Show 20 Lines | |||||
MempoolAcceptResult | MempoolAcceptResult | ||||
MemPoolAccept::AcceptSingleTransaction(const CTransactionRef &ptx, | MemPoolAccept::AcceptSingleTransaction(const CTransactionRef &ptx, | ||||
ATMPArgs &args) { | ATMPArgs &args) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
// mempool "read lock" (held through | // mempool "read lock" (held through | ||||
// GetMainSignals().TransactionAddedToMempool()) | // GetMainSignals().TransactionAddedToMempool()) | ||||
LOCK(m_pool.cs); | LOCK(m_pool.cs); | ||||
const Consensus::Params &consensusParams = | |||||
args.m_config.GetChainParams().GetConsensus(); | |||||
const CBlockIndex *tip = m_active_chainstate.m_chain.Tip(); | const CBlockIndex *tip = m_active_chainstate.m_chain.Tip(); | ||||
Workspace ws(ptx, GetNextBlockScriptFlags(consensusParams, tip)); | Workspace ws(ptx, | ||||
GetNextBlockScriptFlags(tip, m_active_chainstate.m_chainman)); | |||||
// Perform the inexpensive checks first and avoid hashing and signature | // Perform the inexpensive checks first and avoid hashing and signature | ||||
// verification unless those checks pass, to mitigate CPU exhaustion | // verification unless those checks pass, to mitigate CPU exhaustion | ||||
// denial-of-service attacks. | // denial-of-service attacks. | ||||
if (!PreChecks(args, ws)) { | if (!PreChecks(args, ws)) { | ||||
return MempoolAcceptResult::Failure(ws.m_state); | return MempoolAcceptResult::Failure(ws.m_state); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions( | ||||
// lock. | // lock. | ||||
PackageValidationState package_state; | PackageValidationState package_state; | ||||
if (!CheckPackage(txns, package_state)) { | if (!CheckPackage(txns, package_state)) { | ||||
return PackageMempoolAcceptResult(package_state, {}); | return PackageMempoolAcceptResult(package_state, {}); | ||||
} | } | ||||
std::vector<Workspace> workspaces{}; | std::vector<Workspace> workspaces{}; | ||||
workspaces.reserve(txns.size()); | workspaces.reserve(txns.size()); | ||||
std::transform(txns.cbegin(), txns.cend(), std::back_inserter(workspaces), | std::transform( | ||||
[&args, this](const auto &tx) { | txns.cbegin(), txns.cend(), std::back_inserter(workspaces), | ||||
[this](const auto &tx) { | |||||
return Workspace( | return Workspace( | ||||
tx, | tx, GetNextBlockScriptFlags(m_active_chainstate.m_chain.Tip(), | ||||
GetNextBlockScriptFlags( | m_active_chainstate.m_chainman)); | ||||
args.m_config.GetChainParams().GetConsensus(), | |||||
m_active_chainstate.m_chain.Tip())); | |||||
}); | }); | ||||
std::map<const TxId, const MempoolAcceptResult> results; | std::map<const TxId, const MempoolAcceptResult> results; | ||||
LOCK(m_pool.cs); | LOCK(m_pool.cs); | ||||
// Do all PreChecks first and fail fast to avoid running expensive script | // Do all PreChecks first and fail fast to avoid running expensive script | ||||
// checks when unnecessary. | // checks when unnecessary. | ||||
for (Workspace &ws : workspaces) { | for (Workspace &ws : workspaces) { | ||||
if (!PreChecks(args, ws)) { | if (!PreChecks(args, ws)) { | ||||
▲ Show 20 Lines • Show All 720 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void StopScriptCheckWorkerThreads() { | void StopScriptCheckWorkerThreads() { | ||||
scriptcheckqueue.StopWorkerThreads(); | scriptcheckqueue.StopWorkerThreads(); | ||||
} | } | ||||
// Returns the script flags which should be checked for the block after | // Returns the script flags which should be checked for the block after | ||||
// the given block. | // the given block. | ||||
static uint32_t GetNextBlockScriptFlags(const Consensus::Params ¶ms, | static uint32_t GetNextBlockScriptFlags(const CBlockIndex *pindex, | ||||
const CBlockIndex *pindex) { | const ChainstateManager &chainman) { | ||||
const Consensus::Params &consensusparams = chainman.GetConsensus(); | |||||
uint32_t flags = SCRIPT_VERIFY_NONE; | uint32_t flags = SCRIPT_VERIFY_NONE; | ||||
// Enforce P2SH (BIP16) | // Enforce P2SH (BIP16) | ||||
if (DeploymentActiveAfter(pindex, params, Consensus::DEPLOYMENT_P2SH)) { | if (DeploymentActiveAfter(pindex, chainman, Consensus::DEPLOYMENT_P2SH)) { | ||||
flags |= SCRIPT_VERIFY_P2SH; | flags |= SCRIPT_VERIFY_P2SH; | ||||
} | } | ||||
// Enforce the DERSIG (BIP66) rule. | // Enforce the DERSIG (BIP66) rule. | ||||
if (DeploymentActiveAfter(pindex, params, Consensus::DEPLOYMENT_DERSIG)) { | if (DeploymentActiveAfter(pindex, chainman, Consensus::DEPLOYMENT_DERSIG)) { | ||||
flags |= SCRIPT_VERIFY_DERSIG; | flags |= SCRIPT_VERIFY_DERSIG; | ||||
} | } | ||||
// Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule. | // Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule. | ||||
if (DeploymentActiveAfter(pindex, params, Consensus::DEPLOYMENT_CLTV)) { | if (DeploymentActiveAfter(pindex, chainman, Consensus::DEPLOYMENT_CLTV)) { | ||||
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; | flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; | ||||
} | } | ||||
// Start enforcing CSV (BIP68, BIP112 and BIP113) rule. | // Start enforcing CSV (BIP68, BIP112 and BIP113) rule. | ||||
if (DeploymentActiveAfter(pindex, params, Consensus::DEPLOYMENT_CSV)) { | if (DeploymentActiveAfter(pindex, chainman, Consensus::DEPLOYMENT_CSV)) { | ||||
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(params, pindex)) { | if (IsUAHFenabled(consensusparams, pindex)) { | ||||
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(params, pindex)) { | if (IsDAAEnabled(consensusparams, pindex)) { | ||||
flags |= SCRIPT_VERIFY_LOW_S; | flags |= SCRIPT_VERIFY_LOW_S; | ||||
flags |= SCRIPT_VERIFY_NULLFAIL; | flags |= SCRIPT_VERIFY_NULLFAIL; | ||||
} | } | ||||
// When the magnetic anomaly fork is enabled, we start accepting | // When the magnetic anomaly fork is enabled, we start accepting | ||||
// transactions using the OP_CHECKDATASIG opcode and it's verify | // transactions using the OP_CHECKDATASIG opcode and it's verify | ||||
// alternative. We also start enforcing push only signatures and | // alternative. We also start enforcing push only signatures and | ||||
// clean stack. | // clean stack. | ||||
if (IsMagneticAnomalyEnabled(params, pindex)) { | if (IsMagneticAnomalyEnabled(consensusparams, pindex)) { | ||||
flags |= SCRIPT_VERIFY_SIGPUSHONLY; | flags |= SCRIPT_VERIFY_SIGPUSHONLY; | ||||
flags |= SCRIPT_VERIFY_CLEANSTACK; | flags |= SCRIPT_VERIFY_CLEANSTACK; | ||||
} | } | ||||
if (IsGravitonEnabled(params, pindex)) { | if (IsGravitonEnabled(consensusparams, pindex)) { | ||||
flags |= SCRIPT_ENABLE_SCHNORR_MULTISIG; | flags |= SCRIPT_ENABLE_SCHNORR_MULTISIG; | ||||
flags |= SCRIPT_VERIFY_MINIMALDATA; | flags |= SCRIPT_VERIFY_MINIMALDATA; | ||||
} | } | ||||
if (IsPhononEnabled(params, pindex)) { | if (IsPhononEnabled(consensusparams, pindex)) { | ||||
flags |= SCRIPT_ENFORCE_SIGCHECKS; | flags |= SCRIPT_ENFORCE_SIGCHECKS; | ||||
} | } | ||||
// 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(params, pindex)) { | if (IsReplayProtectionEnabled(consensusparams, pindex)) { | ||||
flags |= SCRIPT_ENABLE_REPLAY_PROTECTION; | flags |= SCRIPT_ENABLE_REPLAY_PROTECTION; | ||||
} | } | ||||
return flags; | return flags; | ||||
} | } | ||||
static int64_t nTimeCheck = 0; | static int64_t nTimeCheck = 0; | ||||
static int64_t nTimeForks = 0; | static int64_t nTimeForks = 0; | ||||
▲ Show 20 Lines • Show All 223 Lines • ▼ Show 20 Lines | bool Chainstate::ConnectBlock(const CBlock &block, BlockValidationState &state, | ||||
// Enforce BIP68 (sequence locks). | // Enforce BIP68 (sequence locks). | ||||
int nLockTimeFlags = 0; | int nLockTimeFlags = 0; | ||||
if (DeploymentActiveAt(*pindex, consensusParams, | if (DeploymentActiveAt(*pindex, consensusParams, | ||||
Consensus::DEPLOYMENT_CSV)) { | Consensus::DEPLOYMENT_CSV)) { | ||||
nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; | nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; | ||||
} | } | ||||
const uint32_t flags = | const uint32_t flags = GetNextBlockScriptFlags(pindex->pprev, m_chainman); | ||||
GetNextBlockScriptFlags(consensusParams, pindex->pprev); | |||||
int64_t nTime2 = GetTimeMicros(); | int64_t nTime2 = GetTimeMicros(); | ||||
nTimeForks += nTime2 - nTime1; | nTimeForks += nTime2 - nTime1; | ||||
LogPrint(BCLog::BENCH, " - Fork checks: %.2fms [%.2fs (%.2fms/blk)]\n", | LogPrint(BCLog::BENCH, " - Fork checks: %.2fms [%.2fs (%.2fms/blk)]\n", | ||||
MILLI * (nTime2 - nTime1), nTimeForks * MICRO, | MILLI * (nTime2 - nTime1), nTimeForks * MICRO, | ||||
nTimeForks * MILLI / nBlocksTotal); | nTimeForks * MILLI / nBlocksTotal); | ||||
std::vector<int> prevheights; | std::vector<int> prevheights; | ||||
▲ Show 20 Lines • Show All 515 Lines • ▼ Show 20 Lines | if (!FlushStateToDisk(state, FlushStateMode::IF_NEEDED)) { | ||||
return false; | return false; | ||||
} | } | ||||
if (m_mempool) { | if (m_mempool) { | ||||
// If this block is deactivating a fork, we move all mempool | // If this block is deactivating a fork, we move all mempool | ||||
// transactions in front of disconnectpool for reprocessing in a future | // transactions in front of disconnectpool for reprocessing in a future | ||||
// updateMempoolForReorg call | // updateMempoolForReorg call | ||||
if (pindexDelete->pprev != nullptr && | if (pindexDelete->pprev != nullptr && | ||||
GetNextBlockScriptFlags(consensusParams, pindexDelete) != | GetNextBlockScriptFlags(pindexDelete, m_chainman) != | ||||
GetNextBlockScriptFlags(consensusParams, pindexDelete->pprev)) { | GetNextBlockScriptFlags(pindexDelete->pprev, m_chainman)) { | ||||
LogPrint(BCLog::MEMPOOL, | LogPrint(BCLog::MEMPOOL, | ||||
"Disconnecting mempool due to rewind of upgrade block\n"); | "Disconnecting mempool due to rewind of upgrade block\n"); | ||||
if (disconnectpool) { | if (disconnectpool) { | ||||
disconnectpool->importMempool(*m_mempool); | disconnectpool->importMempool(*m_mempool); | ||||
} | } | ||||
m_mempool->clear(); | m_mempool->clear(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | bool Chainstate::ConnectTip(BlockValidationState &state, | ||||
// Remove conflicting transactions from the mempool; | // Remove conflicting transactions from the mempool; | ||||
if (m_mempool) { | if (m_mempool) { | ||||
disconnectpool.removeForBlock(blockConnecting.vtx, *m_mempool); | disconnectpool.removeForBlock(blockConnecting.vtx, *m_mempool); | ||||
// If this block is activating a fork, we move all mempool transactions | // If this block is activating a fork, we move all mempool transactions | ||||
// in front of disconnectpool for reprocessing in a future | // in front of disconnectpool for reprocessing in a future | ||||
// updateMempoolForReorg call | // updateMempoolForReorg call | ||||
if (pindexNew->pprev != nullptr && | if (pindexNew->pprev != nullptr && | ||||
GetNextBlockScriptFlags(consensusParams, pindexNew) != | GetNextBlockScriptFlags(pindexNew, m_chainman) != | ||||
GetNextBlockScriptFlags(consensusParams, pindexNew->pprev)) { | GetNextBlockScriptFlags(pindexNew->pprev, m_chainman)) { | ||||
LogPrint( | LogPrint( | ||||
BCLog::MEMPOOL, | BCLog::MEMPOOL, | ||||
"Disconnecting mempool due to acceptance of upgrade block\n"); | "Disconnecting mempool due to acceptance of upgrade block\n"); | ||||
disconnectpool.importMempool(*m_mempool); | disconnectpool.importMempool(*m_mempool); | ||||
} | } | ||||
} | } | ||||
// Update m_chain & related variables. | // Update m_chain & related variables. | ||||
▲ Show 20 Lines • Show All 1,195 Lines • ▼ Show 20 Lines | |||||
* By "context", we mean only the previous block headers, but not the UTXO | * By "context", we mean only the previous block headers, but not the UTXO | ||||
* set; UTXO-related validity checks are done in ConnectBlock(). | * set; UTXO-related validity checks are done in ConnectBlock(). | ||||
* NOTE: This function is not currently invoked by ConnectBlock(), so we | * NOTE: This function is not currently invoked by ConnectBlock(), so we | ||||
* should consider upgrade issues if we change which consensus rules are | * should consider upgrade issues if we change which consensus rules are | ||||
* enforced in this function (eg by adding a new consensus rule). See comment | * enforced in this function (eg by adding a new consensus rule). See comment | ||||
* in ConnectBlock(). | * in ConnectBlock(). | ||||
* Note that -reindex-chainstate skips the validation that happens here! | * Note that -reindex-chainstate skips the validation that happens here! | ||||
*/ | */ | ||||
static bool ContextualCheckBlockHeader(const CChainParams ¶ms, | static bool ContextualCheckBlockHeader(const CBlockHeader &block, | ||||
const CBlockHeader &block, | |||||
BlockValidationState &state, | BlockValidationState &state, | ||||
BlockManager &blockman, | BlockManager &blockman, | ||||
ChainstateManager &chainman, | |||||
const CBlockIndex *pindexPrev, | const CBlockIndex *pindexPrev, | ||||
NodeClock::time_point now) | NodeClock::time_point now) | ||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { | ||||
AssertLockHeld(::cs_main); | AssertLockHeld(::cs_main); | ||||
assert(pindexPrev != nullptr); | assert(pindexPrev != nullptr); | ||||
const int nHeight = pindexPrev->nHeight + 1; | const int nHeight = pindexPrev->nHeight + 1; | ||||
const CChainParams ¶ms = chainman.GetParams(); | |||||
// Check proof of work | // Check proof of work | ||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, params)) { | if (block.nBits != GetNextWorkRequired(pindexPrev, &block, params)) { | ||||
LogPrintf("bad bits after height: %d\n", pindexPrev->nHeight); | LogPrintf("bad bits after height: %d\n", pindexPrev->nHeight); | ||||
return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, | return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, | ||||
"bad-diffbits", "incorrect proof of work"); | "bad-diffbits", "incorrect proof of work"); | ||||
} | } | ||||
// Check against checkpoints | // Check against checkpoints | ||||
Show All 34 Lines | static bool ContextualCheckBlockHeader(const CBlockHeader &block, | ||||
// Check timestamp | // Check timestamp | ||||
if (block.Time() > now + std::chrono::seconds{MAX_FUTURE_BLOCK_TIME}) { | if (block.Time() > now + std::chrono::seconds{MAX_FUTURE_BLOCK_TIME}) { | ||||
return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, | return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, | ||||
"time-too-new", | "time-too-new", | ||||
"block timestamp too far in the future"); | "block timestamp too far in the future"); | ||||
} | } | ||||
const Consensus::Params &consensusParams = params.GetConsensus(); | |||||
// Reject blocks with outdated version | // Reject blocks with outdated version | ||||
if ((block.nVersion < 2 && | if ((block.nVersion < 2 && | ||||
DeploymentActiveAfter(pindexPrev, consensusParams, | DeploymentActiveAfter(pindexPrev, chainman, | ||||
Consensus::DEPLOYMENT_HEIGHTINCB)) || | Consensus::DEPLOYMENT_HEIGHTINCB)) || | ||||
(block.nVersion < 3 && | (block.nVersion < 3 && | ||||
DeploymentActiveAfter(pindexPrev, consensusParams, | DeploymentActiveAfter(pindexPrev, chainman, | ||||
Consensus::DEPLOYMENT_DERSIG)) || | Consensus::DEPLOYMENT_DERSIG)) || | ||||
(block.nVersion < 4 && | (block.nVersion < 4 && | ||||
DeploymentActiveAfter(pindexPrev, consensusParams, | DeploymentActiveAfter(pindexPrev, chainman, | ||||
Consensus::DEPLOYMENT_CLTV))) { | Consensus::DEPLOYMENT_CLTV))) { | ||||
return state.Invalid( | return state.Invalid( | ||||
BlockValidationResult::BLOCK_INVALID_HEADER, | BlockValidationResult::BLOCK_INVALID_HEADER, | ||||
strprintf("bad-version(0x%08x)", block.nVersion), | strprintf("bad-version(0x%08x)", block.nVersion), | ||||
strprintf("rejected nVersion=0x%08x block", block.nVersion)); | strprintf("rejected nVersion=0x%08x block", block.nVersion)); | ||||
} | } | ||||
return true; | return true; | ||||
Show All 31 Lines | |||||
* NOTE: This function is not currently invoked by ConnectBlock(), so we | * NOTE: This function is not currently invoked by ConnectBlock(), so we | ||||
* should consider upgrade issues if we change which consensus rules are | * should consider upgrade issues if we change which consensus rules are | ||||
* enforced in this function (eg by adding a new consensus rule). See comment | * enforced in this function (eg by adding a new consensus rule). See comment | ||||
* in ConnectBlock(). | * in ConnectBlock(). | ||||
* Note that -reindex-chainstate skips the validation that happens here! | * Note that -reindex-chainstate skips the validation that happens here! | ||||
*/ | */ | ||||
static bool ContextualCheckBlock(const CBlock &block, | static bool ContextualCheckBlock(const CBlock &block, | ||||
BlockValidationState &state, | BlockValidationState &state, | ||||
const Consensus::Params ¶ms, | const ChainstateManager &chainman, | ||||
const CBlockIndex *pindexPrev) { | const CBlockIndex *pindexPrev) { | ||||
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; | const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; | ||||
// Enforce BIP113 (Median Time Past). | // Enforce BIP113 (Median Time Past). | ||||
bool enforce_locktime_median_time_past{false}; | bool enforce_locktime_median_time_past{false}; | ||||
if (DeploymentActiveAfter(pindexPrev, params, Consensus::DEPLOYMENT_CSV)) { | if (DeploymentActiveAfter(pindexPrev, chainman, | ||||
Consensus::DEPLOYMENT_CSV)) { | |||||
assert(pindexPrev != nullptr); | assert(pindexPrev != nullptr); | ||||
enforce_locktime_median_time_past = true; | enforce_locktime_median_time_past = true; | ||||
} | } | ||||
const int64_t nMedianTimePast = | const int64_t nMedianTimePast = | ||||
pindexPrev == nullptr ? 0 : pindexPrev->GetMedianTimePast(); | pindexPrev == nullptr ? 0 : pindexPrev->GetMedianTimePast(); | ||||
const int64_t nLockTimeCutoff{enforce_locktime_median_time_past | const int64_t nLockTimeCutoff{enforce_locktime_median_time_past | ||||
? nMedianTimePast | ? nMedianTimePast | ||||
: block.GetBlockTime()}; | : block.GetBlockTime()}; | ||||
const Consensus::Params params = chainman.GetConsensus(); | |||||
const bool fIsMagneticAnomalyEnabled = | const bool fIsMagneticAnomalyEnabled = | ||||
IsMagneticAnomalyEnabled(params, pindexPrev); | IsMagneticAnomalyEnabled(params, pindexPrev); | ||||
// Check transactions: | // Check transactions: | ||||
// - canonical ordering | // - canonical ordering | ||||
// - ensure they are finalized | // - ensure they are finalized | ||||
// - check they have the minimum size | // - check they have the minimum size | ||||
const CTransaction *prevTx = nullptr; | const CTransaction *prevTx = nullptr; | ||||
Show All 25 Lines | for (const auto &ptx : block.vtx) { | ||||
nLockTimeCutoff)) { | nLockTimeCutoff)) { | ||||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, | return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, | ||||
tx_state.GetRejectReason(), | tx_state.GetRejectReason(), | ||||
tx_state.GetDebugMessage()); | tx_state.GetDebugMessage()); | ||||
} | } | ||||
} | } | ||||
// Enforce rule that the coinbase starts with serialized block height | // Enforce rule that the coinbase starts with serialized block height | ||||
if (DeploymentActiveAfter(pindexPrev, params, | if (DeploymentActiveAfter(pindexPrev, chainman, | ||||
Consensus::DEPLOYMENT_HEIGHTINCB)) { | Consensus::DEPLOYMENT_HEIGHTINCB)) { | ||||
CScript expect = CScript() << nHeight; | CScript expect = CScript() << nHeight; | ||||
if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() || | if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() || | ||||
!std::equal(expect.begin(), expect.end(), | !std::equal(expect.begin(), expect.end(), | ||||
block.vtx[0]->vin[0].scriptSig.begin())) { | block.vtx[0]->vin[0].scriptSig.begin())) { | ||||
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, | return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, | ||||
"bad-cb-height", | "bad-cb-height", | ||||
"block height mismatch in coinbase"); | "block height mismatch in coinbase"); | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | if (hash != chainparams.GetConsensus().hashGenesisBlock) { | ||||
if (pindexPrev->nStatus.isInvalid()) { | if (pindexPrev->nStatus.isInvalid()) { | ||||
LogPrint(BCLog::VALIDATION, | LogPrint(BCLog::VALIDATION, | ||||
"header %s has prev block invalid: %s\n", hash.ToString(), | "header %s has prev block invalid: %s\n", hash.ToString(), | ||||
block.hashPrevBlock.ToString()); | block.hashPrevBlock.ToString()); | ||||
return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, | return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, | ||||
"bad-prevblk"); | "bad-prevblk"); | ||||
} | } | ||||
if (!ContextualCheckBlockHeader(chainparams, block, state, m_blockman, | if (!ContextualCheckBlockHeader(block, state, m_blockman, *this, | ||||
pindexPrev, | pindexPrev, | ||||
m_options.adjusted_time_callback())) { | m_options.adjusted_time_callback())) { | ||||
LogPrint(BCLog::VALIDATION, | LogPrint(BCLog::VALIDATION, | ||||
"%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", | "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", | ||||
__func__, hash.ToString(), state.ToString()); | __func__, hash.ToString(), state.ToString()); | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 242 Lines • ▼ Show 20 Lines | if (!fRequested) { | ||||
} | } | ||||
} | } | ||||
const CChainParams ¶ms{m_chainman.GetParams()}; | const CChainParams ¶ms{m_chainman.GetParams()}; | ||||
const Consensus::Params &consensusParams = params.GetConsensus(); | const Consensus::Params &consensusParams = params.GetConsensus(); | ||||
if (!CheckBlock(block, state, consensusParams, | if (!CheckBlock(block, state, consensusParams, | ||||
BlockValidationOptions(m_chainman.GetConfig())) || | BlockValidationOptions(m_chainman.GetConfig())) || | ||||
!ContextualCheckBlock(block, state, consensusParams, pindex->pprev)) { | !ContextualCheckBlock(block, state, m_chainman, pindex->pprev)) { | ||||
if (state.IsInvalid() && | if (state.IsInvalid() && | ||||
state.GetResult() != BlockValidationResult::BLOCK_MUTATED) { | state.GetResult() != BlockValidationResult::BLOCK_MUTATED) { | ||||
pindex->nStatus = pindex->nStatus.withFailed(); | pindex->nStatus = pindex->nStatus.withFailed(); | ||||
m_blockman.m_dirty_blockindex.insert(pindex); | m_blockman.m_dirty_blockindex.insert(pindex); | ||||
} | } | ||||
return error("%s: %s (block %s)", __func__, state.ToString(), | return error("%s: %s (block %s)", __func__, state.ToString(), | ||||
block.GetHash().ToString()); | block.GetHash().ToString()); | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | bool TestBlockValidity( | ||||
CCoinsViewCache viewNew(&chainstate.CoinsTip()); | CCoinsViewCache viewNew(&chainstate.CoinsTip()); | ||||
BlockHash block_hash(block.GetHash()); | BlockHash block_hash(block.GetHash()); | ||||
CBlockIndex indexDummy(block); | CBlockIndex indexDummy(block); | ||||
indexDummy.pprev = pindexPrev; | indexDummy.pprev = pindexPrev; | ||||
indexDummy.nHeight = pindexPrev->nHeight + 1; | indexDummy.nHeight = pindexPrev->nHeight + 1; | ||||
indexDummy.phashBlock = &block_hash; | indexDummy.phashBlock = &block_hash; | ||||
// NOTE: CheckBlockHeader is called by CheckBlock | // NOTE: CheckBlockHeader is called by CheckBlock | ||||
if (!ContextualCheckBlockHeader(params, block, state, chainstate.m_blockman, | if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, | ||||
pindexPrev, adjusted_time_callback())) { | chainstate.m_chainman, pindexPrev, | ||||
adjusted_time_callback())) { | |||||
return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, | return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, | ||||
state.ToString()); | state.ToString()); | ||||
} | } | ||||
if (!CheckBlock(block, state, params.GetConsensus(), validationOptions)) { | if (!CheckBlock(block, state, params.GetConsensus(), validationOptions)) { | ||||
return error("%s: Consensus::CheckBlock: %s", __func__, | return error("%s: Consensus::CheckBlock: %s", __func__, | ||||
state.ToString()); | state.ToString()); | ||||
} | } | ||||
if (!ContextualCheckBlock(block, state, params.GetConsensus(), | if (!ContextualCheckBlock(block, state, chainstate.m_chainman, | ||||
pindexPrev)) { | pindexPrev)) { | ||||
return error("%s: Consensus::ContextualCheckBlock: %s", __func__, | return error("%s: Consensus::ContextualCheckBlock: %s", __func__, | ||||
state.ToString()); | state.ToString()); | ||||
} | } | ||||
if (!chainstate.ConnectBlock(block, state, &indexDummy, viewNew, | if (!chainstate.ConnectBlock(block, state, &indexDummy, viewNew, | ||||
validationOptions, nullptr, true)) { | validationOptions, nullptr, true)) { | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 1,969 Lines • Show Last 20 Lines |