@@ -68,7 +68,7 @@ static void add_coin(const CAmount& nValue, int nInput, CoinSet& set, CAmount fe
68
68
set.insert (std::make_shared<COutput>(coin));
69
69
}
70
70
71
- static void add_coin (CoinsResult& available_coins, CWallet& wallet, const CAmount& nValue, CFeeRate feerate = CFeeRate(0 ), int nAge = 6*24, bool fIsFromMe = false, int nInput =0, bool spendable = false)
71
+ static void add_coin (CoinsResult& available_coins, CWallet& wallet, const CAmount& nValue, CFeeRate feerate = CFeeRate(0 ), int nAge = 6*24, bool fIsFromMe = false, int nInput =0, bool spendable = false, int custom_size = 0 )
72
72
{
73
73
CMutableTransaction tx;
74
74
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
@@ -84,7 +84,7 @@ static void add_coin(CoinsResult& available_coins, CWallet& wallet, const CAmoun
84
84
assert (ret.second );
85
85
CWalletTx& wtx = (*ret.first ).second ;
86
86
const auto & txout = wtx.tx ->vout .at (nInput);
87
- available_coins.Add (OutputType::BECH32, {COutPoint (wtx.GetHash (), nInput), txout, nAge, CalculateMaximumSignedInputSize (txout, &wallet, /* coin_control=*/ nullptr ), /* spendable=*/ true , /* solvable=*/ true , /* safe=*/ true , wtx.GetTxTime (), fIsFromMe , feerate});
87
+ available_coins.Add (OutputType::BECH32, {COutPoint (wtx.GetHash (), nInput), txout, nAge, custom_size == 0 ? CalculateMaximumSignedInputSize (txout, &wallet, /* coin_control=*/ nullptr ) : custom_size , /* spendable=*/ true , /* solvable=*/ true , /* safe=*/ true , wtx.GetTxTime (), fIsFromMe , feerate});
88
88
}
89
89
90
90
// Helpers
@@ -142,13 +142,15 @@ static CAmount make_hard_case(int utxos, std::vector<COutput>& utxo_pool)
142
142
return target;
143
143
}
144
144
145
- inline std::vector<OutputGroup>& GroupCoins (const std::vector<COutput>& available_coins)
145
+ inline std::vector<OutputGroup>& GroupCoins (const std::vector<COutput>& available_coins, bool subtract_fee_outputs = false )
146
146
{
147
147
static std::vector<OutputGroup> static_groups;
148
148
static_groups.clear ();
149
149
for (auto & coin : available_coins) {
150
150
static_groups.emplace_back ();
151
- static_groups.back ().Insert (std::make_shared<COutput>(coin), /* ancestors=*/ 0 , /* descendants=*/ 0 );
151
+ OutputGroup& group = static_groups.back ();
152
+ group.Insert (std::make_shared<COutput>(coin), /* ancestors=*/ 0 , /* descendants=*/ 0 );
153
+ group.m_subtract_fee_outputs = subtract_fee_outputs;
152
154
}
153
155
return static_groups;
154
156
}
@@ -411,6 +413,41 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
411
413
const auto result13 = SelectCoins (*wallet, available_coins, selected_input, 10 * CENT, coin_control, coin_selection_params_bnb);
412
414
BOOST_CHECK (EquivalentResult (expected_result, *result13));
413
415
}
416
+
417
+ {
418
+ // Test bnb max weight exceeded
419
+ // Inputs set [10, 9, 8, 5, 3, 1], Selection Target = 16 and coin 5 exceeding the max weight.
420
+
421
+ std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain .get (), " " , m_args, CreateMockWalletDatabase ());
422
+ wallet->LoadWallet ();
423
+ LOCK (wallet->cs_wallet );
424
+ wallet->SetWalletFlag (WALLET_FLAG_DESCRIPTORS);
425
+ wallet->SetupDescriptorScriptPubKeyMans ();
426
+
427
+ CoinsResult available_coins;
428
+ add_coin (available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate , 6 * 24 , false , 0 , true );
429
+ add_coin (available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate , 6 * 24 , false , 0 , true );
430
+ add_coin (available_coins, *wallet, 8 * CENT, coin_selection_params_bnb.m_effective_feerate , 6 * 24 , false , 0 , true );
431
+ add_coin (available_coins, *wallet, 5 * CENT, coin_selection_params_bnb.m_effective_feerate , 6 * 24 , false , 0 , true , /* custom_size=*/ MAX_STANDARD_TX_WEIGHT);
432
+ add_coin (available_coins, *wallet, 3 * CENT, coin_selection_params_bnb.m_effective_feerate , 6 * 24 , false , 0 , true );
433
+ add_coin (available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate , 6 * 24 , false , 0 , true );
434
+
435
+ CAmount selection_target = 16 * CENT;
436
+ const auto & no_res = SelectCoinsBnB (GroupCoins (available_coins.All (), /* subtract_fee_outputs*/ true ),
437
+ selection_target, /* cost_of_change=*/ 0 , MAX_STANDARD_TX_WEIGHT);
438
+ BOOST_ASSERT (!no_res);
439
+ BOOST_CHECK (util::ErrorString (no_res).original .find (" The inputs size exceeds the maximum weight" ) != std::string::npos);
440
+
441
+ // Now add same coin value with a good size and check that it gets selected
442
+ add_coin (available_coins, *wallet, 5 * CENT, coin_selection_params_bnb.m_effective_feerate , 6 * 24 , false , 0 , true );
443
+ const auto & res = SelectCoinsBnB (GroupCoins (available_coins.All (), /* subtract_fee_outputs*/ true ), selection_target, /* cost_of_change=*/ 0 );
444
+
445
+ expected_result.Clear ();
446
+ add_coin (8 * CENT, 2 , expected_result);
447
+ add_coin (5 * CENT, 2 , expected_result);
448
+ add_coin (3 * CENT, 2 , expected_result);
449
+ BOOST_CHECK (EquivalentResult (expected_result, *res));
450
+ }
414
451
}
415
452
416
453
BOOST_AUTO_TEST_CASE (knapsack_solver_test)
0 commit comments