Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | |||||
uint64_t nPruneTarget = 0; | uint64_t nPruneTarget = 0; | ||||
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; | int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; | ||||
uint256 hashAssumeValid; | uint256 hashAssumeValid; | ||||
arith_uint256 nMinimumChainWork; | arith_uint256 nMinimumChainWork; | ||||
Amount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; | Amount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; | ||||
CTxMemPool mempool; | CTxMemPool g_mempool; | ||||
static void CheckBlockIndex(const Consensus::Params &consensusParams); | static void CheckBlockIndex(const Consensus::Params &consensusParams); | ||||
/** Constant stuff for coinbase transactions we create: */ | /** Constant stuff for coinbase transactions we create: */ | ||||
CScript COINBASE_FLAGS; | CScript COINBASE_FLAGS; | ||||
const std::string strMessageMagic = "Bitcoin Signed Message:\n"; | const std::string strMessageMagic = "Bitcoin Signed Message:\n"; | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | bool TestLockPointValidity(const LockPoints *lp) { | ||||
// LockPoints still valid | // LockPoints still valid | ||||
return true; | return true; | ||||
} | } | ||||
bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints *lp, | bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints *lp, | ||||
bool useExistingLockPoints) { | bool useExistingLockPoints) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
AssertLockHeld(mempool.cs); | AssertLockHeld(g_mempool.cs); | ||||
CBlockIndex *tip = chainActive.Tip(); | CBlockIndex *tip = chainActive.Tip(); | ||||
CBlockIndex index; | CBlockIndex index; | ||||
index.pprev = tip; | index.pprev = tip; | ||||
// CheckSequenceLocks() uses chainActive.Height()+1 to evaluate height based | // CheckSequenceLocks() uses chainActive.Height()+1 to evaluate height based | ||||
// locks because when SequenceLocks() is called within ConnectBlock(), the | // locks because when SequenceLocks() is called within ConnectBlock(), the | ||||
// height of the block *being* evaluated is what is used. Thus if we want to | // height of the block *being* evaluated is what is used. Thus if we want to | ||||
// know if a transaction can be part of the *next* block, we need to use one | // know if a transaction can be part of the *next* block, we need to use one | ||||
// more than chainActive.Height() | // more than chainActive.Height() | ||||
index.nHeight = tip->nHeight + 1; | index.nHeight = tip->nHeight + 1; | ||||
std::pair<int, int64_t> lockPair; | std::pair<int, int64_t> lockPair; | ||||
if (useExistingLockPoints) { | if (useExistingLockPoints) { | ||||
assert(lp); | assert(lp); | ||||
lockPair.first = lp->height; | lockPair.first = lp->height; | ||||
lockPair.second = lp->time; | lockPair.second = lp->time; | ||||
} else { | } else { | ||||
// pcoinsTip contains the UTXO set for chainActive.Tip() | // pcoinsTip contains the UTXO set for chainActive.Tip() | ||||
CCoinsViewMemPool viewMemPool(pcoinsTip.get(), mempool); | CCoinsViewMemPool viewMemPool(pcoinsTip.get(), g_mempool); | ||||
std::vector<int> prevheights; | std::vector<int> prevheights; | ||||
prevheights.resize(tx.vin.size()); | prevheights.resize(tx.vin.size()); | ||||
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { | for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { | ||||
const CTxIn &txin = tx.vin[txinIndex]; | const CTxIn &txin = tx.vin[txinIndex]; | ||||
Coin coin; | Coin coin; | ||||
if (!viewMemPool.GetCoin(txin.prevout, coin)) { | if (!viewMemPool.GetCoin(txin.prevout, coin)) { | ||||
return error("%s: Missing input", __func__); | return error("%s: Missing input", __func__); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 522 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
bool GetTransaction(const Config &config, const TxId &txid, | bool GetTransaction(const Config &config, const TxId &txid, | ||||
CTransactionRef &txOut, uint256 &hashBlock, | CTransactionRef &txOut, uint256 &hashBlock, | ||||
bool fAllowSlow) { | bool fAllowSlow) { | ||||
CBlockIndex *pindexSlow = nullptr; | CBlockIndex *pindexSlow = nullptr; | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CTransactionRef ptx = mempool.get(txid); | CTransactionRef ptx = g_mempool.get(txid); | ||||
if (ptx) { | if (ptx) { | ||||
txOut = ptx; | txOut = ptx; | ||||
return true; | return true; | ||||
} | } | ||||
if (fTxIndex) { | if (fTxIndex) { | ||||
CDiskTxPos postx; | CDiskTxPos postx; | ||||
if (pblocktree->ReadTxIndex(txid, postx)) { | if (pblocktree->ReadTxIndex(txid, postx)) { | ||||
▲ Show 20 Lines • Show All 1,099 Lines • ▼ Show 20 Lines | static bool ConnectBlock(const Config &config, const CBlock &block, | ||||
LogPrint(BCLog::BENCH, " - Callbacks: %.2fms [%.2fs]\n", | LogPrint(BCLog::BENCH, " - Callbacks: %.2fms [%.2fs]\n", | ||||
0.001 * (nTime6 - nTime5), nTimeCallbacks * 0.000001); | 0.001 * (nTime6 - nTime5), nTimeCallbacks * 0.000001); | ||||
// If we just activated the replay protection with that block, it means | // If we just activated the replay protection with that block, it means | ||||
// transaction in the mempool are now invalid. As a result, we need to clear | // transaction in the mempool are now invalid. As a result, we need to clear | ||||
// the mempool. | // the mempool. | ||||
if (IsReplayProtectionEnabled(config, pindex) && | if (IsReplayProtectionEnabled(config, pindex) && | ||||
!IsReplayProtectionEnabled(config, pindex->pprev)) { | !IsReplayProtectionEnabled(config, pindex->pprev)) { | ||||
mempool.clear(); | g_mempool.clear(); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Update the on-disk chain state. | * Update the on-disk chain state. | ||||
* The caches and indexes are flushed depending on the mode we're called with if | * The caches and indexes are flushed depending on the mode we're called with if | ||||
* they're too large, if it's been a while since the last write, or always and | * they're too large, if it's been a while since the last write, or always and | ||||
* in all cases if we're in prune mode and are deleting files. | * in all cases if we're in prune mode and are deleting files. | ||||
*/ | */ | ||||
static bool FlushStateToDisk(const CChainParams &chainparams, | static bool FlushStateToDisk(const CChainParams &chainparams, | ||||
CValidationState &state, FlushStateMode mode, | CValidationState &state, FlushStateMode mode, | ||||
int nManualPruneHeight) { | int nManualPruneHeight) { | ||||
int64_t nMempoolUsage = mempool.DynamicMemoryUsage(); | int64_t nMempoolUsage = g_mempool.DynamicMemoryUsage(); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
static int64_t nLastWrite = 0; | static int64_t nLastWrite = 0; | ||||
static int64_t nLastFlush = 0; | static int64_t nLastFlush = 0; | ||||
static int64_t nLastSetChain = 0; | static int64_t nLastSetChain = 0; | ||||
std::set<int> setFilesToPrune; | std::set<int> setFilesToPrune; | ||||
bool fFlushForPrune = false; | bool fFlushForPrune = false; | ||||
bool fDoFullFlush = false; | bool fDoFullFlush = false; | ||||
int64_t nNow = 0; | int64_t nNow = 0; | ||||
▲ Show 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
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 | ||||
mempool.AddTransactionsUpdated(1); | g_mempool.AddTransactionsUpdated(1); | ||||
{ | { | ||||
LOCK(g_best_block_mutex); | LOCK(g_best_block_mutex); | ||||
g_best_block = pindexNew->GetBlockHash(); | g_best_block = pindexNew->GetBlockHash(); | ||||
g_best_block_cv.notify_all(); | g_best_block_cv.notify_all(); | ||||
} | } | ||||
static bool fWarned = false; | static bool fWarned = false; | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | static bool DisconnectTip(const Config &config, CValidationState &state, | ||||
// have transactions in the mempool that use newly introduced opcodes. As a | // have transactions in the mempool that use newly introduced opcodes. As a | ||||
// result, we also cleanup the mempool. | // result, we also cleanup the mempool. | ||||
if ((IsReplayProtectionEnabled(config, pindexDelete) && | if ((IsReplayProtectionEnabled(config, pindexDelete) && | ||||
!IsReplayProtectionEnabled(config, pindexDelete->pprev)) || | !IsReplayProtectionEnabled(config, pindexDelete->pprev)) || | ||||
(IsMagneticAnomalyEnabled(config, pindexDelete) && | (IsMagneticAnomalyEnabled(config, pindexDelete) && | ||||
!IsMagneticAnomalyEnabled(config, pindexDelete->pprev))) { | !IsMagneticAnomalyEnabled(config, pindexDelete->pprev))) { | ||||
LogPrint(BCLog::MEMPOOL, "Clearing mempool for reorg"); | LogPrint(BCLog::MEMPOOL, "Clearing mempool for reorg"); | ||||
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(); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | static bool ConnectTip(const Config &config, CValidationState &state, | ||||
} | } | ||||
int64_t nTime5 = GetTimeMicros(); | int64_t nTime5 = GetTimeMicros(); | ||||
nTimeChainState += nTime5 - nTime4; | nTimeChainState += nTime5 - nTime4; | ||||
LogPrint(BCLog::BENCH, " - Writing chainstate: %.2fms [%.2fs]\n", | LogPrint(BCLog::BENCH, " - Writing chainstate: %.2fms [%.2fs]\n", | ||||
(nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); | (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); | ||||
// Remove conflicting transactions from the mempool.; | // Remove conflicting transactions from the mempool.; | ||||
mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); | g_mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); | ||||
disconnectpool.removeForBlock(blockConnecting.vtx); | disconnectpool.removeForBlock(blockConnecting.vtx); | ||||
// Update chainActive & related variables. | // Update chainActive & related variables. | ||||
UpdateTip(config, pindexNew); | UpdateTip(config, pindexNew); | ||||
int64_t nTime6 = GetTimeMicros(); | int64_t nTime6 = GetTimeMicros(); | ||||
nTimePostConnect += nTime6 - nTime5; | nTimePostConnect += nTime6 - nTime5; | ||||
nTimeTotal += nTime6 - nTime1; | nTimeTotal += nTime6 - nTime1; | ||||
LogPrint(BCLog::BENCH, " - Connect postprocess: %.2fms [%.2fs]\n", | LogPrint(BCLog::BENCH, " - Connect postprocess: %.2fms [%.2fs]\n", | ||||
▲ Show 20 Lines • Show All 257 Lines • ▼ Show 20 Lines | static bool ActivateBestChainStep(const Config &config, CValidationState &state, | ||||
} | } | ||||
if (fBlocksDisconnected) { | if (fBlocksDisconnected) { | ||||
// If any blocks were disconnected, disconnectpool may be non empty. Add | // If any blocks were disconnected, disconnectpool may be non empty. Add | ||||
// any disconnected transactions back to the mempool. | // any disconnected transactions back to the mempool. | ||||
disconnectpool.updateMempoolForReorg(config, true); | disconnectpool.updateMempoolForReorg(config, true); | ||||
} | } | ||||
mempool.check(pcoinsTip.get()); | g_mempool.check(pcoinsTip.get()); | ||||
// Callbacks/notifications for a new best chain. | // Callbacks/notifications for a new best chain. | ||||
if (fInvalidFound) { | if (fInvalidFound) { | ||||
CheckForkWarningConditionsOnNewFork(pindexMostWork); | CheckForkWarningConditionsOnNewFork(pindexMostWork); | ||||
} else { | } else { | ||||
CheckForkWarningConditions(); | CheckForkWarningConditions(); | ||||
} | } | ||||
Show All 38 Lines | do { | ||||
} | } | ||||
const CBlockIndex *pindexFork; | const CBlockIndex *pindexFork; | ||||
bool fInitialDownload; | bool fInitialDownload; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// Destructed before cs_main is unlocked. | // Destructed before cs_main is unlocked. | ||||
ConnectTrace connectTrace(mempool); | ConnectTrace connectTrace(g_mempool); | ||||
CBlockIndex *pindexOldTip = chainActive.Tip(); | CBlockIndex *pindexOldTip = chainActive.Tip(); | ||||
if (pindexMostWork == nullptr) { | if (pindexMostWork == nullptr) { | ||||
pindexMostWork = FindMostWorkChain(); | pindexMostWork = FindMostWorkChain(); | ||||
} | } | ||||
// Whether we have anything to do at all. | // Whether we have anything to do at all. | ||||
if (pindexMostWork == nullptr || | if (pindexMostWork == nullptr || | ||||
▲ Show 20 Lines • Show All 1,969 Lines • ▼ Show 20 Lines | |||||
void UnloadBlockIndex() { | void UnloadBlockIndex() { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
setBlockIndexCandidates.clear(); | setBlockIndexCandidates.clear(); | ||||
chainActive.SetTip(nullptr); | chainActive.SetTip(nullptr); | ||||
pindexFinalized = nullptr; | pindexFinalized = nullptr; | ||||
pindexBestInvalid = nullptr; | pindexBestInvalid = nullptr; | ||||
pindexBestParked = nullptr; | pindexBestParked = nullptr; | ||||
pindexBestHeader = nullptr; | pindexBestHeader = nullptr; | ||||
mempool.clear(); | g_mempool.clear(); | ||||
mapBlocksUnlinked.clear(); | mapBlocksUnlinked.clear(); | ||||
vinfoBlockFile.clear(); | vinfoBlockFile.clear(); | ||||
nLastBlockFile = 0; | nLastBlockFile = 0; | ||||
nBlockSequenceId = 1; | nBlockSequenceId = 1; | ||||
setDirtyBlockIndex.clear(); | setDirtyBlockIndex.clear(); | ||||
setDirtyFileInfo.clear(); | setDirtyFileInfo.clear(); | ||||
versionbitscache.Clear(); | versionbitscache.Clear(); | ||||
▲ Show 20 Lines • Show All 595 Lines • ▼ Show 20 Lines | try { | ||||
int64_t nTime; | int64_t nTime; | ||||
int64_t nFeeDelta; | int64_t nFeeDelta; | ||||
file >> tx; | file >> tx; | ||||
file >> nTime; | file >> nTime; | ||||
file >> nFeeDelta; | file >> nFeeDelta; | ||||
Amount amountdelta = nFeeDelta * SATOSHI; | Amount amountdelta = nFeeDelta * SATOSHI; | ||||
if (amountdelta != Amount::zero()) { | if (amountdelta != Amount::zero()) { | ||||
mempool.PrioritiseTransaction(tx->GetId(), | g_mempool.PrioritiseTransaction(tx->GetId(), | ||||
tx->GetId().ToString(), | tx->GetId().ToString(), | ||||
prioritydummy, amountdelta); | prioritydummy, amountdelta); | ||||
} | } | ||||
CValidationState state; | CValidationState state; | ||||
if (nTime + nExpiryTimeout > nNow) { | if (nTime + nExpiryTimeout > nNow) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
AcceptToMemoryPoolWithTime(config, mempool, state, tx, true, | AcceptToMemoryPoolWithTime(config, g_mempool, state, tx, true, | ||||
nullptr, nTime); | nullptr, nTime); | ||||
if (state.IsValid()) { | if (state.IsValid()) { | ||||
++count; | ++count; | ||||
} else { | } else { | ||||
++failed; | ++failed; | ||||
} | } | ||||
} else { | } else { | ||||
++skipped; | ++skipped; | ||||
} | } | ||||
if (ShutdownRequested()) { | if (ShutdownRequested()) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
std::map<uint256, Amount> mapDeltas; | std::map<uint256, Amount> mapDeltas; | ||||
file >> mapDeltas; | file >> mapDeltas; | ||||
for (const auto &i : mapDeltas) { | for (const auto &i : mapDeltas) { | ||||
mempool.PrioritiseTransaction(i.first, i.first.ToString(), | g_mempool.PrioritiseTransaction(i.first, i.first.ToString(), | ||||
prioritydummy, i.second); | prioritydummy, i.second); | ||||
} | } | ||||
} catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing " | LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing " | ||||
"anyway.\n", | "anyway.\n", | ||||
e.what()); | e.what()); | ||||
return false; | return false; | ||||
} | } | ||||
LogPrintf("Imported mempool transactions from disk: %i successes, %i " | LogPrintf("Imported mempool transactions from disk: %i successes, %i " | ||||
"failed, %i expired\n", | "failed, %i expired\n", | ||||
count, failed, skipped); | count, failed, skipped); | ||||
return true; | return true; | ||||
} | } | ||||
void DumpMempool(void) { | void DumpMempool(void) { | ||||
int64_t start = GetTimeMicros(); | int64_t start = GetTimeMicros(); | ||||
std::map<uint256, Amount> mapDeltas; | std::map<uint256, Amount> mapDeltas; | ||||
std::vector<TxMempoolInfo> vinfo; | std::vector<TxMempoolInfo> vinfo; | ||||
{ | { | ||||
LOCK(mempool.cs); | LOCK(g_mempool.cs); | ||||
for (const auto &i : mempool.mapDeltas) { | for (const auto &i : g_mempool.mapDeltas) { | ||||
mapDeltas[i.first] = i.second.second; | mapDeltas[i.first] = i.second.second; | ||||
} | } | ||||
vinfo = mempool.infoAll(); | vinfo = g_mempool.infoAll(); | ||||
} | } | ||||
int64_t mid = GetTimeMicros(); | int64_t mid = GetTimeMicros(); | ||||
try { | try { | ||||
FILE *filestr = fsbridge::fopen(GetDataDir() / "mempool.dat.new", "wb"); | FILE *filestr = fsbridge::fopen(GetDataDir() / "mempool.dat.new", "wb"); | ||||
if (!filestr) { | if (!filestr) { | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 59 Lines • Show Last 20 Lines |