@@ -17,10 +17,12 @@ use sync::Arc;
1717use crate :: miniscript:: context:: SigType ;
1818use crate :: miniscript:: types:: { self , Property } ;
1919use crate :: miniscript:: ScriptContext ;
20+ use crate :: plan:: Assets ;
2021use crate :: prelude:: * ;
2122use crate :: util:: MsKeyBuilder ;
2223use crate :: {
23- errstr, expression, AbsLockTime , Error , Miniscript , MiniscriptKey , Terminal , ToPublicKey ,
24+ errstr, expression, AbsLockTime , DescriptorPublicKey , Error , Miniscript , MiniscriptKey ,
25+ Terminal , ToPublicKey ,
2426} ;
2527
2628impl < Pk : MiniscriptKey , Ctx : ScriptContext > Terminal < Pk , Ctx > {
@@ -593,3 +595,212 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
593595 }
594596 }
595597}
598+
599+ impl < Ctx : ScriptContext > Terminal < DescriptorPublicKey , Ctx > {
600+ /// Retrieve the assets associated with the type of miniscript element.
601+ pub fn all_assets ( & self ) -> Vec < Assets > {
602+ match self {
603+ Terminal :: True => vec ! [ Assets :: new( ) ] ,
604+ Terminal :: False => Vec :: new ( ) ,
605+ Terminal :: PkK ( k) => {
606+ let mut asset = Assets :: new ( ) ;
607+ asset = asset. add ( k. clone ( ) ) ;
608+ vec ! [ asset]
609+ }
610+ Terminal :: PkH ( k) => {
611+ let mut asset = Assets :: new ( ) ;
612+ asset = asset. add ( k. clone ( ) ) ;
613+ vec ! [ asset]
614+ }
615+ Terminal :: RawPkH ( k) => {
616+ let mut asset = Assets :: new ( ) ;
617+ asset = asset. add ( k. clone ( ) ) ;
618+ vec ! [ asset]
619+ }
620+ Terminal :: After ( k) => {
621+ let mut asset = Assets :: new ( ) ;
622+ asset. absolute_timelock = Some ( k. clone ( ) . into ( ) ) ;
623+ vec ! [ asset]
624+ }
625+ Terminal :: Older ( k) => {
626+ let mut asset = Assets :: new ( ) ;
627+ asset. relative_timelock = Some ( k. clone ( ) ) ;
628+ vec ! [ asset]
629+ }
630+ Terminal :: Sha256 ( k) => {
631+ let mut asset = Assets :: new ( ) ;
632+ asset = asset. add ( k. clone ( ) ) ;
633+ vec ! [ asset]
634+ }
635+ Terminal :: Hash256 ( k) => {
636+ let mut asset = Assets :: new ( ) ;
637+ asset = asset. add ( k. clone ( ) ) ;
638+ vec ! [ asset]
639+ }
640+ Terminal :: Ripemd160 ( k) => {
641+ let mut asset = Assets :: new ( ) ;
642+ asset = asset. add ( k. clone ( ) ) ;
643+ vec ! [ asset]
644+ }
645+ Terminal :: Hash160 ( k) => {
646+ let mut asset = Assets :: new ( ) ;
647+ asset = asset. add ( k. clone ( ) ) ;
648+ vec ! [ asset]
649+ }
650+ Terminal :: Alt ( k) => k. all_assets ( ) ,
651+ Terminal :: Swap ( k) => k. all_assets ( ) ,
652+ Terminal :: Check ( k) => k. all_assets ( ) ,
653+ Terminal :: DupIf ( k) => k. all_assets ( ) ,
654+ Terminal :: Verify ( k) => k. all_assets ( ) ,
655+ Terminal :: NonZero ( k) => k. all_assets ( ) ,
656+ Terminal :: ZeroNotEqual ( k) => k. all_assets ( ) ,
657+ Terminal :: AndB ( left, right) |
658+ Terminal :: AndV ( left, right)
659+ => {
660+ let a = left. all_assets ( ) ;
661+ let b = right. all_assets ( ) ;
662+ let result: Vec < Assets > = a
663+ . into_iter ( )
664+ . flat_map ( |x| {
665+ b. clone ( ) . into_iter ( ) . map ( move |y| {
666+ let mut new_asset = Assets :: new ( ) ;
667+ new_asset = new_asset. add ( x. clone ( ) ) ;
668+ new_asset = new_asset. add ( y. clone ( ) ) ;
669+ new_asset
670+ } )
671+ } )
672+ . collect ( ) ;
673+ result
674+ }
675+ Terminal :: AndOr ( a, b, c) => {
676+ let a = a. all_assets ( ) ;
677+ let b = b. all_assets ( ) ;
678+ let mut c = c. all_assets ( ) ;
679+ let and: Vec < Assets > = a
680+ . into_iter ( )
681+ . flat_map ( |x| {
682+ b. clone ( ) . into_iter ( ) . map ( move |y| {
683+ let mut new_asset = Assets :: new ( ) ;
684+ new_asset = new_asset. add ( x. clone ( ) ) ;
685+ new_asset = new_asset. add ( y. clone ( ) ) ;
686+ new_asset
687+ } )
688+ } )
689+ . collect ( ) ;
690+ c. extend ( and) ;
691+ c
692+ }
693+ Terminal :: OrB ( left, right) |
694+ Terminal :: OrC ( left, right) |
695+ Terminal :: OrD ( left, right) |
696+ Terminal :: OrI ( left, right)
697+ => {
698+ let mut a = left. all_assets ( ) ;
699+ let b = right. all_assets ( ) ;
700+ a. extend ( b) ;
701+ a
702+ }
703+ Terminal :: Thresh ( k, ms) => {
704+ // In order to understand working of below code consider k of n as 2 of 3 thresh policy
705+ // Eg : thresh(2,ms(A),ms(B),ms(C)) Here ms(A),ms(B) and ms(C) are miniscript policies
706+ // k = 2
707+ // ms = [ms(A),ms(B),ms(C)];
708+ // We would consider the possible combinations of k policies into the ms_v
709+ // here k=2 so all possible combinations of 2.
710+ // ms_v = [[ms(A),ms(B)],[ms(A),ms(C)],[ms(B),ms(C)]]
711+ // Between each set of combination we would need to do an OR
712+ // (i.e ms_v[0] OR ms_v[1] OR ms_v[3])
713+ // Now inside of each policy combination we need to have AND
714+ // Eg : ms_v[0] = [ms(A),ms(B)] so here -> ms(A) AND ms(B)
715+
716+ let ms_v = Self :: get_ms_combination_thresh ( * k, ms) ;
717+ let mut result = Vec :: new ( ) ;
718+ for ms in ms_v {
719+ // AND between each miniscript policy
720+ let mut and: Vec < Assets > = Vec :: new ( ) ;
721+ if let Some ( first_assets) = ms. first ( ) {
722+ and = first_assets. all_assets ( ) . clone ( ) ;
723+ }
724+ for i in ms. iter ( ) . skip ( 1 ) {
725+ let i_assets = i. all_assets ( ) ;
726+ and = and
727+ . iter ( )
728+ . flat_map ( |x| {
729+ i_assets. iter ( ) . map ( move |y| {
730+ let mut new_asset = x. clone ( ) ;
731+ new_asset = new_asset. add ( y. clone ( ) ) ;
732+ new_asset
733+ } )
734+ } )
735+ . collect ( ) ;
736+ }
737+ // OR of possible combinations of k miniscript policies.
738+ result. extend ( and. clone ( ) ) ;
739+ }
740+ result
741+ }
742+ Terminal :: Multi ( k, dpk_v) |
743+ Terminal :: MultiA ( k, dpk_v ) => Self :: get_asset_combination ( * k, dpk_v) ,
744+ }
745+ }
746+
747+ // Helper to get all possible pairs of K of N assets
748+ fn get_asset_combination ( k : usize , dpk_v : & Vec < DescriptorPublicKey > ) -> Vec < Assets > {
749+ let mut all_assets: Vec < Assets > = Vec :: new ( ) ;
750+ let current_assets = Assets :: new ( ) ;
751+ Self :: combine_assets ( k, dpk_v, 0 , current_assets, & mut all_assets) ;
752+ all_assets
753+ }
754+
755+ // Combine K of N assets
756+ fn combine_assets (
757+ k : usize ,
758+ dpk_v : & [ DescriptorPublicKey ] ,
759+ index : usize ,
760+ current_assets : Assets ,
761+ all_assets : & mut Vec < Assets > ,
762+ ) {
763+ if k == 0 {
764+ all_assets. push ( current_assets) ;
765+ return ;
766+ }
767+ if index >= dpk_v. len ( ) {
768+ return ;
769+ }
770+ Self :: combine_assets ( k, dpk_v, index + 1 , current_assets. clone ( ) , all_assets) ;
771+ let mut new_asset = current_assets;
772+ new_asset = new_asset. add ( dpk_v[ index] . clone ( ) ) ;
773+ println ! ( "{:#?}" , new_asset) ;
774+ Self :: combine_assets ( k - 1 , dpk_v, index + 1 , new_asset, all_assets)
775+ }
776+
777+ // Helper to get all combinations of K policies of N for thresh
778+ fn get_ms_combination_thresh (
779+ k : usize ,
780+ ms : & Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > ,
781+ ) -> Vec < Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > > {
782+ let mut result = Vec :: new ( ) ;
783+ let mut current_combination = Vec :: new ( ) ;
784+ Self :: combine_ms ( 0 , & mut current_combination, & mut result, ms, k) ;
785+ result
786+ }
787+
788+ // combine K policies of N for thresh
789+ fn combine_ms (
790+ start : usize ,
791+ current_combination : & mut Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > ,
792+ result : & mut Vec < Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > > ,
793+ ms : & Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > ,
794+ k : usize ,
795+ ) {
796+ if current_combination. len ( ) == k {
797+ result. push ( current_combination. clone ( ) ) ;
798+ return ;
799+ }
800+ for i in start..ms. len ( ) {
801+ current_combination. push ( ms[ i] . clone ( ) ) ;
802+ Self :: combine_ms ( i + 1 , current_combination, result, ms, k) ;
803+ current_combination. truncate ( current_combination. len ( ) - 1 ) ;
804+ }
805+ }
806+ }
0 commit comments