Skip to content

Commit 27c443e

Browse files
committed
feat(stm): make 'AggregateSignature' support multiple proof systems
1 parent 7c7a0e5 commit 27c443e

File tree

7 files changed

+125
-11
lines changed

7 files changed

+125
-11
lines changed

demo/protocol-demo/src/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub type ProtocolKeyRegistrationNotCertified = KeyRegistration;
3232
/// Alias of [MithrilStm:SingleSignature](struct@mithril_stm::SingleSignature).
3333
pub type ProtocolSingleSignature = SingleSignature;
3434

35-
/// Alias of [MithrilStm:AggregateSignature](struct@mithril_stm::AggregateSignature).
35+
/// Alias of [MithrilStm:AggregateSignature](enum@mithril_stm::AggregateSignature).
3636
pub type ProtocolMultiSignature = AggregateSignature<D>;
3737

3838
/// Alias of [MithrilStm:VerificationKeyProofOfPossession](type@mithril_stm::VerificationKeyProofOfPossession).

mithril-common/src/crypto_helper/types/wrappers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub type ProtocolSignerVerificationKeySignature = ProtocolKey<Sum6KesSig>;
1717
/// Wrapper of [MithrilStm:SingleSignature](type@SingleSignature) to add serialization utilities.
1818
pub type ProtocolSingleSignature = ProtocolKey<SingleSignature>;
1919

20-
/// Wrapper of [MithrilStm:AggregateSignature](struct@AggregateSignature) to add serialization utilities.
20+
/// Wrapper of [MithrilStm:AggregateSignature](enum@AggregateSignature) to add serialization utilities.
2121
pub type ProtocolMultiSignature = ProtocolKey<AggregateSignature<D>>;
2222

2323
/// Wrapper of [OpCert] to add serialization utilities.

mithril-common/src/test/double/fake_keys.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub const fn single_signature<'a>() -> [&'a str; 4] {
5252
]
5353
}
5454

