Skip to content

Commit

Permalink
Rework mempool accounts view
Browse files Browse the repository at this point in the history
Signed-off-by: Anthony Fieroni <[email protected]>
  • Loading branch information
bvbfan committed Nov 15, 2021
1 parent 3282d5a commit 08ecf02
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 59 deletions.
107 changes: 50 additions & 57 deletions src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator)
// accepting transactions becomes O(N^2) where N is the number
// of transactions in the pool
nCheckFrequency = 0;
accountsViewDirty = false;
}

bool CTxMemPool::isSpent(const COutPoint& outpoint) const
Expand Down Expand Up @@ -582,49 +583,15 @@ void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigne
// Before the txs in the new block have been removed from the mempool, update policy estimates
if (minerPolicyEstimator) {minerPolicyEstimator->processBlock(nBlockHeight, entries);}

for (auto& it : staged) {
auto& tx = it->GetTx();
removeConflicts(tx);
ClearPrioritisation(tx.GetHash());
}

RemoveStaged(staged, true, MemPoolRemovalReason::BLOCK);

if (pcustomcsview) { // can happen in tests
// check entire mempool
CAmount txfee = 0;
accountsView().Discard();
CCustomCSView viewDuplicate(accountsView());
CCoinsViewCache mempoolDuplicate(&::ChainstateActive().CoinsTip());

setEntries staged;
// Check custom TX consensus types are now not in conflict with account layer
auto& txsByEntryTime = mapTx.get<entry_time>();
for (auto it = txsByEntryTime.begin(); it != txsByEntryTime.end(); ++it) {
CValidationState state;
const auto& tx = it->GetTx();
if (!Consensus::CheckTxInputs(tx, state, mempoolDuplicate, &viewDuplicate, nBlockHeight, txfee, Params())) {
LogPrintf("%s: Remove conflicting TX: %s\n", __func__, tx.GetHash().GetHex());
staged.insert(mapTx.project<0>(it));
continue;
}
auto res = ApplyCustomTx(viewDuplicate, mempoolDuplicate, tx, Params().GetConsensus(), nBlockHeight);
if (!res.ok && (res.code & CustomTxErrCodes::Fatal)) {
LogPrintf("%s: Remove conflicting custom TX: %s\n", __func__, tx.GetHash().GetHex());
staged.insert(mapTx.project<0>(it));
}
}

for (auto& it : staged) {
auto& tx = it->GetTx();
removeConflicts(tx);
ClearPrioritisation(tx.GetHash());
}

RemoveStaged(staged, true, MemPoolRemovalReason::BLOCK);
viewDuplicate.Flush();
for (const auto& tx : vtx) {
removeConflicts(*tx);
ClearPrioritisation(tx->GetHash());
}

rebuildAccountsView(nBlockHeight);

lastRollingFeeUpdate = GetTime();
blockSinceLastRollingFeeBump = true;
}
Expand Down Expand Up @@ -975,27 +942,10 @@ size_t CTxMemPool::DynamicMemoryUsage() const {
void CTxMemPool::RemoveStaged(const setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) {
AssertLockHeld(cs);
UpdateForRemoveFromMempool(stage, updateDescendants);
std::set<uint256> txids;
for (txiter it : stage) {
txids.insert(it->GetTx().GetHash());
removeUnchecked(it, reason);
}
if (pcustomcsview && !txids.empty()) {
auto& view = accountsView();
std::map<uint32_t, uint256> orderedTxs;
auto it = NewKVIterator<CUndosView::ByUndoKey>(UndoKey{}, view.GetStorage().GetRaw());
for (; it.Valid() && !txids.empty(); it.Next()) {
auto& key = it.Key();
auto itTx = txids.find(key.txid);
if (itTx != txids.end()) {
orderedTxs.emplace(key.height, key.txid);
txids.erase(itTx);
}
}
for (auto it = orderedTxs.rbegin(); it != orderedTxs.rend(); ++it) {
view.OnUndoTx(it->second, it->first);
}
}
accountsViewDirty = accountsViewDirty || !stage.empty();
}

int CTxMemPool::Expire(int64_t time) {
Expand Down Expand Up @@ -1134,6 +1084,49 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpends
}
}

