Skip to content

Commit 1de6684

Browse files
committed
include missing folders
1 parent a54779e commit 1de6684

File tree

2 files changed

+251
-0
lines changed

2 files changed

+251
-0
lines changed
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
use anyhow::Context;
2+
use blake2::digest::{Digest, FixedOutput};
3+
4+
use serde::{Deserialize, Serialize};
5+
6+
use crate::key_registration::RegisteredParty;
7+
use crate::membership_commitment::MerkleBatchPath;
8+
use crate::signature_scheme::{BlsSignature, BlsVerificationKey};
9+
use crate::{
10+
AggregateSignatureError, AggregateVerificationKey, BasicVerifier, Clerk, Parameters,
11+
SingleSignature, SingleSignatureWithRegisteredParty, StmResult,
12+
};
13+
14+
/// `ConcatenationProof` uses the "concatenation" proving system (as described in Section 4.3 of the original paper.)
15+
/// This means that the aggregated signature contains a vector with all individual signatures.
16+
/// BatchPath is also a part of the aggregate signature which covers path for all signatures.
17+
#[derive(Debug, Clone, Serialize, Deserialize)]
18+
#[serde(bound(
19+
serialize = "MerkleBatchPath<D>: Serialize",
20+
deserialize = "MerkleBatchPath<D>: Deserialize<'de>"
21+
))]
22+
pub struct ConcatenationProof<D: Clone + Digest + FixedOutput> {
23+
pub(crate) signatures: Vec<SingleSignatureWithRegisteredParty>,
24+
/// The list of unique merkle tree nodes that covers path for all signatures.
25+
pub batch_proof: MerkleBatchPath<D>,
26+
}
27+
28+
impl<D: Clone + Digest + FixedOutput + Send + Sync> ConcatenationProof<D> {
29+
/// Aggregate a set of signatures for their corresponding indices.
30+
///
31+
/// This function first deduplicates the repeated signatures, and if there are enough signatures, it collects the merkle tree indexes of unique signatures.
32+
/// The list of merkle tree indexes is used to create a batch proof, to prove that all signatures are from eligible signers.
33+
///
34+
/// It returns an instance of `ConcatenationProof`.
35+
pub fn aggregate_signatures(
36+
clerk: &Clerk<D>,
37+
sigs: &[SingleSignature],
38+
msg: &[u8],
39+
) -> StmResult<ConcatenationProof<D>> {
40+
let sig_reg_list = sigs
41+
.iter()
42+
.map(|sig| SingleSignatureWithRegisteredParty {
43+
sig: sig.clone(),
44+
reg_party: clerk.closed_reg.reg_parties[sig.signer_index as usize],
45+
})
46+
.collect::<Vec<SingleSignatureWithRegisteredParty>>();
47+
48+
let avk = AggregateVerificationKey::from(&clerk.closed_reg);
49+
let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg);
50+
let mut unique_sigs = BasicVerifier::select_valid_signatures_for_k_indices(
51+
&clerk.closed_reg.total_stake,
52+
&clerk.params,
53+
&msgp,
54+
&sig_reg_list,
55+
)
56+
.with_context(
57+
|| "Failed to aggregate unique signatures during selection for the k indices.",
58+
)?;
59+
60+
unique_sigs.sort_unstable();
61+
62+
let mt_index_list = unique_sigs
63+
.iter()
64+
.map(|sig_reg| sig_reg.sig.signer_index as usize)
65+
.collect::<Vec<usize>>();
66+
67+
let batch_proof = clerk
68+
.closed_reg
69+
.merkle_tree
70+
.compute_merkle_tree_batch_path(mt_index_list);
71+
72+
Ok(Self {
73+
signatures: unique_sigs,
74+
batch_proof,
75+
})
76+
}
77+
78+
/// Verify all checks from signatures, except for the signature verification itself.
79+
///
80+
/// Indices and quorum are checked by `BasicVerifier::preliminary_verify` with `msgp`.
81+
/// It collects leaves from signatures and checks the batch proof.
82+
/// After batch proof is checked, it collects and returns the signatures and
83+
/// verification keys to be used by aggregate verification.
84+
fn preliminary_verify(
85+
&self,
86+
msg: &[u8],
87+
avk: &AggregateVerificationKey<D>,
88+
parameters: &Parameters,
89+
) -> StmResult<(Vec<BlsSignature>, Vec<BlsVerificationKey>)> {
90+
let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg);
91+
BasicVerifier::preliminary_verify(
92+
&avk.get_total_stake(),
93+
&self.signatures,
94+
parameters,
95+
&msgp,
96+
)
97+
.with_context(|| "Preliminary verification of aggregate signatures failed.")?;
98+
99+
let leaves = self
100+
.signatures
101+
.iter()
102+
.map(|r| r.reg_party)
103+
.collect::<Vec<RegisteredParty>>();
104+
105+
avk.get_merkle_tree_batch_commitment()
106+
.verify_leaves_membership_from_batch_path(&leaves, &self.batch_proof)
107+
.with_context(|| "Batch proof is invalid in preliminary verification.")?;
108+
109+
Ok(BasicVerifier::collect_signatures_verification_keys(
110+
&self.signatures,
111+
))
112+
}
113+
114+
/// Verify concatenation proof, by checking that
115+
/// * each signature contains only valid indices,
116+
/// * the lottery is indeed won by each one of them,
117+
/// * the merkle tree path is valid,
118+
/// * the aggregate signature validates with respect to the aggregate verification key
119+
/// (aggregation is computed using functions `MSP.BKey` and `MSP.BSig` as described in Section 2.4 of the paper).
120+
pub fn verify(
121+
&self,
122+
msg: &[u8],
123+
avk: &AggregateVerificationKey<D>,
124+
parameters: &Parameters,
125+
) -> StmResult<()> {
126+
let msgp = avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg);
127+
let (sigs, vks) = self
128+
.preliminary_verify(msg, avk, parameters)
129+
.with_context(|| "Aggregate signature verification failed")?;
130+
131+
BlsSignature::verify_aggregate(msgp.as_slice(), &vks, &sigs)
132+
.with_context(|| "Aggregate signature verification failed")?;
133+
Ok(())
134+
}
135+
136+
/// Batch verify a set of signatures, with different messages and avks.
137+
pub fn batch_verify(
138+
stm_signatures: &[Self],
139+
msgs: &[Vec<u8>],
140+
avks: &[AggregateVerificationKey<D>],
141+
parameters: &[Parameters],
142+
) -> StmResult<()> {
143+
let batch_size = stm_signatures.len();
144+
assert_eq!(
145+
batch_size,
146+
msgs.len(),
147+
"Number of messages should correspond to size of the batch"
148+
);
149+
assert_eq!(
150+
batch_size,
151+
avks.len(),
152+
"Number of avks should correspond to size of the batch"
153+
);
154+
assert_eq!(
155+
batch_size,
156+
parameters.len(),
157+
"Number of parameters should correspond to size of the batch"
158+
);
159+
160+
let mut aggr_sigs = Vec::with_capacity(batch_size);
161+
let mut aggr_vks = Vec::with_capacity(batch_size);
162+
for (idx, sig_group) in stm_signatures.iter().enumerate() {
163+
sig_group.preliminary_verify(&msgs[idx], &avks[idx], &parameters[idx])?;
164+
let grouped_sigs: Vec<BlsSignature> =
165+
sig_group.signatures.iter().map(|sig_reg| sig_reg.sig.sigma).collect();
166+
let grouped_vks: Vec<BlsVerificationKey> = sig_group
167+
.signatures
168+
.iter()
169+
.map(|sig_reg| sig_reg.reg_party.0)
170+
.collect();
171+
172+
let (aggr_vk, aggr_sig) = BlsSignature::aggregate(&grouped_vks, &grouped_sigs).unwrap();
173+
aggr_sigs.push(aggr_sig);
174+
aggr_vks.push(aggr_vk);
175+
}
176+
177+
let concat_msgs: Vec<Vec<u8>> = msgs
178+
.iter()
179+
.zip(avks.iter())
180+
.map(|(msg, avk)| avk.get_merkle_tree_batch_commitment().concatenate_with_message(msg))
181+
.collect();
182+
183+
BlsSignature::batch_verify_aggregates(&concat_msgs, &aggr_vks, &aggr_sigs)?;
184+
Ok(())
185+
}
186+
187+
/// Convert concatenation proof to bytes
188+
/// # Layout
189+
/// * Number of the pairs of Signatures and Registered Parties (SigRegParty) (as u64)
190+
/// * Pairs of Signatures and Registered Parties (prefixed with their size as u64)
191+
/// * Batch proof
192+
pub fn to_bytes(&self) -> Vec<u8> {
193+
let mut out = Vec::new();
194+
out.extend_from_slice(&u64::try_from(self.signatures.len()).unwrap().to_be_bytes());
195+
for sig_reg in &self.signatures {
196+
out.extend_from_slice(&u64::try_from(sig_reg.to_bytes().len()).unwrap().to_be_bytes());
197+
out.extend_from_slice(&sig_reg.to_bytes());
198+
}
199+
let proof = &self.batch_proof;
200+
out.extend_from_slice(&proof.to_bytes());
201+
202+
out
203+
}
204+
205+
///Extract a concatenation proof from a byte slice.
206+
pub fn from_bytes(bytes: &[u8]) -> StmResult<ConcatenationProof<D>> {
207+
let mut bytes_index = 0;
208+
209+
let mut u64_bytes = [0u8; 8];
210+
u64_bytes.copy_from_slice(
211+
bytes
212+
.get(bytes_index..bytes_index + 8)
213+
.ok_or(AggregateSignatureError::SerializationError)?,
214+
);
215+
let total_sigs = usize::try_from(u64::from_be_bytes(u64_bytes))
216+
.map_err(|_| AggregateSignatureError::SerializationError)?;
217+
bytes_index += 8;
218+
219+
let mut sig_reg_list = Vec::with_capacity(total_sigs);
220+
for _ in 0..total_sigs {
221+
u64_bytes.copy_from_slice(
222+
bytes
223+
.get(bytes_index..bytes_index + 8)
224+
.ok_or(AggregateSignatureError::SerializationError)?,
225+
);
226+
let sig_reg_size = usize::try_from(u64::from_be_bytes(u64_bytes))
227+
.map_err(|_| AggregateSignatureError::SerializationError)?;
228+
let sig_reg = SingleSignatureWithRegisteredParty::from_bytes::<D>(
229+
bytes
230+
.get(bytes_index + 8..bytes_index + 8 + sig_reg_size)
231+
.ok_or(AggregateSignatureError::SerializationError)?,
232+
)?;
233+
bytes_index += 8 + sig_reg_size;
234+
sig_reg_list.push(sig_reg);
235+
}
236+
237+
let batch_proof = MerkleBatchPath::from_bytes(
238+
bytes
239+
.get(bytes_index..)
240+
.ok_or(AggregateSignatureError::SerializationError)?,
241+
)?;
242+
243+
Ok(ConcatenationProof {
244+
signatures: sig_reg_list,
245+
batch_proof,
246+
})
247+
}
248+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mod concatenation;
2+
3+
pub use concatenation::*;

0 commit comments

Comments
 (0)