Skip to content

Commit 400d563

Browse files
committed
refactor(stm): move proof type encoding byte to aggregate signature
1 parent c871f94 commit 400d563

File tree

2 files changed

+96
-29
lines changed

2 files changed

+96
-29
lines changed

mithril-stm/src/aggregate_signature/proof/concatenation.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl<D: Clone + Digest + FixedOutput + Send + Sync> ConcatenationProof<D> {
5959
))
6060
}
6161

62-
/// Verify aggregate signature, by checking that
62+
/// Verify concatenation proof, by checking that
6363
/// * each signature contains only valid indices,
6464
/// * the lottery is indeed won by each one of them,
6565
/// * the merkle tree path is valid,
@@ -129,19 +129,13 @@ impl<D: Clone + Digest + FixedOutput + Send + Sync> ConcatenationProof<D> {
129129
Ok(())
130130
}
131131

132-
/// Convert multi signature to bytes
132+
/// Convert concatenation proof to bytes
133133
/// # Layout
134-
/// * Aggregate signature type (u8)
135134
/// * Number of the pairs of Signatures and Registered Parties (SigRegParty) (as u64)
136135
/// * Pairs of Signatures and Registered Parties (prefixed with their size as u64)
137136
/// * Batch proof
138137
pub fn to_bytes(&self) -> Vec<u8> {
139138
let mut out = Vec::new();
140-
// This proof type is not strictly necessary, but it will help to identify
141-
// the type of the proof used to aggregate when implementing multiple aggregation proof systems.
142-
// We use '0' for concatenation proof.
143-
let proof_type: u8 = 0;
144-
out.extend_from_slice(&proof_type.to_be_bytes());
145139
out.extend_from_slice(&u64::try_from(self.signatures.len()).unwrap().to_be_bytes());
146140
for sig_reg in &self.signatures {
147141
out.extend_from_slice(&u64::try_from(sig_reg.to_bytes().len()).unwrap().to_be_bytes());
@@ -153,21 +147,12 @@ impl<D: Clone + Digest + FixedOutput + Send + Sync> ConcatenationProof<D> {
153147
out
154148
}
155149

156-
///Extract a `AggregateSignature` from a byte slice.
150+
///Extract a concatenation proof from a byte slice.
157151
pub fn from_bytes(
158152
bytes: &[u8],
159153
) -> Result<ConcatenationProof<D>, StmAggregateSignatureError<D>> {
160-
let mut u8_bytes = [0u8; 1];
161154
let mut bytes_index = 0;
162155

163-
u8_bytes
164-
.copy_from_slice(bytes.get(..1).ok_or(StmAggregateSignatureError::SerializationError)?);
165-
bytes_index += 1;
166-
let proof_type = u8::from_be_bytes(u8_bytes);
167-
if proof_type != 0 {
168-
return Err(StmAggregateSignatureError::SerializationError);
169-
}
170-
171156
let mut u64_bytes = [0u8; 8];
172157
u64_bytes.copy_from_slice(
173158
bytes

mithril-stm/src/aggregate_signature/signature.rs

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,64 @@
11
use std::collections::HashMap;
2+
use std::fmt::Display;
23
use std::hash::Hash;
34

45
use blake2::digest::{Digest, FixedOutput};
56
use serde::{Deserialize, Serialize};
6-
use strum::{Display, EnumDiscriminants};
77

88
use crate::error::StmAggregateSignatureError;
99
use crate::merkle_tree::MerkleBatchPath;
1010
use crate::{AggregateVerificationKey, Parameters, SingleSignatureWithRegisteredParty};
1111

1212
use super::ConcatenationProof;
1313

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)]
1962
#[serde(bound(
2063
serialize = "MerkleBatchPath<D>: Serialize",
2164
deserialize = "MerkleBatchPath<D>: Deserialize<'de>"
@@ -75,18 +118,36 @@ impl<D: Clone + Digest + FixedOutput + Send + Sync> AggregateSignature<D> {
75118

76119
/// Convert an aggregate signature to bytes
77120
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
81134
}
82135

83136
/// Extract an aggregate signature from a byte slice.
84137
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+
}
87147
}
88148

89149
/// Extract the list of signatures.
150+
// TODO: transfer this function to the concatenation proof ? Some proofs might not fully carry this information
90151
pub fn signatures(&self) -> Vec<SingleSignatureWithRegisteredParty> {
91152
match self {
92153
AggregateSignature::Concatenation(stm_aggr_sig) => stm_aggr_sig.signatures.clone(),
@@ -112,3 +173,24 @@ impl<D: Clone + Digest + FixedOutput + Send + Sync> AggregateSignature<D> {
112173
}
113174
}
114175
}
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

Comments
 (0)