Skip to content

Commit 8dec9c5

Browse files
committed
wallet, mempool: propagete checkChainLimits error message to wallet
Update CheckPackageLimits to use util::Result to pass the error message instead of out parameter. Also update test to reflect the error message from `CTxMempool` `CheckPackageLimits` output.
1 parent 3695ecb commit 8dec9c5

File tree

7 files changed

+25
-30
lines changed

7 files changed

+25
-30
lines changed

src/interfaces/chain.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <blockfilter.h>
99
#include <common/settings.h>
1010
#include <primitives/transaction.h> // For CTransactionRef
11+
#include <util/result.h>
1112

1213
#include <functional>
1314
#include <memory>
@@ -260,7 +261,7 @@ class Chain
260261
virtual void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) = 0;
261262

262263
//! Check if transaction will pass the mempool's chain limits.
263-
virtual bool checkChainLimits(const CTransactionRef& tx) = 0;
264+
virtual util::Result<void> checkChainLimits(const CTransactionRef& tx) = 0;
264265

265266
//! Estimate smart fee.
266267
virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc = nullptr) = 0;

src/node/interfaces.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <uint256.h>
4646
#include <univalue.h>
4747
#include <util/check.h>
48+
#include <util/result.h>
4849
#include <util/signalinterrupt.h>
4950
#include <util/translation.h>
5051
#include <validation.h>
@@ -702,14 +703,13 @@ class ChainImpl : public Chain
702703
limit_ancestor_count = limits.ancestor_count;
703704
limit_descendant_count = limits.descendant_count;
704705
}
705-
bool checkChainLimits(const CTransactionRef& tx) override
706+
util::Result<void> checkChainLimits(const CTransactionRef& tx) override
706707
{
707-
if (!m_node.mempool) return true;
708+
if (!m_node.mempool) return {};
708709
LockPoints lp;
709710
CTxMemPoolEntry entry(tx, 0, 0, 0, 0, false, 0, lp);
710711
LOCK(m_node.mempool->cs);
711-
std::string err_string;
712-
return m_node.mempool->CheckPackageLimits({tx}, entry.GetTxSize(), err_string);
712+
return m_node.mempool->CheckPackageLimits({tx}, entry.GetTxSize());
713713
}
714714
CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
715715
{

src/txmempool.cpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -196,25 +196,20 @@ util::Result<CTxMemPool::setEntries> CTxMemPool::CalculateAncestorsAndCheckLimit
196196
return ancestors;
197197
}
198198

