@@ -17,10 +17,12 @@ use sync::Arc;
17
17
use crate :: miniscript:: context:: SigType ;
18
18
use crate :: miniscript:: types:: { self , Property } ;
19
19
use crate :: miniscript:: ScriptContext ;
20
+ use crate :: plan:: Assets ;
20
21
use crate :: prelude:: * ;
21
22
use crate :: util:: MsKeyBuilder ;
22
23
use crate :: {
23
- errstr, expression, AbsLockTime , Error , Miniscript , MiniscriptKey , Terminal , ToPublicKey ,
24
+ errstr, expression, AbsLockTime , DescriptorPublicKey , Error , Miniscript , MiniscriptKey ,
25
+ Terminal , ToPublicKey ,
24
26
} ;
25
27
26
28
impl < Pk : MiniscriptKey , Ctx : ScriptContext > Terminal < Pk , Ctx > {
@@ -593,3 +595,212 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
593
595
}
594
596
}
595
597
}
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