Merge bitcoin/bitcoin#24560: wallet: Use single FastRandomContext when creating a wallet tx

fa7deaa046 wallet: Pass FastRandomContext& to coin selection (MarcoFalke)
77773b061c wallet: Pass FastRandomContext& to DiscourageFeeSniping (MarcoFalke)

Pull request description:

  Passing around a single randomness context shouldn't come with any downsides, but documents better where randomness is used and allows the unit test to be deterministic, if they wish to be so.

ACKs for top commit:
  achow101:
    ACK fa7deaa046
  promag:
    Code review ACK fa7deaa046.
  glozow:
    light code review ACK fa7deaa046

Tree-SHA512: c16287708cc82ce58311710595d0127af42fb156c93fbcaa5bde634ce323d325f4d8c99a74af24423ab22b5ad58163dd771e8b1a0e7d6bff39c9fb2a1cb21bc7
This commit is contained in:
Andrew Chow
2022-03-23 13:41:16 -04:00
5 changed files with 86 additions and 52 deletions

View File

@@ -164,10 +164,17 @@ inline std::vector<OutputGroup>& GroupCoins(const std::vector<COutput>& coins)
inline std::vector<OutputGroup>& KnapsackGroupOutputs(const std::vector<COutput>& coins, CWallet& wallet, const CoinEligibilityFilter& filter)
{
CoinSelectionParams coin_selection_params(/* change_output_size= */ 0,
/* change_spend_size= */ 0, /* effective_feerate= */ CFeeRate(0),
/* long_term_feerate= */ CFeeRate(0), /* discard_feerate= */ CFeeRate(0),
/* tx_noinputs_size= */ 0, /* avoid_partial= */ false);
FastRandomContext rand{};
CoinSelectionParams coin_selection_params{
rand,
/* change_output_size= */ 0,
/* change_spend_size= */ 0,
/* effective_feerate= */ CFeeRate(0),
/* long_term_feerate= */ CFeeRate(0),
/* discard_feerate= */ CFeeRate(0),
/* tx_noinputs_size= */ 0,
/* avoid_partial= */ false,
};
static std::vector<OutputGroup> static_groups;
static_groups = GroupOutputs(wallet, coins, coin_selection_params, filter, /*positive_only=*/false);
return static_groups;
@@ -176,6 +183,7 @@ inline std::vector<OutputGroup>& KnapsackGroupOutputs(const std::vector<COutput>
// Branch and bound coin selection tests
BOOST_AUTO_TEST_CASE(bnb_search_test)
{
FastRandomContext rand{};
// Setup
std::vector<CInputCoin> utxo_pool;
SelectionResult expected_result(CAmount(0));
@@ -301,10 +309,16 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
}
// Make sure that effective value is working in AttemptSelection when BnB is used
CoinSelectionParams coin_selection_params_bnb(/* change_output_size= */ 0,
/* change_spend_size= */ 0, /* effective_feerate= */ CFeeRate(3000),
/* long_term_feerate= */ CFeeRate(1000), /* discard_feerate= */ CFeeRate(1000),
/* tx_noinputs_size= */ 0, /* avoid_partial= */ false);
CoinSelectionParams coin_selection_params_bnb{
rand,
/* change_output_size= */ 0,
/* change_spend_size= */ 0,
/* effective_feerate= */ CFeeRate(3000),
/* long_term_feerate= */ CFeeRate(1000),
/* discard_feerate= */ CFeeRate(1000),
/* tx_noinputs_size= */ 0,
/* avoid_partial= */ false,
};
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", m_args, CreateMockWalletDatabase());
wallet->LoadWallet();
@@ -351,6 +365,9 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
BOOST_AUTO_TEST_CASE(knapsack_solver_test)
{
FastRandomContext rand{};
const auto temp1{[&rand](std::vector<OutputGroup>& g, const CAmount& v) { return KnapsackSolver(g, v, rand); }};
const auto KnapsackSolver{temp1};
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", m_args, CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
@@ -660,6 +677,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
{
FastRandomContext rand{};
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", m_args, CreateMockWalletDatabase());
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
@@ -673,7 +691,7 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
add_coin(coins, *wallet, 1000 * COIN);
add_coin(coins, *wallet, 3 * COIN);
const auto result = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard), 1003 * COIN);
const auto result = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard), 1003 * COIN, rand);
BOOST_CHECK(result);
BOOST_CHECK_EQUAL(result->GetSelectedValue(), 1003 * COIN);
BOOST_CHECK_EQUAL(result->GetInputSet().size(), 2U);
@@ -714,10 +732,16 @@ BOOST_AUTO_TEST_CASE(SelectCoins_test)
CAmount target = rand.randrange(balance - 1000) + 1000;
// Perform selection
CoinSelectionParams cs_params(/* change_output_size= */ 34,
/* change_spend_size= */ 148, /* effective_feerate= */ CFeeRate(0),
/* long_term_feerate= */ CFeeRate(0), /* discard_feerate= */ CFeeRate(0),
/* tx_noinputs_size= */ 0, /* avoid_partial= */ false);
CoinSelectionParams cs_params{
rand,
/* change_output_size= */ 34,
/* change_spend_size= */ 148,
/* effective_feerate= */ CFeeRate(0),
/* long_term_feerate= */ CFeeRate(0),
/* discard_feerate= */ CFeeRate(0),
/* tx_noinputs_size= */ 0,
/* avoid_partial= */ false,
};
CCoinControl cc;
const auto result = SelectCoins(*wallet, coins, target, cc, cs_params);
BOOST_CHECK(result);