Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14864832
D16019.id47299.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Subscribers
None
D16019.id47299.diff
View Options
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -1223,7 +1223,7 @@
// All of the following cache a recent block, and are protected by
// m_most_recent_block_mutex
- Mutex m_most_recent_block_mutex;
+ mutable Mutex m_most_recent_block_mutex;
std::shared_ptr<const CBlock>
m_most_recent_block GUARDED_BY(m_most_recent_block_mutex);
std::shared_ptr<const CBlockHeaderAndShortTxIDs>
@@ -6240,6 +6240,30 @@
LOCK(cs_main);
m_chainman.ActiveChainstate().UnparkBlock(pindex);
}
+
+ if (fPreConsensus) {
+ // First check if the block is cached before reading
+ // from disk.
+ auto pblock = WITH_LOCK(m_most_recent_block_mutex,
+ return m_most_recent_block);
+
+ if (!pblock ||
+ pblock->GetHash() != pindex->GetBlockHash()) {
+ std::shared_ptr<CBlock> pblockRead =
+ std::make_shared<CBlock>();
+ if (!ReadBlockFromDisk(
+ *pblockRead, pindex,
+ m_chainparams.GetConsensus())) {
+ assert(!"cannot load block from disk");
+ }
+ pblock = pblockRead;
+ }
+ assert(pblock);
+
+ LOCK(m_mempool.cs);
+ m_mempool.removeForFinalizedBlock(pblock->vtx);
+ }
+
m_chainman.ActiveChainstate().AvalancheFinalizeBlock(
pindex);
} break;
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -581,4 +581,57 @@
checkOrdering(entryB, entryA);
}
+BOOST_AUTO_TEST_CASE(remove_for_finalized_block) {
+ CTxMemPool &pool = *Assert(m_node.mempool);
+ TestMemPoolEntryHelper entry;
+
+ LOCK2(cs_main, pool.cs);
+
+ std::vector<CTransactionRef> txs;
+ txs.reserve(100);
+ for (size_t i = 0; i < 100; i++) {
+ CTransactionRef tx = make_tx({int64_t(i + 1) * COIN});
+ const TxId &txid = tx->GetId();
+ auto mempoolEntry = entry.FromTx(tx);
+
+ pool.addUnchecked(mempoolEntry);
+ BOOST_CHECK(pool.exists(txid));
+
+ BOOST_CHECK(pool.setAvalancheFinalized(mempoolEntry));
+ BOOST_CHECK(pool.isAvalancheFinalized(txid));
+
+ txs.push_back(std::move(tx));
+ }
+
+ std::vector<CTransactionRef> minedTxs(txs.begin(), txs.begin() + 50);
+ pool.removeForFinalizedBlock(minedTxs);
+
+ for (const auto &tx : minedTxs) {
+ // No longer in the radix tree
+ BOOST_CHECK(!pool.isAvalancheFinalized(tx->GetId()));
+ }
+ // Other txs are still there
+ for (size_t i = 50; i < 100; i++) {
+ BOOST_CHECK(pool.isAvalancheFinalized(txs[i]->GetId()));
+ }
+
+ // Repeat is no op
+ pool.removeForFinalizedBlock(minedTxs);
+ for (const auto &tx : minedTxs) {
+ // No longer in the radix tree
+ BOOST_CHECK(!pool.isAvalancheFinalized(tx->GetId()));
+ }
+ // Other txs are still there
+ for (size_t i = 50; i < 100; i++) {
+ BOOST_CHECK(pool.isAvalancheFinalized(txs[i]->GetId()));
+ }
+
+ // Remove them all
+ pool.removeForFinalizedBlock(txs);
+ for (const auto &tx : txs) {
+ // No longer in the radix tree
+ BOOST_CHECK(!pool.isAvalancheFinalized(tx->GetId()));
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/txmempool.h b/src/txmempool.h
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -365,6 +365,8 @@
EXCLUSIVE_LOCKS_REQUIRED(cs);
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs);
void updateFeeForBlock() EXCLUSIVE_LOCKS_REQUIRED(cs);
+ void removeForFinalizedBlock(const std::vector<CTransactionRef> &vtx)
+ EXCLUSIVE_LOCKS_REQUIRED(cs);
void clear();
// lock free
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -192,6 +192,8 @@
// even if not directly reported below.
uint64_t mempool_sequence = GetAndIncrementSequence();
+ const TxId &txid = (*it)->GetTx().GetId();
+
if (reason != MemPoolRemovalReason::BLOCK) {
// Notify clients that a transaction has been removed from the mempool
// for any reason except being included in a block. Clients interested
@@ -199,6 +201,8 @@
// BlockConnected notification.
GetMainSignals().TransactionRemovedFromMempool(
(*it)->GetSharedTx(), reason, mempool_sequence);
+
+ finalizedTxs.remove(txid);
}
for (const CTxIn &txin : (*it)->GetTx().vin) {
@@ -206,11 +210,8 @@
}
/* add logging because unchecked */
- const TxId &txid = (*it)->GetTx().GetId();
RemoveUnbroadcastTx(txid, true);
- finalizedTxs.remove(txid);
-
totalTxSize -= (*it)->GetTxSize();
m_total_fee -= (*it)->GetFee();
cachedInnerUsage -= (*it)->DynamicMemoryUsage();
@@ -310,6 +311,19 @@
blockSinceLastRollingFeeBump = true;
}
+void CTxMemPool::removeForFinalizedBlock(
+ const std::vector<CTransactionRef> &vtx) {
+ AssertLockHeld(cs);
+
+ for (const auto &tx : vtx) {
+ // If the tx has a parent, it will be in the block as well or the block
+ // is invalid. If the tx has a child, it can remain in the tree for the
+ // next block. So we can simply remove the txs from the block with no
+ // further check.
+ finalizedTxs.remove(tx->GetId());
+ }
+}
+
void CTxMemPool::_clear() {
mapTx.clear();
mapNextTx.clear();
diff --git a/test/functional/abc_p2p_avalanche_transaction_voting.py b/test/functional/abc_p2p_avalanche_transaction_voting.py
--- a/test/functional/abc_p2p_avalanche_transaction_voting.py
+++ b/test/functional/abc_p2p_avalanche_transaction_voting.py
@@ -195,6 +195,26 @@
assert txid in node.getrawmempool()
tip = self.generate(node, 1)[0]
+
+ self.log.info("The transaction remains finalized after it's mined")
+
+ assert node.isfinaltransaction(txid, tip)
+ assert txid not in node.getrawmempool()
+
+ self.log.info("The transaction remains finalized even when reorg'ed")
+
+ node.parkblock(tip)
+ assert node.getbestblockhash() != tip
+ assert node.isfinaltransaction(txid)
+ assert txid in node.getrawmempool()
+
+ node.unparkblock(tip)
+ assert_equal(node.getbestblockhash(), tip)
+ assert node.isfinaltransaction(txid, tip)
+ assert txid not in node.getrawmempool()
+
+ self.log.info("The transaction remains finalized after the block is finalized")
+
self.wait_until(lambda: has_finalized_block(tip))
assert node.isfinaltransaction(txid, tip)
assert txid not in node.getrawmempool()
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, May 20, 22:42 (4 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5866082
Default Alt Text
D16019.id47299.diff (7 KB)
Attached To
D16019: [avalanche] Remove finalized txs upon block finalization
Event Timeline
Log In to Comment