199-
bool CTxMemPool::CheckPackageLimits(const Package& package,
200-
const int64_t total_vsize,
201-
std::string &errString) const
199+
util::Result<void> CTxMemPool::CheckPackageLimits(const Package& package,
200+
const int64_t total_vsize) const
202201
{
203202
size_t pack_count = package.size();
204203

205204
// Package itself is busting mempool limits; should be rejected even if no staged_ancestors exist
206205
if (pack_count > static_cast<uint64_t>(m_limits.ancestor_count)) {
207-
errString = strprintf("package count %u exceeds ancestor count limit [limit: %u]", pack_count, m_limits.ancestor_count);
208-
return false;
206+
return util::Error{Untranslated(strprintf("package count %u exceeds ancestor count limit [limit: %u]", pack_count, m_limits.ancestor_count))};
209207
} else if (pack_count > static_cast<uint64_t>(m_limits.descendant_count)) {
210-
errString = strprintf("package count %u exceeds descendant count limit [limit: %u]", pack_count, m_limits.descendant_count);
211-
return false;
208+
return util::Error{Untranslated(strprintf("package count %u exceeds descendant count limit [limit: %u]", pack_count, m_limits.descendant_count))};
212209
} else if (total_vsize > m_limits.ancestor_size_vbytes) {
213-
errString = strprintf("package size %u exceeds ancestor size limit [limit: %u]", total_vsize, m_limits.ancestor_size_vbytes);
214-
return false;
210+
return util::Error{Untranslated(strprintf("package size %u exceeds ancestor size limit [limit: %u]", total_vsize, m_limits.ancestor_size_vbytes))};
215211
} else if (total_vsize > m_limits.descendant_size_vbytes) {
216-
errString = strprintf("package size %u exceeds descendant size limit [limit: %u]", total_vsize, m_limits.descendant_size_vbytes);
217-
return false;
212+
return util::Error{Untranslated(strprintf("package size %u exceeds descendant size limit [limit: %u]", total_vsize, m_limits.descendant_size_vbytes))};
218213
}
219214

220215
CTxMemPoolEntry::Parents staged_ancestors;
@@ -224,8 +219,7 @@ bool CTxMemPool::CheckPackageLimits(const Package& package,
224219
if (piter) {
225220
staged_ancestors.insert(**piter);
226221
if (staged_ancestors.size() + package.size() > static_cast<uint64_t>(m_limits.ancestor_count)) {
227-
errString = strprintf("too many unconfirmed parents [limit: %u]", m_limits.ancestor_count);
228-
return false;
222+
return util::Error{Untranslated(strprintf("too many unconfirmed parents [limit: %u]", m_limits.ancestor_count))};
229223
}
230224
}
231225
}
@@ -236,8 +230,8 @@ bool CTxMemPool::CheckPackageLimits(const Package& package,
236230
const auto ancestors{CalculateAncestorsAndCheckLimits(total_vsize, package.size(),
237231
staged_ancestors, m_limits)};
238232
// It's possible to overestimate the ancestor/descendant totals.
239-
if (!ancestors.has_value()) errString = "possibly " + util::ErrorString(ancestors).original;
240-
return ancestors.has_value();
233+
if (!ancestors.has_value()) return util::Error{Untranslated("possibly " + util::ErrorString(ancestors).original)};
234+
return {};
241235
}
242236

243237
util::Result<CTxMemPool::setEntries> CTxMemPool::CalculateMemPoolAncestors(

src/txmempool.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -605,11 +605,9 @@ class CTxMemPool
605605
* to mempool. The transactions need not be direct
606606
* ancestors/descendants of each other.
607607
* @param[in] total_vsize Sum of virtual sizes for all transactions in package.
608-
* @param[out] errString Populated with error reason if a limit is hit.
609608
*/
610-
bool CheckPackageLimits(const Package& package,
611-
int64_t total_vsize,
612-
std::string &errString) const EXCLUSIVE_LOCKS_REQUIRED(cs);
609+
util::Result<void> CheckPackageLimits(const Package& package,
610+
int64_t total_vsize) const EXCLUSIVE_LOCKS_REQUIRED(cs);
613611

614612
/** Populate setDescendants with all in-mempool descendants of hash.
615613
* Assumes that setDescendants includes all in-mempool descendants of anything

src/validation.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include <util/hasher.h>
5252
#include <util/moneystr.h>
5353
#include <util/rbf.h>
54+
#include <util/result.h>
5455
#include <util/signalinterrupt.h>
5556
#include <util/strencodings.h>
5657
#include <util/time.h>
@@ -1024,10 +1025,10 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
10241025
assert(std::all_of(txns.cbegin(), txns.cend(), [this](const auto& tx)
10251026
{ return !m_pool.exists(GenTxid::Txid(tx->GetHash()));}));
10261027

1027-
std::string err_string;
1028-
if (!m_pool.CheckPackageLimits(txns, total_vsize, err_string)) {
1028+
auto result = m_pool.CheckPackageLimits(txns, total_vsize);
1029+
if (!result) {
10291030
// This is a package-wide error, separate from an individual transaction error.
1030-
return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", err_string);
1031+
return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", util::ErrorString(result).original);
10311032
}
10321033
return true;
10331034
}

src/wallet/spend.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,8 +1296,9 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
12961296

12971297
if (gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) {
12981298
// Lastly, ensure this tx will pass the mempool's chain limits
1299-
if (!wallet.chain().checkChainLimits(tx)) {
1300-
return util::Error{_("Transaction has too long of a mempool chain")};
1299+
auto result = wallet.chain().checkChainLimits(tx);
1300+
if (!result) {
1301+
return util::Error{util::ErrorString(result)};
13011302
}
13021303
}
13031304

test/functional/wallet_basic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ def run_test(self):
639639

640640
node0_balance = self.nodes[0].getbalance()
641641
# With walletrejectlongchains we will not create the tx and store it in our wallet.
642-
assert_raises_rpc_error(-6, "Transaction has too long of a mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01'))
642+
assert_raises_rpc_error(-6, f"too many unconfirmed ancestors [limit: {chainlimit * 2}]", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01'))
643643

644644
# Verify nothing new in wallet
645645
assert_equal(total_txs, len(self.nodes[0].listtransactions("*", 99999)))

0 commit comments

Comments
 (0)