Skip to content

Commit dca59dd

Browse files
nougzarmmmaker
andauthored
Code review and minor corrections (#52)
Co-authored-by: Michele Orrù <[email protected]>
1 parent 1ecd4ff commit dca59dd

File tree

11 files changed

+228
-192
lines changed

11 files changed

+228
-192
lines changed

src/composition.rs

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
1-
//! Implementation of a structure [`Protocol`] aimed at generalizing the [`SchnorrProof`]
2-
//! using the compositions of the latter via AND and OR links
1+
//! # Protocol Composition with AND/OR Logic
32
//!
4-
//! This structure allows, for example, the construction of protocols of the form:
3+
//! This module defines the [`Protocol`] enum, which generalizes the [`SchnorrProof`]
4+
//! by enabling compositional logic between multiple proof instances.
5+
//!
6+
//! Specifically, it supports:
7+
//! - Simple atomic proofs (e.g., discrete logarithm, Pedersen commitments)
8+
//! - Conjunctions (`And`) of multiple sub-protocols
9+
//! - Disjunctions (`Or`) of multiple sub-protocols
10+
//!
11+
//! ## Example Composition
12+
//!
13+
//! ```ignore
514
//! And(
615
//! Or( dleq, pedersen_commitment ),
716
//! Simple( discrete_logarithm ),
817
//! And( pedersen_commitment_dleq, bbs_blind_commitment_computation )
918
//! )
19+
//! ```
1020
1121
use ff::{Field, PrimeField};
1222
use group::{Group, GroupEncoding};
@@ -104,11 +114,12 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
104114
) -> Result<(Self::Commitment, Self::ProverState), Error> {
105115
match (self, witness) {
106116
(Protocol::Simple(p), ProtocolWitness::Simple(w)) => {
107-
let (c, s) = p.prover_commit(w, rng)?;
108-
Ok((
109-
ProtocolCommitment::Simple(c),
110-
ProtocolProverState::Simple(s),
111-
))
117+
p.prover_commit(w, rng).map(|(c, s)| {
118+
(
119+
ProtocolCommitment::Simple(c),
120+
ProtocolProverState::Simple(s),
121+
)
122+
})
112123
}
113124
(Protocol::And(ps), ProtocolWitness::And(ws)) => {
114125
if ps.len() != ws.len() {
@@ -162,20 +173,20 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
162173
challenge: &Self::Challenge,
163174
) -> Result<Self::Response, Error> {
164175
match (self, state) {
165-
(Protocol::Simple(p), ProtocolProverState::Simple(state)) => {
166-
let response = p.prover_response(state, challenge)?;
167-
Ok(ProtocolResponse::Simple(response))
168-
}
176+
(Protocol::Simple(p), ProtocolProverState::Simple(state)) => p
177+
.prover_response(state, challenge)
178+
.map(ProtocolResponse::Simple),
169179
(Protocol::And(ps), ProtocolProverState::And(states)) => {
170180
if ps.len() != states.len() {
171181
return Err(Error::InvalidInstanceWitnessPair);
172182
}
173-
let mut responses = Vec::with_capacity(ps.len());
174-
for (i, p) in ps.iter().enumerate() {
175-
let r = p.prover_response(states[i].clone(), challenge)?;
176-
responses.push(r);
177-
}
178-
Ok(ProtocolResponse::And(responses))
183+
let responses: Result<Vec<_>, _> = ps
184+
.iter()
185+
.zip(states)
186+
.map(|(p, s)| p.prover_response(s, challenge))
187+
.collect();
188+
189+
Ok(ProtocolResponse::And(responses?))
179190
}
180191
(
181192
Protocol::Or(ps),
@@ -225,12 +236,11 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
225236
Protocol::And(ps),
226237
ProtocolCommitment::And(commitments),
227238
ProtocolResponse::And(responses),
228-
) => {
229-
for (i, p) in ps.iter().enumerate() {
230-
p.verifier(&commitments[i], challenge, &responses[i])?;
231-
}
232-
Ok(())
233-
}
239+
) => ps
240+
.iter()
241+
.zip(commitments)
242+
.zip(responses)
243+
.try_for_each(|((p, c), r)| p.verifier(c, challenge, r)),
234244
(
235245
Protocol::Or(ps),
236246
ProtocolCommitment::Or(commitments),
@@ -253,20 +263,12 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
253263
fn serialize_commitment(&self, commitment: &Self::Commitment) -> Vec<u8> {
254264
match (self, commitment) {
255265
(Protocol::Simple(p), ProtocolCommitment::Simple(c)) => p.serialize_commitment(c),
256-
(Protocol::And(ps), ProtocolCommitment::And(commitments)) => {
257-
let mut bytes = Vec::new();
258-
for (i, p) in ps.iter().enumerate() {
259-
bytes.extend(p.serialize_commitment(&commitments[i]));
260-
}
261-
bytes
262-
}
263-
(Protocol::Or(ps), ProtocolCommitment::Or(commitments)) => {
264-
let mut bytes = Vec::new();
265-
for (i, p) in ps.iter().enumerate() {
266-
bytes.extend(p.serialize_commitment(&commitments[i]));
267-
}
268-
bytes
269-
}
266+
(Protocol::And(ps), ProtocolCommitment::And(commitments))
267+
| (Protocol::Or(ps), ProtocolCommitment::Or(commitments)) => ps
268+
.iter()
269+
.zip(commitments)
270+
.flat_map(|(p, c)| p.serialize_commitment(c))
271+
.collect(),
270272
_ => panic!(),
271273
}
272274
}
@@ -354,27 +356,22 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
354356
let c = p.deserialize_commitment(data)?;
355357
Ok(ProtocolCommitment::Simple(c))
356358
}
357-
Protocol::And(ps) => {
358-
let mut cursor = 0;
359-
let mut commitments = Vec::with_capacity(ps.len());
360-
for p in ps {
361-
let c = p.deserialize_commitment(&data[cursor..])?;
362-
let size = p.serialize_commitment(&c).len();
363-
cursor += size;
364-
commitments.push(c);
365-
}
366-
Ok(ProtocolCommitment::And(commitments))
367-
}
368-
Protocol::Or(ps) => {
359+
Protocol::And(ps) | Protocol::Or(ps) => {
369360
let mut cursor = 0;
370361
let mut commitments = Vec::with_capacity(ps.len());
362+
371363
for p in ps {
372364
let c = p.deserialize_commitment(&data[cursor..])?;
373365
let size = p.serialize_commitment(&c).len();
374366
cursor += size;
375367
commitments.push(c);
376368
}
377-
Ok(ProtocolCommitment::Or(commitments))
369+
370+
Ok(match self {
371+
Protocol::And(_) => ProtocolCommitment::And(commitments),
372+
Protocol::Or(_) => ProtocolCommitment::Or(commitments),
373+
_ => unreachable!(),
374+
})
378375
}
379376
}
380377
}
@@ -436,17 +433,20 @@ impl<G: Group + GroupEncoding> SigmaProtocolSimulator for Protocol<G> {
436433
p.simulate_commitment(challenge, r)?,
437434
)),
438435
(Protocol::And(ps), ProtocolResponse::And(rs)) => {
439-
let mut commitments = Vec::with_capacity(ps.len());
440-
for (i, p) in ps.iter().enumerate() {
441-
commitments.push(p.simulate_commitment(challenge, &rs[i])?);
442-
}
436+
let commitments = ps
437+
.iter()
438+
.zip(rs)
439+
.map(|(p, r)| p.simulate_commitment(challenge, r))
440+
.collect::<Result<Vec<_>, _>>()?;
443441
Ok(ProtocolCommitment::And(commitments))
444442
}
445-
(Protocol::Or(ps), ProtocolResponse::Or(ch, rs)) => {
446-
let mut commitments = Vec::with_capacity(ps.len());
447-
for (i, p) in ps.iter().enumerate() {
448-
commitments.push(p.simulate_commitment(&ch[i], &rs[i])?);
449-
}
443+
(Protocol::Or(ps), ProtocolResponse::Or(challenges, rs)) => {
444+
let commitments = ps
445+
.iter()
446+
.zip(challenges)
447+
.zip(rs)
448+
.map(|((p, ch), r)| p.simulate_commitment(ch, r))
449+
.collect::<Result<Vec<_>, _>>()?;
450450
Ok(ProtocolCommitment::Or(commitments))
451451
}
452452
_ => panic!(),

src/duplex_sponge/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! This module defines the [`DuplexSpongeInterface`] trait, which provides
44
//! a generic interface for cryptographic sponge functions that support
5-
//! duplex operation (absorb and squeeze phases).
5+
//! duplex operations: alternating absorb and squeeze phases.
66
77
pub mod keccak;
88
pub mod shake;
@@ -15,7 +15,9 @@ pub mod shake;
1515
///
1616
/// This is the core primitive used for building cryptographic codecs.
1717
pub trait DuplexSpongeInterface {
18-
/// Creates a new sponge instance with an initialization vector.
18+
/// Creates a new sponge instance with a given initialization vector (IV).
19+
///
20+
/// The IV enables domain separation and reproducibility between parties.
1921
fn new(iv: [u8; 32]) -> Self;
2022

2123
/// Absorbs input data into the sponge state.
@@ -24,5 +26,6 @@ pub trait DuplexSpongeInterface {
2426
/// Squeezes output data from the sponge state.
2527
fn squeeze(&mut self, length: usize) -> Vec<u8>;
2628

29+
/// Applies a state ratcheting mechanism to prevent backtracking attacks.
2730
fn ratchet(&mut self);
2831
}

src/errors.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
//! # Error: Error Types for Zero-Knowledge Proofs.
22
//!
3-
//! This module defines the [`Error`] enum, which encapsulates possible errors that may occur
4-
//! during the execution of Sigma protocols or their non-interactive variants.
3+
//! This module defines the [`Error`] enum, which enumerates the possible failure modes
4+
//! encountered during the execution of interactive or non-interactive Sigma protocols.
55
//!
66
//! These errors include:
7-
//! - Verification failures (e.g., when a proof does not verify correctly).
8-
//! - Mismatched parameters during batch verification.
9-
//! - Uninitialized group variables.
7+
//! - Failed proof verification,
8+
//! - Mismatched parameter lengths (e.g., during batch verification),
9+
//! - Access to unassigned group variables in constraint systems.
1010
11-
/// An error during proving or verification, such as a verification failure.
11+
/// Represents an error encountered during the execution of a Sigma protocol.
12+
///
13+
/// This may occur during proof generation, response computation, or verification.
1214
#[non_exhaustive]
1315
#[derive(Debug, thiserror::Error)]
1416
pub enum Error {
15-
/// Something is wrong with the proof, causing a verification failure.
17+
/// The proof is invalid: verification failed.
1618
#[error("Verification failed.")]
1719
VerificationFailure,
1820
/// Indicates an invalid statement/witness pair
1921
#[error("Invalid instance/witness pair.")]
2022
InvalidInstanceWitnessPair,
2123
/// Uninitialized group element variable.
2224
#[error("Uninitialized group element variable: {var_debug}")]
23-
UnassignedGroupVar { var_debug: String },
25+
UnassignedGroupVar {
26+
/// Debug representation of the unassigned variable.
27+
var_debug: String,
28+
},
2429
}

src/lib.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,26 @@
1-
//! # Σ-rs
1+
//! # Σ-rs: Sigma Protocols in Rust
22
//!
3-
//! A Rust library for building zero-knowledge proofs using Sigma protocols (Σ-protocols).
4-
//! Create proofs that demonstrate knowledge of secret information without revealing it.
3+
//! **Σ-rs** is a Rust library for constructing zero-knowledge proofs using Sigma protocols (Σ-protocols).
4+
//! It allows proving knowledge of secret data without revealing the data itself.
5+
//!
6+
//! ---
57
//!
68
//! ## What are Sigma Protocols?
79
//!
810
//! Sigma protocols are interactive cryptographic protocols that allow a prover to convince
911
//! a verifier they know a secret (like a private key) without revealing the secret itself.
1012
//! They follow a simple three-step pattern: commitment, challenge, response.
1113
//!
14+
//! ---
15+
//!
1216
//! ## Key Features
1317
//!
1418
//! - **Composable**: Combine multiple proofs into compound statements
1519
//! - **Generic**: Works with any cryptographic group supporting the required operations
1620
//! - **Flexible Hashing**: Multiple hash function backends for different use cases
21+
//! - **Non-Interactive Ready**: Support for Fiat–Shamir transformation
22+
//!
23+
//! ---
1724
//!
1825
//! ## Basic Usage
1926
//!
@@ -24,13 +31,19 @@
2431
//! 3. Convert to non-interactive using [`fiat_shamir::NISigmaProtocol`]
2532
//! 4. Generate and verify proofs using the protocol interface
2633
//!
34+
//! ---
35+
//!
2736
//! ## Core Components
2837
//!
2938
//! - **[`traits::SigmaProtocol`]**: The fundamental three-move protocol interface
3039
//! - **[`linear_relation::LinearRelation`]**: Express mathematical relations over groups
3140
//! - **[`fiat_shamir::NISigmaProtocol`]**: Convert interactive proofs to standalone proofs
3241
//! - **[`composition::Protocol`]**: Combine multiple proofs together
3342
//! - **[`codec`]**: Hash function backends for proof generation
43+
//!
44+
//! ---
45+
//!
46+
//! Σ-rs is designed to be modular, extensible, and easy to integrate into zero-knowledge applications.
3447
3548
#![allow(non_snake_case)]
3649
#![doc(html_logo_url = "https://mmaker.github.io/sigma-rs/")]

0 commit comments

Comments
 (0)