aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/test/fuzz/coinselection.cpp
diff options
context:
space:
mode:
authorfurszy <matiasfurszyfer@protonmail.com>2022-12-18 10:28:59 -0300
committerfurszy <matiasfurszyfer@protonmail.com>2023-04-05 09:32:39 -0300
commit6107ec2229c5f5b4e944a6b10d38010c850094ac (patch)
tree2871cf2354d648487253ddab816da55e529dd8ac /src/wallet/test/fuzz/coinselection.cpp
parent1284223691127e76135a46d251c52416104f0ff1 (diff)
downloadbitcoin-6107ec2229c5f5b4e944a6b10d38010c850094ac.tar.xz
coin selection: knapsack, select closest UTXO above target if result exceeds max tx size
The simplest scenario where this is useful is on the 'check_max_weight' unit test already: We create 1515 UTXOs with 0.033 BTC each, and 1 UTXO with 50 BTC. Then perform Coin Selection. As the selection of the 1515 small UTXOs exceeds the max allowed tx size, the expectation here is to receive a selection result that only contain the big UTXO (which is not happening for the reasons stated below). As knapsack returns a result that exceeds the max allowed transaction size, we fallback to SRD, which selects coins randomly up until the target is met. So we end up with a selection result with lot more coins than what is needed.
Diffstat (limited to 'src/wallet/test/fuzz/coinselection.cpp')
-rw-r--r--src/wallet/test/fuzz/coinselection.cpp10
1 files changed, 7 insertions, 3 deletions
diff --git a/src/wallet/test/fuzz/coinselection.cpp b/src/wallet/test/fuzz/coinselection.cpp
index 304190eec1..4878b24c30 100644
--- a/src/wallet/test/fuzz/coinselection.cpp
+++ b/src/wallet/test/fuzz/coinselection.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <policy/feerate.h>
+#include <policy/policy.h>
#include <primitives/transaction.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
@@ -44,6 +45,9 @@ static void GroupCoins(FuzzedDataProvider& fuzzed_data_provider, const std::vect
if (valid_outputgroup) output_groups.push_back(output_group);
}
+// Returns true if the result contains an error and the message is not empty
+static bool HasErrorMsg(const util::Result<SelectionResult>& res) { return !util::ErrorString(res).empty(); }
+
FUZZ_TARGET(coinselection)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
@@ -90,12 +94,12 @@ FUZZ_TARGET(coinselection)
if (result_srd) result_srd->ComputeAndSetWaste(cost_of_change, cost_of_change, 0);
CAmount change_target{GenerateChangeTarget(target, coin_params.m_change_fee, fast_random_context)};
- auto result_knapsack = KnapsackSolver(group_all, target, change_target, fast_random_context);
+ auto result_knapsack = KnapsackSolver(group_all, target, change_target, fast_random_context, MAX_STANDARD_TX_WEIGHT);
if (result_knapsack) result_knapsack->ComputeAndSetWaste(cost_of_change, cost_of_change, 0);
// If the total balance is sufficient for the target and we are not using
- // effective values, Knapsack should always find a solution.
- if (total_balance >= target && subtract_fee_outputs) {
+ // effective values, Knapsack should always find a solution (unless the selection exceeded the max tx weight).
+ if (total_balance >= target && subtract_fee_outputs && !HasErrorMsg(result_knapsack)) {
assert(result_knapsack);
}
}