@@ -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