Skip to content

Commit 879de4f

Browse files
authored
fix: Get rid of GroupSerializationFailure, implement batch serialization
1 parent 544b143 commit 879de4f

File tree

6 files changed

+117
-195
lines changed

6 files changed

+117
-195
lines changed

src/codec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
pub use crate::duplex_sponge::keccak::KeccakDuplexSponge;
44
use crate::duplex_sponge::{shake::ShakeDuplexSponge, DuplexSpongeInterface};
5-
use crate::serialization::scalar_byte_size;
65
use ff::PrimeField;
76
use group::{Group, GroupEncoding};
87
use num_bigint::BigUint;
@@ -71,7 +70,8 @@ where
7170
}
7271

7372
fn verifier_challenge(&mut self) -> G::Scalar {
74-
let scalar_byte_length = scalar_byte_size::<G::Scalar>();
73+
#[allow(clippy::manual_div_ceil)]
74+
let scalar_byte_length = (G::Scalar::NUM_BITS as usize + 7) / 8;
7575

7676
let uniform_bytes = self.hasher.squeeze(scalar_byte_length + 16);
7777
let scalar = BigUint::from_bytes_be(&uniform_bytes);

src/composition.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
errors::Error,
1616
linear_relation::LinearRelation,
1717
schnorr_protocol::SchnorrProof,
18-
serialization::{deserialize_scalar, serialize_scalar},
18+
serialization::{deserialize_scalars, serialize_scalars},
1919
traits::{SigmaProtocol, SigmaProtocolSimulator},
2020
};
2121

@@ -270,7 +270,7 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
270270
}
271271

272272
fn serialize_challenge(&self, challenge: &Self::Challenge) -> Vec<u8> {
273-
serialize_scalar::<G>(challenge)
273+
serialize_scalars::<G>(&[*challenge])
274274
}
275275