55-
/// A list of pre json hex encoded [MithrilStm:AggregateSignature](struct@mithril_stm::AggregateSignature)
55+
/// A list of pre json hex encoded [MithrilStm:AggregateSignature](enum@mithril_stm::AggregateSignature)
5656
pub const fn multi_signature<'a>() -> [&'a str; 2] {
5757
[
5858
"7b227369676e617475726573223a5b5b7b227369676d61223a5b3137312c3136312c3232352c3139342c32382c\

mithril-stm/src/aggregate_signature/clerk.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
AggregateSignature, AggregateVerificationKey, AggregationError, BasicVerifier,
55
ClosedKeyRegistration, Index, Parameters, Signer, SingleSignature,
66
SingleSignatureWithRegisteredParty, Stake, VerificationKey,
7+
aggregate_signature::ConcatenationProof,
78
};
89

910
/// `Clerk` can verify and aggregate `SingleSignature`s and verify `AggregateSignature`s.
@@ -15,7 +16,7 @@ pub struct Clerk<D: Clone + Digest> {
1516
pub(crate) params: Parameters,
1617
}
1718

18-
impl<D: Digest + Clone + FixedOutput> Clerk<D> {
19+
impl<D: Digest + Clone + FixedOutput + Send + Sync> Clerk<D> {
1920
/// Create a new `Clerk` from a closed registration instance.
2021
pub fn new_clerk_from_closed_key_registration(
2122
params: &Parameters,
@@ -96,10 +97,10 @@ impl<D: Digest + Clone + FixedOutput> Clerk<D> {
9697
.merkle_tree
9798
.compute_merkle_tree_batch_path(mt_index_list);
9899

99-
Ok(AggregateSignature {
100+
Ok(AggregateSignature::Concatenation(ConcatenationProof {
100101
signatures: unique_sigs,
101102
batch_proof,
102-
})
103+
}))
103104
}
104105

105106
/// Aggregate a set of signatures for their corresponding indices.

mithril-stm/src/aggregate_signature/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ mod tests {
461461
#[test]
462462
fn test_invalid_proof_index_unique(tc in arb_proof_setup(10)) {
463463
with_proof_mod(tc, |aggr, clerk, _msg| {
464-
for sig_reg in aggr.signatures.iter_mut() {
464+
for sig_reg in aggr.signatures().iter_mut() {
465465
for index in sig_reg.sig.indexes.iter_mut() {
466466
*index %= clerk.params.k - 1
467467
}
@@ -471,7 +471,7 @@ mod tests {
471471
#[test]
472472
fn test_invalid_proof_path(tc in arb_proof_setup(10)) {
473473
with_proof_mod(tc, |aggr, _, _msg| {
474-
let p = aggr.batch_proof.clone();
474+
let p = aggr.batch_proof().clone();
475475
let mut index_list = p.indices.clone();
476476
let values = p.values;
477477
let batch_proof = {
@@ -482,7 +482,7 @@ mod tests {
482482
hasher: Default::default()
483483
}
484484
};
485-
aggr.batch_proof = batch_proof;
485+
aggr.set_batch_proof(batch_proof);
486486
})
487487
}
488488
}
Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,114 @@
1+
use std::collections::HashMap;
2+
use std::hash::Hash;
3+
4+
use blake2::digest::{Digest, FixedOutput};
5+
use serde::{Deserialize, Serialize};
6+
use strum::{Display, EnumDiscriminants};
7+
8+
use crate::error::StmAggregateSignatureError;
9+
use crate::merkle_tree::MerkleBatchPath;
10+
use crate::{AggregateVerificationKey, Parameters, SingleSignatureWithRegisteredParty};
11+
112
use super::ConcatenationProof;
213

3-
pub type AggregateSignature<D> = ConcatenationProof<D>;
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))]
19+
#[serde(bound(
20+
serialize = "MerkleBatchPath<D>: Serialize",
21+
deserialize = "MerkleBatchPath<D>: Deserialize<'de>"
22+
))]
23+
#[serde(untagged)]
24+
pub enum AggregateSignature<D: Clone + Digest + FixedOutput + Send + Sync> {
25+
/// Concatenation proof system.
26+
Concatenation(ConcatenationProof<D>),
27+
}
28+
29+
impl<D: Clone + Digest + FixedOutput + Send + Sync> AggregateSignature<D> {
30+
/// Verify an aggregate signature
31+
pub fn verify(
32+
&self,
33+
msg: &[u8],
34+
avk: &AggregateVerificationKey<D>,
35+
parameters: &Parameters,
36+
) -> Result<(), StmAggregateSignatureError<D>> {
37+
match self {
38+
AggregateSignature::Concatenation(stm_aggr_sig) => {
39+
stm_aggr_sig.verify(msg, avk, parameters)
40+
}
41+
}
42+
}
43+
44+
/// Batch verify a set of aggregate signatures
45+
pub fn batch_verify(
46+
stm_signatures: &[Self],
47+
msgs: &[Vec<u8>],
48+
avks: &[AggregateVerificationKey<D>],
49+
parameters: &[Parameters],
50+
) -> Result<(), StmAggregateSignatureError<D>> {
51+
let stm_signatures: HashMap<AggregateSignatureType, Vec<Self>> =
52+
stm_signatures.iter().fold(HashMap::new(), |mut acc, sig| {
53+
acc.entry(sig.into()).or_default().push(sig.clone());
54+
acc
55+
});
56+
stm_signatures
57+
.into_iter()
58+
.try_for_each(
59+
|(stm_aggr_sig_type, stm_aggr_sigs)| match stm_aggr_sig_type {
60+
AggregateSignatureType::Concatenation => ConcatenationProof::batch_verify(
61+
&stm_aggr_sigs
62+
.into_iter()
63+
.filter_map(|s| match s {
64+
Self::Concatenation(stm_aggr_sig) => Some(stm_aggr_sig),
65+
})
66+
.collect::<Vec<_>>(),
67+
msgs,
68+
avks,
69+
parameters,
70+
),
71+
},
72+
)
73+
.map_err(|_| StmAggregateSignatureError::BatchInvalid)
74+
}
75+
76+
/// Convert an aggregate signature to bytes
77+
pub fn to_bytes(&self) -> Vec<u8> {
78+
match self {
79+
AggregateSignature::Concatenation(stm_aggr_sig) => stm_aggr_sig.to_bytes(),
80+
}
81+
}
82+
83+
/// Extract an aggregate signature from a byte slice.
84+
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)?))
87+
}
88+
89+
/// Extract the list of signatures.
90+
pub fn signatures(&self) -> Vec<SingleSignatureWithRegisteredParty> {
91+
match self {
92+
AggregateSignature::Concatenation(stm_aggr_sig) => stm_aggr_sig.signatures.clone(),
93+
}
94+
}
95+
96+
/// Extract the list of unique merkle tree nodes that covers path for all signatures.
97+
// TODO: transfer this function to the concatenation proof
98+
pub fn batch_proof(&self) -> MerkleBatchPath<D> {
99+
match self {
100+
AggregateSignature::Concatenation(stm_aggr_sig) => stm_aggr_sig.batch_proof.clone(),
101+
}
102+
}
103+
104+
/// Extract the list of unique merkle tree nodes that covers path for all signatures. (test only)
105+
// TODO: transfer this function to the concatenation proof
106+
#[cfg(test)]
107+
pub(crate) fn set_batch_proof(&mut self, batch_proof: MerkleBatchPath<D>) {
108+
match self {
109+
AggregateSignature::Concatenation(stm_aggr_sig) => {
110+
stm_aggr_sig.batch_proof = batch_proof
111+
}
112+
}
113+
}
114+
}

mithril-stm/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ mod parameters;
116116
mod participant;
117117
mod single_signature;
118118

119-
pub use aggregate_signature::{AggregateSignature, AggregateVerificationKey, BasicVerifier, Clerk};
119+
pub use aggregate_signature::{
120+
AggregateSignature, AggregateSignatureType, AggregateVerificationKey, BasicVerifier, Clerk,
121+
};
120122
pub use error::{
121123
AggregationError, CoreVerifierError, RegisterError, StmAggregateSignatureError,
122124
StmSignatureError,

0 commit comments

Comments
 (0)