Skip to content

Commit 12a40b6

Browse files
authored
Merge branch 'main' into minor-update
Signed-off-by: Michele Orrù <[email protected]>
2 parents 22d4b2f + 1ecd4ff commit 12a40b6

File tree

9 files changed

+598
-203
lines changed

9 files changed

+598
-203
lines changed

src/composition.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
123123
}
124124
(Protocol::And(ps), ProtocolWitness::And(ws)) => {
125125
if ps.len() != ws.len() {
126-
return Err(Error::ProofSizeMismatch);
126+
return Err(Error::InvalidInstanceWitnessPair);
127127
}
128128
let mut commitments = Vec::with_capacity(ps.len());
129129
let mut prover_states = Vec::with_capacity(ps.len());
@@ -178,7 +178,7 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
178178
.map(ProtocolResponse::Simple),
179179
(Protocol::And(ps), ProtocolProverState::And(states)) => {
180180
if ps.len() != states.len() {
181-
return Err(Error::ProofSizeMismatch);
181+
return Err(Error::InvalidInstanceWitnessPair);
182182
}
183183
let responses: Result<Vec<_>, _> = ps
184184
.iter()

src/errors.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,9 @@ pub enum Error {
1717
/// The proof is invalid: verification failed.
1818
#[error("Verification failed.")]
1919
VerificationFailure,
20-
21-
/// The sizes of input parameters (e.g., witnesses, commitments) do not match expected values.
22-
#[error("Mismatched parameter sizes in proof or batch verification.")]
23-
ProofSizeMismatch,
24-
20+
/// Indicates an invalid statement/witness pair
21+
#[error("Invalid instance/witness pair.")]
22+
InvalidInstanceWitnessPair,
2523
/// Uninitialized group element variable.
2624
#[error("Uninitialized group element variable: {var_debug}")]
2725
UnassignedGroupVar {

src/fiat_shamir.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ where
4545
/// Current codec state.
4646
pub hash_state: C,
4747
/// Underlying interactive proof.
48-
pub ip: P,
48+
pub interactive_proof: P,
4949
}
5050

5151
impl<P, C> NISigmaProtocol<P, C>
@@ -70,15 +70,15 @@ where
7070
);
7171
Self {
7272
hash_state,
73-
ip: interactive_proof,
73+
interactive_proof,
7474
}
7575
}
7676

77-
pub fn from_iv(iv: [u8; 32], instance: P) -> Self {
77+
pub fn from_iv(iv: [u8; 32], interactive_proof: P) -> Self {
7878
let hash_state = C::from_iv(iv);
7979
Self {
8080
hash_state,
81-
ip: instance,
81+
interactive_proof,
8282
}
8383
}
8484

@@ -106,15 +106,16 @@ where
106106
) -> Result<Transcript<P>, Error> {
107107
let mut hash_state = self.hash_state.clone();
108108

109-
let (commitment, prover_state) = self.ip.prover_commit(witness, rng)?;
109+
let (commitment, prover_state) = self.interactive_proof.prover_commit(witness, rng)?;
110110
// Fiat Shamir challenge
111-
let serialized_commitment = self.ip.serialize_commitment(&commitment);
111+
let serialized_commitment = self.interactive_proof.serialize_commitment(&commitment);
112112
hash_state.prover_message(&serialized_commitment);
113113
let challenge = hash_state.verifier_challenge();
114114
// Prover's response
115-
let response = self.ip.prover_response(prover_state, &challenge)?;
115+
let response = self.interactive_proof.prover_response(prover_state, &challenge)?;
116+
116117
// Local verification of the proof
117-
self.ip.verifier(&commitment, &challenge, &response)?;
118+
debug_assert!(self.interactive_proof.verifier(&commitment, &challenge, &response).is_ok());
118119
Ok((commitment, challenge, response))
119120
}
120121

@@ -142,12 +143,12 @@ where
142143
let mut hash_state = self.hash_state.clone();
143144

144145
// Recompute the challenge
145-
let serialized_commitment = self.ip.serialize_commitment(commitment);
146+
let serialized_commitment = self.interactive_proof.serialize_commitment(commitment);
146147
hash_state.prover_message(&serialized_commitment);
147148
let expected_challenge = hash_state.verifier_challenge();
148149
// Verification of the proof
149150
match *challenge == expected_challenge {
150-
true => self.ip.verifier(commitment, challenge, response),
151+
true => self.interactive_proof.verifier(commitment, challenge, response),
151152
false => Err(Error::VerificationFailure),
152153
}
153154
}
@@ -169,8 +170,8 @@ where
169170
) -> Result<Vec<u8>, Error> {
170171
let (commitment, _challenge, response) = self.prove(witness, rng)?;
171172
let mut bytes = Vec::new();
172-
bytes.extend_from_slice(&self.ip.serialize_commitment(&commitment));
173-
bytes.extend_from_slice(&self.ip.serialize_response(&response));
173+
bytes.extend_from_slice(&self.interactive_proof.serialize_commitment(&commitment));
174+
bytes.extend_from_slice(&self.interactive_proof.serialize_response(&response));
174175
Ok(bytes)
175176
}
176177

