wallet: unconfirmed ancestors and descendants are always truc
What changed, and why it matters
This Bitcoin Core wallet patch changes how the wallet selects unconfirmed coins to spend. It adds a filter so that when a user is building a transaction, unconfirmed ancestor or descendant coins are only used if their transaction version matches the version chosen for the new transaction. The commit title says these unconfirmed relatives are 'always TRUC' (a new v3 transaction version type). The change prevents mixing v3 (TRUC) and non-v3 unconfirmed coins in the same spend, which could otherwise cause the resulting transaction to violate network relay rules and get rejected.
Reviewers should verify that TRUC_VERSION is correctly defined in policy/truc_policy.h, that m_version in CCoinControl is reliably set for all transaction-construction paths, and that no edge cases exist where check_version_trucness remains enabled unexpectedly. Users running nodes/wallets with TRUC support should ensure they are on a version containing this fix to avoid constructing invalid spends from unconfirmed TRUC relatives.
Security signals we found
Transaction version policy enforcement added to coin selection
Prevents mixing TRUC (v3) and non-TRUC unconfirmed inputs/ancestors
Avoids creation of transactions that may be rejected by mempool policy
Default-on filtering with explicit opt-out for listing operations
Evidence from the diff
The commit modifies AvailableCoins() in src/wallet/spend.cpp and CoinFilterParams in src/wallet/spend.h. A new boolean flag check_version_trucness is added to CoinFilterParams, defaulting to true. When filtering unconfirmed coins (nDepth == 0) and this flag is true, the code compares the coin’s transaction version against the version set in CCoinControl (m_version). If the coinControl version is TRUC_VERSION, only TRUC-version coins are kept; otherwise, TRUC-version coins are skipped. AvailableCoinsListUnspent() explicitly disables this filter because it is used for listing, not for constructing spends. The intent is to ensure that unconfirmed ancestors/descendants selected by the wallet are consistent with the transaction version policy (TRUC), avoiding creation of transactions that would fail policy checks due to mixed transaction-version ancestry.
Changed components
src/wallet/spend.cppsrc/wallet/spend.hBitcoin Core wallet coin selectionCCoinControl transaction version handlingInspect captured patch +13 / −0
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 86aa137b..8e24bb95 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -12,6 +12,7 @@
#include <node/types.h>
#include <numeric>
#include <policy/policy.h>
+#include <policy/truc_policy.h>
#include <primitives/transaction.h>
#include <primitives/transaction_identifier.h>
#include <script/script.h>
@@ -386,6 +387,14 @@ CoinsResult AvailableCoins(const CWallet& wallet,
safeTx = false;
}
+ if (nDepth == 0 && params.check_version_trucness) {
+ if (coinControl->m_version == TRUC_VERSION) {
+ if (wtx.tx->version != TRUC_VERSION) continue;
+ } else {
+ if (wtx.tx->version == TRUC_VERSION) continue;
+ }
+ }
+
if (only_safe && !safeTx) {
continue;
}
@@ -484,6 +493,7 @@ CoinsResult AvailableCoins(const CWallet& wallet,
CoinsResult AvailableCoinsListUnspent(const CWallet& wallet, const CCoinControl* coinControl, CoinFilterParams params)
{
params.only_spendable = false;
+ params.check_version_trucness = false;
return AvailableCoins(wallet, coinControl, /*feerate=*/ std::nullopt, params);
}
diff --git a/src/wallet/spend.h b/src/wallet/spend.h
index c8e7737e..19625c11 100644
--- a/src/wallet/spend.h
+++ b/src/wallet/spend.h
@@ -83,6 +83,9 @@ struct CoinFilterParams {
bool include_immature_coinbase{false};
// By default, skip locked UTXOs
bool skip_locked{true};
+ // When true, filter unconfirmed coins by whether their
+ // version's TRUCness matches what is set by CCoinControl.
+ bool check_version_trucness{true};
};
/**
Why this scored 27/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.