@@ -122,6 +122,7 @@ use std::cmp::Ordering;
122
122
use std:: collections:: { BTreeMap , HashMap , HashSet } ;
123
123
use std:: convert:: { From , TryFrom , TryInto } ;
124
124
use std:: hash:: { Hash , Hasher } ;
125
+ use strum:: { Display , EnumDiscriminants } ;
125
126
126
127
/// The quantity of stake held by a party, represented as a `u64`.
127
128
pub type Stake = u64 ;
@@ -641,7 +642,7 @@ pub struct StmClerk<D: Clone + Digest> {
641
642
pub ( crate ) params : StmParameters ,
642
643
}
643
644
644
- impl < D : Digest + Clone + FixedOutput > StmClerk < D > {
645
+ impl < D : Digest + Clone + FixedOutput + Send + Sync > StmClerk < D > {
645
646
/// Create a new `Clerk` from a closed registration instance.
646
647
pub fn from_registration ( params : & StmParameters , closed_reg : & ClosedKeyReg < D > ) -> Self {
647
648
Self {
@@ -700,10 +701,12 @@ impl<D: Digest + Clone + FixedOutput> StmClerk<D> {
700
701
701
702
let batch_proof = self . closed_reg . merkle_tree . get_batched_path ( mt_index_list) ;
702
703
703
- Ok ( StmAggrSig {
704
- signatures : unique_sigs,
705
- batch_proof,
706
- } )
704
+ Ok ( StmAggrSig :: StmAggrSigConcatenation (
705
+ StmAggrSigConcatenationProof {
706
+ signatures : unique_sigs,
707
+ batch_proof,
708
+ } ,
709
+ ) )
707
710
}
708
711
709
712
/// Compute the `StmAggrVerificationKey` related to the used registration.
@@ -720,21 +723,139 @@ impl<D: Digest + Clone + FixedOutput> StmClerk<D> {
720
723
}
721
724
}
722
725
723
- /// `StmMultiSig` uses the "concatenation" proving system (as described in Section 4.3 of the original paper.)
726
+ /// A STM aggregate signature.
727
+ #[ derive( Debug , Clone , Serialize , Deserialize , EnumDiscriminants ) ]
728
+ #[ strum( serialize_all = "PascalCase" ) ]
729
+ #[ strum_discriminants( derive( Serialize , Hash , Display ) ) ]
730
+ #[ strum_discriminants( name( StmAggrSigType ) ) ]
731
+ #[ serde( bound(
732
+ serialize = "BatchPath<D>: Serialize" ,
733
+ deserialize = "BatchPath<D>: Deserialize<'de>"
734
+ ) ) ]
735
+ #[ serde( untagged) ]
736
+ pub enum StmAggrSig < D : Clone + Digest + FixedOutput + Send + Sync > {
737
+ /// STM aggregate signature with concatenation proving system.
738
+ StmAggrSigConcatenation ( StmAggrSigConcatenationProof < D > ) ,
739
+ }
740
+
741
+ impl < D : Clone + Digest + FixedOutput + Send + Sync > StmAggrSig < D > {
742
+ /// Verify aggregate signature, by checking that
743
+ /// * each signature contains only valid indices,
744
+ /// * the lottery is indeed won by each one of them,
745
+ /// * the merkle tree path is valid,
746
+ /// * the aggregate signature validates with respect to the aggregate verification key
747
+ /// (aggregation is computed using functions `MSP.BKey` and `MSP.BSig` as described in Section 2.4 of the paper).
748
+ pub fn verify (
749
+ & self ,
750
+ msg : & [ u8 ] ,
751
+ avk : & StmAggrVerificationKey < D > ,
752
+ parameters : & StmParameters ,
753
+ ) -> Result < ( ) , StmAggregateSignatureError < D > > {
754
+ match self {
755
+ StmAggrSig :: StmAggrSigConcatenation ( stm_aggr_sig) => {
756
+ stm_aggr_sig. verify ( msg, avk, parameters)
757
+ }
758
+ }
759
+ }
760
+
761
+ /// Batch verify a set of signatures, with different messages and avks.
762
+ #[ cfg( feature = "batch-verify-aggregates" ) ]
763
+ pub fn batch_verify (
764
+ stm_signatures : & [ Self ] ,
765
+ msgs : & [ Vec < u8 > ] ,
766
+ avks : & [ StmAggrVerificationKey < D > ] ,
767
+ parameters : & [ StmParameters ] ,
768
+ ) -> Result < ( ) , StmAggregateSignatureError < D > > {
769
+ let stm_signatures: HashMap < StmAggrSigType , Vec < Self > > =
770
+ stm_signatures. iter ( ) . fold ( HashMap :: new ( ) , |mut acc, sig| {
771
+ acc. entry ( sig. into ( ) ) . or_default ( ) . push ( sig. clone ( ) ) ;
772
+ acc
773
+ } ) ;
774
+ stm_signatures
775
+ . into_iter ( )
776
+ . try_for_each (
777
+ |( stm_aggr_sig_type, stm_aggr_sigs) | match stm_aggr_sig_type {
778
+ StmAggrSigType :: StmAggrSigConcatenation => {
779
+ StmAggrSigConcatenationProof :: batch_verify (
780
+ & stm_aggr_sigs
781
+ . into_iter ( )
782
+ . filter_map ( |s| match s {
783
+ Self :: StmAggrSigConcatenation ( stm_aggr_sig) => {
784
+ Some ( stm_aggr_sig)
785
+ }
786
+ _ => None ,
787
+ } )
788
+ . collect :: < Vec < _ > > ( ) ,
789
+ msgs,
790
+ avks,
791
+ parameters,
792
+ )
793
+ }
794
+ } ,
795
+ )
796
+ . map_err ( |_| StmAggregateSignatureError :: BatchInvalid )
797
+ }
798
+
799
+ /// Convert multi signature to bytes
800
+ /// # Layout
801
+ /// * Number of the pairs of Signatures and Registered Parties (SigRegParty) (as u64)
802
+ /// * Size of a pair of Signature and Registered Party
803
+ /// * Pairs of Signatures and Registered Parties
804
+ /// * Batch proof
805
+ pub fn to_bytes ( & self ) -> Vec < u8 > {
806
+ match self {
807
+ StmAggrSig :: StmAggrSigConcatenation ( stm_aggr_sig) => stm_aggr_sig. to_bytes ( ) ,
808
+ }
809
+ }
810
+
811
+ ///Extract a `StmAggrSig` from a byte slice.
812
+ pub fn from_bytes ( bytes : & [ u8 ] ) -> Result < Self , StmAggregateSignatureError < D > > {
813
+ // TODO: How to properly support multiple variants?
814
+ Ok ( Self :: StmAggrSigConcatenation (
815
+ StmAggrSigConcatenationProof :: from_bytes ( bytes) ?,
816
+ ) )
817
+ }
818
+
819
+ /// Extract the list of signatures.
820
+ pub fn signatures ( & self ) -> Vec < StmSigRegParty > {
821
+ match self {
822
+ StmAggrSig :: StmAggrSigConcatenation ( stm_aggr_sig) => stm_aggr_sig. signatures . clone ( ) ,
823
+ }
824
+ }
825
+
826
+ /// Extract the list of unique merkle tree nodes that covers path for all signatures.
827
+ pub fn batch_proof ( & self ) -> BatchPath < D > {
828
+ match self {
829
+ StmAggrSig :: StmAggrSigConcatenation ( stm_aggr_sig) => stm_aggr_sig. batch_proof . clone ( ) ,
830
+ }
831
+ }
832
+
833
+ /// Extract the list of unique merkle tree nodes that covers path for all signatures. (test only)
834
+ #[ cfg( test) ]
835
+ pub ( crate ) fn set_batch_proof ( & mut self , batch_proof : BatchPath < D > ) {
836
+ match self {
837
+ StmAggrSig :: StmAggrSigConcatenation ( ref mut stm_aggr_sig) => {
838
+ stm_aggr_sig. batch_proof = batch_proof
839
+ }
840
+ }
841
+ }
842
+ }
843
+
844
+ /// `StmAggrSigConcatenationProof` uses the "concatenation" proving system (as described in Section 4.3 of the original paper.)
724
845
/// This means that the aggregated signature contains a vector with all individual signatures.
725
846
/// BatchPath is also a part of the aggregate signature which covers path for all signatures.
726
847
#[ derive( Debug , Clone , Serialize , Deserialize ) ]
727
848
#[ serde( bound(
728
849
serialize = "BatchPath<D>: Serialize" ,
729
850
deserialize = "BatchPath<D>: Deserialize<'de>"
730
851
) ) ]
731
- pub struct StmAggrSig < D : Clone + Digest + FixedOutput > {
852
+ pub struct StmAggrSigConcatenationProof < D : Clone + Digest + FixedOutput > {
732
853
pub ( crate ) signatures : Vec < StmSigRegParty > ,
733
854
/// The list of unique merkle tree nodes that covers path for all signatures.
734
855
pub batch_proof : BatchPath < D > ,
735
856
}
736
857
737
- impl < D : Clone + Digest + FixedOutput + Send + Sync > StmAggrSig < D > {
858
+ impl < D : Clone + Digest + FixedOutput + Send + Sync > StmAggrSigConcatenationProof < D > {
738
859
/// Verify all checks from signatures, except for the signature verification itself.
739
860
///
740
861
/// Indices and quorum are checked by `CoreVerifier::preliminary_verify` with `msgp`.
@@ -859,7 +980,9 @@ impl<D: Clone + Digest + FixedOutput + Send + Sync> StmAggrSig<D> {
859
980
}
860
981
861
982
///Extract a `StmAggrSig` from a byte slice.
862
- pub fn from_bytes ( bytes : & [ u8 ] ) -> Result < StmAggrSig < D > , StmAggregateSignatureError < D > > {
983
+ pub fn from_bytes (
984
+ bytes : & [ u8 ] ,
985
+ ) -> Result < StmAggrSigConcatenationProof < D > , StmAggregateSignatureError < D > > {
863
986
let mut u64_bytes = [ 0u8 ; 8 ] ;
864
987
865
988
u64_bytes. copy_from_slice ( & bytes[ ..8 ] ) ;
@@ -881,7 +1004,7 @@ impl<D: Clone + Digest + FixedOutput + Send + Sync> StmAggrSig<D> {
881
1004
let offset = 16 + sig_reg_size * size;
882
1005
let batch_proof = BatchPath :: from_bytes ( & bytes[ offset..] ) ?;
883
1006
884
- Ok ( StmAggrSig {
1007
+ Ok ( StmAggrSigConcatenationProof {
885
1008
signatures : sig_reg_list,
886
1009
batch_proof,
887
1010
} )
@@ -1526,7 +1649,7 @@ mod tests {
1526
1649
#[ test]
1527
1650
fn test_invalid_proof_index_unique( tc in arb_proof_setup( 10 ) ) {
1528
1651
with_proof_mod( tc, |aggr, clerk, _msg| {
1529
- for sig_reg in aggr. signatures. iter_mut( ) {
1652
+ for sig_reg in aggr. signatures( ) . iter_mut( ) {
1530
1653
for index in sig_reg. sig. indexes. iter_mut( ) {
1531
1654
* index %= clerk. params. k - 1
1532
1655
}
@@ -1536,7 +1659,7 @@ mod tests {
1536
1659
#[ test]
1537
1660
fn test_invalid_proof_path( tc in arb_proof_setup( 10 ) ) {
1538
1661
with_proof_mod( tc, |aggr, _, _msg| {
1539
- let p = aggr. batch_proof. clone( ) ;
1662
+ let p = aggr. batch_proof( ) . clone( ) ;
1540
1663
let mut index_list = p. indices. clone( ) ;
1541
1664
let values = p. values;
1542
1665
let batch_proof = {
@@ -1547,7 +1670,7 @@ mod tests {
1547
1670
hasher: Default :: default ( )
1548
1671
}
1549
1672
} ;
1550
- aggr. batch_proof = batch_proof ;
1673
+ aggr. set_batch_proof ( batch_proof) ;
1551
1674
} )
1552
1675
}
1553
1676
}
0 commit comments