refresh the cached bitcoin core descriptor ranges when a wallet wants a range beyond them, so a range bitcoin core has already extended is not imported again or refused
What changed, and why it matters
This change fixes a bookkeeping issue between the Sparrow Wallet app and Bitcoin Core. When Bitcoin Core automatically expands the set of addresses it watches for a wallet, Sparrow could get out of sync and either try to re-import descriptors it already had, or refuse to extend the wallet's address range. The patch refreshes Sparrow's cached view of those ranges before deciding whether to import. The main risk is operational: users could see missing transactions, failed wallet loads, or address gaps, rather than a direct theft-of-funds bug.
Treat as a bug-fix commit worth including in the next release. Review whether duplicate imports or refused extensions could cause address gaps, and add regression tests for the extending-descriptor scenario. No emergency response is indicated from the diff alone.
Security signals we found
Stale cache leading to incorrect descriptor import decisions
Potential address-range gap or missed transactions if descriptor extension is mishandled
No cryptographic or remote-code-execution signal in the diff
Evidence from the diff
BitcoindClient.addDescriptors() previously only refreshed the cached list of imported descriptors when the client was not yet initialized or when a forced rescan was requested. Because Bitcoin Core itself extends descriptor ranges as addresses are used, Sparrow’s cached importedDescriptors map could become stale. If a wallet later requested a range larger than the cached range, Sparrow might attempt to import a descriptor Bitcoin Core already had (duplicate import) or reject the request as already imported. The patch adds an extending flag that triggers a fresh listDescriptors() call whenever any requested descriptor range exceeds the cached range, so the comparison uses Bitcoin Core’s current state.
Changed components
src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClient.javaBitcoin Core descriptor import / range-extension flowInspect captured patch +4 / −1
### src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClient.java
@@ -361,7 +361,10 @@ private void importDescriptors(Map<String, ScanDate> descriptors) throws ScanDat
private Set<String> addDescriptors(Map<String, ScanDate> descriptors) throws ScanDateBeforePruneException, ImportFailedException {
boolean forceRescan = descriptors.values().stream().anyMatch(scanDate -> scanDate.forceRescan);
- if(!initialized || forceRescan) {
+ //Bitcoin Core extends the range of a descriptor as its addresses are used, so a wanted range beyond the one last seen is compared against its current range
+ boolean extending = initialized && descriptors.entrySet().stream().anyMatch(entry -> entry.getValue().range != null && importedDescriptors.containsKey(entry.getKey())
+ && importedDescriptors.get(entry.getKey()).range != null && entry.getValue().range > importedDescriptors.get(entry.getKey()).range);
+ if(!initialized || forceRescan || extending) {
ListDescriptorsResult listDescriptorsResult = getBitcoindService().listDescriptors(false);
for(ListDescriptorResult result : listDescriptorsResult.descriptors()) {
String descriptor = OutputDescriptor.normalize(result.desc());Why this scored 35/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.