mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
Convert txmempool exists
to GenTxidVariant
This commit is contained in:
parent
c5da76b54b
commit
a3b6eda613
18 changed files with 61 additions and 59 deletions
|
@ -4238,7 +4238,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
||||||
// Always relay transactions received from peers with forcerelay
|
// Always relay transactions received from peers with forcerelay
|
||||||
// permission, even if they were already in the mempool, allowing
|
// permission, even if they were already in the mempool, allowing
|
||||||
// the node to function as a gateway for nodes hidden behind it.
|
// the node to function as a gateway for nodes hidden behind it.
|
||||||
if (!m_mempool.exists(GenTxid::Txid(tx.GetHash()))) {
|
if (!m_mempool.exists(tx.GetHash())) {
|
||||||
LogPrintf("Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
|
LogPrintf("Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
|
||||||
tx.GetHash().ToString(), tx.GetWitnessHash().ToString(), pfrom.GetId());
|
tx.GetHash().ToString(), tx.GetWitnessHash().ToString(), pfrom.GetId());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -673,7 +673,7 @@ public:
|
||||||
{
|
{
|
||||||
if (!m_node.mempool) return false;
|
if (!m_node.mempool) return false;
|
||||||
LOCK(m_node.mempool->cs);
|
LOCK(m_node.mempool->cs);
|
||||||
return m_node.mempool->exists(GenTxid::Txid(txid));
|
return m_node.mempool->exists(Txid::FromUint256(txid));
|
||||||
}
|
}
|
||||||
bool hasDescendantsInMempool(const uint256& txid) override
|
bool hasDescendantsInMempool(const uint256& txid) override
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,7 +106,7 @@ bool LoadMempool(CTxMemPool& pool, const fs::path& load_path, Chainstate& active
|
||||||
// wallet(s) having loaded it while we were processing
|
// wallet(s) having loaded it while we were processing
|
||||||
// mempool transactions; consider these as valid, instead of
|
// mempool transactions; consider these as valid, instead of
|
||||||
// failed, but mark them as 'already there'
|
// failed, but mark them as 'already there'
|
||||||
if (pool.exists(GenTxid::Txid(tx->GetHash()))) {
|
if (pool.exists(tx->GetHash())) {
|
||||||
++already_there;
|
++already_there;
|
||||||
} else {
|
} else {
|
||||||
++failed;
|
++failed;
|
||||||
|
|
|
@ -27,7 +27,7 @@ MiniMiner::MiniMiner(const CTxMemPool& mempool, const std::vector<COutPoint>& ou
|
||||||
// Anything that's spent by the mempool is to-be-replaced
|
// Anything that's spent by the mempool is to-be-replaced
|
||||||
// Anything otherwise unavailable just has a bump fee of 0
|
// Anything otherwise unavailable just has a bump fee of 0
|
||||||
for (const auto& outpoint : outpoints) {
|
for (const auto& outpoint : outpoints) {
|
||||||
if (!mempool.exists(GenTxid::Txid(outpoint.hash))) {
|
if (!mempool.exists(outpoint.hash)) {
|
||||||
// This UTXO is either confirmed or not yet submitted to mempool.
|
// This UTXO is either confirmed or not yet submitted to mempool.
|
||||||
// If it's confirmed, no bump fee is required.
|
// If it's confirmed, no bump fee is required.
|
||||||
// If it's not yet submitted, we have no information, so return 0.
|
// If it's not yet submitted, we have no information, so return 0.
|
||||||
|
|
|
@ -148,7 +148,7 @@ bool TxDownloadManagerImpl::AlreadyHaveTx(const GenTxid& gtxid, bool include_rec
|
||||||
|
|
||||||
if (RecentConfirmedTransactionsFilter().contains(hash)) return true;
|
if (RecentConfirmedTransactionsFilter().contains(hash)) return true;
|
||||||
|
|
||||||
return RecentRejectsFilter().contains(hash) || m_opts.m_mempool.exists(gtxid);
|
return RecentRejectsFilter().contains(hash) || m_opts.m_mempool.exists(gtxid.ToVariant());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TxDownloadManagerImpl::ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo& info)
|
void TxDownloadManagerImpl::ConnectedPeer(NodeId nodeid, const TxDownloadConnectionInfo& info)
|
||||||
|
@ -383,7 +383,7 @@ node::RejectedTxTodo TxDownloadManagerImpl::MempoolRejectedTx(const CTransaction
|
||||||
fRejectedParents = true;
|
fRejectedParents = true;
|
||||||
break;
|
break;
|
||||||
} else if (RecentRejectsReconsiderableFilter().contains(parent_txid) &&
|
} else if (RecentRejectsReconsiderableFilter().contains(parent_txid) &&
|
||||||
!m_opts.m_mempool.exists(GenTxid::Txid(parent_txid))) {
|
!m_opts.m_mempool.exists(Txid::FromUint256(parent_txid))) {
|
||||||
// More than 1 parent in m_lazy_recent_rejects_reconsiderable: 1p1c will not be
|
// More than 1 parent in m_lazy_recent_rejects_reconsiderable: 1p1c will not be
|
||||||
// sufficient to accept this package, so just give up here.
|
// sufficient to accept this package, so just give up here.
|
||||||
if (rejected_parent_reconsiderable.has_value()) {
|
if (rejected_parent_reconsiderable.has_value()) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
|
||||||
|
|
||||||
// If this transaction is not in our mempool, then we can't be sure
|
// If this transaction is not in our mempool, then we can't be sure
|
||||||
// we will know about all its inputs.
|
// we will know about all its inputs.
|
||||||
if (!pool.exists(GenTxid::Txid(tx.GetHash()))) {
|
if (!pool.exists(tx.GetHash())) {
|
||||||
return RBFTransactionState::UNKNOWN;
|
return RBFTransactionState::UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx,
|
||||||
if (!parents_of_conflicts.count(tx.vin[j].prevout.hash)) {
|
if (!parents_of_conflicts.count(tx.vin[j].prevout.hash)) {
|
||||||
// Rather than check the UTXO set - potentially expensive - it's cheaper to just check
|
// Rather than check the UTXO set - potentially expensive - it's cheaper to just check
|
||||||
// if the new input refers to a tx that's in the mempool.
|
// if the new input refers to a tx that's in the mempool.
|
||||||
if (pool.exists(GenTxid::Txid(tx.vin[j].prevout.hash))) {
|
if (pool.exists(tx.vin[j].prevout.hash)) {
|
||||||
return strprintf("replacement %s adds unconfirmed input, idx %d",
|
return strprintf("replacement %s adds unconfirmed input, idx %d",
|
||||||
tx.GetHash().ToString(), j);
|
tx.GetHash().ToString(), j);
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,7 +309,7 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool
|
||||||
std::set<std::string> setDepends;
|
std::set<std::string> setDepends;
|
||||||
for (const CTxIn& txin : tx.vin)
|
for (const CTxIn& txin : tx.vin)
|
||||||
{
|
{
|
||||||
if (pool.exists(GenTxid::Txid(txin.prevout.hash)))
|
if (pool.exists(txin.prevout.hash))
|
||||||
setDepends.insert(txin.prevout.hash.ToString());
|
setDepends.insert(txin.prevout.hash.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1030,7 +1030,7 @@ static RPCHelpMan submitpackage()
|
||||||
// Belt-and-suspenders check; everything should be successful here
|
// Belt-and-suspenders check; everything should be successful here
|
||||||
CHECK_NONFATAL(package_result.m_tx_results.size() == txns.size());
|
CHECK_NONFATAL(package_result.m_tx_results.size() == txns.size());
|
||||||
for (const auto& tx : txns) {
|
for (const auto& tx : txns) {
|
||||||
CHECK_NONFATAL(mempool.exists(GenTxid::Txid(tx->GetHash())));
|
CHECK_NONFATAL(mempool.exists(tx->GetHash()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1054,7 +1054,7 @@ static RPCHelpMan submitpackage()
|
||||||
size_t num_broadcast{0};
|
size_t num_broadcast{0};
|
||||||
for (const auto& tx : txns) {
|
for (const auto& tx : txns) {
|
||||||
// We don't want to re-submit the txn for validation in BroadcastTransaction
|
// We don't want to re-submit the txn for validation in BroadcastTransaction
|
||||||
if (!mempool.exists(GenTxid::Txid(tx->GetHash()))) {
|
if (!mempool.exists(tx->GetHash())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
|
||||||
if (!pool.GetConflictTx(coin)) outpoints.push_back(coin);
|
if (!pool.GetConflictTx(coin)) outpoints.push_back(coin);
|
||||||
}
|
}
|
||||||
for (const auto& tx : transactions) {
|
for (const auto& tx : transactions) {
|
||||||
assert(pool.exists(GenTxid::Txid(tx->GetHash())));
|
assert(pool.exists(tx->GetHash()));
|
||||||
for (uint32_t n{0}; n < tx->vout.size(); ++n) {
|
for (uint32_t n{0}; n < tx->vout.size(); ++n) {
|
||||||
COutPoint coin{tx->GetHash(), n};
|
COutPoint coin{tx->GetHash(), n};
|
||||||
if (!pool.GetConflictTx(coin)) outpoints.push_back(coin);
|
if (!pool.GetConflictTx(coin)) outpoints.push_back(coin);
|
||||||
|
|
|
@ -310,7 +310,7 @@ FUZZ_TARGET(ephemeral_package_eval, .init = initialize_tx_pool)
|
||||||
const auto delta = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-50 * COIN, +50 * COIN);
|
const auto delta = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(-50 * COIN, +50 * COIN);
|
||||||
// We only prioritise out of mempool transactions since PrioritiseTransaction doesn't
|
// We only prioritise out of mempool transactions since PrioritiseTransaction doesn't
|
||||||
// filter for ephemeral dust
|
// filter for ephemeral dust
|
||||||
if (tx_pool.exists(GenTxid::Txid(txid))) {
|
if (tx_pool.exists(txid)) {
|
||||||
const auto tx_info{tx_pool.info(GenTxid::Txid(txid))};
|
const auto tx_info{tx_pool.info(GenTxid::Txid(txid))};
|
||||||
if (GetDust(*tx_info.tx, tx_pool.m_opts.dust_relay_feerate).empty()) {
|
if (GetDust(*tx_info.tx, tx_pool.m_opts.dust_relay_feerate).empty()) {
|
||||||
tx_pool.PrioritiseTransaction(txid.ToUint256(), delta);
|
tx_pool.PrioritiseTransaction(txid.ToUint256(), delta);
|
||||||
|
|
|
@ -79,7 +79,7 @@ FUZZ_TARGET(partially_downloaded_block, .init = initialize_pdb)
|
||||||
available.insert(i);
|
available.insert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_to_mempool && !pool.exists(GenTxid::Txid(tx->GetHash()))) {
|
if (add_to_mempool && !pool.exists(tx->GetHash())) {
|
||||||
LOCK2(cs_main, pool.cs);
|
LOCK2(cs_main, pool.cs);
|
||||||
AddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));
|
AddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));
|
||||||
available.insert(i);
|
available.insert(i);
|
||||||
|
|
|
@ -315,8 +315,8 @@ FUZZ_TARGET(tx_pool_standard, .init = initialize_tx_pool)
|
||||||
node.validation_signals->SyncWithValidationInterfaceQueue();
|
node.validation_signals->SyncWithValidationInterfaceQueue();
|
||||||
node.validation_signals->UnregisterSharedValidationInterface(txr);
|
node.validation_signals->UnregisterSharedValidationInterface(txr);
|
||||||
|
|
||||||
bool txid_in_mempool = tx_pool.exists(GenTxid::Txid(tx->GetHash()));
|
bool txid_in_mempool = tx_pool.exists(tx->GetHash());
|
||||||
bool wtxid_in_mempool = tx_pool.exists(GenTxid::Wtxid(tx->GetWitnessHash()));
|
bool wtxid_in_mempool = tx_pool.exists(tx->GetWitnessHash());
|
||||||
CheckATMPInvariants(res, txid_in_mempool, wtxid_in_mempool);
|
CheckATMPInvariants(res, txid_in_mempool, wtxid_in_mempool);
|
||||||
|
|
||||||
Assert(accepted != added.empty());
|
Assert(accepted != added.empty());
|
||||||
|
|
|
@ -454,12 +454,12 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||||
AddToMempool(pool, entry.Fee(5000LL).FromTx(tx2));
|
AddToMempool(pool, entry.Fee(5000LL).FromTx(tx2));
|
||||||
|
|
||||||
pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing
|
pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(tx1.GetHash())));
|
BOOST_CHECK(pool.exists(tx1.GetHash()));
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(tx2.GetHash())));
|
BOOST_CHECK(pool.exists(tx2.GetHash()));
|
||||||
|
|
||||||
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // should remove the lower-feerate transaction
|
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // should remove the lower-feerate transaction
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(tx1.GetHash())));
|
BOOST_CHECK(pool.exists(tx1.GetHash()));
|
||||||
BOOST_CHECK(!pool.exists(GenTxid::Txid(tx2.GetHash())));
|
BOOST_CHECK(!pool.exists(tx2.GetHash()));
|
||||||
|
|
||||||
AddToMempool(pool, entry.FromTx(tx2));
|
AddToMempool(pool, entry.FromTx(tx2));
|
||||||
CMutableTransaction tx3 = CMutableTransaction();
|
CMutableTransaction tx3 = CMutableTransaction();
|
||||||
|
@ -472,14 +472,14 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||||
AddToMempool(pool, entry.Fee(20000LL).FromTx(tx3));
|
AddToMempool(pool, entry.Fee(20000LL).FromTx(tx3));
|
||||||
|
|
||||||
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP)
|
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP)
|
||||||
BOOST_CHECK(!pool.exists(GenTxid::Txid(tx1.GetHash())));
|
BOOST_CHECK(!pool.exists(tx1.GetHash()));
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(tx2.GetHash())));
|
BOOST_CHECK(pool.exists(tx2.GetHash()));
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(tx3.GetHash())));
|
BOOST_CHECK(pool.exists(tx3.GetHash()));
|
||||||
|
|
||||||
pool.TrimToSize(GetVirtualTransactionSize(CTransaction(tx1))); // mempool is limited to tx1's size in memory usage, so nothing fits
|
pool.TrimToSize(GetVirtualTransactionSize(CTransaction(tx1))); // mempool is limited to tx1's size in memory usage, so nothing fits
|
||||||
BOOST_CHECK(!pool.exists(GenTxid::Txid(tx1.GetHash())));
|
BOOST_CHECK(!pool.exists(tx1.GetHash()));
|
||||||
BOOST_CHECK(!pool.exists(GenTxid::Txid(tx2.GetHash())));
|
BOOST_CHECK(!pool.exists(tx2.GetHash()));
|
||||||
BOOST_CHECK(!pool.exists(GenTxid::Txid(tx3.GetHash())));
|
BOOST_CHECK(!pool.exists(tx3.GetHash()));
|
||||||
|
|
||||||
CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2)));
|
CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2)));
|
||||||
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
|
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
|
||||||
|
@ -539,19 +539,19 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
|
||||||
|
|
||||||
// we only require this to remove, at max, 2 txn, because it's not clear what we're really optimizing for aside from that
|
// we only require this to remove, at max, 2 txn, because it's not clear what we're really optimizing for aside from that
|
||||||
pool.TrimToSize(pool.DynamicMemoryUsage() - 1);
|
pool.TrimToSize(pool.DynamicMemoryUsage() - 1);
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(tx4.GetHash())));
|
BOOST_CHECK(pool.exists(tx4.GetHash()));
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(tx6.GetHash())));
|
BOOST_CHECK(pool.exists(tx6.GetHash()));
|
||||||
BOOST_CHECK(!pool.exists(GenTxid::Txid(tx7.GetHash())));
|
BOOST_CHECK(!pool.exists(tx7.GetHash()));
|
||||||
|
|
||||||
if (!pool.exists(GenTxid::Txid(tx5.GetHash())))
|
if (!pool.exists(tx5.GetHash()))
|
||||||
AddToMempool(pool, entry.Fee(1000LL).FromTx(tx5));
|
AddToMempool(pool, entry.Fee(1000LL).FromTx(tx5));
|
||||||
AddToMempool(pool, entry.Fee(9000LL).FromTx(tx7));
|
AddToMempool(pool, entry.Fee(9000LL).FromTx(tx7));
|
||||||
|
|
||||||
pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7
|
pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(tx4.GetHash())));
|
BOOST_CHECK(pool.exists(tx4.GetHash()));
|
||||||
BOOST_CHECK(!pool.exists(GenTxid::Txid(tx5.GetHash())));
|
BOOST_CHECK(!pool.exists(tx5.GetHash()));
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(tx6.GetHash())));
|
BOOST_CHECK(pool.exists(tx6.GetHash()));
|
||||||
BOOST_CHECK(!pool.exists(GenTxid::Txid(tx7.GetHash())));
|
BOOST_CHECK(!pool.exists(tx7.GetHash()));
|
||||||
|
|
||||||
AddToMempool(pool, entry.Fee(1000LL).FromTx(tx5));
|
AddToMempool(pool, entry.Fee(1000LL).FromTx(tx5));
|
||||||
AddToMempool(pool, entry.Fee(9000LL).FromTx(tx7));
|
AddToMempool(pool, entry.Fee(9000LL).FromTx(tx7));
|
||||||
|
|
|
@ -293,7 +293,7 @@ BOOST_FIXTURE_TEST_CASE(rbf_helper_functions, TestChain100Setup)
|
||||||
const auto spends_unconfirmed = make_tx({tx1}, {36 * CENT});
|
const auto spends_unconfirmed = make_tx({tx1}, {36 * CENT});
|
||||||
for (const auto& input : spends_unconfirmed->vin) {
|
for (const auto& input : spends_unconfirmed->vin) {
|
||||||
// Spends unconfirmed inputs.
|
// Spends unconfirmed inputs.
|
||||||
BOOST_CHECK(pool.exists(GenTxid::Txid(input.prevout.hash)));
|
BOOST_CHECK(pool.exists(input.prevout.hash));
|
||||||
}
|
}
|
||||||
BOOST_CHECK(HasNoNewUnconfirmed(/*tx=*/ *spends_unconfirmed.get(),
|
BOOST_CHECK(HasNoNewUnconfirmed(/*tx=*/ *spends_unconfirmed.get(),
|
||||||
/*pool=*/ pool,
|
/*pool=*/ pool,
|
||||||
|
|
|
@ -1090,7 +1090,7 @@ BOOST_AUTO_TEST_CASE(package_rbf_tests)
|
||||||
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
|
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
|
||||||
|
|
||||||
// child1 has been replaced
|
// child1 has been replaced
|
||||||
BOOST_CHECK(!m_node.mempool->exists(GenTxid::Txid(tx_child_1->GetHash())));
|
BOOST_CHECK(!m_node.mempool->exists(tx_child_1->GetHash()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test package rbf.
|
// Test package rbf.
|
||||||
|
|
|
@ -122,17 +122,17 @@ std::optional<std::string> CheckPackageMempoolAcceptResult(const Package& txns,
|
||||||
if (mempool) {
|
if (mempool) {
|
||||||
// The tx by txid should be in the mempool iff the result was not INVALID.
|
// The tx by txid should be in the mempool iff the result was not INVALID.
|
||||||
const bool txid_in_mempool{atmp_result.m_result_type != MempoolAcceptResult::ResultType::INVALID};
|
const bool txid_in_mempool{atmp_result.m_result_type != MempoolAcceptResult::ResultType::INVALID};
|
||||||
if (mempool->exists(GenTxid::Txid(tx->GetHash())) != txid_in_mempool) {
|
if (mempool->exists(tx->GetHash()) != txid_in_mempool) {
|
||||||
return strprintf("tx %s should %sbe in mempool", wtxid.ToString(), txid_in_mempool ? "" : "not ");
|
return strprintf("tx %s should %sbe in mempool", wtxid.ToString(), txid_in_mempool ? "" : "not ");
|
||||||
}
|
}
|
||||||
// Additionally, if the result was DIFFERENT_WITNESS, we shouldn't be able to find the tx in mempool by wtxid.
|
// Additionally, if the result was DIFFERENT_WITNESS, we shouldn't be able to find the tx in mempool by wtxid.
|
||||||
if (tx->HasWitness() && atmp_result.m_result_type == MempoolAcceptResult::ResultType::DIFFERENT_WITNESS) {
|
if (tx->HasWitness() && atmp_result.m_result_type == MempoolAcceptResult::ResultType::DIFFERENT_WITNESS) {
|
||||||
if (mempool->exists(GenTxid::Wtxid(wtxid))) {
|
if (mempool->exists(wtxid)) {
|
||||||
return strprintf("wtxid %s should not be in mempool", wtxid.ToString());
|
return strprintf("wtxid %s should not be in mempool", wtxid.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto& tx_ref : atmp_result.m_replaced_transactions) {
|
for (const auto& tx_ref : atmp_result.m_replaced_transactions) {
|
||||||
if (mempool->exists(GenTxid::Txid(tx_ref->GetHash()))) {
|
if (mempool->exists(tx_ref->GetHash())) {
|
||||||
return strprintf("tx %s should not be in mempool as it was replaced", tx_ref->GetWitnessHash().ToString());
|
return strprintf("tx %s should not be in mempool as it was replaced", tx_ref->GetWitnessHash().ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1017,7 +1017,7 @@ std::vector<CTxMemPool::txiter> CTxMemPool::GetIterVec(const std::vector<uint256
|
||||||
bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
|
bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||||
if (exists(GenTxid::Txid(tx.vin[i].prevout.hash)))
|
if (exists(tx.vin[i].prevout.hash))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1187,7 +1187,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpends
|
||||||
if (pvNoSpendsRemaining) {
|
if (pvNoSpendsRemaining) {
|
||||||
for (const CTransaction& tx : txn) {
|
for (const CTransaction& tx : txn) {
|
||||||
for (const CTxIn& txin : tx.vin) {
|
for (const CTxIn& txin : tx.vin) {
|
||||||
if (exists(GenTxid::Txid(txin.prevout.hash))) continue;
|
if (exists(txin.prevout.hash)) continue;
|
||||||
pvNoSpendsRemaining->push_back(txin.prevout);
|
pvNoSpendsRemaining->push_back(txin.prevout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
#include <util/epochguard.h>
|
#include <util/epochguard.h>
|
||||||
#include <util/hasher.h>
|
#include <util/hasher.h>
|
||||||
|
#include <util/overloaded.h>
|
||||||
#include <util/result.h>
|
#include <util/result.h>
|
||||||
#include <util/feefrac.h>
|
#include <util/feefrac.h>
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class CChain;
|
class CChain;
|
||||||
|
@ -644,13 +646,13 @@ public:
|
||||||
return m_total_fee;
|
return m_total_fee;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool exists(const GenTxid& gtxid) const
|
bool exists(const GenTxidVariant& gtxid) const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
if (gtxid.IsWtxid()) {
|
return std::visit(util::Overloaded{
|
||||||
return (mapTx.get<index_by_wtxid>().count(gtxid.GetHash()) != 0);
|
[this](const Wtxid& wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs) { return (mapTx.get<index_by_wtxid>().count(wtxid) != 0); },
|
||||||
}
|
[this](const Txid& txid) EXCLUSIVE_LOCKS_REQUIRED(cs) { return (mapTx.count(txid) != 0); }
|
||||||
return (mapTx.count(gtxid.GetHash()) != 0);
|
}, gtxid);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CTxMemPoolEntry* GetEntry(const Txid& txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs);
|
const CTxMemPoolEntry* GetEntry(const Txid& txid) const LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
@ -677,7 +679,7 @@ public:
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
// Sanity check the transaction is in the mempool & insert into
|
// Sanity check the transaction is in the mempool & insert into
|
||||||
// unbroadcast set.
|
// unbroadcast set.
|
||||||
if (exists(GenTxid::Txid(txid))) m_unbroadcast_txids.insert(txid);
|
if (exists(Txid::FromUint256(txid))) m_unbroadcast_txids.insert(txid);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Removes a transaction from the unbroadcast set */
|
/** Removes a transaction from the unbroadcast set */
|
||||||
|
|
|
@ -319,7 +319,7 @@ void Chainstate::MaybeUpdateMempoolForReorg(
|
||||||
// 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).
|
||||||
m_mempool->removeRecursive(**it, MemPoolRemovalReason::REORG);
|
m_mempool->removeRecursive(**it, MemPoolRemovalReason::REORG);
|
||||||
} else if (m_mempool->exists(GenTxid::Txid((*it)->GetHash()))) {
|
} else if (m_mempool->exists((*it)->GetHash())) {
|
||||||
vHashUpdate.push_back((*it)->GetHash());
|
vHashUpdate.push_back((*it)->GetHash());
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
|
@ -370,7 +370,7 @@ void Chainstate::MaybeUpdateMempoolForReorg(
|
||||||
// If the transaction spends any coinbase outputs, it must be mature.
|
// If the transaction spends any coinbase outputs, it must be mature.
|
||||||
if (it->GetSpendsCoinbase()) {
|
if (it->GetSpendsCoinbase()) {
|
||||||
for (const CTxIn& txin : tx.vin) {
|
for (const CTxIn& txin : tx.vin) {
|
||||||
if (m_mempool->exists(GenTxid::Txid(txin.prevout.hash))) continue;
|
if (m_mempool->exists(txin.prevout.hash)) continue;
|
||||||
const Coin& coin{CoinsTip().AccessCoin(txin.prevout)};
|
const Coin& coin{CoinsTip().AccessCoin(txin.prevout)};
|
||||||
assert(!coin.IsSpent());
|
assert(!coin.IsSpent());
|
||||||
const auto mempool_spend_height{m_chain.Tip()->nHeight + 1};
|
const auto mempool_spend_height{m_chain.Tip()->nHeight + 1};
|
||||||
|
@ -805,10 +805,10 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||||
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
|
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pool.exists(GenTxid::Wtxid(tx.GetWitnessHash()))) {
|
if (m_pool.exists(tx.GetWitnessHash())) {
|
||||||
// Exact transaction already exists in the mempool.
|
// Exact transaction already exists in the mempool.
|
||||||
return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-already-in-mempool");
|
return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-already-in-mempool");
|
||||||
} else if (m_pool.exists(GenTxid::Txid(tx.GetHash()))) {
|
} else if (m_pool.exists(tx.GetHash())) {
|
||||||
// Transaction with the same non-witness data but different witness (same txid, different
|
// Transaction with the same non-witness data but different witness (same txid, different
|
||||||
// wtxid) already exists in the mempool.
|
// wtxid) already exists in the mempool.
|
||||||
return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-same-nonwitness-data-in-mempool");
|
return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-same-nonwitness-data-in-mempool");
|
||||||
|
@ -1134,7 +1134,7 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
|
||||||
|
|
||||||
// CheckPackageLimits expects the package transactions to not already be in the mempool.
|
// CheckPackageLimits expects the package transactions to not already be in the mempool.
|
||||||
assert(std::all_of(txns.cbegin(), txns.cend(), [this](const auto& tx)
|
assert(std::all_of(txns.cbegin(), txns.cend(), [this](const auto& tx)
|
||||||
{ return !m_pool.exists(GenTxid::Txid(tx->GetHash()));}));
|
{ return !m_pool.exists(tx->GetHash());}));
|
||||||
|
|
||||||
assert(txns.size() == workspaces.size());
|
assert(txns.size() == workspaces.size());
|
||||||
|
|
||||||
|
@ -1345,7 +1345,7 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
|
||||||
// Sanity check: none of the transactions should be in the mempool, and none of the transactions
|
// Sanity check: none of the transactions should be in the mempool, and none of the transactions
|
||||||
// should have a same-txid-different-witness equivalent in the mempool.
|
// should have a same-txid-different-witness equivalent in the mempool.
|
||||||
assert(std::all_of(workspaces.cbegin(), workspaces.cend(), [this](const auto& ws){
|
assert(std::all_of(workspaces.cbegin(), workspaces.cend(), [this](const auto& ws){
|
||||||
return !m_pool.exists(GenTxid::Txid(ws.m_ptx->GetHash())); }));
|
return !m_pool.exists(ws.m_ptx->GetHash()); }));
|
||||||
|
|
||||||
bool all_submitted = true;
|
bool all_submitted = true;
|
||||||
FinalizeSubpackage(args);
|
FinalizeSubpackage(args);
|
||||||
|
@ -1470,7 +1470,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
|
||||||
// Limit the mempool, if appropriate.
|
// Limit the mempool, if appropriate.
|
||||||
if (!args.m_package_submission && !args.m_bypass_limits) {
|
if (!args.m_package_submission && !args.m_bypass_limits) {
|
||||||
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
|
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
|
||||||
if (!m_pool.exists(GenTxid::Txid(ws.m_hash))) {
|
if (!m_pool.exists(ws.m_hash)) {
|
||||||
// The tx no longer meets our (new) mempool minimum feerate but could be reconsidered in a package.
|
// The tx no longer meets our (new) mempool minimum feerate but could be reconsidered in a package.
|
||||||
ws.m_state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "mempool full");
|
ws.m_state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "mempool full");
|
||||||
return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), {ws.m_ptx->GetWitnessHash()});
|
return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), {ws.m_ptx->GetWitnessHash()});
|
||||||
|
@ -1765,7 +1765,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
|
||||||
// There are 3 possibilities: already in mempool, same-txid-diff-wtxid already in mempool,
|
// There are 3 possibilities: already in mempool, same-txid-diff-wtxid already in mempool,
|
||||||
// or not in mempool. An already confirmed tx is treated as one not in mempool, because all
|
// or not in mempool. An already confirmed tx is treated as one not in mempool, because all
|
||||||
// we know is that the inputs aren't available.
|
// we know is that the inputs aren't available.
|
||||||
if (m_pool.exists(GenTxid::Wtxid(wtxid))) {
|
if (m_pool.exists(wtxid)) {
|
||||||
// Exact transaction already exists in the mempool.
|
// Exact transaction already exists in the mempool.
|
||||||
// Node operators are free to set their mempool policies however they please, nodes may receive
|
// Node operators are free to set their mempool policies however they please, nodes may receive
|
||||||
// transactions in different orders, and malicious counterparties may try to take advantage of
|
// transactions in different orders, and malicious counterparties may try to take advantage of
|
||||||
|
@ -1777,7 +1777,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
|
||||||
// checking ancestor/descendant limits, or double-count transaction fees for fee-related policy.
|
// checking ancestor/descendant limits, or double-count transaction fees for fee-related policy.
|
||||||
const auto& entry{*Assert(m_pool.GetEntry(txid))};
|
const auto& entry{*Assert(m_pool.GetEntry(txid))};
|
||||||
results_final.emplace(wtxid, MempoolAcceptResult::MempoolTx(entry.GetTxSize(), entry.GetFee()));
|
results_final.emplace(wtxid, MempoolAcceptResult::MempoolTx(entry.GetTxSize(), entry.GetFee()));
|
||||||
} else if (m_pool.exists(GenTxid::Txid(txid))) {
|
} else if (m_pool.exists(txid)) {
|
||||||
// Transaction with the same non-witness data but different witness (same txid,
|
// Transaction with the same non-witness data but different witness (same txid,
|
||||||
// different wtxid) already exists in the mempool.
|
// different wtxid) already exists in the mempool.
|
||||||
//
|
//
|
||||||
|
@ -1796,7 +1796,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
|
||||||
if (single_res.m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
if (single_res.m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
||||||
// The transaction succeeded on its own and is now in the mempool. Don't include it
|
// The transaction succeeded on its own and is now in the mempool. Don't include it
|
||||||
// in package validation, because its fees should only be "used" once.
|
// in package validation, because its fees should only be "used" once.
|
||||||
assert(m_pool.exists(GenTxid::Wtxid(wtxid)));
|
assert(m_pool.exists(wtxid));
|
||||||
results_final.emplace(wtxid, single_res);
|
results_final.emplace(wtxid, single_res);
|
||||||
} else if (package.size() == 1 || // If there is only one transaction, no need to retry it "as a package"
|
} else if (package.size() == 1 || // If there is only one transaction, no need to retry it "as a package"
|
||||||
(single_res.m_state.GetResult() != TxValidationResult::TX_RECONSIDERABLE &&
|
(single_res.m_state.GetResult() != TxValidationResult::TX_RECONSIDERABLE &&
|
||||||
|
@ -1841,7 +1841,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
|
||||||
// If it was submitted, check to see if the tx is still in the mempool. It could have
|
// If it was submitted, check to see if the tx is still in the mempool. It could have
|
||||||
// been evicted due to LimitMempoolSize() above.
|
// been evicted due to LimitMempoolSize() above.
|
||||||
const auto& txresult = multi_submission_result.m_tx_results.at(wtxid);
|
const auto& txresult = multi_submission_result.m_tx_results.at(wtxid);
|
||||||
if (txresult.m_result_type == MempoolAcceptResult::ResultType::VALID && !m_pool.exists(GenTxid::Wtxid(wtxid))) {
|
if (txresult.m_result_type == MempoolAcceptResult::ResultType::VALID && !m_pool.exists(wtxid)) {
|
||||||
package_state_final.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
|
package_state_final.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
|
||||||
TxValidationState mempool_full_state;
|
TxValidationState mempool_full_state;
|
||||||
mempool_full_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
|
mempool_full_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
|
||||||
|
@ -1855,7 +1855,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
|
||||||
Assume(it->second.m_result_type != MempoolAcceptResult::ResultType::INVALID);
|
Assume(it->second.m_result_type != MempoolAcceptResult::ResultType::INVALID);
|
||||||
Assume(individual_results_nonfinal.count(wtxid) == 0);
|
Assume(individual_results_nonfinal.count(wtxid) == 0);
|
||||||
// Query by txid to include the same-txid-different-witness ones.
|
// Query by txid to include the same-txid-different-witness ones.
|
||||||
if (!m_pool.exists(GenTxid::Txid(tx->GetHash()))) {
|
if (!m_pool.exists(tx->GetHash())) {
|
||||||
package_state_final.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
|
package_state_final.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
|
||||||
TxValidationState mempool_full_state;
|
TxValidationState mempool_full_state;
|
||||||
mempool_full_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
|
mempool_full_state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
|
||||||
|
|
Loading…
Add table
Reference in a new issue