@@ -23,8 +23,9 @@ use sync::Arc;
23
23
use self :: checksum:: verify_checksum;
24
24
use crate :: miniscript:: decode:: Terminal ;
25
25
use crate :: miniscript:: { satisfy, Legacy , Miniscript , Segwitv0 } ;
26
- use crate :: plan:: { AssetProvider , Plan } ;
26
+ use crate :: plan:: { AssetProvider , Assets , Plan } ;
27
27
use crate :: prelude:: * ;
28
+ use crate :: util:: get_asset_combination;
28
29
use crate :: {
29
30
expression, hash256, BareCtx , Error , ForEachKey , MiniscriptKey , Satisfier , ToPublicKey ,
30
31
TranslateErr , TranslatePk , Translator ,
@@ -568,6 +569,124 @@ impl Descriptor<DefiniteDescriptorKey> {
568
569
}
569
570
}
570
571
572
+ impl Descriptor < DescriptorPublicKey > {
573
+ /// Count total possible assets for a given descriptor.
574
+ pub fn count_assets ( & self ) -> u64 {
575
+ match self {
576
+ Descriptor :: Bare ( k) => k. as_inner ( ) . count_assets ( ) ,
577
+ Descriptor :: Pkh ( _) => 1 ,
578
+ Descriptor :: Wpkh ( _) => 1 ,
579
+ Descriptor :: Sh ( k) => match k. as_inner ( ) {
580
+ ShInner :: Wsh ( k) => match k. as_inner ( ) {
581
+ WshInner :: SortedMulti ( k) => {
582
+ let n = k. pks . len ( ) as u64 ;
583
+ let k = k. k as u64 ;
584
+ Self :: k_of_n ( k, n)
585
+ }
586
+ WshInner :: Ms ( k) => k. count_assets ( ) ,
587
+ } ,
588
+ ShInner :: Wpkh ( _) => 1 ,
589
+ ShInner :: SortedMulti ( k) => {
590
+ let n = k. clone ( ) . pks . len ( ) as u64 ;
591
+ let k = k. clone ( ) . k as u64 ;
592
+ Self :: k_of_n ( k, n)
593
+ }
594
+ ShInner :: Ms ( k) => k. count_assets ( ) ,
595
+ } ,
596
+ Descriptor :: Wsh ( k) => match k. as_inner ( ) {
597
+ WshInner :: SortedMulti ( k) => {
598
+ let n = k. clone ( ) . pks . len ( ) as u64 ;
599
+ let k = k. clone ( ) . k as u64 ;
600
+ Self :: k_of_n ( k, n)
601
+ }
602
+ WshInner :: Ms ( k) => k. count_assets ( ) ,
603
+ } ,
604
+ Descriptor :: Tr ( k) => {
605
+ let s = k. taptree ( ) . clone ( ) . unwrap ( ) ;
606
+ match s {
607
+ TapTree :: Tree ( ref left, ref right) => {
608
+ let a = left. count_assets ( ) ;
609
+ let b = right. count_assets ( ) ;
610
+ a + b
611
+ }
612
+ TapTree :: Leaf ( k) => k. count_assets ( ) ,
613
+ }
614
+ }
615
+ }
616
+ }
617
+
618
+ /// Get all possible assets for a given descriptor
619
+ pub fn all_assets ( & self ) -> Result < Vec < Assets > , Error > {
620
+ match self {
621
+ Descriptor :: Bare ( k) => Ok ( k. as_inner ( ) . all_assets ( ) ) ,
622
+ Descriptor :: Pkh ( k) => {
623
+ let mut asset = Assets :: new ( ) ;
624
+ asset = asset. add ( k. as_inner ( ) . clone ( ) ) ;
625
+ Ok ( vec ! [ asset] )
626
+ }
627
+ Descriptor :: Wpkh ( k) => {
628
+ let mut asset = Assets :: new ( ) ;
629
+ asset = asset. add ( k. as_inner ( ) . clone ( ) ) ;
630
+ Ok ( vec ! [ asset] )
631
+ }
632
+ Descriptor :: Sh ( k) => match k. as_inner ( ) {
633
+ ShInner :: Wsh ( k) => match k. as_inner ( ) {
634
+ WshInner :: SortedMulti ( k) => {
635
+ let dpk_v = k. clone ( ) . pks ;
636
+ let k = k. clone ( ) . k ;
637
+ Ok ( get_asset_combination ( k, & dpk_v) )
638
+ }
639
+ WshInner :: Ms ( k) => Ok ( k. all_assets ( ) ) ,
640
+ } ,
641
+ ShInner :: Wpkh ( k) => {
642
+ let mut asset = Assets :: new ( ) ;
643
+ asset = asset. add ( k. as_inner ( ) . clone ( ) ) ;
644
+ Ok ( vec ! [ asset] )
645
+ }
646
+ ShInner :: SortedMulti ( k) => {
647
+ let dpk_v = k. clone ( ) . pks ;
648
+ let k = k. clone ( ) . k ;
649
+ Ok ( get_asset_combination ( k, & dpk_v) )
650
+ }
651
+ ShInner :: Ms ( k) => Ok ( k. all_assets ( ) ) ,
652
+ } ,
653
+ Descriptor :: Wsh ( k) => match k. as_inner ( ) {
654
+ WshInner :: SortedMulti ( k) => {
655
+ let dpk_v = k. clone ( ) . pks ;
656
+ let k = k. clone ( ) . k ;
657
+ Ok ( get_asset_combination ( k, & dpk_v) )
658
+ }
659
+ WshInner :: Ms ( k) => {
660
+ println ! ( "{}" , k) ;
661
+ let a = k. all_assets ( ) ;
662
+ println ! ( "{:#?}" , a) ;
663
+ Ok ( a)
664
+ }
665
+ } ,
666
+ Descriptor :: Tr ( k) => {
667
+ let s = k. taptree ( ) . clone ( ) . unwrap ( ) ;
668
+ match s {
669
+ TapTree :: Tree ( ref left, ref right) => {
670
+ let mut a = left. all_assets ( ) ;
671
+ let b = right. all_assets ( ) ;
672
+ a. extend ( b) ;
673
+ Ok ( a)
674
+ }
675
+ TapTree :: Leaf ( k) => Ok ( k. all_assets ( ) ) ,
676
+ }
677
+ }
678
+ }
679
+ }
680
+
681
+ // ways to select k things out of n
682
+ fn k_of_n ( k : u64 , n : u64 ) -> u64 {
683
+ if k == 0 || k == n {
684
+ return 1 ;
685
+ }
686
+ Self :: k_of_n ( k - 1 , n - 1 ) + Self :: k_of_n ( k - 1 , n)
687
+ }
688
+ }
689
+
571
690
impl < P , Q > TranslatePk < P , Q > for Descriptor < P >
572
691
where
573
692
P : MiniscriptKey ,
@@ -2094,4 +2213,75 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
2094
2213
Desc :: from_str ( & format ! ( "tr({},pk({}))" , x_only_key, uncomp_key) ) . unwrap_err ( ) ;
2095
2214
Desc :: from_str ( & format ! ( "tr({},pk({}))" , x_only_key, x_only_key) ) . unwrap ( ) ;
2096
2215
}
2216
+
2217
+ #[ test]
2218
+ fn test_all_assets_bare ( ) {
2219
+ let descriptor = Descriptor :: < DescriptorPublicKey > :: from_str (
2220
+ "pk(0237b1c59ab055a8d3de40eaeb215c7b1922664b5ac049d849fb3346f81431e77f)" ,
2221
+ )
2222
+ . unwrap ( ) ;
2223
+
2224
+ // Getting the assets from the all_assets method
2225
+ let assets = descriptor. all_assets ( ) . unwrap ( ) ;
2226
+
2227
+ let mut expected_asset = Assets :: new ( ) ;
2228
+ expected_asset = expected_asset. add (
2229
+ DescriptorPublicKey :: from_str (
2230
+ "0237b1c59ab055a8d3de40eaeb215c7b1922664b5ac049d849fb3346f81431e77f" ,
2231
+ )
2232
+ . unwrap ( ) ,
2233
+ ) ;
2234
+ assert_eq ! ( assets, vec![ expected_asset] ) ;
2235
+ }
2236
+
2237
+ #[ test]
2238
+ fn test_all_assets_sh_sortedmulti ( ) {
2239
+ let keys = vec ! [
2240
+ "0360eabc52e04f70c89e944f379895cdff28fed60849afe7736815c091765afb3c" ,
2241
+ "03a80a24196e66ccf6bca6e6f96633bb629ec702acd76b074de10922b0cf41cc81" ,
2242
+ ] ;
2243
+
2244
+ let descriptor = Descriptor :: < DescriptorPublicKey > :: from_str ( & format ! (
2245
+ "sh(sortedmulti(1,{},{}))" ,
2246
+ keys[ 0 ] , keys[ 1 ]
2247
+ ) )
2248
+ . unwrap ( ) ;
2249
+
2250
+ let assets = descriptor. all_assets ( ) . unwrap ( ) ;
2251
+
2252
+ let mut expected_assets: Vec < Assets > = Vec :: new ( ) ;
2253
+
2254
+ let mut asset1 = Assets :: new ( ) ;
2255
+ asset1 = asset1. add ( DescriptorPublicKey :: from_str ( keys[ 0 ] ) . unwrap ( ) ) ;
2256
+ expected_assets. push ( asset1) ;
2257
+
2258
+ let mut asset2 = Assets :: new ( ) ;
2259
+ asset2 = asset2. add ( DescriptorPublicKey :: from_str ( keys[ 1 ] ) . unwrap ( ) ) ;
2260
+ expected_assets. push ( asset2) ;
2261
+
2262
+ for expected_asset in & expected_assets {
2263
+ assert ! ( assets. contains( expected_asset) ) ;
2264
+ }
2265
+ }
2266
+
2267
+ #[ test]
2268
+ fn test_all_assets_taproot ( ) {
2269
+ let x_only_key = bitcoin:: key:: XOnlyPublicKey :: from_str (
2270
+ "015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab" ,
2271
+ )
2272
+ . unwrap ( ) ;
2273
+ let descriptor =
2274
+ Descriptor :: from_str ( & format ! ( "tr({},pk({}))" , x_only_key, x_only_key) ) . unwrap ( ) ;
2275
+ let assets = descriptor. all_assets ( ) . unwrap ( ) ;
2276
+ let mut expected_assets: Vec < Assets > = Vec :: new ( ) ;
2277
+ let mut asset_1 = Assets :: new ( ) ;
2278
+ asset_1 = asset_1. add (
2279
+ DescriptorPublicKey :: from_str (
2280
+ "015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab" ,
2281
+ )
2282
+ . unwrap ( ) ,
2283
+ ) ;
2284
+ expected_assets. push ( asset_1) ;
2285
+ assert_eq ! ( assets, expected_assets) ;
2286
+ }
2097
2287
}
0 commit comments