276276
fn serialize_response(&self, response: &Self::Response) -> Vec<u8> {
@@ -286,7 +286,7 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
286286
(Protocol::Or(ps), ProtocolResponse::Or(challenges, responses)) => {
287287
let mut bytes = Vec::new();
288288
for (i, p) in ps.iter().enumerate() {
289-
bytes.extend(&serialize_scalar::<G>(&challenges[i]));
289+
bytes.extend(&serialize_scalars::<G>(&[challenges[i]]));
290290
bytes.extend(p.serialize_response(&responses[i]));
291291
}
292292
bytes
@@ -327,7 +327,8 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
327327
}
328328

329329
fn deserialize_challenge(&self, data: &[u8]) -> Result<Self::Challenge, Error> {
330-
deserialize_scalar::<G>(data)
330+
let scalars = deserialize_scalars::<G>(data, 1).ok_or(Error::VerificationFailure)?;
331+
Ok(scalars[0])
331332
}
332333

333334
fn deserialize_response(&self, data: &[u8]) -> Result<Self::Response, Error> {
@@ -355,7 +356,9 @@ impl<G: Group + GroupEncoding> SigmaProtocol for Protocol<G> {
355356
let mut challenges = Vec::with_capacity(ps.len());
356357
let mut responses = Vec::with_capacity(ps.len());
357358
for p in ps {
358-
let ch = deserialize_scalar::<G>(&data[cursor..cursor + ch_bytes_len])?;
359+
let ch_vec = deserialize_scalars::<G>(&data[cursor..cursor + ch_bytes_len], 1)
360+
.ok_or(Error::VerificationFailure)?;
361+
let ch = ch_vec[0];
359362
cursor += ch_bytes_len;
360363
let r = p.deserialize_response(&data[cursor..])?;
361364
let size = p.serialize_response(&r).len();

src/errors.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
//! - Verification failures (e.g., when a proof does not verify correctly).
88
//! - Mismatched parameters during batch verification.
99
//! - Uninitialized group variables.
10-
//! - Group element or scalar serialization failures.
1110
1211
use crate::linear_relation::GroupVar;
1312

@@ -21,9 +20,6 @@ pub enum Error {
2120
/// Indicates a mismatch in parameter sizes during batch verification.
2221
#[error("Mismatched parameter sizes for batch verification.")]
2322
ProofSizeMismatch,
24-
/// Serialization of a group element/scalar has failed.
25-
#[error("Serialization of a group element/scalar failed.")]
26-
GroupSerializationFailure,
2723
/// Uninitialized group element variable.
2824
#[error("Uninitialized group element variable {var:?}")]
2925
UnassignedGroupVar { var: GroupVar },

src/schnorr_protocol.rs

Lines changed: 24 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use crate::errors::Error;
88
use crate::linear_relation::LinearRelation;
99
use crate::{
1010
serialization::{
11-
deserialize_element, deserialize_scalar, scalar_byte_size, serialize_element,
12-
serialize_scalar,
11+
deserialize_elements, deserialize_scalars, serialize_elements, serialize_scalars,
1312
},
1413
traits::{SigmaProtocol, SigmaProtocolSimulator},
1514
};
@@ -29,11 +28,11 @@ use rand::{CryptoRng, RngCore};
2928
pub struct SchnorrProof<G: Group + GroupEncoding>(pub LinearRelation<G>);
3029

3130
impl<G: Group + GroupEncoding> SchnorrProof<G> {
32-
pub fn scalars_nb(&self) -> usize {
31+
pub fn witness_length(&self) -> usize {
3332
self.0.linear_map.num_scalars
3433
}
3534

36-
pub fn statements_nb(&self) -> usize {
35+
pub fn commitment_length(&self) -> usize {
3736
self.0.linear_map.num_constraints()
3837
}
3938
}
@@ -75,11 +74,11 @@ where
7574
witness: &Self::Witness,
7675
mut rng: &mut (impl RngCore + CryptoRng),
7776
) -> Result<(Self::Commitment, Self::ProverState), Error> {
78-
if witness.len() != self.scalars_nb() {
77+
if witness.len() != self.witness_length() {
7978
return Err(Error::ProofSizeMismatch);
8079
}
8180

82-
let nonces: Vec<G::Scalar> = (0..self.scalars_nb())
81+
let nonces: Vec<G::Scalar> = (0..self.witness_length())
8382
.map(|_| G::Scalar::random(&mut rng))
8483
.collect();
8584
let prover_state = (nonces.clone(), witness.clone());
@@ -100,16 +99,18 @@ where
10099
/// - Returns [`Error::ProofSizeMismatch`] if the prover state vectors have incorrect lengths.
101100
fn prover_response(
102101
&self,
103-
state: Self::ProverState,
102+
prover_state: Self::ProverState,
104103
challenge: &Self::Challenge,
105104
) -> Result<Self::Response, Error> {
106-
if state.0.len() != self.scalars_nb() || state.1.len() != self.scalars_nb() {
105+
let (nonces, witness) = prover_state;
106+
107+
if nonces.len() != self.witness_length() || witness.len() != self.witness_length() {
107108
return Err(Error::ProofSizeMismatch);
108109
}
109110

110111
let mut responses = Vec::new();
111-
for i in 0..self.scalars_nb() {
112-
responses.push(state.0[i] + state.1[i] * challenge);
112+
for i in 0..self.witness_length() {
113+
responses.push(nonces[i] + witness[i] * challenge);
113114
}
114115
Ok(responses)
115116
}
@@ -135,13 +136,13 @@ where
135136
challenge: &Self::Challenge,
136137
response: &Self::Response,
137138
) -> Result<(), Error> {
138-
if commitment.len() != self.statements_nb() || response.len() != self.scalars_nb() {
139+
if commitment.len() != self.commitment_length() || response.len() != self.witness_length() {
139140
return Err(Error::ProofSizeMismatch);
140141
}
141142

142143
let lhs = self.0.linear_map.evaluate(response)?;
143144
let mut rhs = Vec::new();
144-
for (i, g) in commitment.iter().enumerate().take(self.statements_nb()) {
145+
for (i, g) in commitment.iter().enumerate().take(self.commitment_length()) {
145146
rhs.push({
146147
let image_var = self.0.image[i];
147148
self.0.linear_map.group_elements.get(image_var)? * challenge + g
@@ -166,23 +167,15 @@ where
166167
/// # Errors
167168
/// - [`Error::ProofSizeMismatch`] if the commitment or response length is incorrect.
168169
fn serialize_commitment(&self, commitment: &Self::Commitment) -> Vec<u8> {
169-
let mut bytes = Vec::new();
170-
for commit in commitment {
171-
bytes.extend_from_slice(&serialize_element(commit));
172-
}
173-
bytes
170+
serialize_elements(commitment)
174171
}
175172

176173
fn serialize_challenge(&self, challenge: &Self::Challenge) -> Vec<u8> {
177-
serialize_scalar::<G>(challenge)
174+
serialize_scalars::<G>(&[*challenge])
178175
}
179176

180177
fn serialize_response(&self, response: &Self::Response) -> Vec<u8> {
181-
let mut bytes = Vec::new();
182-
for resp in response {
183-
bytes.extend_from_slice(&serialize_scalar::<G>(resp));
184-
}
185-
bytes
178+
serialize_scalars::<G>(response)
186179
}
187180

188181
/// Deserializes a batchable proof into a commitment vector and response vector.
@@ -198,57 +191,19 @@ where
198191
/// # Errors
199192
/// - [`Error::ProofSizeMismatch`] if the input length is not the exact number of bytes
200193
/// expected for `commit_nb` commitments plus `response_nb` responses.
201-
/// - [`Error::GroupSerializationFailure`] if any group element or scalar fails to
202-
/// deserialize (propagated from `deserialize_element` or `deserialize_scalar`).
194+
/// - [`Error::VerificationFailure`] if any group element or scalar fails to
195+
/// deserialize (invalid encoding).
203196
fn deserialize_commitment(&self, data: &[u8]) -> Result<Self::Commitment, Error> {
204-
let commit_nb = self.statements_nb();
205-
let commit_size = G::generator().to_bytes().as_ref().len();
206-
let expected_len = commit_nb * commit_size;
207-
208-
if data.len() < expected_len {
209-
return Err(Error::ProofSizeMismatch);
210-
}
211-
212-
let mut commitments: Self::Commitment = Vec::new();
213-
for i in 0..commit_nb {
214-
let start = i * commit_size;
215-
let end = start + commit_size;
216-
let slice = &data[start..end];
217-
let elem = deserialize_element(slice)?;
218-
commitments.push(elem);
219-
}
220-
221-
Ok(commitments)
197+
deserialize_elements::<G>(data, self.commitment_length()).ok_or(Error::VerificationFailure)
222198
}
223199

224200
fn deserialize_challenge(&self, data: &[u8]) -> Result<Self::Challenge, Error> {
225-
let scalar_size = scalar_byte_size::<G::Scalar>();
226-
if data.len() < scalar_size {
227-
return Err(Error::ProofSizeMismatch);
228-
}
229-
let challenge = deserialize_scalar::<G>(&data[..scalar_size])?;
230-
Ok(challenge)
201+
let scalars = deserialize_scalars::<G>(data, 1).ok_or(Error::VerificationFailure)?;
202+
Ok(scalars[0])
231203
}
232204

233205
fn deserialize_response(&self, data: &[u8]) -> Result<Self::Response, Error> {
234-
let response_nb = self.scalars_nb();
235-
let response_size = scalar_byte_size::<G::Scalar>();
236-
let expected_len = response_nb * response_size;
237-
238-
if data.len() < expected_len {
239-
return Err(Error::ProofSizeMismatch);
240-
}
241-
242-
let mut responses: Self::Response = Vec::new();
243-
for i in 0..response_nb {
244-
let start = i * response_size;
245-
let end = start + response_size;
246-
let slice = &data[start..end];
247-
let scalar = deserialize_scalar::<G>(slice)?;
248-
responses.push(scalar);
249-
}
250-
251-
Ok(responses)
206+
deserialize_scalars::<G>(data, self.witness_length()).ok_or(Error::VerificationFailure)
252207
}
253208

254209
/// Recomputes the commitment from the challenge and response (used in compact proofs).
@@ -267,7 +222,7 @@ where
267222
challenge: &Self::Challenge,
268223
response: &Self::Response,
269224
) -> Result<Self::Commitment, Error> {
270-
if response.len() != self.scalars_nb() {
225+
if response.len() != self.witness_length() {
271226
return Err(Error::ProofSizeMismatch);
272227
}
273228

@@ -299,7 +254,7 @@ where
299254
challenge: &Self::Challenge,
300255
mut rng: &mut (impl RngCore + CryptoRng),
301256
) -> (Self::Commitment, Self::Response) {
302-
let response: Vec<G::Scalar> = (0..self.scalars_nb())
257+
let response: Vec<G::Scalar> = (0..self.witness_length())
303258
.map(|_| G::Scalar::random(&mut rng))
304259
.collect();
305260

0 commit comments

Comments
 (0)