Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Transaction Pool Layer #13804

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/interfaces/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ class ChainImpl : public Chain
auto limit_descendant_size = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000;
std::string unused_error_string;
LOCK(::mempool.cs);
return ::mempool.CalculateMemPoolAncestors(entry, ancestors, limit_ancestor_count, limit_ancestor_size,
limit_descendant_count, limit_descendant_size, unused_error_string);
return ::mempool.CalculateMemPoolAncestors(CTxMemPool::txiter{}, ancestors, limit_ancestor_count, limit_ancestor_size,
limit_descendant_count, limit_descendant_size, unused_error_string, /* search_parents_for_entry */ &entry);
}
CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
{
Expand Down
2 changes: 1 addition & 1 deletion src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda
CTxMemPool::setEntries ancestors;
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
std::string dummy;
mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
mempool.CalculateMemPoolAncestors(iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);

onlyUnconfirmed(ancestors);
ancestors.insert(iter);
Expand Down
2 changes: 1 addition & 1 deletion src/node/coin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void FindCoins(std::map<COutPoint, Coin>& coins)
LOCK2(cs_main, ::mempool.cs);
assert(pcoinsTip);
CCoinsViewCache& chain_view = *::pcoinsTip;
CCoinsViewMemPool mempool_view(&chain_view, ::mempool);
CoinsViewMemPool<CTxMemPool> mempool_view(&chain_view, ::mempool);
for (auto& coin : coins) {
if (!mempool_view.GetCoin(coin.first, coin.second)) {
// Either the coin is not in the CCoinsViewCache or is spent. Clear it.
Expand Down
4 changes: 2 additions & 2 deletions src/policy/rbf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
// signaled for RBF if any unconfirmed parents have signaled.
uint64_t noLimit = std::numeric_limits<uint64_t>::max();
std::string dummy;
CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash());
pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
auto it_tx = pool.mapTx.find(tx.GetHash());
pool.CalculateMemPoolAncestors(it_tx, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy);

for (CTxMemPool::txiter it : setAncestors) {
if (SignalsOptInRBF(it->GetTx())) {
Expand Down
2 changes: 1 addition & 1 deletion src/rest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
// use db+mempool as cache backend in case user likes to query mempool
LOCK2(cs_main, mempool.cs);
CCoinsViewCache& viewChain = *pcoinsTip;
CCoinsViewMemPool viewMempool(&viewChain, mempool);
CoinsViewMemPool<CTxMemPool> viewMempool(&viewChain, mempool);
process_utxos(viewMempool, mempool);
} else {
LOCK(cs_main); // no need to lock mempool!
Expand Down
4 changes: 2 additions & 2 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request)
CTxMemPool::setEntries setAncestors;
uint64_t noLimit = std::numeric_limits<uint64_t>::max();
std::string dummy;
mempool.CalculateMemPoolAncestors(*it, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
mempool.CalculateMemPoolAncestors(it, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy);

if (!fVerbose) {
UniValue o(UniValue::VARR);
Expand Down Expand Up @@ -1128,7 +1128,7 @@ UniValue gettxout(const JSONRPCRequest& request)
Coin coin;
if (fMempool) {
LOCK(mempool.cs);
CCoinsViewMemPool view(pcoinsTip.get(), mempool);
CoinsViewMemPool<CTxMemPool> view(pcoinsTip.get(), mempool);
if (!view.GetCoin(out, coin) || mempool.isSpent(out)) {
return NullUniValue;
}
Expand Down
62 changes: 34 additions & 28 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
LOCK(cs_main);
LOCK(mempool.cs);
CCoinsViewCache &viewChain = *pcoinsTip;
CCoinsViewMemPool viewMempool(&viewChain, mempool);
CoinsViewMemPool<CTxMemPool> viewMempool(&viewChain, mempool);
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view

for (const CTxIn& txin : mergedTx.vin) {
Expand Down Expand Up @@ -863,19 +863,21 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Array must contain exactly one raw transaction for now");
}

CMutableTransaction mtx;
if (!DecodeHexTx(mtx, request.params[0].get_array()[0].get_str())) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
std::vector<CTransactionRef> txs;
for (const auto& tx : request.params[0].get_array().getValues()) {
CMutableTransaction mtx;
if (!DecodeHexTx(mtx, tx.get_str())) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
}
txs.push_back(MakeTransactionRef(std::move(mtx)));
}
CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
const uint256& tx_hash = tx->GetHash();

CAmount max_raw_tx_fee = DEFAULT_MAX_RAW_TX_FEE;
// TODO: temporary migration code for old clients. Remove in v0.20
if (request.params[1].isBool()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Second argument must be numeric (maxfeerate) and no longer supports a boolean. To allow a transaction with high fees, set maxfeerate to 0.");
} else if (!request.params[1].isNull()) {
size_t weight = GetTransactionWeight(*tx);
size_t weight = /* TODO fix */ 4000; //GetTransactionWeight(*tx);
CFeeRate fr(AmountFromValue(request.params[1]));
// the +3/4 part rounds the value up, and is the same formula used when
// calculating the fee for a transaction
Expand All @@ -884,29 +886,33 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
}

UniValue result(UniValue::VARR);
UniValue result_0(UniValue::VOBJ);
result_0.pushKV("txid", tx_hash.GetHex());

CValidationState state;
bool missing_inputs;
bool test_accept_res;
{
LOCK(cs_main);
test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx), &missing_inputs,
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_raw_tx_fee, /* test_accept */ true);
}
result_0.pushKV("allowed", test_accept_res);
if (!test_accept_res) {
if (state.IsInvalid()) {
result_0.pushKV("reject-reason", strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else if (missing_inputs) {
result_0.pushKV("reject-reason", "missing-inputs");
} else {
result_0.pushKV("reject-reason", state.GetRejectReason());
LOCK2(cs_main, ::mempool.cs);
TxPoolLayer pool_layer{::mempool};
for (const auto& tx : txs) {
UniValue result_i(UniValue::VOBJ);
result_i.pushKV("txid", tx->GetHash().GetHex());

CValidationState state;
bool missing_inputs;
bool test_accept_res;
{
test_accept_res = AcceptToMemoryPool(pool_layer, state, tx, &missing_inputs,
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_raw_tx_fee, /* test_accept */ false);
}
result_i.pushKV("allowed", test_accept_res);
if (!test_accept_res) {
if (state.IsInvalid()) {
result_i.pushKV("reject-reason", strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else if (missing_inputs) {
result_i.pushKV("reject-reason", "missing-inputs");
} else {
result_i.pushKV("reject-reason", state.GetRejectReason());
}
}
}

result.push_back(std::move(result_0));
result.push_back(std::move(result_i));
}
return result;
}

Expand Down Expand Up @@ -1495,7 +1501,7 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request)
{
LOCK2(cs_main, mempool.cs);
CCoinsViewCache &viewChain = *pcoinsTip;
CCoinsViewMemPool viewMempool(&viewChain, mempool);
CoinsViewMemPool<CTxMemPool> viewMempool(&viewChain, mempool);
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view

for (const CTxIn& txin : psbtx.tx->vin) {
Expand Down
6 changes: 4 additions & 2 deletions src/test/mempool_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,10 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
tx7.vout[1].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx7.vout[1].nValue = 1 * COIN;

const CTxMemPoolEntry& search_parents_for_entry_1 = entry.Fee(2000000LL).FromTx(tx7);
CTxMemPool::setEntries setAncestorsCalculated;
std::string dummy;
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(2000000LL).FromTx(tx7), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(CTxMemPool::txiter{}, setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy, &search_parents_for_entry_1), true);
BOOST_CHECK(setAncestorsCalculated == setAncestors);

pool.addUnchecked(entry.FromTx(tx7), setAncestors);
Expand Down Expand Up @@ -252,8 +253,9 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
tx10.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
tx10.vout[0].nValue = 10 * COIN;

const CTxMemPoolEntry& search_parents_for_entry_2 = entry.Fee(200000LL).Time(4).FromTx(tx10);
setAncestorsCalculated.clear();
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(200000LL).Time(4).FromTx(tx10), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(CTxMemPool::txiter{}, setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy, &search_parents_for_entry_2), true);
BOOST_CHECK(setAncestorsCalculated == setAncestors);

pool.addUnchecked(entry.FromTx(tx10), setAncestors);
Expand Down
Loading