@@ -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,233 @@ 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 get_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. get_all_assets ( ) ,
651
+ Terminal :: Swap ( k) => k. get_all_assets ( ) ,
652
+ Terminal :: Check ( k) => k. get_all_assets ( ) ,
653
+ Terminal :: DupIf ( k) => k. get_all_assets ( ) ,
654
+ Terminal :: Verify ( k) => k. get_all_assets ( ) ,
655
+ Terminal :: NonZero ( k) => k. get_all_assets ( ) ,
656
+ Terminal :: ZeroNotEqual ( k) => k. get_all_assets ( ) ,
657
+ Terminal :: AndV ( left, right) => {
658
+ let a = left. get_all_assets ( ) ;
659
+ let b = right. get_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 :: AndB ( left, right) => {
674
+ let a = left. get_all_assets ( ) ;
675
+ let b = right. get_all_assets ( ) ;
676
+ let result: Vec < Assets > = a
677
+ . into_iter ( )
678
+ . flat_map ( |x| {
679
+ b. clone ( ) . into_iter ( ) . map ( move |y| {
680
+ let mut new_asset = Assets :: new ( ) ;
681
+ new_asset = new_asset. add ( x. clone ( ) ) ;
682
+ new_asset = new_asset. add ( y. clone ( ) ) ;
683
+ new_asset
684
+ } )
685
+ } )
686
+ . collect ( ) ;
687
+ result
688
+ }
689
+ Terminal :: AndOr ( a, b, c) => {
690
+ let a = a. get_all_assets ( ) ;
691
+ let b = b. get_all_assets ( ) ;
692
+ let mut c = c. get_all_assets ( ) ;
693
+ let and: Vec < Assets > = a
694
+ . into_iter ( )
695
+ . flat_map ( |x| {
696
+ b. clone ( ) . into_iter ( ) . map ( move |y| {
697
+ let mut new_asset = Assets :: new ( ) ;
698
+ new_asset = new_asset. add ( x. clone ( ) ) ;
699
+ new_asset = new_asset. add ( y. clone ( ) ) ;
700
+ new_asset
701
+ } )
702
+ } )
703
+ . collect ( ) ;
704
+ c. extend ( and) ;
705
+ c
706
+ }
707
+ Terminal :: OrB ( left, right) => {
708
+ let mut a = left. get_all_assets ( ) ;
709
+ let b = right. get_all_assets ( ) ;
710
+ a. extend ( b) ;
711
+ a
712
+ }
713
+ Terminal :: OrD ( left, right) => {
714
+ let mut a = left. get_all_assets ( ) ;
715
+ let b = right. get_all_assets ( ) ;
716
+ a. extend ( b) ;
717
+ a
718
+ }
719
+ Terminal :: OrC ( left, right) => {
720
+ let mut a = left. get_all_assets ( ) ;
721
+ let b = right. get_all_assets ( ) ;
722
+ a. extend ( b) ;
723
+ a
724
+ }
725
+ Terminal :: OrI ( left, right) => {
726
+ let mut a = left. get_all_assets ( ) ;
727
+ let b = right. get_all_assets ( ) ;
728
+ a. extend ( b) ;
729
+ a
730
+ }
731
+ Terminal :: Thresh ( k, ms) => {
732
+ let ms_v = Self :: get_ms_combination_thresh ( * k, ms) ;
733
+ // k = 2
734
+ // ms = [ms(A),ms(B),ms(C)];
735
+ // ms_v = [[ms(A),ms(B)],[ms(A),ms(C)],[ms(B),ms(C)]]
736
+ // Do ms_v[0] OR ms_v[1] OR ms_v[2]
737
+ // Also Do ms_v[0][0] AND ms_v[0][1] and so on in the inner for loop
738
+
739
+ let mut result = Vec :: new ( ) ;
740
+ for ms in ms_v {
741
+ let mut and: Vec < Assets > = Vec :: new ( ) ;
742
+ if let Some ( first_assets) = ms. first ( ) {
743
+ and = first_assets. get_all_assets ( ) . clone ( ) ;
744
+ }
745
+ for i in ms. iter ( ) . skip ( 1 ) {
746
+ let i_assets = i. get_all_assets ( ) ;
747
+ and = and
748
+ . iter ( )
749
+ . flat_map ( |x| {
750
+ i_assets. iter ( ) . map ( move |y| {
751
+ let mut new_asset = x. clone ( ) ;
752
+ new_asset = new_asset. add ( y. clone ( ) ) ;
753
+ new_asset
754
+ } )
755
+ } )
756
+ . collect ( ) ;
757
+ }
758
+ // OR of all combinations.
759
+ result. extend ( and. clone ( ) ) ;
760
+ }
761
+ result
762
+ }
763
+ Terminal :: Multi ( k, dpk_v) => Self :: get_asset_combination ( * k, dpk_v) ,
764
+ Terminal :: MultiA ( k, dpk_v) => Self :: get_asset_combination ( * k, dpk_v) ,
765
+ }
766
+ }
767
+
768
+ // Helper to get all possible pairs of K of N assets
769
+ fn get_asset_combination ( k : usize , dpk_v : & Vec < DescriptorPublicKey > ) -> Vec < Assets > {
770
+ let mut all_assets: Vec < Assets > = Vec :: new ( ) ;
771
+ let current_assets = Assets :: new ( ) ;
772
+ Self :: combine_assets ( k, dpk_v, 0 , current_assets, & mut all_assets) ;
773
+ all_assets
774
+ }
775
+
776
+ // Combine K of N assets
777
+ fn combine_assets (
778
+ k : usize ,
779
+ dpk_v : & [ DescriptorPublicKey ] ,
780
+ index : usize ,
781
+ current_assets : Assets ,
782
+ all_assets : & mut Vec < Assets > ,
783
+ ) {
784
+ if k == 0 {
785
+ all_assets. push ( current_assets) ;
786
+ return ;
787
+ }
788
+ if index >= dpk_v. len ( ) {
789
+ return ;
790
+ }
791
+ Self :: combine_assets ( k, dpk_v, index + 1 , current_assets. clone ( ) , all_assets) ;
792
+ let mut new_asset = current_assets;
793
+ new_asset = new_asset. add ( dpk_v[ index] . clone ( ) ) ;
794
+ println ! ( "{:#?}" , new_asset) ;
795
+ Self :: combine_assets ( k - 1 , dpk_v, index + 1 , new_asset, all_assets)
796
+ }
797
+
798
+ // Helper to get all combinations of K policies of N for thresh
799
+ fn get_ms_combination_thresh (
800
+ k : usize ,
801
+ ms : & Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > ,
802
+ ) -> Vec < Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > > {
803
+ let mut result = Vec :: new ( ) ;
804
+ let mut current_combination = Vec :: new ( ) ;
805
+ Self :: combine_ms ( 0 , & mut current_combination, & mut result, ms, k) ;
806
+ result
807
+ }
808
+
809
+ // combine K policies of N for thresh
810
+ fn combine_ms (
811
+ start : usize ,
812
+ current_combination : & mut Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > ,
813
+ result : & mut Vec < Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > > ,
814
+ ms : & Vec < Arc < Miniscript < DescriptorPublicKey , Ctx > > > ,
815
+ k : usize ,
816
+ ) {
817
+ if current_combination. len ( ) == k {
818
+ result. push ( current_combination. clone ( ) ) ;
819
+ return ;
820
+ }
821
+ for i in start..ms. len ( ) {
822
+ current_combination. push ( ms[ i] . clone ( ) ) ;
823
+ Self :: combine_ms ( i + 1 , current_combination, result, ms, k) ;
824
+ current_combination. truncate ( current_combination. len ( ) - 1 ) ;
825
+ }
826
+ }
827
+ }
0 commit comments