Skip to content

Commit 3f44c8c

Browse files
authored
chore: refactor SchnorrProof implementation for improved code quality (#49)
1 parent c4a1d3e commit 3f44c8c

File tree

2 files changed

+75
-29
lines changed

2 files changed

+75
-29
lines changed

src/duplex_sponge/keccak.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,4 @@ mod tests {
124124
assert_eq!(out1, expected_output);
125125
assert_eq!(out2, expected_output);
126126
}
127-
128127
}

src/schnorr_protocol.rs

Lines changed: 75 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,11 @@ where
108108
return Err(Error::ProofSizeMismatch);
109109
}
110110

111-
let mut responses = Vec::new();
112-
for i in 0..self.witness_length() {
113-
responses.push(nonces[i] + witness[i] * challenge);
114-
}
111+
let responses = nonces
112+
.into_iter()
113+
.zip(witness)
114+
.map(|(r, w)| r + w * challenge)
115+
.collect();
115116
Ok(responses)
116117
}
117118
/// Verifies the correctness of the proof.
@@ -148,60 +149,105 @@ where
148149
self.0.linear_map.group_elements.get(image_var)? * challenge + g
149150
});
150151
}
151-
match lhs == rhs {
152-
true => Ok(()),
153-
false => Err(Error::VerificationFailure),
152+
if lhs == rhs {
153+
Ok(())
154+
} else {
155+
Err(Error::VerificationFailure)
154156
}
155157
}
156158

157-
/// Serializes the proof into a batchable format: commitments followed by responses.
159+
/// Serializes the prover's commitment into a byte vector.
160+
///
161+
/// This function encodes the vector of group elements (the commitment)
162+
/// into a binary format suitable for transmission or storage. This is
163+
/// typically the first message sent in a Sigma protocol round.
158164
///
159165
/// # Parameters
160-
/// - `commitment`: A vector of group elements (typically sent in the first round).
161-
/// - `_challenge`: The verifier’s challenge (omitted from batchable format).
162-
/// - `response`: A vector of scalars forming the prover’s response.
166+
/// - `commitment`: A vector of group elements representing the prover's commitment.
163167
///
164168
/// # Returns
165-
/// - A byte vector representing the serialized batchable proof.
166-
///
167-
/// # Errors
168-
/// - [`Error::ProofSizeMismatch`] if the commitment or response length is incorrect.
169+
/// A `Vec<u8>` containing the serialized group elements.
169170
fn serialize_commitment(&self, commitment: &Self::Commitment) -> Vec<u8> {
170171
serialize_elements(commitment)
171172
}
172173

174+
/// Serializes the verifier's challenge scalar into bytes.
175+
///
176+
/// Converts the challenge scalar into a fixed-length byte encoding. This can be used
177+
/// for Fiat–Shamir hashing, transcript recording, or proof transmission.
178+
///
179+
/// # Parameters
180+
/// - `challenge`: The scalar challenge value.
181+
///
182+
/// # Returns
183+
/// A `Vec<u8>` containing the serialized scalar.
173184
fn serialize_challenge(&self, challenge: &Self::Challenge) -> Vec<u8> {
174185
serialize_scalars::<G>(&[*challenge])
175186
}
176187

188+
/// Serializes the prover's response vector into a byte format.
189+
///
190+
/// The response is a vector of scalars computed by the prover after receiving
191+
/// the verifier's challenge. This function encodes the vector into a format
192+
/// suitable for transmission or inclusion in a batchable proof.
193+
///
194+
/// # Parameters
195+
/// - `response`: A vector of scalar responses computed by the prover.
196+
///
197+
/// # Returns
198+
/// A `Vec<u8>` containing the serialized scalars.
177199
fn serialize_response(&self, response: &Self::Response) -> Vec<u8> {
178200
serialize_scalars::<G>(response)
179201
}
180202

181-
/// Deserializes a batchable proof into a commitment vector and response vector.
203+
/// Deserializes a byte slice into a vector of group elements (commitment).
204+
///
205+
/// This function reconstructs the prover’s commitment from its binary representation.
206+
/// The number of elements expected is determined by the number of linear constraints
207+
/// in the underlying linear relation.
182208
///
183209
/// # Parameters
184-
/// - `data`: A byte slice containing the serialized proof.
210+
/// - `data`: A byte slice containing the serialized commitment.
185211
///
186212
/// # Returns
187-
/// - A tuple `(commitment, response)` where
188-
/// * `commitment` is a vector of group elements, and
189-
/// * `response` is a vector of scalars.
213+
/// A `Vec<G>` containing the deserialized group elements.
190214
///
191215
/// # Errors
192-
/// - [`Error::ProofSizeMismatch`] if the input length is not the exact number of bytes
193-
/// expected for `commit_nb` commitments plus `response_nb` responses.
194-
/// - [`Error::VerificationFailure`] if any group element or scalar fails to
195-
/// deserialize (invalid encoding).
216+
/// - Returns [`Error::VerificationFailure`] if the data is malformed or contains an invalid encoding.
196217
fn deserialize_commitment(&self, data: &[u8]) -> Result<Self::Commitment, Error> {
197218
deserialize_elements::<G>(data, self.commitment_length()).ok_or(Error::VerificationFailure)
198219
}
199220

221+
/// Deserializes a byte slice into a challenge scalar.
222+
///
223+
/// This function expects a single scalar to be encoded and returns it as the verifier's challenge.
224+
///
225+
/// # Parameters
226+
/// - `data`: A byte slice containing the serialized scalar challenge.
227+
///
228+
/// # Returns
229+
/// The deserialized scalar challenge value.
230+
///
231+
/// # Errors
232+
/// - Returns [`Error::VerificationFailure`] if deserialization fails or data is invalid.
200233
fn deserialize_challenge(&self, data: &[u8]) -> Result<Self::Challenge, Error> {
201234
let scalars = deserialize_scalars::<G>(data, 1).ok_or(Error::VerificationFailure)?;
202235
Ok(scalars[0])
203236
}
204237

238+
/// Deserializes a byte slice into the prover's response vector.
239+
///
240+
/// The response vector contains scalars used in the second round of the Sigma protocol.
241+
/// The expected number of scalars matches the number of witness variables.
242+
///
243+
/// # Parameters
244+
/// - `data`: A byte slice containing the serialized response.
245+
///
246+
/// # Returns
247+
/// A vector of deserialized scalars.
248+
///
249+
/// # Errors
250+
/// - Returns [`Error::VerificationFailure`] if the byte data is malformed or the length is incorrect.
205251
fn deserialize_response(&self, data: &[u8]) -> Result<Self::Response, Error> {
206252
deserialize_scalars::<G>(data, self.witness_length()).ok_or(Error::VerificationFailure)
207253
}
@@ -229,10 +275,11 @@ where
229275
let response_image = self.0.linear_map.evaluate(response)?;
230276
let image = self.0.image()?;
231277

232-
let mut commitment = Vec::new();
233-
for i in 0..image.len() {
234-
commitment.push(response_image[i] - image[i] * challenge);
235-
}
278+
let commitment = response_image
279+
.iter()
280+
.zip(&image)
281+
.map(|(res, img)| *res - *img * challenge)
282+
.collect::<Vec<_>>();
236283
Ok(commitment)
237284
}
238285
}

0 commit comments

Comments
 (0)