mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 14:53:43 +01:00
Merge bitcoin/bitcoin#33268: wallet: Identify transactions spending 0-value outputs, and add tests for anchor outputs in a wallet
113a422822wallet: Add m_cached_from_me to cache "from me" status (Ava Chow)609d265ebctest: Add a test for anchor outputs in the wallet (Ava Chow)c40dc822d7wallet: Throw an error in sendall if the tx size cannot be calculated (Ava Chow)39a7dbdd27wallet: Determine IsFromMe by checking for TXOs of inputs (Ava Chow)e76c2f7a41test: Test wallet 'from me' status change (Ava Chow) Pull request description: One of the ways that the wallet would determine if a transaction was sent from the wallet was by checking if the total amount being spent by a transaction from outputs known to the wallet was greater than 0. This has worked fine until recently since there was no reason for 0-value outputs to be created. However, with ephemeral dust and P2A, it is possible to create standard 0-value outputs, and the wallet was not correctly identifying the spends of such outputs. This PR updates `IsFromMe` to only check whether the wallet knows any of the inputs, rather than checking the debit amount of a transaction. Additionally, a new functional test is added to test for this case, as well as a few other anchor output related scenarios. This also revealed a bug in `sendall` which would cause an assertion error when trying to spend all of the outputs in a wallet that has anchor outputs. Fixes #33265 ACKs for top commit: rkrux: lgtm ACK113a422822enirox001: Tested ACK113a422. Ran the full functional test suite including `wallet_anchor.py`; all tests passed. Fix for 0 value anchor detection and sendall size errors looks good. LGTM. furszy: ACK113a422822Tree-SHA512: df2ce4b258d1875ad0b4f27a5b9b4437137a5889a7d5ed7fbca65f904615e9572d232a8b8d070760f75ac168c1a49b7981f6b5052308575866dc610d191ca964
This commit is contained in:
@@ -195,7 +195,10 @@ void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
|
||||
|
||||
bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx)
|
||||
{
|
||||
return (CachedTxGetDebit(wallet, wtx, /*avoid_reuse=*/false) > 0);
|
||||
if (!wtx.m_cached_from_me.has_value()) {
|
||||
wtx.m_cached_from_me = wallet.IsFromMe(*wtx.tx);
|
||||
}
|
||||
return wtx.m_cached_from_me.value();
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(misc-no-recursion)
|
||||
|
||||
@@ -1521,7 +1521,6 @@ RPCHelpMan sendall()
|
||||
CoinFilterParams coins_params;
|
||||
coins_params.min_amount = 0;
|
||||
for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, coins_params).All()) {
|
||||
CHECK_NONFATAL(output.input_bytes > 0);
|
||||
if (send_max && fee_rate.GetFee(output.input_bytes) > output.txout.nValue) {
|
||||
continue;
|
||||
}
|
||||
@@ -1544,6 +1543,9 @@ RPCHelpMan sendall()
|
||||
|
||||
// estimate final size of tx
|
||||
const TxSize tx_size{CalculateMaximumSignedTxSize(CTransaction(rawTx), pwallet.get())};
|
||||
if (tx_size.vsize == -1) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Unable to determine the size of the transaction, the wallet contains unsolvable descriptors");
|
||||
}
|
||||
const CAmount fee_from_size{fee_rate.GetFee(tx_size.vsize)};
|
||||
const std::optional<CAmount> total_bump_fees{pwallet->chain().calculateCombinedBumpFee(outpoints_spent, fee_rate)};
|
||||
CAmount effective_value = total_input_value - fee_from_size - total_bump_fees.value_or(0);
|
||||
|
||||
@@ -232,6 +232,8 @@ public:
|
||||
* CWallet::ComputeTimeSmart().
|
||||
*/
|
||||
unsigned int nTimeSmart;
|
||||
// Cached value for whether the transaction spends any inputs known to the wallet
|
||||
mutable std::optional<bool> m_cached_from_me{std::nullopt};
|
||||
int64_t nOrderPos; //!< position in ordered transaction list
|
||||
std::multimap<int64_t, CWalletTx*>::const_iterator m_it_wtxOrdered;
|
||||
|
||||
@@ -339,6 +341,7 @@ public:
|
||||
m_amounts[CREDIT].Reset();
|
||||
fChangeCached = false;
|
||||
m_is_cache_empty = true;
|
||||
m_cached_from_me = std::nullopt;
|
||||
}
|
||||
|
||||
/** True if only scriptSigs are different */
|
||||
|
||||
@@ -1634,7 +1634,11 @@ bool CWallet::IsMine(const COutPoint& outpoint) const
|
||||
|
||||
bool CWallet::IsFromMe(const CTransaction& tx) const
|
||||
{
|
||||
return (GetDebit(tx) > 0);
|
||||
LOCK(cs_wallet);
|
||||
for (const CTxIn& txin : tx.vin) {
|
||||
if (GetTXO(txin.prevout)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CAmount CWallet::GetDebit(const CTransaction& tx) const
|
||||
|
||||
Reference in New Issue
Block a user