Repository navigation
Description
Describe the bug
SpkTxOutIndex::is_used returns true for an index that was never added to or tracked by the index (i.e. not present in self.spks).
Because is_used is implemented as:
pub fn is_used(&self, index: &I) -> bool {
!self.unused.contains(index)
}and self.unused only tracks indices that were explicitly added via insert_spk, any index that has never been tracked is absent from self.unused. As a result, !self.unused.contains(index) evaluates to true.
Consequently:
- On a newly initialized or empty
SpkTxOutIndex::<u32>::default(), queryingindex.is_used(&0)returnstrueeven though no script pubkeys have ever been added. - In
KeychainTxOutIndex, queryingkeychain_txout.is_used(keychain, untracked_index)similarly returnstruefor any derivation index that has not been revealed or tracked.
In contrast, unmark_used in SpkTxOutIndex already explicitly guards against untracked indices:
if !self.spks.contains_key(index) {
return false;
}To Reproduce
Run the following unit test in crates/chain/tests/test_spk_txout_index.rs:
#[test]
fn is_used_returns_false_for_untracked_index() {
let index = SpkTxOutIndex::<u32>::default();
assert!(!index.is_used(&0));
}The assertion fails:
assertion failed: !index.is_used(&0)
Similarly, on KeychainTxOutIndex:
let keychain_txout = KeychainTxOutIndex::<Keychain>::default();
assert!(!keychain_txout.is_used(&Keychain::External, 0));returns true for any unrevealed derivation index.
Expected behavior
is_used should return false for untracked indices (indices not present in self.spks), and only return true for indices that are tracked in self.spks and have been marked used (i.e. not in self.unused).
Build environment
- BDK tag/commit:
f2528da88b1041bdddf547d677511aea19ad3573 - OS+version: Windows 11
- Rust/Cargo version:
1.99.0 - Rust/Cargo target:
x86_64-pc-windows-gnullvm
Which backend(s) are relevant (if any)?
- Electrum
- Esplora
- Bitcoin Core RPC
- None / not backend-related (e.g.
bdk_chain,bdk_core) - Other (please specify):
____
Is this blocking production use?
- Yes
- No
Additional context
Checking self.spks.contains_key(index) ensures that untracked indices are not mistakenly reported as used:
pub fn is_used(&self, index: &I) -> bool {
self.spks.contains_key(index) && !self.unused.contains(index)
}Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsIn Progress
Activity
fix(chain): return false for untracked indices in SpkTxOutIndex::is_used
fix(chain): return false for untracked indices in SpkTxOutIndex::is_used