Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1251add_coin(available_coins, wallet, CAmount(50 * COIN), CFeeRate(0), 144, false, 0, true);1252return available_coins;1253},1254m_node);1256BOOST_CHECK(result);1257// Verify that the 50 BTC UTXO was selected, and result is below max_weight1258BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(50 * COIN)));1259BOOST_CHECK_LE(result->GetWeight(), max_weight);1260}1262{1263// Scenario 2:1265// The actor starts with 400x 0.0625 BTC and 2000x 0.025 BTC (75.0 BTC total) unspent outputs1266// Then tries to spend 49.5 BTC1267// A combination of coins should be selected, such that the created transaction is not too large1269// Perform selection1270const auto result = select_coins(1271target, cs_params, cc, [&](CWallet& wallet) {1272CoinsResult available_coins;1273for (int j = 0; j < 400; ++j) {1274add_coin(available_coins, wallet, CAmount(0.0625 * COIN), CFeeRate(0), 144, false, 0, true);1275}1276for (int j = 0; j < 2000; ++j) {1277add_coin(available_coins, wallet, CAmount(0.025 * COIN), CFeeRate(0), 144, false, 0, true);1278}1279return available_coins;1280},1281m_node);1283BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(0.0625 * COIN)));1284BOOST_CHECK(has_coin(result->GetInputSet(), CAmount(0.025 * COIN)));1285BOOST_CHECK_LE(result->GetWeight(), max_weight);1286}1288{1289// Scenario 3:1291// The actor starts with 1515x 0.033 BTC (49.995 BTC total) unspent outputs1292// No results should be returned, because the transaction would be too large1294// Perform selection1295const auto result = select_coins(1296target, cs_params, cc, [&](CWallet& wallet) {1297CoinsResult available_coins;1298for (int j = 0; j < 1515; ++j) {1299add_coin(available_coins, wallet, CAmount(0.033 * COIN), CFeeRate(0), 144, false, 0, true);1300}1301return available_coins;1302},1303m_node);1305// No results1306// 1515 inputs * 68 bytes = 103,020 bytes1307// 103,020 bytes * 4 = 412,080 weight, which is above the MAX_STANDARD_TX_WEIGHT of 400,0001308BOOST_CHECK(!result);1309}1310}1312BOOST_AUTO_TEST_CASE(SelectCoins_effective_value_test)1313{1314// Test that the effective value is used to check whether preset inputs provide sufficient funds when subtract_fee_outputs is not used.1315// This test creates a coin whose value is higher than the target but whose effective value is lower than the target.1316// The coin is selected using coin control, with m_allow_other_inputs = false. SelectCoins should fail due to insufficient funds.1318std::unique_ptr<CWallet> wallet = NewWallet(m_node);1320CoinsResult available_coins;1321{1322std::unique_ptr<CWallet> dummyWallet = NewWallet(m_node, /*wallet_name=*/"dummy");1323add_coin(available_coins, *dummyWallet, 100000); // 0.001 BTC1324}1326CAmount target{99900}; // 0.000999 BTC1328FastRandomContext rand;1329CoinSelectionParams cs_params{1330rand,1331/*change_output_size=*/34,1332/*change_spend_size=*/148,1333/*min_change_target=*/1000,1334/*effective_feerate=*/CFeeRate(3000),1335/*long_term_feerate=*/CFeeRate(1000),1336/*discard_feerate=*/CFeeRate(1000),1337/*tx_noinputs_size=*/0,1338/*avoid_partial=*/false,1339};1340CCoinControl cc;1341cc.m_allow_other_inputs = false;1342COutput output = available_coins.All().at(0);1343cc.SetInputWeight(output.outpoint, 148);1344cc.Select(output.outpoint).SetTxOut(output.txout);1346LOCK(wallet->cs_wallet);1347const auto preset_inputs = *Assert(FetchSelectedInputs(*wallet, cc, cs_params));1348available_coins.Erase({available_coins.coins[OutputType::BECH32].begin()->outpoint});1350const auto result = SelectCoins(*wallet, available_coins, preset_inputs, target, cc, cs_params);1351BOOST_CHECK(!result);1352}1354BOOST_FIXTURE_TEST_CASE(wallet_coinsresult_test, BasicTestingSetup)1355{1356// Test case to verify CoinsResult object sanity.1357CoinsResult available_coins;1358{1359std::unique_ptr<CWallet> dummyWallet = NewWallet(m_node, /*wallet_name=*/"dummy");1361// Add some coins to 'available_coins'1362for (int i=0; i<10; i++) {1363add_coin(available_coins, *dummyWallet, 1 * COIN);1364}1365}1367{1368// First test case, check that 'CoinsResult::Erase' function works as expected.1369// By trying to erase two elements from the 'available_coins' object.1370std::unordered_set<COutPoint, SaltedOutpointHasher> outs_to_remove;1371const auto& coins = available_coins.All();1372for (int i = 0; i < 2; i++) {1373outs_to_remove.emplace(coins[i].outpoint);1374}1375available_coins.Erase(outs_to_remove);1377// Check that the elements were actually removed.1378const auto& updated_coins = available_coins.All();1379for (const auto& out: outs_to_remove) {1380auto it = std::find_if(updated_coins.begin(), updated_coins.end(), [&out](const COutput &coin) {1381return coin.outpoint == out;1382});1383BOOST_CHECK(it == updated_coins.end());1384}1385// And verify that no extra element were removed1386BOOST_CHECK_EQUAL(available_coins.Size(), 8);1387}1388}1390BOOST_AUTO_TEST_SUITE_END()1391} // namespace wallet
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.