Skip to content

Commit fcf3834

Browse files
committed
test(keychain_txout): test spk cache
- Test cached spk matches derived - Recover state of spk cache from changeset
1 parent e07ec1c commit fcf3834

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

crates/chain/src/indexer/keychain_txout.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,3 +1107,70 @@ impl<K: Clone + Ord + core::fmt::Debug> FullScanRequestBuilderExt<K> for FullSca
11071107
self
11081108
}
11091109
}
1110+
1111+
#[cfg(test)]
1112+
mod test {
1113+
use super::*;
1114+
1115+
use bdk_testenv::utils::DESCRIPTORS;
1116+
use bitcoin::secp256k1::Secp256k1;
1117+
use miniscript::Descriptor;
1118+
1119+
// Test that `KeychainTxOutIndex` uses the spk cache.
1120+
// And the indexed spks are as expected.
1121+
#[test]
1122+
fn test_spk_cache() {
1123+
let lookahead = 10;
1124+
let use_cache = true;
1125+
let mut index = KeychainTxOutIndex::new(lookahead, use_cache);
1126+
let s = DESCRIPTORS[0];
1127+
1128+
let desc = Descriptor::parse_descriptor(&Secp256k1::new(), s)
1129+
.unwrap()
1130+
.0;
1131+
1132+
let did = desc.descriptor_id();
1133+
1134+
let reveal_to = 2;
1135+
let end_index = reveal_to + lookahead;
1136+
1137+
let _ = index.insert_descriptor(0i32, desc.clone());
1138+
assert_eq!(index.spk_cache.get(&did).unwrap().len() as u32, lookahead);
1139+
assert_eq!(index.next_index(0), Some((0, true)));
1140+
1141+
// Now reveal some scripts
1142+
for _ in 0..=reveal_to {
1143+
let _ = index.reveal_next_spk(0).unwrap();
1144+
}
1145+
assert_eq!(index.last_revealed_index(0), Some(reveal_to));
1146+
1147+
let spk_cache = &index.spk_cache;
1148+
assert!(!spk_cache.is_empty());
1149+
1150+
for (&did, cached_spks) in spk_cache {
1151+
assert_eq!(did, desc.descriptor_id());
1152+
for (&i, cached_spk) in cached_spks {
1153+
// Cached spk matches derived
1154+
let exp_spk = desc.at_derivation_index(i).unwrap().script_pubkey();
1155+
assert_eq!(&exp_spk, cached_spk);
1156+
// Also matches the inner index
1157+
assert_eq!(index.spk_at_index(0, i), Some(cached_spk.clone()));
1158+
}
1159+
}
1160+
1161+
let init_cs = index.initial_changeset();
1162+
assert_eq!(
1163+
init_cs.spk_cache.get(&did).unwrap().len() as u32,
1164+
end_index + 1
1165+
);
1166+
1167+
// Now test load from changeset
1168+
let recovered =
1169+
KeychainTxOutIndex::<&str>::from_changeset(lookahead, use_cache, init_cs.clone());
1170+
assert_eq!(&recovered.spk_cache, spk_cache);
1171+
1172+
// The cache is optional at load time
1173+
let index = KeychainTxOutIndex::<i32>::from_changeset(lookahead, false, init_cs);
1174+
assert!(index.spk_cache.is_empty());
1175+
}
1176+
}

0 commit comments

Comments
 (0)