mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-12 15:09:59 +01:00
Merge bitcoin/bitcoin#25005: wallet: remove extra wtx lookup in 'AvailableCoins' + several code cleanups.
fd5c996d16wallet: GetAvailableBalance, remove double walk-through every available coin (furszy)162d4ad10fwallet: add 'only_spendable' filter to AvailableCoins (furszy)cdf185ccfbwallet: remove unused IsSpentKey(hash, index) method (furszy)4b83bf8dbcwallet: avoid extra IsSpentKey -> GetWalletTx lookups (furszy)3d8a282257wallet: decouple IsSpentKey(scriptPubKey) from IsSpentKey(hash, n) (furszy)a06fa94ff8wallet: IsSpent, 'COutPoint' arg instead of (hash, index) (furszy)91902b7720wallet: IsLockedCoin, 'COutPoint' arg instead of (hash, index) (furszy)9472ca0a65wallet: AvailableCoins, don't call 'wtx.tx->vout[i]' multiple times (furszy)4ce235ef8fwallet: return 'CoinsResult' struct in `AvailableCoins` (furszy) Pull request description: This started in #24845 but grew out of scope of it. So, points tackled: 1) Avoid extra `GetWalletTx` lookups inside `AvailableCoins -> IsSpentKey`. `IsSpentKey` was receiving the tx hash and index to internally lookup the tx inside the wallet's map. As all the `IsSpentKey` function callers already have the wtx available, them can provide the `scriptPubKey` directly. 2) Most of the time, we call `Wallet::AvailableCoins`, and later on the process, skip the non-spendable coins from the result in subsequent for-loops. So to speedup the process: introduced the ability to filter by "only_spendable" coins inside `Wallet::AvailableCoins` directly. (the non-spendable coins skip examples are inside `AttemptSelection->GroupOutputs` and `GetAvailableBalance`). 4) Refactored `AvailableCoins` in several ways: a) Now it will return a new struct `CoinsResult` instead of receiving the vCoins vector reference (which was being cleared at the beginning of the method anyway). --> this is coming from #24845 but cherry-picked it here too to make the following commits look nicer. b) Unified all the 'wtx.tx->vout[I]' calls into a single call (coming from this comment https://github.com/bitcoin/bitcoin/pull/24699#discussion_r854163032). 5) The wallet `IsLockedCoin` and `IsSpent` methods now accept an `OutPoint` instead of a hash:index. Which let me cleanup a bunch of extra code. 6) Speeded up the wallet 'GetAvailableBalance': filtering `AvailableCoins` by spendable outputs only and using the 'AvailableCoins' retrieved `total_amount` instead of looping over all the retrieved coins once more. ------------------------------------------------------- Side topic, all this process will look even nicer with #25218 ACKs for top commit: achow101: ACKfd5c996d16brunoerg: crACKfd5c996d16w0xlt: Code Review ACKfd5c996d16Tree-SHA512: 376a85476f907f4f7d1fc3de74b3dbe159b8cc24687374d8739711ad202ea07a33e86f4e66dece836da3ae6985147119fe584f6e672f11d0450ba6bd165b3220
This commit is contained in:
@@ -1367,7 +1367,6 @@ RPCHelpMan sendall()
|
||||
|
||||
CMutableTransaction rawTx{ConstructTransaction(options["inputs"], recipient_key_value_pairs, options["locktime"], rbf)};
|
||||
LOCK(pwallet->cs_wallet);
|
||||
std::vector<COutput> all_the_utxos;
|
||||
|
||||
CAmount total_input_value(0);
|
||||
bool send_max{options.exists("send_max") ? options["send_max"].get_bool() : false};
|
||||
@@ -1375,7 +1374,7 @@ RPCHelpMan sendall()
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot combine send_max with specific inputs.");
|
||||
} else if (options.exists("inputs")) {
|
||||
for (const CTxIn& input : rawTx.vin) {
|
||||
if (pwallet->IsSpent(input.prevout.hash, input.prevout.n)) {
|
||||
if (pwallet->IsSpent(input.prevout)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not available. UTXO (%s:%d) was already spent.", input.prevout.hash.ToString(), input.prevout.n));
|
||||
}
|
||||
const CWalletTx* tx{pwallet->GetWalletTx(input.prevout.hash)};
|
||||
@@ -1385,8 +1384,7 @@ RPCHelpMan sendall()
|
||||
total_input_value += tx->tx->vout[input.prevout.n].nValue;
|
||||
}
|
||||
} else {
|
||||
AvailableCoins(*pwallet, all_the_utxos, &coin_control, fee_rate, /*nMinimumAmount=*/0);
|
||||
for (const COutput& output : all_the_utxos) {
|
||||
for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, /*nMinimumAmount=*/0).coins) {
|
||||
CHECK_NONFATAL(output.input_bytes > 0);
|
||||
if (send_max && fee_rate.GetFee(output.input_bytes) > output.txout.nValue) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user