@@ -188,18 +189,18 @@ where
188189
/// - The challenge doesn't match the recomputed one from the commitment.
189190
/// - The response fails verification under the Sigma protocol.
190191
pub fn verify_batchable(&self, proof: &[u8]) -> Result<(), Error> {
191-
let commitment = self.ip.deserialize_commitment(proof)?;
192-
let commitment_size = self.ip.serialize_commitment(&commitment).len();
193-
let response = self.ip.deserialize_response(&proof[commitment_size..])?;
192+
let commitment = self.interactive_proof.deserialize_commitment(proof)?;
193+
let commitment_size = self.interactive_proof.serialize_commitment(&commitment).len();
194+
let response = self.interactive_proof.deserialize_response(&proof[commitment_size..])?;
194195

195196
let mut hash_state = self.hash_state.clone();
196197

197198
// Recompute the challenge
198-
let serialized_commitment = self.ip.serialize_commitment(&commitment);
199+
let serialized_commitment = self.interactive_proof.serialize_commitment(&commitment);
199200
hash_state.prover_message(&serialized_commitment);
200201
let challenge = hash_state.verifier_challenge();
201202
// Verification of the proof
202-
self.ip.verifier(&commitment, &challenge, &response)
203+
self.interactive_proof.verifier(&commitment, &challenge, &response)
203204
}
204205
}
205206

@@ -229,8 +230,8 @@ where
229230
) -> Result<Vec<u8>, Error> {
230231
let (_commitment, challenge, response) = self.prove(witness, rng)?;
231232
let mut bytes = Vec::new();
232-
bytes.extend_from_slice(&self.ip.serialize_challenge(&challenge));
233-
bytes.extend_from_slice(&self.ip.serialize_response(&response));
233+
bytes.extend_from_slice(&self.interactive_proof.serialize_challenge(&challenge));
234+
bytes.extend_from_slice(&self.interactive_proof.serialize_response(&response));
234235
Ok(bytes)
235236
}
236237

@@ -251,12 +252,12 @@ where
251252
/// - The recomputed commitment or response is invalid under the Sigma protocol.
252253
pub fn verify_compact(&self, proof: &[u8]) -> Result<(), Error> {
253254
// Deserialize challenge and response from compact proof
254-
let challenge = self.ip.deserialize_challenge(proof)?;
255-
let challenge_size = self.ip.serialize_challenge(&challenge).len();
256-
let response = self.ip.deserialize_response(&proof[challenge_size..])?;
255+
let challenge = self.interactive_proof.deserialize_challenge(proof)?;
256+
let challenge_size = self.interactive_proof.serialize_challenge(&challenge).len();
257+
let response = self.interactive_proof.deserialize_response(&proof[challenge_size..])?;
257258

258259
// Compute the commitments
259-
let commitment = self.ip.simulate_commitment(&challenge, &response)?;
260+
let commitment = self.interactive_proof.simulate_commitment(&challenge, &response)?;
260261
// Verify the proof
261262
self.verify(&commitment, &challenge, &response)
262263
}

