Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | bool AcceptBlock(const Config &config, | ||||
const FlatFilePos *dbp, bool *fNewBlock); | const FlatFilePos *dbp, bool *fNewBlock); | ||||
// Block (dis)connection on a given view: | // Block (dis)connection on a given view: | ||||
DisconnectResult DisconnectBlock(const CBlock &block, | DisconnectResult DisconnectBlock(const CBlock &block, | ||||
const CBlockIndex *pindex, | const CBlockIndex *pindex, | ||||
CCoinsViewCache &view); | CCoinsViewCache &view); | ||||
bool ConnectBlock(const Config &config, const CBlock &block, | bool ConnectBlock(const Config &config, const CBlock &block, | ||||
CValidationState &state, CBlockIndex *pindex, | CValidationState &state, CBlockIndex *pindex, | ||||
CCoinsViewCache &view, bool fJustCheck = false); | CCoinsViewCache &view, bool fJustCheck = false) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
// Block disconnection on our pcoinsTip: | // Block disconnection on our pcoinsTip: | ||||
bool DisconnectTip(const Config &config, CValidationState &state, | bool DisconnectTip(const Config &config, CValidationState &state, | ||||
DisconnectedBlockTransactions *disconnectpool); | DisconnectedBlockTransactions *disconnectpool); | ||||
// Manual block validity manipulation: | // Manual block validity manipulation: | ||||
bool PreciousBlock(const Config &config, CValidationState &state, | bool PreciousBlock(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex); | CBlockIndex *pindex); | ||||
Show All 15 Lines | public: | ||||
void PruneBlockIndexCandidates(); | void PruneBlockIndexCandidates(); | ||||
void UnloadBlockIndex(); | void UnloadBlockIndex(); | ||||
private: | private: | ||||
bool ActivateBestChainStep(const Config &config, CValidationState &state, | bool ActivateBestChainStep(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindexMostWork, | CBlockIndex *pindexMostWork, | ||||
const std::shared_ptr<const CBlock> &pblock, | const std::shared_ptr<const CBlock> &pblock, | ||||
bool &fInvalidFound, ConnectTrace &connectTrace); | bool &fInvalidFound, ConnectTrace &connectTrace) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool ConnectTip(const Config &config, CValidationState &state, | bool ConnectTip(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindexNew, | CBlockIndex *pindexNew, | ||||
const std::shared_ptr<const CBlock> &pblock, | const std::shared_ptr<const CBlock> &pblock, | ||||
ConnectTrace &connectTrace, | ConnectTrace &connectTrace, | ||||
DisconnectedBlockTransactions &disconnectpool); | DisconnectedBlockTransactions &disconnectpool) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
CBlockIndex *AddToBlockIndex(const CBlockHeader &block); | CBlockIndex *AddToBlockIndex(const CBlockHeader &block); | ||||
/** Create a new block index entry for a given block hash */ | /** Create a new block index entry for a given block hash */ | ||||
CBlockIndex *InsertBlockIndex(const uint256 &hash); | CBlockIndex *InsertBlockIndex(const uint256 &hash); | ||||
void CheckBlockIndex(const Consensus::Params &consensusParams); | void CheckBlockIndex(const Consensus::Params &consensusParams); | ||||
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state); | void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) | ||||
CBlockIndex *FindMostWorkChain(); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
CBlockIndex *FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool ReceivedBlockTransactions(const CBlock &block, CValidationState &state, | bool ReceivedBlockTransactions(const CBlock &block, CValidationState &state, | ||||
CBlockIndex *pindexNew, | CBlockIndex *pindexNew, | ||||
const FlatFilePos &pos); | const FlatFilePos &pos) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &inputs, | bool RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &inputs, | ||||
const Config &config); | const Config &config); | ||||
} g_chainstate; | } g_chainstate; | ||||
/** | /** | ||||
* Global state | * Global state | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 240 Lines • ▼ Show 20 Lines | static bool IsReplayProtectionEnabledForCurrentBlock(const Config &config) { | ||||
return IsReplayProtectionEnabled(config, chainActive.Tip()); | return IsReplayProtectionEnabled(config, chainActive.Tip()); | ||||
} | } | ||||
// Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool | // Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool | ||||
// were somehow broken and returning the wrong scriptPubKeys | // were somehow broken and returning the wrong scriptPubKeys | ||||
static bool CheckInputsFromMempoolAndCache( | static bool CheckInputsFromMempoolAndCache( | ||||
const CTransaction &tx, CValidationState &state, | const CTransaction &tx, CValidationState &state, | ||||
const CCoinsViewCache &view, const CTxMemPool &pool, const uint32_t flags, | const CCoinsViewCache &view, const CTxMemPool &pool, const uint32_t flags, | ||||
bool cacheSigStore, PrecomputedTransactionData &txdata) { | bool cacheSigStore, PrecomputedTransactionData &txdata) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
// pool.cs should be locked already, but go ahead and re-take the lock here | // pool.cs should be locked already, but go ahead and re-take the lock here | ||||
// to enforce that mempool doesn't change between when we check the view and | // to enforce that mempool doesn't change between when we check the view and | ||||
// when we actually call through to CheckInputs | // when we actually call through to CheckInputs | ||||
LOCK(pool.cs); | LOCK(pool.cs); | ||||
assert(!tx.IsCoinBase()); | assert(!tx.IsCoinBase()); | ||||
Show All 23 Lines | static bool CheckInputsFromMempoolAndCache( | ||||
return CheckInputs(tx, state, view, true, flags, cacheSigStore, true, | return CheckInputs(tx, state, view, true, flags, cacheSigStore, true, | ||||
txdata); | txdata); | ||||
} | } | ||||
static bool AcceptToMemoryPoolWorker( | static bool AcceptToMemoryPoolWorker( | ||||
const Config &config, CTxMemPool &pool, CValidationState &state, | const Config &config, CTxMemPool &pool, CValidationState &state, | ||||
const CTransactionRef &ptx, bool fLimitFree, bool *pfMissingInputs, | const CTransactionRef &ptx, bool fLimitFree, bool *pfMissingInputs, | ||||
int64_t nAcceptTime, bool fOverrideMempoolLimit, const Amount nAbsurdFee, | int64_t nAcceptTime, bool fOverrideMempoolLimit, const Amount nAbsurdFee, | ||||
std::vector<COutPoint> &coins_to_uncache, bool test_accept) { | std::vector<COutPoint> &coins_to_uncache, bool test_accept) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
const CTransaction &tx = *ptx; | const CTransaction &tx = *ptx; | ||||
const TxId txid = tx.GetId(); | const TxId txid = tx.GetId(); | ||||
// mempool "read lock" (held through | // mempool "read lock" (held through | ||||
// GetMainSignals().TransactionAddedToMempool()) | // GetMainSignals().TransactionAddedToMempool()) | ||||
LOCK(pool.cs); | LOCK(pool.cs); | ||||
▲ Show 20 Lines • Show All 304 Lines • ▼ Show 20 Lines | static bool AcceptToMemoryPoolWorker( | ||||
GetMainSignals().TransactionAddedToMempool(ptx); | GetMainSignals().TransactionAddedToMempool(ptx); | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* (try to) add transaction to memory pool with a specified acceptance time. | * (try to) add transaction to memory pool with a specified acceptance time. | ||||
*/ | */ | ||||
static bool | static bool AcceptToMemoryPoolWithTime( | ||||
AcceptToMemoryPoolWithTime(const Config &config, CTxMemPool &pool, | const Config &config, CTxMemPool &pool, CValidationState &state, | ||||
CValidationState &state, const CTransactionRef &tx, | const CTransactionRef &tx, bool fLimitFree, bool *pfMissingInputs, | ||||
bool fLimitFree, bool *pfMissingInputs, | int64_t nAcceptTime, bool fOverrideMempoolLimit, const Amount nAbsurdFee, | ||||
int64_t nAcceptTime, bool fOverrideMempoolLimit, | bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
const Amount nAbsurdFee, bool test_accept) { | |||||
std::vector<COutPoint> coins_to_uncache; | std::vector<COutPoint> coins_to_uncache; | ||||
bool res = AcceptToMemoryPoolWorker( | bool res = AcceptToMemoryPoolWorker( | ||||
config, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, | config, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, | ||||
fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, test_accept); | fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, test_accept); | ||||
if (!res) { | if (!res) { | ||||
for (const COutPoint &outpoint : coins_to_uncache) { | for (const COutPoint &outpoint : coins_to_uncache) { | ||||
pcoinsTip->Uncache(outpoint); | pcoinsTip->Uncache(outpoint); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | static void AlertNotify(const std::string &strMessage) { | ||||
safeStatus = singleQuote + safeStatus + singleQuote; | safeStatus = singleQuote + safeStatus + singleQuote; | ||||
boost::replace_all(strCmd, "%s", safeStatus); | boost::replace_all(strCmd, "%s", safeStatus); | ||||
std::thread t(runCommand, strCmd); | std::thread t(runCommand, strCmd); | ||||
// thread runs free | // thread runs free | ||||
t.detach(); | t.detach(); | ||||
} | } | ||||
static void CheckForkWarningConditions() { | static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
// Before we get past initial download, we cannot reliably alert about forks | // Before we get past initial download, we cannot reliably alert about forks | ||||
// (we assume we don't get stuck on a fork before finishing our initial | // (we assume we don't get stuck on a fork before finishing our initial | ||||
// sync) | // sync) | ||||
if (IsInitialBlockDownload()) { | if (IsInitialBlockDownload()) { | ||||
return; | return; | ||||
} | } | ||||
Show All 35 Lines | if (pindexBestForkTip || | ||||
} | } | ||||
} else { | } else { | ||||
SetfLargeWorkForkFound(false); | SetfLargeWorkForkFound(false); | ||||
SetfLargeWorkInvalidChainFound(false); | SetfLargeWorkInvalidChainFound(false); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
CheckForkWarningConditionsOnNewFork(const CBlockIndex *pindexNewForkTip) { | CheckForkWarningConditionsOnNewFork(const CBlockIndex *pindexNewForkTip) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
// If we are on a fork that is sufficiently large, set a warning flag. | // If we are on a fork that is sufficiently large, set a warning flag. | ||||
const CBlockIndex *pfork = chainActive.FindFork(pindexNewForkTip); | const CBlockIndex *pfork = chainActive.FindFork(pindexNewForkTip); | ||||
// We define a condition where we should warn the user about as a fork of at | // We define a condition where we should warn the user about as a fork of at | ||||
// least 7 blocks with a tip within 72 blocks (+/- 12 hours if no one mines | // least 7 blocks with a tip within 72 blocks (+/- 12 hours if no one mines | ||||
// it) of ours. We use 7 blocks rather arbitrarily as it represents just | // it) of ours. We use 7 blocks rather arbitrarily as it represents just | ||||
// under 10% of sustained network hash rate operating on the fork, or a | // under 10% of sustained network hash rate operating on the fork, or a | ||||
Show All 9 Lines | if (pfork && | ||||
chainActive.Height() - pindexNewForkTip->nHeight < 72) { | chainActive.Height() - pindexNewForkTip->nHeight < 72) { | ||||
pindexBestForkTip = pindexNewForkTip; | pindexBestForkTip = pindexNewForkTip; | ||||
pindexBestForkBase = pfork; | pindexBestForkBase = pfork; | ||||
} | } | ||||
CheckForkWarningConditions(); | CheckForkWarningConditions(); | ||||
} | } | ||||
static void InvalidChainFound(CBlockIndex *pindexNew) { | void static InvalidChainFound(CBlockIndex *pindexNew) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
if (!pindexBestInvalid || | if (!pindexBestInvalid || | ||||
pindexNew->nChainWork > pindexBestInvalid->nChainWork) { | pindexNew->nChainWork > pindexBestInvalid->nChainWork) { | ||||
pindexBestInvalid = pindexNew; | pindexBestInvalid = pindexNew; | ||||
} | } | ||||
// If the invalid chain found is supposed to be finalized, we need to move | // If the invalid chain found is supposed to be finalized, we need to move | ||||
// back the finalization point. | // back the finalization point. | ||||
if (IsBlockFinalized(pindexNew)) { | if (IsBlockFinalized(pindexNew)) { | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | int GetSpendHeight(const CCoinsViewCache &inputs) { | ||||
return pindexPrev->nHeight + 1; | return pindexPrev->nHeight + 1; | ||||
} | } | ||||
bool CheckInputs(const CTransaction &tx, CValidationState &state, | bool CheckInputs(const CTransaction &tx, CValidationState &state, | ||||
const CCoinsViewCache &inputs, bool fScriptChecks, | const CCoinsViewCache &inputs, bool fScriptChecks, | ||||
const uint32_t flags, bool sigCacheStore, | const uint32_t flags, bool sigCacheStore, | ||||
bool scriptCacheStore, | bool scriptCacheStore, | ||||
const PrecomputedTransactionData &txdata, | const PrecomputedTransactionData &txdata, | ||||
std::vector<CScriptCheck> *pvChecks) { | std::vector<CScriptCheck> *pvChecks) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
assert(!tx.IsCoinBase()); | assert(!tx.IsCoinBase()); | ||||
if (pvChecks) { | if (pvChecks) { | ||||
pvChecks->reserve(tx.vin.size()); | pvChecks->reserve(tx.vin.size()); | ||||
} | } | ||||
// Skip script verification when connecting blocks under the assumevalid | // Skip script verification when connecting blocks under the assumevalid | ||||
// block. Assuming the assumevalid block is valid this is safe because | // block. Assuming the assumevalid block is valid this is safe because | ||||
▲ Show 20 Lines • Show All 347 Lines • ▼ Show 20 Lines | int32_t ComputeBlockVersion(const CBlockIndex *pindexPrev, | ||||
const Consensus::Params ¶ms) { | const Consensus::Params ¶ms) { | ||||
int32_t nVersion = VERSIONBITS_TOP_BITS; | int32_t nVersion = VERSIONBITS_TOP_BITS; | ||||
return nVersion; | return nVersion; | ||||
} | } | ||||
// 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 Config &config, | static uint32_t GetNextBlockScriptFlags(const Config &config, | ||||
const CBlockIndex *pindex) { | const CBlockIndex *pindex) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
const Consensus::Params &consensusParams = | const Consensus::Params &consensusParams = | ||||
config.GetChainParams().GetConsensus(); | config.GetChainParams().GetConsensus(); | ||||
uint32_t flags = SCRIPT_VERIFY_NONE; | uint32_t flags = SCRIPT_VERIFY_NONE; | ||||
// Start enforcing P2SH (BIP16) | // Start enforcing P2SH (BIP16) | ||||
if ((pindex->nHeight + 1) >= consensusParams.BIP16Height) { | if ((pindex->nHeight + 1) >= consensusParams.BIP16Height) { | ||||
▲ Show 20 Lines • Show All 4,084 Lines • Show Last 20 Lines |