@@ -23,8 +23,9 @@ use sync::Arc;
2323use self :: checksum:: verify_checksum;
2424use crate :: miniscript:: decode:: Terminal ;
2525use crate :: miniscript:: { satisfy, Legacy , Miniscript , Segwitv0 } ;
26- use crate :: plan:: { AssetProvider , Plan } ;
26+ use crate :: plan:: { AssetProvider , Assets , Plan } ;
2727use crate :: prelude:: * ;
28+ use crate :: util:: get_asset_combination;
2829use crate :: {
2930 expression, hash256, BareCtx , Error , ForEachKey , MiniscriptKey , Satisfier , ToPublicKey ,
3031 TranslateErr , TranslatePk , Translator ,
@@ -546,6 +547,124 @@ impl Descriptor<DefiniteDescriptorKey> {
546547 }
547548}
548549
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+
549668impl < P , Q > TranslatePk < P , Q > for Descriptor < P >
550669where
551670 P : MiniscriptKey ,
@@ -2041,4 +2160,75 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
20412160 Desc :: from_str ( & format ! ( "tr({},pk({}))" , x_only_key, uncomp_key) ) . unwrap_err ( ) ;
20422161 Desc :: from_str ( & format ! ( "tr({},pk({}))" , x_only_key, x_only_key) ) . unwrap ( ) ;
20432162 }
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+ }
20442234}
0 commit comments