@@ -40,6 +40,7 @@ use crate::collections::{BTreeMap, HashSet, VecDeque};
40
40
use alloc:: string:: String ;
41
41
use alloc:: vec:: Vec ;
42
42
use core:: cmp:: max;
43
+ use miniscript:: miniscript:: limits:: { MAX_PUBKEYS_IN_CHECKSIGADD , MAX_PUBKEYS_PER_MULTISIG } ;
43
44
44
45
use core:: fmt;
45
46
@@ -53,7 +54,7 @@ use bitcoin::{absolute, key::XOnlyPublicKey, PublicKey, Sequence};
53
54
use miniscript:: descriptor:: {
54
55
DescriptorPublicKey , ShInner , SinglePub , SinglePubKey , SortedMultiVec , WshInner ,
55
56
} ;
56
- use miniscript:: hash256;
57
+ use miniscript:: { hash256, Threshold } ;
57
58
use miniscript:: {
58
59
Descriptor , Miniscript , Satisfier , ScriptContext , SigType , Terminal , ToPublicKey ,
59
60
} ;
@@ -586,30 +587,25 @@ impl Policy {
586
587
Ok ( Some ( policy) )
587
588
}
588
589
589
- fn make_multisig < Ctx : ScriptContext + ' static > (
590
- keys : & [ DescriptorPublicKey ] ,
590
+ fn make_multi < Ctx : ScriptContext + ' static > (
591
+ threshold : & Threshold < DescriptorPublicKey , MAX_PUBKEYS_PER_MULTISIG > ,
591
592
signers : & SignersContainer ,
592
593
build_sat : BuildSatisfaction ,
593
- threshold : usize ,
594
594
sorted : bool ,
595
595
secp : & SecpCtx ,
596
596
) -> Result < Option < Policy > , PolicyError > {
597
- if threshold == 0 {
598
- return Ok ( None ) ;
599
- }
600
-
601
- let parsed_keys = keys. iter ( ) . map ( |k| PkOrF :: from_key ( k, secp) ) . collect ( ) ;
597
+ let parsed_keys = threshold. iter ( ) . map ( |k| PkOrF :: from_key ( k, secp) ) . collect ( ) ;
602
598
603
599
let mut contribution = Satisfaction :: Partial {
604
- n : keys . len ( ) ,
605
- m : threshold,
600
+ n : threshold . n ( ) ,
601
+ m : threshold. k ( ) ,
606
602
items : vec ! [ ] ,
607
603
conditions : Default :: default ( ) ,
608
604
sorted : Some ( sorted) ,
609
605
} ;
610
606
let mut satisfaction = contribution. clone ( ) ;
611
607
612
- for ( index, key) in keys . iter ( ) . enumerate ( ) {
608
+ for ( index, key) in threshold . iter ( ) . enumerate ( ) {
613
609
if signers. find ( signer_id ( key, secp) ) . is_some ( ) {
614
610
contribution. add (
615
611
& Satisfaction :: Complete {
@@ -635,7 +631,7 @@ impl Policy {
635
631
636
632
let mut policy: Policy = SatisfiableItem :: Multisig {
637
633
keys : parsed_keys,
638
- threshold,
634
+ threshold : threshold . k ( ) ,
639
635
}
640
636
. into ( ) ;
641
637
policy. contribution = contribution;
@@ -644,6 +640,57 @@ impl Policy {
644
640
Ok ( Some ( policy) )
645
641
}
646
642
643
+ fn make_multi_a < Ctx : ScriptContext + ' static > (
644
+ threshold : & Threshold < DescriptorPublicKey , MAX_PUBKEYS_IN_CHECKSIGADD > ,
645
+ signers : & SignersContainer ,
646
+ build_sat : BuildSatisfaction ,
647
+ sorted : bool ,
648
+ secp : & SecpCtx ,
649
+ ) -> Result < Option < Policy > , PolicyError > {
650
+ let parsed_keys = threshold. iter ( ) . map ( |k| PkOrF :: from_key ( k, secp) ) . collect ( ) ;
651
+
652
+ let mut contribution = Satisfaction :: Partial {
653
+ n : threshold. n ( ) ,
654
+ m : threshold. k ( ) ,
655
+ items : vec ! [ ] ,
656
+ conditions : Default :: default ( ) ,
657
+ sorted : Some ( sorted) ,
658
+ } ;
659
+ let mut satisfaction = contribution. clone ( ) ;
660
+
661
+ for ( index, key) in threshold. iter ( ) . enumerate ( ) {
662
+ if signers. find ( signer_id ( key, secp) ) . is_some ( ) {
663
+ contribution. add (
664
+ & Satisfaction :: Complete {
665
+ condition : Default :: default ( ) ,
666
+ } ,
667
+ index,
668
+ ) ?;
669
+ }
670
+ if let Some ( psbt) = build_sat. psbt ( ) {
671
+ if Ctx :: find_signature ( psbt, key, secp) {
672
+ satisfaction. add (
673
+ & Satisfaction :: Complete {
674
+ condition : Default :: default ( ) ,
675
+ } ,
676
+ index,
677
+ ) ?;
678
+ }
679
+ }
680
+ }
681
+ satisfaction. finalize ( ) ;
682
+ contribution. finalize ( ) ;
683
+
684
+ let mut policy: Policy = SatisfiableItem :: Multisig {
685
+ keys : parsed_keys,
686
+ threshold : threshold. k ( ) ,
687
+ }
688
+ . into ( ) ;
689
+ policy. contribution = contribution;
690
+ policy. satisfaction = satisfaction;
691
+ Ok ( Some ( policy) )
692
+ }
693
+
647
694
/// Return whether or not a specific path in the policy tree is required to unambiguously
648
695
/// create a transaction
649
696
///
@@ -952,7 +999,10 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
952
999
Some ( policy)
953
1000
}
954
1001
Terminal :: Older ( value) => {
955
- let mut policy: Policy = SatisfiableItem :: RelativeTimelock { value : ( * value) . into ( ) } . into ( ) ;
1002
+ let mut policy: Policy = SatisfiableItem :: RelativeTimelock {
1003
+ value : ( * value) . into ( ) ,
1004
+ }
1005
+ . into ( ) ;
956
1006
policy. contribution = Satisfaction :: Complete {
957
1007
condition : Condition {
958
1008
timelock : None ,
@@ -966,9 +1016,11 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
966
1016
} = build_sat
967
1017
{
968
1018
let older = Older :: new ( Some ( current_height) , Some ( input_max_height) , false ) ;
969
- let older_sat = Satisfier :: < bitcoin:: PublicKey > :: check_older ( & older, ( * value) . into ( ) ) ;
970
- let inputs_sat = psbt_inputs_sat ( psbt)
971
- . all ( |sat| Satisfier :: < bitcoin:: PublicKey > :: check_older ( & sat, ( * value) . into ( ) ) ) ;
1019
+ let older_sat =
1020
+ Satisfier :: < bitcoin:: PublicKey > :: check_older ( & older, ( * value) . into ( ) ) ;
1021
+ let inputs_sat = psbt_inputs_sat ( psbt) . all ( |sat| {
1022
+ Satisfier :: < bitcoin:: PublicKey > :: check_older ( & sat, ( * value) . into ( ) )
1023
+ } ) ;
972
1024
if older_sat && inputs_sat {
973
1025
policy. satisfaction = policy. contribution . clone ( ) ;
974
1026
}
@@ -986,8 +1038,11 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
986
1038
Terminal :: Hash160 ( hash) => {
987
1039
Some ( SatisfiableItem :: Hash160Preimage { hash : * hash } . into ( ) )
988
1040
}
989
- Terminal :: Multi ( k, pks) | Terminal :: MultiA ( k, pks) => {
990
- Policy :: make_multisig :: < Ctx > ( pks, signers, build_sat, * k, false , secp) ?
1041
+ Terminal :: Multi ( threshold) => {
1042
+ Policy :: make_multi :: < Ctx > ( threshold, signers, build_sat, false , secp) ?
1043
+ }
1044
+ Terminal :: MultiA ( threshold) => {
1045
+ Policy :: make_multi_a :: < Ctx > ( threshold, signers, build_sat, false , secp) ?
991
1046
}
992
1047
// Identities
993
1048
Terminal :: Alt ( inner)
@@ -1016,8 +1071,9 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
1016
1071
a. extract_policy ( signers, build_sat, secp) ?,
1017
1072
b. extract_policy ( signers, build_sat, secp) ?,
1018
1073
) ?,
1019
- Terminal :: Thresh ( k, nodes) => {
1020
- let mut threshold = * k;
1074
+ Terminal :: Thresh ( threshold) => {
1075
+ let mut k = threshold. k ( ) ;
1076
+ let nodes = threshold. data ( ) ;
1021
1077
let mapped: Vec < _ > = nodes
1022
1078
. iter ( )
1023
1079
. map ( |n| n. extract_policy ( signers, build_sat, secp) )
@@ -1027,13 +1083,13 @@ impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublic
1027
1083
. collect ( ) ;
1028
1084
1029
1085
if mapped. len ( ) < nodes. len ( ) {
1030
- threshold = match threshold . checked_sub ( nodes. len ( ) - mapped. len ( ) ) {
1086
+ k = match k . checked_sub ( nodes. len ( ) - mapped. len ( ) ) {
1031
1087
None => return Ok ( None ) ,
1032
1088
Some ( x) => x,
1033
1089
} ;
1034
1090
}
1035
1091
1036
- Policy :: make_thresh ( mapped, threshold ) ?
1092
+ Policy :: make_thresh ( mapped, k ) ?
1037
1093
}
1038
1094
1039
1095
// Unsupported
@@ -1087,13 +1143,10 @@ impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
1087
1143
build_sat : BuildSatisfaction ,
1088
1144
secp : & SecpCtx ,
1089
1145
) -> Result < Option < Policy > , Error > {
1090
- Ok ( Policy :: make_multisig :: < Ctx > (
1091
- keys. pks . as_ref ( ) ,
1092
- signers,
1093
- build_sat,
1094
- keys. k ,
1095
- true ,
1096
- secp,
1146
+ let threshold = Threshold :: new ( keys. k ( ) , keys. pks ( ) . to_vec ( ) )
1147
+ . expect ( "valid threshold and pks collection" ) ;
1148
+ Ok ( Policy :: make_multi :: < Ctx > (
1149
+ & threshold, signers, build_sat, true , secp,
1097
1150
) ?)
1098
1151
}
1099
1152
0 commit comments