26
26
use std:: { collections:: HashMap , sync:: Arc } ;
27
27
use std:: {
28
28
fmt,
29
- marker:: PhantomData ,
30
29
str:: { self , FromStr } ,
31
30
} ;
32
31
33
- use bitcoin:: blockdata:: { opcodes, script} ;
34
32
use bitcoin:: secp256k1;
35
33
use bitcoin:: util:: bip32;
36
34
use bitcoin:: { self , Script } ;
37
35
38
36
use self :: checksum:: verify_checksum;
39
- use errstr;
40
37
use expression;
41
38
use miniscript;
42
- use miniscript:: context:: { ScriptContext , ScriptContextError } ;
43
- use miniscript:: { decode:: Terminal , Legacy , Miniscript , Segwitv0 } ;
44
- use policy;
45
- use push_opcode_size;
46
- use script_num_size;
47
- use util:: witness_to_scriptsig;
39
+ use miniscript:: { Legacy , Miniscript , Segwitv0 } ;
48
40
use BareCtx ;
49
41
use Error ;
50
42
use MiniscriptKey ;
@@ -54,14 +46,15 @@ use ToPublicKey;
54
46
mod bare;
55
47
mod segwitv0;
56
48
mod sh;
49
+ mod sortedmulti;
57
50
// Descriptor Exports
58
51
pub use self :: bare:: { Bare , Pkh } ;
59
52
pub use self :: segwitv0:: { Wpkh , Wsh } ;
60
53
pub use self :: sh:: Sh ;
54
+ pub use self :: sortedmulti:: SortedMultiVec ;
61
55
62
56
mod checksum;
63
57
mod key;
64
- use self :: checksum:: desc_checksum;
65
58
pub use self :: key:: {
66
59
DescriptorKeyParseError , DescriptorPublicKey , DescriptorPublicKeyCtx , DescriptorSecretKey ,
67
60
DescriptorSinglePriv , DescriptorSinglePub , DescriptorXKey ,
@@ -677,225 +670,13 @@ impl<Pk: MiniscriptKey> fmt::Display for Descriptor<Pk> {
677
670
}
678
671
}
679
672
680
- /// Contents of a "sortedmulti" descriptor
681
- #[ derive( Clone , PartialEq , Eq , PartialOrd , Ord ) ]
682
- pub struct SortedMultiVec < Pk : MiniscriptKey , Ctx : ScriptContext > {
683
- /// signatures required
684
- pub k : usize ,
685
- /// public keys inside sorted Multi
686
- pub pks : Vec < Pk > ,
687
- /// The current ScriptContext for sortedmulti
688
- pub ( crate ) phantom : PhantomData < Ctx > ,
689
- }
690
-
691
- impl < Pk : MiniscriptKey , Ctx : ScriptContext > SortedMultiVec < Pk , Ctx > {
692
- /// Create a new instance of `SortedMultiVec` given a list of keys and the threshold
693
- ///
694
- /// Internally checks all the applicable size limits and pubkey types limitations according to the current `Ctx`.
695
- pub fn new ( k : usize , pks : Vec < Pk > ) -> Result < Self , Error > {
696
- // A sortedmulti() is only defined for <= 20 keys (it maps to CHECKMULTISIG)
697
- if pks. len ( ) > 20 {
698
- Error :: BadDescriptor ( "Too many public keys" . to_string ( ) ) ;
699
- }
700
-
701
- // Check the limits before creating a new SortedMultiVec
702
- // For example, under p2sh context the scriptlen can only be
703
- // upto 520 bytes.
704
- let term: miniscript:: decode:: Terminal < Pk , Ctx > = Terminal :: Multi ( k, pks. clone ( ) ) ;
705
- let ms = Miniscript :: from_ast ( term) ?;
706
-
707
- // This would check all the consensus rules for p2sh/p2wsh and
708
- // even tapscript in future
709
- Ctx :: check_local_validity ( & ms) ?;
710
-
711
- Ok ( Self {
712
- k,
713
- pks,
714
- phantom : PhantomData ,
715
- } )
716
- }
717
- /// Parse an expression tree into a SortedMultiVec
718
- fn from_tree ( tree : & expression:: Tree ) -> Result < Self , Error >
719
- where
720
- <Pk as FromStr >:: Err : ToString ,
721
- {
722
- if tree. args . is_empty ( ) {
723
- return Err ( errstr ( "no arguments given for sortedmulti" ) ) ;
724
- }
725
- let k = expression:: parse_num ( tree. args [ 0 ] . name ) ?;
726
- if k > ( tree. args . len ( ) - 1 ) as u32 {
727
- return Err ( errstr (
728
- "higher threshold than there were keys in sortedmulti" ,
729
- ) ) ;
730
- }
731
- let pks: Result < Vec < Pk > , _ > = tree. args [ 1 ..]
732
- . iter ( )
733
- . map ( |sub| expression:: terminal ( sub, Pk :: from_str) )
734
- . collect ( ) ;
735
-
736
- pks. map ( |pks| SortedMultiVec :: new ( k as usize , pks) ) ?
737
- }
738
- }
739
-
740
- impl < Pk : MiniscriptKey , Ctx : ScriptContext > SortedMultiVec < Pk , Ctx > {
741
- /// This will panic if translatefpk returns an uncompressed key when
742
- /// converting to a Segwit descriptor. To prevent this panic, ensure
743
- /// translatefpk returns an error in this case instead.
744
- pub fn translate_pk < FPk , Q , FuncError > (
745
- & self ,
746
- translatefpk : & mut FPk ,
747
- ) -> Result < SortedMultiVec < Q , Ctx > , FuncError >
748
- where
749
- FPk : FnMut ( & Pk ) -> Result < Q , FuncError > ,
750
- Q : MiniscriptKey ,
751
- {
752
- let pks: Result < Vec < Q > , _ > = self . pks . iter ( ) . map ( & mut * translatefpk) . collect ( ) ;
753
- Ok ( SortedMultiVec {
754
- k : self . k ,
755
- pks : pks?,
756
- phantom : PhantomData ,
757
- } )
758
- }
759
- }
760
- impl < Pk : MiniscriptKey , Ctx : ScriptContext > SortedMultiVec < Pk , Ctx > {
761
- // utility function to sanity a sorted multi vec
762
- fn sanity_check ( & self ) -> Result < ( ) , Error > {
763
- let ms: Miniscript < Pk , Ctx > =
764
- Miniscript :: from_ast ( Terminal :: Multi ( self . k , self . pks . clone ( ) ) )
765
- . expect ( "Must typecheck" ) ;
766
- // '?' for doing From conversion
767
- ms. sanity_check ( ) ?;
768
- Ok ( ( ) )
769
- }
770
- }
771
-
772
- impl < Pk : MiniscriptKey , Ctx : ScriptContext > SortedMultiVec < Pk , Ctx > {
773
- /// Create Terminal::Multi containing sorted pubkeys
774
- pub fn sorted_node < ToPkCtx : Copy > ( & self , to_pk_ctx : ToPkCtx ) -> Terminal < Pk , Ctx >
775
- where
776
- Pk : ToPublicKey < ToPkCtx > ,
777
- {
778
- let mut pks = self . pks . clone ( ) ;
779
- // Sort pubkeys lexicographically according to BIP 67
780
- pks. sort_by ( |a, b| {
781
- a. to_public_key ( to_pk_ctx)
782
- . key
783
- . serialize ( )
784
- . partial_cmp ( & b. to_public_key ( to_pk_ctx) . key . serialize ( ) )
785
- . unwrap ( )
786
- } ) ;
787
- Terminal :: Multi ( self . k , pks)
788
- }
789
-
790
- /// Encode as a Bitcoin script
791
- pub fn encode < ToPkCtx : Copy > ( & self , to_pk_ctx : ToPkCtx ) -> script:: Script
792
- where
793
- Pk : ToPublicKey < ToPkCtx > ,
794
- {
795
- self . sorted_node ( to_pk_ctx)
796
- . encode ( script:: Builder :: new ( ) , to_pk_ctx)
797
- . into_script ( )
798
- }
799
-
800
- /// Attempt to produce a satisfying witness for the
801
- /// witness script represented by the parse tree
802
- pub fn satisfy < ToPkCtx , S > (
803
- & self ,
804
- satisfier : S ,
805
- to_pk_ctx : ToPkCtx ,
806
- ) -> Result < Vec < Vec < u8 > > , Error >
807
- where
808
- ToPkCtx : Copy ,
809
- Pk : ToPublicKey < ToPkCtx > ,
810
- S : Satisfier < ToPkCtx , Pk > ,
811
- {
812
- let ms = Miniscript :: from_ast ( self . sorted_node ( to_pk_ctx) ) . expect ( "Multi node typecheck" ) ;
813
- ms. satisfy ( satisfier, to_pk_ctx)
814
- }
815
-
816
- /// Size, in bytes of the script-pubkey. If this Miniscript is used outside
817
- /// of segwit (e.g. in a bare or P2SH descriptor), this quantity should be
818
- /// multiplied by 4 to compute the weight.
819
- ///
820
- /// In general, it is not recommended to use this function directly, but
821
- /// to instead call the corresponding function on a `Descriptor`, which
822
- /// will handle the segwit/non-segwit technicalities for you.
823
- pub fn script_size ( & self ) -> usize {
824
- script_num_size ( self . k )
825
- + 1
826
- + script_num_size ( self . pks . len ( ) )
827
- + self . pks . iter ( ) . map ( |pk| pk. serialized_len ( ) ) . sum :: < usize > ( )
828
- }
829
-
830
- /// Maximum number of witness elements used to satisfy the Miniscript
831
- /// fragment, including the witness script itself. Used to estimate
832
- /// the weight of the `VarInt` that specifies this number in a serialized
833
- /// transaction.
834
- ///
835
- /// This function may panic on malformed `Miniscript` objects which do
836
- /// not correspond to semantically sane Scripts. (Such scripts should be
837
- /// rejected at parse time. Any exceptions are bugs.)
838
- pub fn max_satisfaction_witness_elements ( & self ) -> usize {
839
- 2 + self . k
840
- }
841
-
842
- /// Maximum size, in bytes, of a satisfying witness. For Segwit outputs
843
- /// `one_cost` should be set to 2, since the number `1` requires two
844
- /// bytes to encode. For non-segwit outputs `one_cost` should be set to
845
- /// 1, since `OP_1` is available in scriptSigs.
846
- ///
847
- /// In general, it is not recommended to use this function directly, but
848
- /// to instead call the corresponding function on a `Descriptor`, which
849
- /// will handle the segwit/non-segwit technicalities for you.
850
- ///
851
- /// All signatures are assumed to be 73 bytes in size, including the
852
- /// length prefix (segwit) or push opcode (pre-segwit) and sighash
853
- /// postfix.
854
- ///
855
- /// This function may panic on malformed `Miniscript` objects which do not
856
- /// correspond to semantically sane Scripts. (Such scripts should be
857
- /// rejected at parse time. Any exceptions are bugs.)
858
- pub fn max_satisfaction_size ( & self , _: usize ) -> usize {
859
- 1 + 73 * self . k
860
- }
861
- }
862
-
863
- impl < Pk : MiniscriptKey , Ctx : ScriptContext > policy:: Liftable < Pk > for SortedMultiVec < Pk , Ctx > {
864
- fn lift ( & self ) -> Result < policy:: semantic:: Policy < Pk > , Error > {
865
- let ret = policy:: semantic:: Policy :: Threshold (
866
- self . k ,
867
- self . pks
868
- . clone ( )
869
- . into_iter ( )
870
- . map ( |k| policy:: semantic:: Policy :: KeyHash ( k. to_pubkeyhash ( ) ) )
871
- . collect ( ) ,
872
- ) ;
873
- Ok ( ret)
874
- }
875
- }
876
-
877
- impl < Pk : MiniscriptKey , Ctx : ScriptContext > fmt:: Debug for SortedMultiVec < Pk , Ctx > {
878
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
879
- fmt:: Display :: fmt ( self , f)
880
- }
881
- }
882
-
883
- impl < Pk : MiniscriptKey , Ctx : ScriptContext > fmt:: Display for SortedMultiVec < Pk , Ctx > {
884
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
885
- write ! ( f, "sortedmulti({}" , self . k) ?;
886
- for k in & self . pks {
887
- write ! ( f, ",{}" , k) ?;
888
- }
889
- f. write_str ( ")" )
890
- }
891
- }
892
-
893
673
serde_string_impl_pk ! ( Descriptor , "a script descriptor" ) ;
894
674
895
675
#[ cfg( test) ]
896
676
mod tests {
677
+ use super :: checksum:: desc_checksum;
678
+ use super :: DescriptorPublicKeyCtx ;
897
679
use super :: DescriptorTrait ;
898
- use super :: { desc_checksum, DescriptorPublicKeyCtx } ;
899
680
use bitcoin:: blockdata:: opcodes:: all:: { OP_CLTV , OP_CSV } ;
900
681
use bitcoin:: blockdata:: script:: Instruction ;
901
682
use bitcoin:: blockdata:: { opcodes, script} ;
0 commit comments