Changeset View
Changeset View
Standalone View
Standalone View
src/txmempool.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 | ||||
// 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 "txmempool.h" | #include "txmempool.h" | ||||
#include "chainparams.h" // for GetConsensus. | #include "chainparams.h" // for GetConsensus. | ||||
#include "clientversion.h" | #include "clientversion.h" | ||||
#include "consensus/consensus.h" | #include "consensus/consensus.h" | ||||
#include "consensus/tx_verify.h" | #include "consensus/tx_verify.h" | ||||
#include "consensus/validation.h" | #include "consensus/validation.h" | ||||
#include "policy/fees.h" | #include "policy/fees.h" | ||||
#include "policy/policy.h" | #include "policy/policy.h" | ||||
#include "reverse_iterator.h" | |||||
#include "streams.h" | #include "streams.h" | ||||
#include "timedata.h" | #include "timedata.h" | ||||
#include "util.h" | #include "util.h" | ||||
#include "utilmoneystr.h" | #include "utilmoneystr.h" | ||||
#include "utiltime.h" | #include "utiltime.h" | ||||
#include "validation.h" | #include "validation.h" | ||||
#include "version.h" | #include "version.h" | ||||
#include <boost/range/adaptor/reversed.hpp> | |||||
CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, | CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, | ||||
int64_t _nTime, double _entryPriority, | int64_t _nTime, double _entryPriority, | ||||
unsigned int _entryHeight, | unsigned int _entryHeight, | ||||
Amount _inChainInputValue, | Amount _inChainInputValue, | ||||
bool _spendsCoinbase, int64_t _sigOpsCount, | bool _spendsCoinbase, int64_t _sigOpsCount, | ||||
LockPoints lp) | LockPoints lp) | ||||
: tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), | : tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), | ||||
entryHeight(_entryHeight), inChainInputValue(_inChainInputValue), | entryHeight(_entryHeight), inChainInputValue(_inChainInputValue), | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | void CTxMemPool::UpdateTransactionsFromBlock( | ||||
std::set<TxId> setAlreadyIncluded(txidsToUpdate.begin(), | std::set<TxId> setAlreadyIncluded(txidsToUpdate.begin(), | ||||
txidsToUpdate.end()); | txidsToUpdate.end()); | ||||
// Iterate in reverse, so that whenever we are looking at at a transaction | // Iterate in reverse, so that whenever we are looking at at a transaction | ||||
// we are sure that all in-mempool descendants have already been processed. | // we are sure that all in-mempool descendants have already been processed. | ||||
// This maximizes the benefit of the descendant cache and guarantees that | // This maximizes the benefit of the descendant cache and guarantees that | ||||
// setMemPoolChildren will be updated, an assumption made in | // setMemPoolChildren will be updated, an assumption made in | ||||
// UpdateForDescendants. | // UpdateForDescendants. | ||||
for (const TxId &txid : boost::adaptors::reverse(txidsToUpdate)) { | for (const TxId &txid : reverse_iterate(txidsToUpdate)) { | ||||
// we cache the in-mempool children to avoid duplicate updates | // we cache the in-mempool children to avoid duplicate updates | ||||
setEntries setChildren; | setEntries setChildren; | ||||
// calculate children from mapNextTx | // calculate children from mapNextTx | ||||
txiter it = mapTx.find(txid); | txiter it = mapTx.find(txid); | ||||
if (it == mapTx.end()) { | if (it == mapTx.end()) { | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 491 Lines • ▼ Show 20 Lines | |||||
void CTxMemPool::removeForBlock(const std::vector<CTransactionRef> &vtx, | void CTxMemPool::removeForBlock(const std::vector<CTransactionRef> &vtx, | ||||
unsigned int nBlockHeight) { | unsigned int nBlockHeight) { | ||||
LOCK(cs); | LOCK(cs); | ||||
DisconnectedBlockTransactions disconnectpool; | DisconnectedBlockTransactions disconnectpool; | ||||
disconnectpool.addForBlock(vtx); | disconnectpool.addForBlock(vtx); | ||||
std::vector<const CTxMemPoolEntry *> entries; | std::vector<const CTxMemPoolEntry *> entries; | ||||
for (const CTransactionRef &tx : boost::adaptors::reverse( | for (const CTransactionRef &tx : | ||||
disconnectpool.GetQueuedTx().get<insertion_order>())) { | reverse_iterate(disconnectpool.GetQueuedTx().get<insertion_order>())) { | ||||
uint256 txid = tx->GetId(); | uint256 txid = tx->GetId(); | ||||
indexed_transaction_set::iterator i = mapTx.find(txid); | indexed_transaction_set::iterator i = mapTx.find(txid); | ||||
if (i != mapTx.end()) { | if (i != mapTx.end()) { | ||||
entries.push_back(&*i); | entries.push_back(&*i); | ||||
} | } | ||||
} | } | ||||
// Before the txs in the new block have been removed from the mempool, | // Before the txs in the new block have been removed from the mempool, | ||||
// update policy estimates | // update policy estimates | ||||
minerPolicyEstimator->processBlock(nBlockHeight, entries); | minerPolicyEstimator->processBlock(nBlockHeight, entries); | ||||
for (const CTransactionRef &tx : boost::adaptors::reverse( | for (const CTransactionRef &tx : | ||||
disconnectpool.GetQueuedTx().get<insertion_order>())) { | reverse_iterate(disconnectpool.GetQueuedTx().get<insertion_order>())) { | ||||
txiter it = mapTx.find(tx->GetId()); | txiter it = mapTx.find(tx->GetId()); | ||||
if (it != mapTx.end()) { | if (it != mapTx.end()) { | ||||
setEntries stage; | setEntries stage; | ||||
stage.insert(it); | stage.insert(it); | ||||
RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK); | RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK); | ||||
} | } | ||||
removeConflicts(*tx); | removeConflicts(*tx); | ||||
ClearPrioritisation(tx->GetId()); | ClearPrioritisation(tx->GetId()); | ||||
▲ Show 20 Lines • Show All 607 Lines • ▼ Show 20 Lines | SaltedTxidHasher::SaltedTxidHasher() | ||||
: k0(GetRand(std::numeric_limits<uint64_t>::max())), | : k0(GetRand(std::numeric_limits<uint64_t>::max())), | ||||
k1(GetRand(std::numeric_limits<uint64_t>::max())) {} | k1(GetRand(std::numeric_limits<uint64_t>::max())) {} | ||||
/** Maximum bytes for transactions to store for processing during reorg */ | /** Maximum bytes for transactions to store for processing during reorg */ | ||||
static const size_t MAX_DISCONNECTED_TX_POOL_SIZE = 20 * DEFAULT_MAX_BLOCK_SIZE; | static const size_t MAX_DISCONNECTED_TX_POOL_SIZE = 20 * DEFAULT_MAX_BLOCK_SIZE; | ||||
void DisconnectedBlockTransactions::addForBlock( | void DisconnectedBlockTransactions::addForBlock( | ||||
const std::vector<CTransactionRef> &vtx) { | const std::vector<CTransactionRef> &vtx) { | ||||
for (const auto &tx : boost::adaptors::reverse(vtx)) { | for (const auto &tx : reverse_iterate(vtx)) { | ||||
// If we already added it, just skip. | // If we already added it, just skip. | ||||
auto it = queuedTx.find(tx->GetId()); | auto it = queuedTx.find(tx->GetId()); | ||||
if (it != queuedTx.end()) { | if (it != queuedTx.end()) { | ||||
continue; | continue; | ||||
} | } | ||||
// Insert the transaction into the pool. | // Insert the transaction into the pool. | ||||
addTransaction(tx); | addTransaction(tx); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | void DisconnectedBlockTransactions::updateMempoolForReorg(const Config &config, | ||||
// disconnectpool's insertion_order index sorts the entries from oldest to | // disconnectpool's insertion_order index sorts the entries from oldest to | ||||
// newest, but the oldest entry will be the last tx from the latest mined | // newest, but the oldest entry will be the last tx from the latest mined | ||||
// block that was disconnected. | // block that was disconnected. | ||||
// Iterate disconnectpool in reverse, so that we add transactions back to | // Iterate disconnectpool in reverse, so that we add transactions back to | ||||
// the mempool starting with the earliest transaction that had been | // the mempool starting with the earliest transaction that had been | ||||
// previously seen in a block. | // previously seen in a block. | ||||
for (const CTransactionRef &tx : | for (const CTransactionRef &tx : | ||||
boost::adaptors::reverse(queuedTx.get<insertion_order>())) { | reverse_iterate(queuedTx.get<insertion_order>())) { | ||||
// ignore validation errors in resurrected transactions | // ignore validation errors in resurrected transactions | ||||
CValidationState stateDummy; | CValidationState stateDummy; | ||||
if (!fAddToMempool || tx->IsCoinBase() || | if (!fAddToMempool || tx->IsCoinBase() || | ||||
!AcceptToMemoryPool(config, g_mempool, stateDummy, tx, false, | !AcceptToMemoryPool(config, g_mempool, stateDummy, tx, false, | ||||
nullptr, true)) { | nullptr, true)) { | ||||
// If the transaction doesn't make it in to the mempool, remove any | // If the transaction doesn't make it in to the mempool, remove any | ||||
// transactions that depend on it (which would now be orphans). | // transactions that depend on it (which would now be orphans). | ||||
g_mempool.removeRecursive(*tx, MemPoolRemovalReason::REORG); | g_mempool.removeRecursive(*tx, MemPoolRemovalReason::REORG); | ||||
Show All 24 Lines |