void CTxMemPool::rebuildAccountsView(int height)
{
if (!pcustomcsview || !accountsViewDirty) {
return;
}

CAmount txfee = 0;
accountsView().Discard();
CCustomCSView viewDuplicate(accountsView());
CCoinsViewCache mempoolDuplicate(&::ChainstateActive().CoinsTip());

setEntries staged;
std::vector<CTransactionRef> txs;
// Check custom TX consensus types are now not in conflict with account layer
auto& txsByEntryTime = mapTx.get<entry_time>();
for (auto it = txsByEntryTime.begin(); it != txsByEntryTime.end(); ++it) {
CValidationState state;
const auto& tx = it->GetTx();
if (!Consensus::CheckTxInputs(tx, state, mempoolDuplicate, &viewDuplicate, height, txfee, Params())) {
LogPrintf("%s: Remove conflicting TX: %s\n", __func__, tx.GetHash().GetHex());
staged.insert(mapTx.project<0>(it));
txs.push_back(it->GetSharedTx());
continue;
}
auto res = ApplyCustomTx(viewDuplicate, mempoolDuplicate, tx, Params().GetConsensus(), height);
if (!res && (res.code & CustomTxErrCodes::Fatal)) {
LogPrintf("%s: Remove conflicting custom TX: %s\n", __func__, tx.GetHash().GetHex());
staged.insert(mapTx.project<0>(it));
txs.push_back(it->GetSharedTx());
}
}

RemoveStaged(staged, true, MemPoolRemovalReason::BLOCK);

for (const auto& tx : txs) {
removeConflicts(*tx);
ClearPrioritisation(tx->GetHash());
}

viewDuplicate.Flush();
accountsViewDirty = false;
}

uint64_t CTxMemPool::CalculateDescendantMaximum(txiter entry) const {
// find parent with highest descendant count
std::vector<txiter> candidates;
Expand Down
2 changes: 2 additions & 0 deletions src/txmempool.h
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ class CTxMemPool

std::vector<indexed_transaction_set::const_iterator> GetSortedDepthAndScore() const EXCLUSIVE_LOCKS_REQUIRED(cs);

bool accountsViewDirty;
std::unique_ptr<CCustomCSView> acview;
public:
indirectmap<COutPoint, const CTransaction*> mapNextTx GUARDED_BY(cs);
Expand Down Expand Up @@ -704,6 +705,7 @@ class CTxMemPool
boost::signals2::signal<void (CTransactionRef, MemPoolRemovalReason)> NotifyEntryRemoved;

CCustomCSView& accountsView();
void rebuildAccountsView(int height);
private:
/** UpdateForDescendants is used by UpdateTransactionsFromBlock to update
* the descendants for a single transaction that has been added to the
Expand Down
5 changes: 3 additions & 2 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,8 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool

const auto height = GetSpendHeight(view);

// it does not need to check mempool anymore it has view there
// rebuild accounts view if dirty
pool.rebuildAccountsView(height);

CAmount nFees = 0;
if (!Consensus::CheckTxInputs(tx, state, view, &mnview, height, nFees, chainparams)) {
Expand Down Expand Up @@ -910,14 +911,14 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool

// Store transaction in memory
pool.addUnchecked(entry, setAncestors, validForFeeEstimation);
mnview.Flush();

// trim mempool and check if tx was trimmed
if (!bypass_limits) {
LimitMempoolSize(pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
if (!pool.exists(hash))
return state.Invalid(ValidationInvalidReason::TX_MEMPOOL_POLICY, false, REJECT_INSUFFICIENTFEE, "mempool full");
}
mnview.Flush();
}

GetMainSignals().TransactionAddedToMempool(ptx);
Expand Down

0 comments on commit 08ecf02

Please sign in to comment.