src/linear_relation/convert.rs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
use ff::Field;
2+
use group::Group;
3+
4+
use super::{GroupVar, ScalarTerm, ScalarVar, Sum, Term, Weighted};
5+
6+
impl<G> From<ScalarVar<G>> for ScalarTerm<G> {
7+
fn from(value: ScalarVar<G>) -> Self {
8+
Self::Var(value)
9+
}
10+
}
11+
12+
impl<G: Group> From<ScalarVar<G>> for Weighted<ScalarTerm<G>, G::Scalar> {
13+
fn from(value: ScalarVar<G>) -> Self {
14+
ScalarTerm::from(value).into()
15+
}
16+
}
17+
18+
impl<G: Group> From<Weighted<ScalarVar<G>, G::Scalar>> for Weighted<ScalarTerm<G>, G::Scalar> {
19+
fn from(value: Weighted<ScalarVar<G>, G::Scalar>) -> Self {
20+
Self {
21+
term: value.term.into(),
22+
weight: value.weight,
23+
}
24+
}
25+
}
26+
27+
// NOTE: Rust does not accept an impl over From<G::Scalar>
28+
impl<T: Field + Into<G::Scalar>, G: Group> From<T> for Weighted<ScalarTerm<G>, G::Scalar> {
29+
fn from(value: T) -> Self {
30+
Self {
31+
term: ScalarTerm::Unit,
32+
weight: value.into(),
33+
}
34+
}
35+
}
36+
37+
impl<G> From<(ScalarVar<G>, GroupVar<G>)> for Term<G> {
38+
fn from((scalar, elem): (ScalarVar<G>, GroupVar<G>)) -> Self {
39+
Self {
40+
scalar: scalar.into(),
41+
elem,
42+
}
43+
}
44+
}
45+
46+
impl<G> From<(ScalarTerm<G>, GroupVar<G>)> for Term<G> {
47+
fn from((scalar, elem): (ScalarTerm<G>, GroupVar<G>)) -> Self {
48+
Self { scalar, elem }
49+
}
50+
}
51+
52+
impl<G> From<GroupVar<G>> for Term<G> {
53+
fn from(value: GroupVar<G>) -> Self {
54+
Term {
55+
scalar: ScalarTerm::Unit,
56+
elem: value,
57+
}
58+
}
59+
}
60+
61+
impl<G: Group> From<(ScalarVar<G>, GroupVar<G>)> for Weighted<Term<G>, G::Scalar> {
62+
fn from(pair: (ScalarVar<G>, GroupVar<G>)) -> Self {
63+
Term::from(pair).into()
64+
}
65+
}
66+
67+
impl<G: Group> From<(ScalarTerm<G>, GroupVar<G>)> for Weighted<Term<G>, G::Scalar> {
68+
fn from(pair: (ScalarTerm<G>, GroupVar<G>)) -> Self {
69+
Term::from(pair).into()
70+
}
71+
}
72+
73+
impl<G: Group> From<GroupVar<G>> for Weighted<Term<G>, G::Scalar> {
74+
fn from(value: GroupVar<G>) -> Self {
75+
Term::from(value).into()
76+
}
77+
}
78+
79+
impl<G: Group> From<Weighted<GroupVar<G>, G::Scalar>> for Weighted<Term<G>, G::Scalar> {
80+
fn from(value: Weighted<GroupVar<G>, G::Scalar>) -> Self {
81+
Weighted {
82+
term: value.term.into(),
83+
weight: value.weight,
84+
}
85+
}
86+
}
87+
88+
impl<T, F: Field> From<T> for Weighted<T, F> {
89+
fn from(term: T) -> Self {
90+
Self {
91+
term,
92+
weight: F::ONE,
93+
}
94+
}
95+
}
96+
97+
// NOTE: This is implemented directly for each of the key types to avoid collision with the blanket
98+
// Into impl provided by the standard library.
99+
macro_rules! impl_from_for_sum {
100+
($($type:ty),+) => {
101+
$(
102+
impl<G: Group, T: Into<$type>> From<T> for Sum<$type> {
103+
fn from(value: T) -> Self {
104+
Sum(vec![value.into()])
105+
}
106+
}
107+
108+
impl<G: Group, T: Into<$type>> From<Vec<T>> for Sum<$type> {
109+
fn from(terms: Vec<T>) -> Self {
110+
Self::from_iter(terms)
111+
}
112+
}
113+
114+
impl<G: Group, T: Into<$type>, const N: usize> From<[T; N]> for Sum<$type> {
115+
fn from(terms: [T; N]) -> Self {
116+
Self::from_iter(terms)
117+
}
118+
}
119+
120+
impl<G: Group, T: Into<$type>> FromIterator<T> for Sum<$type> {
121+
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
122+
Self(iter.into_iter().map(|x| x.into()).collect())
123+
}
124+
}
125+
)+
126+
};
127+
}
128+
129+
impl_from_for_sum!(
130+
ScalarVar<G>,
131+
GroupVar<G>,
132+
Term<G>,
133+
Weighted<ScalarVar<G>, G::Scalar>,
134+
Weighted<GroupVar<G>, G::Scalar>,
135+
Weighted<Term<G>, G::Scalar>
136+
);
137+
138+
impl<T, F: Field> From<Sum<T>> for Sum<Weighted<T, F>> {
139+
fn from(sum: Sum<T>) -> Self {
140+
Self(sum.0.into_iter().map(|x| x.into()).collect())
141+
}
142+
}

0 commit comments

Comments
 (0)