@@ -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 ,
@@ -546,6 +547,124 @@ impl Descriptor<DefiniteDescriptorKey> {
546
547
}
547
548
}
548
549
550
+ impl Descriptor < DescriptorPublicKey > {
551
+ /// Count total possible assets for a given descriptor.
552
+ pub fn count_assets ( & self ) -> u64 {
553
+ match self {
554
+ Descriptor :: Bare ( k) => k. as_inner ( ) . count_assets ( ) ,
555
+ Descriptor :: Pkh ( _) => 1 ,
556
+ Descriptor :: Wpkh ( _) => 1 ,
557
+ Descriptor :: Sh ( k) => match k. as_inner ( ) {
558
+ ShInner :: Wsh ( k) => match k. as_inner ( ) {
559
+ WshInner :: SortedMulti ( k) => {
560
+ let n = k. pks . len ( ) as u64 ;
561
+ let k = k. k as u64 ;
562
+ Self :: k_of_n ( k, n)
563
+ }
564
+ WshInner :: Ms ( k) => k. count_assets ( ) ,
565
+ } ,
566
+ ShInner :: Wpkh ( _) => 1 ,
567
+ ShInner :: SortedMulti ( k) => {
568
+ let n = k. clone ( ) . pks . len ( ) as u64 ;
569
+ let k = k. clone ( ) . k as u64 ;
570
+ Self :: k_of_n ( k, n)
571
+ }
572
+ ShInner :: Ms ( k) => k. count_assets ( ) ,
573
+ } ,
574
+ Descriptor :: Wsh ( k) => match k. as_inner ( ) {
575
+ WshInner :: SortedMulti ( k) => {
576
+ let n = k. clone ( ) . pks . len ( ) as u64 ;
577
+ let k = k. clone ( ) . k as u64 ;
578
+ Self :: k_of_n ( k, n)
579
+ }
580
+ WshInner :: Ms ( k) => k. count_assets ( ) ,
581
+ } ,
582
+ Descriptor :: Tr ( k) => {
583
+ let s = k. tap_tree ( ) . clone ( ) . unwrap ( ) ;
584
+ match s {
585
+ TapTree :: Tree { left, right, height : _ } => {
586
+ let a = left. count_assets ( ) ;
587
+ let b = right. count_assets ( ) ;
588
+ a + b
589
+ }
590
+ TapTree :: Leaf ( k) => k. count_assets ( ) ,
591
+ }
592
+ }
593
+ }
594
+ }
595
+
596
+ /// Get all possible assets for a given descriptor
597
+ pub fn all_assets ( & self ) -> Result < Vec < Assets > , Error > {
598
+ match self {
599
+ Descriptor :: Bare ( k) => Ok ( k. as_inner ( ) . all_assets ( ) ) ,
600
+ Descriptor :: Pkh ( k) => {
601
+ let mut asset = Assets :: new ( ) ;
602
+ asset = asset. add ( k. as_inner ( ) . clone ( ) ) ;
603
+ Ok ( vec ! [ asset] )
604
+ }
605
+ Descriptor :: Wpkh ( k) => {
606
+ let mut asset = Assets :: new ( ) ;
607
+ asset = asset. add ( k. as_inner ( ) . clone ( ) ) ;
608
+ Ok ( vec ! [ asset] )
609
+ }
610
+ Descriptor :: Sh ( k) => match k. as_inner ( ) {
611
+ ShInner :: Wsh ( k) => match k. as_inner ( ) {
612
+ WshInner :: SortedMulti ( k) => {
613
+ let dpk_v = k. clone ( ) . pks ;
614
+ let k = k. clone ( ) . k ;
615
+ Ok ( get_asset_combination ( k, & dpk_v) )
616
+ }
617
+ WshInner :: Ms ( k) => Ok ( k. all_assets ( ) ) ,
618
+ } ,
619
+ ShInner :: Wpkh ( k) => {
620
+ let mut asset = Assets :: new ( ) ;
621
+ asset = asset. add ( k. as_inner ( ) . clone ( ) ) ;
622
+ Ok ( vec ! [ asset] )
623
+ }
624
+ ShInner :: SortedMulti ( k) => {
625
+ let dpk_v = k. clone ( ) . pks ;
626
+ let k = k. clone ( ) . k ;
627
+ Ok ( get_asset_combination ( k, & dpk_v) )
628
+ }
629
+ ShInner :: Ms ( k) => Ok ( k. all_assets ( ) ) ,
630
+ } ,
631
+ Descriptor :: Wsh ( k) => match k. as_inner ( ) {
632
+ WshInner :: SortedMulti ( k) => {
633
+ let dpk_v = k. clone ( ) . pks ;
634
+ let k = k. clone ( ) . k ;
635
+ Ok ( get_asset_combination ( k, & dpk_v) )
636
+ }
637
+ WshInner :: Ms ( k) => {
638
+ println ! ( "{}" , k) ;
639
+ let a = k. all_assets ( ) ;
640
+ println ! ( "{:#?}" , a) ;
641
+ Ok ( a)
642
+ }
643
+ } ,
644
+ Descriptor :: Tr ( k) => {
645
+ let s = k. tap_tree ( ) . clone ( ) . unwrap ( ) ;
646
+ match s {
647
+ TapTree :: Tree { left, right, height : _ } => {
648
+ let mut a = left. all_assets ( ) ;
649
+ let b = right. all_assets ( ) ;
650
+ a. extend ( b) ;
651
+ Ok ( a)
652
+ }
653
+ TapTree :: Leaf ( k) => Ok ( k. all_assets ( ) ) ,
654
+ }
655
+ }
656
+ }
657
+ }
658
+
659
+ // ways to select k things out of n
660
+ fn k_of_n ( k : u64 , n : u64 ) -> u64 {
661
+ if k == 0 || k == n {
662
+ return 1 ;
663
+ }
664
+ Self :: k_of_n ( k - 1 , n - 1 ) + Self :: k_of_n ( k - 1 , n)
665
+ }
666
+ }
667
+
549
668
impl < P , Q > TranslatePk < P , Q > for Descriptor < P >
550
669
where
551
670
P : MiniscriptKey ,
@@ -2041,4 +2160,75 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
2041
2160
Desc :: from_str ( & format ! ( "tr({},pk({}))" , x_only_key, uncomp_key) ) . unwrap_err ( ) ;
2042
2161
Desc :: from_str ( & format ! ( "tr({},pk({}))" , x_only_key, x_only_key) ) . unwrap ( ) ;
2043
2162
}
2163
+
2164
+ #[ test]
2165
+ fn test_all_assets_bare ( ) {
2166
+ let descriptor = Descriptor :: < DescriptorPublicKey > :: from_str (
2167
+ "pk(0237b1c59ab055a8d3de40eaeb215c7b1922664b5ac049d849fb3346f81431e77f)" ,
2168
+ )
2169
+ . unwrap ( ) ;
2170
+
2171
+ // Getting the assets from the all_assets method
2172
+ let assets = descriptor. all_assets ( ) . unwrap ( ) ;
2173
+
2174
+ let mut expected_asset = Assets :: new ( ) ;
2175
+ expected_asset = expected_asset. add (
2176
+ DescriptorPublicKey :: from_str (
2177
+ "0237b1c59ab055a8d3de40eaeb215c7b1922664b5ac049d849fb3346f81431e77f" ,
2178
+ )
2179
+ . unwrap ( ) ,
2180
+ ) ;
2181
+ assert_eq ! ( assets, vec![ expected_asset] ) ;
2182
+ }
2183
+
2184
+ #[ test]
2185
+ fn test_all_assets_sh_sortedmulti ( ) {
2186
+ let keys = vec ! [
2187
+ "0360eabc52e04f70c89e944f379895cdff28fed60849afe7736815c091765afb3c" ,
2188
+ "03a80a24196e66ccf6bca6e6f96633bb629ec702acd76b074de10922b0cf41cc81" ,
2189
+ ] ;
2190
+
2191
+ let descriptor = Descriptor :: < DescriptorPublicKey > :: from_str ( & format ! (
2192
+ "sh(sortedmulti(1,{},{}))" ,
2193
+ keys[ 0 ] , keys[ 1 ]
2194
+ ) )
2195
+ . unwrap ( ) ;
2196
+
2197
+ let assets = descriptor. all_assets ( ) . unwrap ( ) ;
2198
+
2199
+ let mut expected_assets: Vec < Assets > = Vec :: new ( ) ;
2200
+
2201
+ let mut asset1 = Assets :: new ( ) ;
2202
+ asset1 = asset1. add ( DescriptorPublicKey :: from_str ( keys[ 0 ] ) . unwrap ( ) ) ;
2203
+ expected_assets. push ( asset1) ;
2204
+
2205
+ let mut asset2 = Assets :: new ( ) ;
2206
+ asset2 = asset2. add ( DescriptorPublicKey :: from_str ( keys[ 1 ] ) . unwrap ( ) ) ;
2207
+ expected_assets. push ( asset2) ;
2208
+
2209
+ for expected_asset in & expected_assets {
2210
+ assert ! ( assets. contains( expected_asset) ) ;
2211
+ }
2212
+ }
2213
+
2214
+ #[ test]
2215
+ fn test_all_assets_taproot ( ) {
2216
+ let x_only_key = bitcoin:: key:: XOnlyPublicKey :: from_str (
2217
+ "015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab" ,
2218
+ )
2219
+ . unwrap ( ) ;
2220
+ let descriptor =
2221
+ Descriptor :: from_str ( & format ! ( "tr({},pk({}))" , x_only_key, x_only_key) ) . unwrap ( ) ;
2222
+ let assets = descriptor. all_assets ( ) . unwrap ( ) ;
2223
+ let mut expected_assets: Vec < Assets > = Vec :: new ( ) ;
2224
+ let mut asset_1 = Assets :: new ( ) ;
2225
+ asset_1 = asset_1. add (
2226
+ DescriptorPublicKey :: from_str (
2227
+ "015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab" ,
2228
+ )
2229
+ . unwrap ( ) ,
2230
+ ) ;
2231
+ expected_assets. push ( asset_1) ;
2232
+ assert_eq ! ( assets, expected_assets) ;
2233
+ }
2044
2234
}
0 commit comments