@@ -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,210 @@ 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) | Terminal :: AndV ( left, right) => {
658+ let a = left. all_assets ( ) ;
659+ let b = right. all_assets ( ) ;
660+ let result: Vec < Assets > = a
661+ . into_iter ( )
662+ . flat_map ( |x| {
663+ b. clone ( ) . into_iter ( ) . map ( move |y| {
664+ let mut new_asset = Assets :: new ( ) ;
665+ new_asset = new_asset. add ( x. clone ( ) ) ;
666+ new_asset = new_asset. add ( y. clone ( ) ) ;
667+ new_asset
668+ } )
669+ } )
670+ . collect ( ) ;
671+ result
672+ }
673+ Terminal :: AndOr ( a, b, c) => {
674+ let a = a. all_assets ( ) ;
675+ let b = b. all_assets ( ) ;
676+ let mut c = c. all_assets ( ) ;
677+ let and: Vec < Assets > = a
678+ . into_iter ( )
679+ . flat_map ( |x| {
680+ b. clone ( ) . into_iter ( ) . map ( move |y| {
681+ let mut new_asset = Assets :: new ( ) ;
682+ new_asset = new_asset. add ( x. clone ( ) ) ;
683+ new_asset = new_asset. add ( y. clone ( ) ) ;
684+ new_asset
685+ } )
686+ } )
687+ . collect ( ) ;
688+ c. extend ( and) ;
689+ c
690+ }
691+ Terminal :: OrB ( left, right)
692+ | Terminal :: OrC ( left, right)
693+ | Terminal :: OrD ( left, right)
694+ | Terminal :: OrI ( left, right) => {
695+ let mut a = left. all_assets ( ) ;
696+ let b = right. all_assets ( ) ;
697+ a. extend ( b) ;
698+ a
699+ }
700+ Terminal :: Thresh ( k, ms) => {
701+ // In order to understand working of below code consider k of n as 2 of 3 thresh policy
702+ // Eg : thresh(2,ms(A),ms(B),ms(C)) Here ms(A),ms(B) and ms(C) are miniscript policies
703+ // k = 2
704+ // ms = [ms(A),ms(B),ms(C)];
705+ // We would consider the possible combinations of k policies into the ms_v
706+ // here k=2 so all possible combinations of 2.
707+ // ms_v = [[ms(A),ms(B)],[ms(A),ms(C)],[ms(B),ms(C)]]
708+ // Between each set of combination we would need to do an OR
709+ // (i.e ms_v[0] OR ms_v[1] OR ms_v[3])
710+ // Now inside of each policy combination we need to have AND
711+ // Eg : ms_v[0] = [ms(A),ms(B)] so here -> ms(A) AND ms(B)
712+
713+ let ms_v = Self :: get_ms_combination_thresh ( * k, ms) ;
714+ let mut result = Vec :: new ( ) ;
715+ for ms in ms_v {
716+ // AND between each miniscript policy
717+ let mut and: Vec < Assets > = Vec :: new ( ) ;
718+ if let Some ( first_assets) = ms. first ( ) {
719+ and = first_assets. all_assets ( ) . clone ( ) ;
720+ }
721+ for i in ms. iter ( ) . skip ( 1 ) {
722+ let i_assets = i. all_assets ( ) ;
723+ and = and
724+ . iter ( )
725+ . flat_map ( |x| {
726+ i_assets. iter ( ) . map ( move |y| {
727+ let mut new_asset = x. clone ( ) ;
728+ new_asset = new_asset. add ( y. clone ( ) ) ;
729+ new_asset
730+ } )
731+ } )
732+ . collect ( ) ;
733+ }
734+ // OR of possible combinations of k miniscript policies.
735+ result. extend ( and. clone ( ) ) ;
736+ }
737+ result
738+ }
739+ Terminal :: Multi ( k, dpk_v) | Terminal :: MultiA ( k, dpk_v) => {
740+ Self :: get_asset_combination ( * k, dpk_v)
741+ }
742+ }
743+ }
744+
745+ // Helper to get all possible pairs of K of N assets
746+ fn get_asset_combination ( k : usize , dpk_v : & Vec < DescriptorPublicKey > ) -> Vec < Assets > {
747+ let mut all_assets: Vec < Assets > = Vec :: new ( ) ;
748+ let current_assets = Assets :: new ( ) ;
749+ Self :: combine_assets ( k, dpk_v, 0 , current_assets, & mut all_assets) ;
750+ all_assets
751+ }
752+
753+ // Combine K of N assets
754+ fn combine_assets (
755+ k : usize ,
756+ dpk_v : & [ DescriptorPublicKey ] ,
757+ index : usize ,
758+ current_assets : Assets ,
759+ all_assets : & mut Vec < Assets > ,
760+ ) {
761+ if k == 0 {
762+ all_assets. push ( current_assets) ;
763+ return ;
764+ }
765+ if index >= dpk_v. len ( ) {
766+ return ;
767+ }
768+ Self :: combine_assets ( k, dpk_v, index + 1 , current_assets. clone ( ) , all_assets) ;
769+ let mut new_asset = current_assets;
770+ new_asset = new_asset. add ( dpk_v[ index] . clone ( ) ) ;
771+ println ! ( "{:#?}" , new_asset) ;
772+ Self :: combine_assets ( k - 1 , dpk_v, index + 1 , new_asset, all_assets)
773+ }
774+
775+ // Helper to get all combinations of K policies of N for thresh
776+ fn get_ms_combination_thresh (
777+ k : usize ,
778+ ms : & Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > ,
779+ ) -> Vec < Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > > {
780+ let mut result = Vec :: new ( ) ;
781+ let mut current_combination = Vec :: new ( ) ;
782+ Self :: combine_ms ( 0 , & mut current_combination, & mut result, ms, k) ;
783+ result
784+ }
785+
786+ // combine K policies of N for thresh
787+ fn combine_ms (
788+ start : usize ,
789+ current_combination : & mut Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > ,
790+ result : & mut Vec < Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > > ,
791+ ms : & Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > ,
792+ k : usize ,
793+ ) {
794+ if current_combination. len ( ) == k {
795+ result. push ( current_combination. clone ( ) ) ;
796+ return ;
797+ }
798+ for i in start..ms. len ( ) {
799+ current_combination. push ( ms[ i] . clone ( ) ) ;
800+ Self :: combine_ms ( i + 1 , current_combination, result, ms, k) ;
801+ current_combination. truncate ( current_combination. len ( ) - 1 ) ;
802+ }
803+ }
804+ }
0 commit comments