Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; | bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; | ||||
size_t nCoinCacheUsage = 5000 * 300; | size_t nCoinCacheUsage = 5000 * 300; | ||||
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; | ||||
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); | CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); | ||||
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE.GetSatoshis(); | Amount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; | ||||
CTxMemPool mempool(::minRelayTxFee); | CTxMemPool mempool(::minRelayTxFee); | ||||
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; | ||||
▲ Show 20 Lines • Show All 578 Lines • ▼ Show 20 Lines | static bool CheckInputsFromMempoolAndCache(const CTransaction &tx, | ||||
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, std::list<CTransactionRef> *plTxnReplaced, | int64_t nAcceptTime, std::list<CTransactionRef> *plTxnReplaced, | ||||
bool fOverrideMempoolLimit, const CAmount &nAbsurdFee, | bool fOverrideMempoolLimit, const Amount nAbsurdFee, | ||||
std::vector<COutPoint> &coins_to_uncache) { | std::vector<COutPoint> &coins_to_uncache) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
const CTransaction &tx = *ptx; | const CTransaction &tx = *ptx; | ||||
const uint256 txid = tx.GetId(); | const uint256 txid = tx.GetId(); | ||||
if (pfMissingInputs) { | if (pfMissingInputs) { | ||||
*pfMissingInputs = false; | *pfMissingInputs = false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | // Check for conflicts with in-memory transactions | ||||
// MAX_BLOCK_SIGOPS_PER_MB; we still consider this an invalid rather | // MAX_BLOCK_SIGOPS_PER_MB; we still consider this an invalid rather | ||||
// than merely non-standard transaction. | // than merely non-standard transaction. | ||||
if (nSigOpsCount > MAX_STANDARD_TX_SIGOPS) { | if (nSigOpsCount > MAX_STANDARD_TX_SIGOPS) { | ||||
return state.DoS(0, false, REJECT_NONSTANDARD, | return state.DoS(0, false, REJECT_NONSTANDARD, | ||||
"bad-txns-too-many-sigops", false, | "bad-txns-too-many-sigops", false, | ||||
strprintf("%d", nSigOpsCount)); | strprintf("%d", nSigOpsCount)); | ||||
} | } | ||||
CAmount mempoolRejectFee = | Amount mempoolRejectFee = | ||||
pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * | pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * | ||||
1000000) | 1000000) | ||||
.GetFee(nSize) | .GetFee(nSize) | ||||
.GetSatoshis(); | .GetSatoshis(); | ||||
if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) { | if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) { | ||||
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, | return state.DoS(0, false, REJECT_INSUFFICIENTFEE, | ||||
"mempool min fee not met", false, | "mempool min fee not met", false, | ||||
strprintf("%d < %d", nFees, mempoolRejectFee)); | strprintf("%d < %d", nFees, mempoolRejectFee)); | ||||
Show All 31 Lines | // Check for conflicts with in-memory transactions | ||||
"rate limited free transaction"); | "rate limited free transaction"); | ||||
} | } | ||||
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, | LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, | ||||
dFreeCount + nSize); | dFreeCount + nSize); | ||||
dFreeCount += nSize; | dFreeCount += nSize; | ||||
} | } | ||||
if (nAbsurdFee && nFees > nAbsurdFee) { | if (nAbsurdFee != 0 && nFees > nAbsurdFee) { | ||||
return state.Invalid(false, REJECT_HIGHFEE, "absurdly-high-fee", | return state.Invalid(false, REJECT_HIGHFEE, "absurdly-high-fee", | ||||
strprintf("%d > %d", nFees, nAbsurdFee)); | strprintf("%d > %d", nFees, nAbsurdFee)); | ||||
} | } | ||||
// Calculate in-mempool ancestors, up to a limit. | // Calculate in-mempool ancestors, up to a limit. | ||||
CTxMemPool::setEntries setAncestors; | CTxMemPool::setEntries setAncestors; | ||||
size_t nLimitAncestors = | size_t nLimitAncestors = | ||||
GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); | GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | static bool AcceptToMemoryPoolWorker( | ||||
return true; | return true; | ||||
} | } | ||||
static bool AcceptToMemoryPoolWithTime( | static bool AcceptToMemoryPoolWithTime( | ||||
const Config &config, CTxMemPool &pool, CValidationState &state, | const Config &config, CTxMemPool &pool, CValidationState &state, | ||||
const CTransactionRef &tx, bool fLimitFree, bool *pfMissingInputs, | const CTransactionRef &tx, bool fLimitFree, bool *pfMissingInputs, | ||||
int64_t nAcceptTime, std::list<CTransactionRef> *plTxnReplaced = nullptr, | int64_t nAcceptTime, std::list<CTransactionRef> *plTxnReplaced = nullptr, | ||||
bool fOverrideMempoolLimit = false, const CAmount nAbsurdFee = 0) { | bool fOverrideMempoolLimit = false, const Amount nAbsurdFee = 0) { | ||||
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, | ||||
plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache); | plTxnReplaced, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache); | ||||
if (!res) { | if (!res) { | ||||
for (const COutPoint &outpoint : coins_to_uncache) { | for (const COutPoint &outpoint : coins_to_uncache) { | ||||
pcoinsTip->Uncache(outpoint); | pcoinsTip->Uncache(outpoint); | ||||
} | } | ||||
} | } | ||||
// After we've (potentially) uncached entries, ensure our coins cache is | // After we've (potentially) uncached entries, ensure our coins cache is | ||||
// still within its size limits | // still within its size limits | ||||
CValidationState stateDummy; | CValidationState stateDummy; | ||||
FlushStateToDisk(stateDummy, FLUSH_STATE_PERIODIC); | FlushStateToDisk(stateDummy, FLUSH_STATE_PERIODIC); | ||||
return res; | return res; | ||||
} | } | ||||
bool AcceptToMemoryPool(const Config &config, CTxMemPool &pool, | bool AcceptToMemoryPool(const Config &config, CTxMemPool &pool, | ||||
CValidationState &state, const CTransactionRef &tx, | CValidationState &state, const CTransactionRef &tx, | ||||
bool fLimitFree, bool *pfMissingInputs, | bool fLimitFree, bool *pfMissingInputs, | ||||
std::list<CTransactionRef> *plTxnReplaced, | std::list<CTransactionRef> *plTxnReplaced, | ||||
bool fOverrideMempoolLimit, const CAmount nAbsurdFee) { | bool fOverrideMempoolLimit, const Amount nAbsurdFee) { | ||||
return AcceptToMemoryPoolWithTime(config, pool, state, tx, fLimitFree, | return AcceptToMemoryPoolWithTime(config, pool, state, tx, fLimitFree, | ||||
pfMissingInputs, GetTime(), plTxnReplaced, | pfMissingInputs, GetTime(), plTxnReplaced, | ||||
fOverrideMempoolLimit, nAbsurdFee); | fOverrideMempoolLimit, nAbsurdFee); | ||||
} | } | ||||
/** Return transaction in txOut, and if it was found inside a block, its hash is | /** Return transaction in txOut, and if it was found inside a block, its hash is | ||||
* placed in hashBlock */ | * placed in hashBlock */ | ||||
bool GetTransaction(const Config &config, const uint256 &txid, | bool GetTransaction(const Config &config, const uint256 &txid, | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | if (!ReadBlockFromDisk(block, pindex->GetBlockPos(), consensusParams)) | ||||
return false; | return false; | ||||
if (block.GetHash() != pindex->GetBlockHash()) | if (block.GetHash() != pindex->GetBlockHash()) | ||||
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() " | return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() " | ||||
"doesn't match index for %s at %s", | "doesn't match index for %s at %s", | ||||
pindex->ToString(), pindex->GetBlockPos().ToString()); | pindex->ToString(), pindex->GetBlockPos().ToString()); | ||||
return true; | return true; | ||||
} | } | ||||
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams) { | Amount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams) { | ||||
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval; | int halvings = nHeight / consensusParams.nSubsidyHalvingInterval; | ||||
// Force block reward to zero when right shift is undefined. | // Force block reward to zero when right shift is undefined. | ||||
if (halvings >= 64) return 0; | if (halvings >= 64) return 0; | ||||
CAmount nSubsidy = 50 * COIN.GetSatoshis(); | Amount nSubsidy = 50 * COIN; | ||||
// Subsidy is cut in half every 210,000 blocks which will occur | // Subsidy is cut in half every 210,000 blocks which will occur | ||||
// approximately every 4 years. | // approximately every 4 years. | ||||
nSubsidy >>= halvings; | return Amount(nSubsidy.GetSatoshis() >> halvings); | ||||
return nSubsidy; | |||||
} | } | ||||
bool IsInitialBlockDownload() { | bool IsInitialBlockDownload() { | ||||
const CChainParams &chainParams = Params(); | const CChainParams &chainParams = Params(); | ||||
// Once this function has returned false, it must remain false. | // Once this function has returned false, it must remain false. | ||||
static std::atomic<bool> latchToFalse{false}; | static std::atomic<bool> latchToFalse{false}; | ||||
// Optimization: pre-test latch before taking the lock. | // Optimization: pre-test latch before taking the lock. | ||||
▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Lines | |||||
bool CheckTxInputs(const CTransaction &tx, CValidationState &state, | bool CheckTxInputs(const CTransaction &tx, CValidationState &state, | ||||
const CCoinsViewCache &inputs, int nSpendHeight) { | const CCoinsViewCache &inputs, int nSpendHeight) { | ||||
// This doesn't trigger the DoS code on purpose; if it did, it would make it | // This doesn't trigger the DoS code on purpose; if it did, it would make it | ||||
// easier for an attacker to attempt to split the network. | // easier for an attacker to attempt to split the network. | ||||
if (!inputs.HaveInputs(tx)) { | if (!inputs.HaveInputs(tx)) { | ||||
return state.Invalid(false, 0, "", "Inputs unavailable"); | return state.Invalid(false, 0, "", "Inputs unavailable"); | ||||
} | } | ||||
CAmount nValueIn = 0; | Amount nValueIn = 0; | ||||
CAmount nFees = 0; | Amount nFees = 0; | ||||
for (size_t i = 0; i < tx.vin.size(); i++) { | for (size_t i = 0; i < tx.vin.size(); i++) { | ||||
const COutPoint &prevout = tx.vin[i].prevout; | const COutPoint &prevout = tx.vin[i].prevout; | ||||
const Coin &coin = inputs.AccessCoin(prevout); | const Coin &coin = inputs.AccessCoin(prevout); | ||||
assert(!coin.IsSpent()); | assert(!coin.IsSpent()); | ||||
// If prev is coinbase, check that it's matured | // If prev is coinbase, check that it's matured | ||||
if (coin.IsCoinBase()) { | if (coin.IsCoinBase()) { | ||||
if (nSpendHeight - coin.GetHeight() < COINBASE_MATURITY) { | if (nSpendHeight - coin.GetHeight() < COINBASE_MATURITY) { | ||||
Show All 16 Lines | bool CheckTxInputs(const CTransaction &tx, CValidationState &state, | ||||
if (nValueIn < tx.GetValueOut()) { | if (nValueIn < tx.GetValueOut()) { | ||||
return state.DoS( | return state.DoS( | ||||
100, false, REJECT_INVALID, "bad-txns-in-belowout", false, | 100, false, REJECT_INVALID, "bad-txns-in-belowout", false, | ||||
strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), | strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), | ||||
FormatMoney(tx.GetValueOut().GetSatoshis()))); | FormatMoney(tx.GetValueOut().GetSatoshis()))); | ||||
} | } | ||||
// Tally transaction fees | // Tally transaction fees | ||||
CAmount nTxFee = nValueIn - tx.GetValueOut().GetSatoshis(); | Amount nTxFee = nValueIn - tx.GetValueOut(); | ||||
if (nTxFee < 0) { | if (nTxFee < 0) { | ||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-negative"); | return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-negative"); | ||||
} | } | ||||
nFees += nTxFee; | nFees += nTxFee; | ||||
if (!MoneyRange(nFees)) { | if (!MoneyRange(nFees)) { | ||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange"); | return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < tx.vin.size(); i++) { | ||||
assert(!coin.IsSpent()); | assert(!coin.IsSpent()); | ||||
// We very carefully only pass in things to CScriptCheck which are | // We very carefully only pass in things to CScriptCheck which are | ||||
// clearly committed to by tx' witness hash. This provides a sanity | // clearly committed to by tx' witness hash. This provides a sanity | ||||
// check that our caching is not introducing consensus failures through | // check that our caching is not introducing consensus failures through | ||||
// additional data in, eg, the coins being spent being checked as a part | // additional data in, eg, the coins being spent being checked as a part | ||||
// of CScriptCheck. | // of CScriptCheck. | ||||
const CScript &scriptPubKey = coin.GetTxOut().scriptPubKey; | const CScript &scriptPubKey = coin.GetTxOut().scriptPubKey; | ||||
const CAmount amount = coin.GetTxOut().nValue.GetSatoshis(); | const Amount amount = coin.GetTxOut().nValue; | ||||
// Verify signature | // Verify signature | ||||
CScriptCheck check(scriptPubKey, amount, tx, i, flags, sigCacheStore, | CScriptCheck check(scriptPubKey, amount, tx, i, flags, sigCacheStore, | ||||
txdata); | txdata); | ||||
if (pvChecks) { | if (pvChecks) { | ||||
pvChecks->push_back(std::move(check)); | pvChecks->push_back(std::move(check)); | ||||
} else if (!check()) { | } else if (!check()) { | ||||
if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) { | if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) { | ||||
▲ Show 20 Lines • Show All 523 Lines • ▼ Show 20 Lines | LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", | ||||
0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); | 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); | ||||
CBlockUndo blockundo; | CBlockUndo blockundo; | ||||
CCheckQueueControl<CScriptCheck> control(fScriptChecks ? &scriptcheckqueue | CCheckQueueControl<CScriptCheck> control(fScriptChecks ? &scriptcheckqueue | ||||
: nullptr); | : nullptr); | ||||
std::vector<int> prevheights; | std::vector<int> prevheights; | ||||
CAmount nFees = 0; | Amount nFees = 0; | ||||
int nInputs = 0; | int nInputs = 0; | ||||
// Sigops counting. We need to do it again because of P2SH. | // Sigops counting. We need to do it again because of P2SH. | ||||
uint64_t nSigOpsCount = 0; | uint64_t nSigOpsCount = 0; | ||||
const uint64_t currentBlockSize = | const uint64_t currentBlockSize = | ||||
::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); | ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); | ||||
const uint64_t nMaxSigOpsCount = GetMaxBlockSigOpsCount(currentBlockSize); | const uint64_t nMaxSigOpsCount = GetMaxBlockSigOpsCount(currentBlockSize); | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | static bool ConnectBlock(const Config &config, const CBlock &block, | ||||
nTimeConnect += nTime3 - nTime2; | nTimeConnect += nTime3 - nTime2; | ||||
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, " | LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, " | ||||
"%.3fms/txin) [%.2fs]\n", | "%.3fms/txin) [%.2fs]\n", | ||||
(unsigned)block.vtx.size(), 0.001 * (nTime3 - nTime2), | (unsigned)block.vtx.size(), 0.001 * (nTime3 - nTime2), | ||||
0.001 * (nTime3 - nTime2) / block.vtx.size(), | 0.001 * (nTime3 - nTime2) / block.vtx.size(), | ||||
nInputs <= 1 ? 0 : 0.001 * (nTime3 - nTime2) / (nInputs - 1), | nInputs <= 1 ? 0 : 0.001 * (nTime3 - nTime2) / (nInputs - 1), | ||||
nTimeConnect * 0.000001); | nTimeConnect * 0.000001); | ||||
CAmount blockReward = | Amount blockReward = | ||||
nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus()); | nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus()); | ||||
if (block.vtx[0]->GetValueOut() > blockReward) { | if (block.vtx[0]->GetValueOut() > blockReward) { | ||||
return state.DoS(100, error("ConnectBlock(): coinbase pays too much " | return state.DoS(100, error("ConnectBlock(): coinbase pays too much " | ||||
"(actual=%d vs limit=%d)", | "(actual=%d vs limit=%d)", | ||||
block.vtx[0]->GetValueOut(), blockReward), | block.vtx[0]->GetValueOut(), blockReward), | ||||
REJECT_INVALID, "bad-cb-amount"); | REJECT_INVALID, "bad-cb-amount"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 2,821 Lines • ▼ Show 20 Lines | try { | ||||
while (num--) { | while (num--) { | ||||
CTransactionRef tx; | CTransactionRef tx; | ||||
int64_t nTime; | int64_t nTime; | ||||
int64_t nFeeDelta; | int64_t nFeeDelta; | ||||
file >> tx; | file >> tx; | ||||
file >> nTime; | file >> nTime; | ||||
file >> nFeeDelta; | file >> nFeeDelta; | ||||
CAmount amountdelta = nFeeDelta; | Amount amountdelta = nFeeDelta; | ||||
if (amountdelta) { | if (amountdelta != 0) { | ||||
mempool.PrioritiseTransaction(tx->GetId(), | 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, 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()) return false; | if (ShutdownRequested()) return false; | ||||
} | } | ||||
std::map<uint256, CAmount> 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(), | 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, CAmount> mapDeltas; | std::map<uint256, Amount> mapDeltas; | ||||
std::vector<TxMempoolInfo> vinfo; | std::vector<TxMempoolInfo> vinfo; | ||||
{ | { | ||||
LOCK(mempool.cs); | LOCK(mempool.cs); | ||||
for (const auto &i : mempool.mapDeltas) { | for (const auto &i : mempool.mapDeltas) { | ||||
mapDeltas[i.first] = i.second.second.GetSatoshis(); | mapDeltas[i.first] = i.second.second.GetSatoshis(); | ||||
} | } | ||||
vinfo = mempool.infoAll(); | vinfo = mempool.infoAll(); | ||||
▲ Show 20 Lines • Show All 66 Lines • Show Last 20 Lines |