aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorglozow <gloriajzhao@gmail.com>2022-10-05 08:52:31 +0100
committerglozow <gloriajzhao@gmail.com>2022-10-05 09:07:39 +0100
commit2e5706d6011cdca650b513eff26fa1ef85ac8a2e (patch)
treecfb7f14bb515db6f6b9312adea14f72280c7ca9e
parent4be489d4d4a1b8ef64d9f6dcdbc0c6574f934aa4 (diff)
parent2730ed2b0d6c5cd8e029c67074aac11e610b19fd (diff)
downloadbitcoin-2e5706d6011cdca650b513eff26fa1ef85ac8a2e.tar.xz
Merge bitcoin/bitcoin#26242: [24.x] wallet: Use correct effective value when checking target
2730ed2b0d6c5cd8e029c67074aac11e610b19fd test: Check external coin effective value is used in CoinSelection (Aurèle Oulès) 21f96f40d18e0b052cb4ef24cda7847051ca16d8 wallet: Use correct effective value when checking target (Aurèle Oulès) Pull request description: backport of #26203 ACKs for top commit: jarolrod: ACK 2730ed2b0d6c5cd8e029c67074aac11e610b19fd Tree-SHA512: ce84ac8d47861f290a26d572512467e89ec6ac27973d954d76245b6c6fdea01e36f2e0bce41599abfe14d0014335ebd17b990177771803de39406097973186ca
-rw-r--r--src/wallet/spend.cpp8
-rw-r--r--src/wallet/test/coinselector_tests.cpp47
2 files changed, 54 insertions, 1 deletions
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index d84310c323..ce41a4e954 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -590,7 +590,13 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
if (coin_control.HasSelected() && !coin_control.m_allow_other_inputs) {
SelectionResult result(nTargetValue, SelectionAlgorithm::MANUAL);
result.AddInput(preset_inputs);
- if (result.GetSelectedValue() < nTargetValue) return std::nullopt;
+
+ if (!coin_selection_params.m_subtract_fee_outputs && result.GetSelectedEffectiveValue() < nTargetValue) {
+ return std::nullopt;
+ } else if (result.GetSelectedValue() < nTargetValue) {
+ return std::nullopt;
+ }
+
result.ComputeAndSetWaste(coin_selection_params.min_viable_change, coin_selection_params.m_cost_of_change, coin_selection_params.m_change_fee);
return result;
}
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index 30a7fb9eb6..23f024247d 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -922,5 +922,52 @@ BOOST_AUTO_TEST_CASE(effective_value_test)
BOOST_CHECK_EQUAL(output5.GetEffectiveValue(), nValue); // The effective value should be equal to the absolute value if input_bytes is -1
}
+BOOST_AUTO_TEST_CASE(SelectCoins_effective_value_test)
+{
+ // Test that the effective value is used to check whether preset inputs provide sufficient funds when subtract_fee_outputs is not used.
+ // This test creates a coin whose value is higher than the target but whose effective value is lower than the target.
+ // The coin is selected using coin control, with m_allow_other_inputs = false. SelectCoins should fail due to insufficient funds.
+
+ std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", m_args, CreateMockWalletDatabase());
+ wallet->LoadWallet();
+ LOCK(wallet->cs_wallet);
+ wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ wallet->SetupDescriptorScriptPubKeyMans();
+
+ CoinsResult available_coins;
+ {
+ std::unique_ptr<CWallet> dummyWallet = std::make_unique<CWallet>(m_node.chain.get(), "dummy", m_args, CreateMockWalletDatabase());
+ dummyWallet->LoadWallet();
+ LOCK(dummyWallet->cs_wallet);
+ dummyWallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ dummyWallet->SetupDescriptorScriptPubKeyMans();
+
+ add_coin(available_coins, *dummyWallet, 100000); // 0.001 BTC
+ }
+
+ CAmount target{99900}; // 0.000999 BTC
+
+ FastRandomContext rand;
+ CoinSelectionParams cs_params{
+ rand,
+ /*change_output_size=*/34,
+ /*change_spend_size=*/148,
+ /*min_change_target=*/1000,
+ /*effective_feerate=*/CFeeRate(3000),
+ /*long_term_feerate=*/CFeeRate(1000),
+ /*discard_feerate=*/CFeeRate(1000),
+ /*tx_noinputs_size=*/0,
+ /*avoid_partial=*/false,
+ };
+ CCoinControl cc;
+ cc.m_allow_other_inputs = false;
+ COutput output = available_coins.All().at(0);
+ cc.SetInputWeight(output.outpoint, 148);
+ cc.SelectExternal(output.outpoint, output.txout);
+
+ const auto result = SelectCoins(*wallet, available_coins, target, cc, cs_params);
+ BOOST_CHECK(!result);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet