@@ -10,11 +10,17 @@ use crate::{
10
10
DescriptorExt , DescriptorId , Indexed , Indexer , KeychainIndexed , SpkIterator ,
11
11
} ;
12
12
use alloc:: { borrow:: ToOwned , vec:: Vec } ;
13
- use bitcoin:: { Amount , OutPoint , ScriptBuf , SignedAmount , Transaction , TxOut , Txid } ;
13
+ use bitcoin:: {
14
+ bip32:: ChildNumber , Amount , OutPoint , ScriptBuf , SignedAmount , Transaction , TxOut , Txid ,
15
+ } ;
14
16
use core:: {
15
17
fmt:: Debug ,
16
18
ops:: { Bound , RangeBounds } ,
17
19
} ;
20
+ use miniscript:: {
21
+ descriptor:: { DescriptorXKey , Wildcard } ,
22
+ ForEachKey ,
23
+ } ;
18
24
19
25
use crate :: Merge ;
20
26
@@ -355,6 +361,23 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
355
361
keychain : K ,
356
362
descriptor : Descriptor < DescriptorPublicKey > ,
357
363
) -> Result < bool , InsertDescriptorError < K > > {
364
+ // Ensure the keys don't contain any hardened derivation steps or hardened wildcards
365
+ let descriptor_contains_hardened_steps = descriptor. for_any_key ( |k| {
366
+ if let DescriptorPublicKey :: XPub ( DescriptorXKey {
367
+ derivation_path,
368
+ wildcard,
369
+ ..
370
+ } ) = k
371
+ {
372
+ return * wildcard == Wildcard :: Hardened
373
+ || derivation_path. into_iter ( ) . any ( ChildNumber :: is_hardened) ;
374
+ }
375
+ false
376
+ } ) ;
377
+ if descriptor_contains_hardened_steps {
378
+ return Err ( InsertDescriptorError :: HardenedDerivationXpub ) ;
379
+ }
380
+ descriptor. sanity_check ( ) ?;
358
381
let did = descriptor. descriptor_id ( ) ;
359
382
if !self . keychain_to_descriptor_id . contains_key ( & keychain)
360
383
&& !self . descriptor_id_to_keychain . contains_key ( & did)
@@ -776,7 +799,7 @@ impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
776
799
}
777
800
}
778
801
779
- #[ derive( Clone , Debug , PartialEq ) ]
802
+ #[ derive( Debug , PartialEq ) ]
780
803
/// Error returned from [`KeychainTxOutIndex::insert_descriptor`]
781
804
pub enum InsertDescriptorError < K > {
782
805
/// The descriptor has already been assigned to a keychain so you can't assign it to another
@@ -793,6 +816,16 @@ pub enum InsertDescriptorError<K> {
793
816
/// The descriptor that the keychain is already assigned to
794
817
existing_assignment : Descriptor < DescriptorPublicKey > ,
795
818
} ,
819
+ /// Miniscript error
820
+ Miniscript ( miniscript:: Error ) ,
821
+ /// The descriptor contains hardened derivation steps on public extended keys
822
+ HardenedDerivationXpub ,
823
+ }
824
+
825
+ impl < K > From < miniscript:: Error > for InsertDescriptorError < K > {
826
+ fn from ( err : miniscript:: Error ) -> Self {
827
+ InsertDescriptorError :: Miniscript ( err)
828
+ }
796
829
}
797
830
798
831
impl < K : core:: fmt:: Debug > core:: fmt:: Display for InsertDescriptorError < K > {
@@ -816,6 +849,11 @@ impl<K: core::fmt::Debug> core::fmt::Display for InsertDescriptorError<K> {
816
849
"attempt to re-assign keychain {keychain:?} already assigned to {existing:?}"
817
850
)
818
851
}
852
+ InsertDescriptorError :: Miniscript ( err) => write ! ( f, "Miniscript error: {}" , err) ,
853
+ InsertDescriptorError :: HardenedDerivationXpub => write ! (
854
+ f,
855
+ "The descriptor contains hardened derivation steps on public extended keys"
856
+ ) ,
819
857
}
820
858
}
821
859
}
0 commit comments