1
1
use std:: collections:: HashMap ;
2
+ use std:: fmt:: Display ;
2
3
use std:: hash:: Hash ;
3
4
4
5
use blake2:: digest:: { Digest , FixedOutput } ;
5
6
use serde:: { Deserialize , Serialize } ;
6
- use strum:: { Display , EnumDiscriminants } ;
7
7
8
8
use crate :: error:: StmAggregateSignatureError ;
9
9
use crate :: merkle_tree:: MerkleBatchPath ;
10
10
use crate :: { AggregateVerificationKey , Parameters , SingleSignatureWithRegisteredParty } ;
11
11
12
12
use super :: ConcatenationProof ;
13
13
14
- /// A STM aggregate signature.
15
- #[ derive( Debug , Clone , Serialize , Deserialize , EnumDiscriminants ) ]
16
- #[ strum( serialize_all = "PascalCase" ) ]
17
- #[ strum_discriminants( derive( Serialize , Hash , Display ) ) ] // TODO: replace strum with custom implementation
18
- #[ strum_discriminants( name( AggregateSignatureType ) ) ]
14
+ /// The type of STM aggregate signature.
15
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
16
+ pub enum AggregateSignatureType {
17
+ /// Concatenation proof system.
18
+ Concatenation ,
19
+ }
20
+
21
+ impl AggregateSignatureType {
22
+ /// The prefix byte used in the byte representation of the aggregate signature type.
23
+ ///
24
+ /// IMPORTANT: This value is used in serialization/deserialization. Changing it will break compatibility.
25
+ pub fn to_bytes_encoding_prefix ( & self ) -> u8 {
26
+ match self {
27
+ AggregateSignatureType :: Concatenation => 0 ,
28
+ }
29
+ }
30
+
31
+ /// Create an aggregate signature type from a prefix byte.
32
+ ///
33
+ /// IMPORTANT: This value is used in serialization/deserialization. Changing it will break compatibility.
34
+ pub fn from_bytes_encoding_prefix ( byte : u8 ) -> Option < Self > {
35
+ match byte {
36
+ 0 => Some ( AggregateSignatureType :: Concatenation ) ,
37
+ _ => None ,
38
+ }
39
+ }
40
+ }
41
+
42
+ impl < D : Clone + Digest + FixedOutput + Send + Sync > From < & AggregateSignature < D > >
43
+ for AggregateSignatureType
44
+ {
45
+ fn from ( aggr_sig : & AggregateSignature < D > ) -> Self {
46
+ match aggr_sig {
47
+ AggregateSignature :: Concatenation ( _) => AggregateSignatureType :: Concatenation ,
48
+ }
49
+ }
50
+ }
51
+
52
+ impl Display for AggregateSignatureType {
53
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
54
+ match self {
55
+ AggregateSignatureType :: Concatenation => write ! ( f, "Concatenation" ) ,
56
+ }
57
+ }
58
+ }
59
+
60
+ /// An STM aggregate signature.
61
+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
19
62
#[ serde( bound(
20
63
serialize = "MerkleBatchPath<D>: Serialize" ,
21
64
deserialize = "MerkleBatchPath<D>: Deserialize<'de>"
@@ -75,18 +118,36 @@ impl<D: Clone + Digest + FixedOutput + Send + Sync> AggregateSignature<D> {
75
118
76
119
/// Convert an aggregate signature to bytes
77
120
pub fn to_bytes ( & self ) -> Vec < u8 > {
78
- match self {
79
- AggregateSignature :: Concatenation ( stm_aggr_sig) => stm_aggr_sig. to_bytes ( ) ,
80
- }
121
+ let mut aggregate_signature_bytes = Vec :: new ( ) ;
122
+ let aggregate_signature_type: AggregateSignatureType = self . into ( ) ;
123
+ aggregate_signature_bytes
124
+ . extend_from_slice ( & [ aggregate_signature_type. to_bytes_encoding_prefix ( ) ] ) ;
125
+
126
+ let mut proof_bytes = match self {
127
+ AggregateSignature :: Concatenation ( concatenation_proof) => {
128
+ concatenation_proof. to_bytes ( )
129
+ }
130
+ } ;
131
+ aggregate_signature_bytes. append ( & mut proof_bytes) ;
132
+
133
+ aggregate_signature_bytes
81
134
}
82
135
83
136
/// Extract an aggregate signature from a byte slice.
84
137
pub fn from_bytes ( bytes : & [ u8 ] ) -> Result < Self , StmAggregateSignatureError < D > > {
85
- // TODO: Move first byte of concatenation proof here to identify the proof system
86
- Ok ( Self :: Concatenation ( ConcatenationProof :: from_bytes ( bytes) ?) )
138
+ let proof_type_byte = bytes. get ( 0 ) . ok_or ( StmAggregateSignatureError :: SerializationError ) ?;
139
+ let proof_bytes = & bytes[ 1 ..] ;
140
+ let proof_type = AggregateSignatureType :: from_bytes_encoding_prefix ( * proof_type_byte)
141
+ . ok_or ( StmAggregateSignatureError :: SerializationError ) ?;
142
+ match proof_type {
143
+ AggregateSignatureType :: Concatenation => Ok ( AggregateSignature :: Concatenation (
144
+ ConcatenationProof :: from_bytes ( proof_bytes) ?,
145
+ ) ) ,
146
+ }
87
147
}
88
148
89
149
/// Extract the list of signatures.
150
+ // TODO: transfer this function to the concatenation proof ? Some proofs might not fully carry this information
90
151
pub fn signatures ( & self ) -> Vec < SingleSignatureWithRegisteredParty > {
91
152
match self {
92
153
AggregateSignature :: Concatenation ( stm_aggr_sig) => stm_aggr_sig. signatures . clone ( ) ,
@@ -112,3 +173,24 @@ impl<D: Clone + Digest + FixedOutput + Send + Sync> AggregateSignature<D> {
112
173
}
113
174
}
114
175
}
176
+
177
+ #[ cfg( test) ]
178
+ mod tests {
179
+ use super :: * ;
180
+
181
+ mod aggregate_signature_type {
182
+ use super :: * ;
183
+
184
+ #[ test]
185
+ fn golden_bytes_encoding_prefix ( ) {
186
+ assert_eq ! (
187
+ 0u8 ,
188
+ AggregateSignatureType :: Concatenation . to_bytes_encoding_prefix( )
189
+ ) ;
190
+ assert_eq ! (
191
+ AggregateSignatureType :: from_bytes_encoding_prefix( 0u8 ) ,
192
+ Some ( AggregateSignatureType :: Concatenation )
193
+ ) ;
194
+ }
195
+ }
196
+ }
0 commit comments