wallet: Use Descriptor::CanSelfExpand() in CanGetAddresses()
What changed, and why it matters
This is a small Bitcoin Core wallet change that lets the wallet generate addresses from certain descriptors even when it does not have private keys and has already used up its pre-derived address range. It only affects descriptors that can expand entirely on their own (public-only, no cached data needed). The change is more of a correctness/availability fix than a security flaw, and there is no direct evidence in the commit that it fixes a vulnerability.
Review as a normal code-quality/behavior fix. No urgent security response is indicated by the commit alone. If monitoring, verify that CanSelfExpand() correctly identifies descriptors that need no private material and that callers of CanGetAddresses() do not rely on it as a security boundary.
Security signals we found
Changes address-derivation gating logic in wallet code
Expands conditions under which addresses can be produced without private keys
No explicit security framing, CVE, or advisory language in commit
Evidence from the diff
The patch modifies DescriptorScriptPubKeyMan::CanGetAddresses() to also return true when the descriptor’s CanSelfExpand() is true. Previously, the wallet would refuse to derive further addresses for a watch-only/range descriptor once next_index reached range_end unless private keys were present. With this change, descriptors that can self-expand (e.g., fully public descriptors needing no private keys or cached expansion data) remain usable for address generation. The diff is a single logical OR addition.
Changed components
src/wallet/scriptpubkeyman.cppDescriptorScriptPubKeyMan::CanGetAddresses()Wallet descriptor address derivationInspect captured patch +1 / −1
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 0759e2d5..738b0e63 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -1222,7 +1222,7 @@ bool DescriptorScriptPubKeyMan::CanGetAddresses(bool internal) const
LOCK(cs_desc_man);
return m_wallet_descriptor.descriptor->IsSingleType() &&
m_wallet_descriptor.descriptor->IsRange() &&
- (HavePrivateKeys() || m_wallet_descriptor.next_index < m_wallet_descriptor.range_end);
+ (HavePrivateKeys() || m_wallet_descriptor.next_index < m_wallet_descriptor.range_end || m_wallet_descriptor.descriptor->CanSelfExpand());
}
bool DescriptorScriptPubKeyMan::HavePrivateKeys() const
Why this scored 23/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.