@@ -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,210 @@ 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) | 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