Skip to content

Commit

Permalink
test: add coverage for BnB-SFFO restriction
Browse files Browse the repository at this point in the history
Verify the transaction creation process does not produce
a BnB solution when SFFO is enabled.
This is currently problematic because it could require a
change output. And BnB is specialized on changeless solutions.
  • Loading branch information
furszy authored and murchandamus committed Oct 6, 2023
1 parent c20c101 commit dac060f
Showing 1 changed file with 35 additions and 1 deletion.
36 changes: 35 additions & 1 deletion src/wallet/test/coinselector_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
#include <policy/policy.h>
#include <primitives/transaction.h>
#include <random.h>
#include <test/util/logging.h>
#include <test/util/setup_common.h>
#include <util/translation.h>
#include <wallet/coincontrol.h>
#include <wallet/coinselection.h>
#include <wallet/fees.h>
#include <wallet/spend.h>
#include <wallet/test/util.h>
#include <wallet/test/wallet_test_fixture.h>
Expand Down Expand Up @@ -83,7 +85,8 @@ static void add_coin(CoinsResult& available_coins, CWallet& wallet, const CAmoun
uint256 txid = tx.GetHash();

LOCK(wallet.cs_wallet);
auto ret = wallet.mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid), std::forward_as_tuple(MakeTransactionRef(std::move(tx)), TxStateInactive{}));
TxState state = (nAge > 0) ? TxStateConfirmed{uint256{}, nAge, 0} : TxState{TxStateInactive{}};
auto ret = wallet.mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid), std::forward_as_tuple(MakeTransactionRef(std::move(tx)), state));
assert(ret.second);
CWalletTx& wtx = (*ret.first).second;
const auto& txout = wtx.tx->vout.at(nInput);
Expand Down Expand Up @@ -449,6 +452,37 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
}
}

BOOST_AUTO_TEST_CASE(tx_creation_bnb_sffo_restriction)
{
// Verify the transaction creation process does not produce a BnB solution when SFFO is enabled.
// This is currently problematic because it could require a change output. And BnB is specialized on changeless solutions.
std::unique_ptr<CWallet> wallet = NewWallet(m_node);
WITH_LOCK(wallet->cs_wallet, wallet->SetLastBlockProcessed(300, uint256{})); // set a high block so internal UTXOs are selectable

CTxDestination change_dest = *Assert(wallet->GetNewChangeDestination(OutputType::BECH32));
CTxOut change_out(0, GetScriptForDestination(change_dest));
size_t change_output_size = GetSerializeSize(change_out);

CFeeRate effective_feerate(10000);
CFeeRate discard_feerate = GetDiscardRate(*wallet);

CAmount change_fee = effective_feerate.GetFee(change_output_size);
size_t change_spend_size = CalculateMaximumSignedInputSize(change_out, wallet.get(), nullptr);
CAmount cost_of_change = discard_feerate.GetFee(change_spend_size) + change_fee;

// Add spendable coin at the BnB selection upper bound
CoinsResult available_coins;
add_coin(available_coins, *wallet, COIN + cost_of_change, /*feerate=*/CFeeRate(0), /*nAge=*/6*24, /*fIsFromMe=*/true, /*nInput=*/0, /*spendable=*/true);

// Now verify coin selection does not produce BnB result
ASSERT_DEBUG_LOG_NOT_FOUND("Coin Selection: Algorithm:bnb");
CCoinControl coin_control;
coin_control.m_feerate = effective_feerate;
coin_control.destChange = change_dest;
CRecipient recipient{GetScriptForRawPubKey({}), /*target=*/COIN, /*subtract_fee=*/true};
BOOST_CHECK(CreateTransaction(*wallet, {recipient}, /*change_pos=*/-1, coin_control));
}

BOOST_AUTO_TEST_CASE(knapsack_solver_test)
{
FastRandomContext rand{};
Expand Down

0 comments on commit dac060f

Please sign in to comment.