diff --git a/plonk/CHANGELOG.md b/plonk/CHANGELOG.md index 7af6b1e9f..9fc4c62b2 100644 --- a/plonk/CHANGELOG.md +++ b/plonk/CHANGELOG.md @@ -3,6 +3,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Breaking Changes + +### Non-breaking Changes + +## 0.5.1 (2024-09-04) + +### Breaking Changes + +- [#648](https://github.com/EspressoSystems/jellyfish/pull/648) Refactored `trait Transcript`; Updated `SolidityTranscript` to use `state`-based logic correctly + +### Non-breaking Changes + +- [#647](https://github.com/EspressoSystems/jellyfish/pull/647) Append G2 points from SRS to `Transcript` + + ## 0.5.0 (2024-07-02) ### Breaking Changes diff --git a/plonk/Cargo.toml b/plonk/Cargo.toml index ceec852e5..5c5e0898a 100644 --- a/plonk/Cargo.toml +++ b/plonk/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "jf-plonk" description = "TurboPlonk and UntraPlonk implementation." -version = "0.5.0" +version = "0.5.1" authors = { workspace = true } edition = { workspace = true } license = { workspace = true } diff --git a/plonk/src/circuit/plonk_verifier/gadgets.rs b/plonk/src/circuit/plonk_verifier/gadgets.rs index cb3e50947..c50dde1b9 100644 --- a/plonk/src/circuit/plonk_verifier/gadgets.rs +++ b/plonk/src/circuit/plonk_verifier/gadgets.rs @@ -229,25 +229,25 @@ where transcript_var.append_commitments_vars(b"witness_poly_comms", wires_poly_comms)?; } - let beta = transcript_var.get_and_append_challenge_var::(b"beta", circuit)?; - let gamma = transcript_var.get_and_append_challenge_var::(b"gamma", circuit)?; + let beta = transcript_var.get_challenge_var::(b"beta", circuit)?; + let gamma = transcript_var.get_challenge_var::(b"gamma", circuit)?; for prod_perm_poly_comm in batch_proof.prod_perm_poly_comms_vec.iter() { transcript_var.append_commitment_var(b"perm_poly_comms", prod_perm_poly_comm)?; } - let alpha = transcript_var.get_and_append_challenge_var::(b"alpha", circuit)?; + let alpha = transcript_var.get_challenge_var::(b"alpha", circuit)?; transcript_var .append_commitments_vars(b"quot_poly_comms", &batch_proof.split_quot_poly_comms)?; - let zeta = transcript_var.get_and_append_challenge_var::(b"zeta", circuit)?; + let zeta = transcript_var.get_challenge_var::(b"zeta", circuit)?; for poly_evals in batch_proof.poly_evals_vec.iter() { transcript_var.append_proof_evaluations_vars(circuit, poly_evals)?; } - let v = transcript_var.get_and_append_challenge_var::(b"v", circuit)?; + let v = transcript_var.get_challenge_var::(b"v", circuit)?; transcript_var.append_commitment_var(b"open_proof", &batch_proof.opening_proof)?; transcript_var .append_commitment_var(b"shifted_open_proof", &batch_proof.shifted_opening_proof)?; - let u = transcript_var.get_and_append_challenge_var::(b"u", circuit)?; + let u = transcript_var.get_challenge_var::(b"u", circuit)?; // convert challenge vars into FpElemVars let challenge_var = ChallengesVar { diff --git a/plonk/src/circuit/transcript.rs b/plonk/src/circuit/transcript.rs index e53fc85ee..6641fb098 100644 --- a/plonk/src/circuit/transcript.rs +++ b/plonk/src/circuit/transcript.rs @@ -137,16 +137,6 @@ where Ok(()) } - // Append a challenge variable to the transcript. - // For efficiency purpose, label is not used for rescue FS. - pub(crate) fn append_challenge_var( - &mut self, - _label: &'static [u8], - challenge_var: &Variable, - ) -> Result<(), CircuitError> { - self.append_variable(_label, challenge_var) - } - // Append the proof evaluation to the transcript pub(crate) fn append_proof_evaluations_vars( &mut self, @@ -171,7 +161,9 @@ where // For efficiency purpose, label is not used for rescue FS. // Note that this function currently only supports bls12-377 // curve due to its decomposition method. - pub(crate) fn get_and_append_challenge_var( + // + // `_label` is omitted for efficiency. + pub(crate) fn get_challenge_var( &mut self, _label: &'static [u8], circuit: &mut PlonkCircuit, @@ -193,7 +185,7 @@ where // This algorithm takes in 3 steps // 1. state: [F: STATE_SIZE] = hash(state|transcript) // 2. challenge = state[0] in Fr - // 3. transcript = vec![challenge] + // 3. transcript = vec![] // ================================== // step 1. state: [F: STATE_SIZE] = hash(state|transcript) @@ -210,7 +202,6 @@ where // finish and update the states self.state_var.copy_from_slice(&res_var[0..STATE_SIZE]); self.transcript_var = Vec::new(); - self.append_challenge_var(_label, &challenge_var)?; Ok(challenge_var) } @@ -267,10 +258,10 @@ mod tests { .unwrap(); } - let challenge = transcript.get_and_append_challenge::(label).unwrap(); + let challenge = transcript.get_challenge::(label).unwrap(); let challenge_var = transcript_var - .get_and_append_challenge_var::(label, &mut circuit) + .get_challenge_var::(label, &mut circuit) .unwrap(); assert_eq!( @@ -329,10 +320,10 @@ mod tests { .append_vk_and_pub_input_vars::(&mut circuit, &dummy_vk_var, &[]) .unwrap(); - let challenge = transcript.get_and_append_challenge::(label).unwrap(); + let challenge = transcript.get_challenge::(label).unwrap(); let challenge_var = transcript_var - .get_and_append_challenge_var::(label, &mut circuit) + .get_challenge_var::(label, &mut circuit) .unwrap(); assert_eq!( @@ -398,10 +389,10 @@ mod tests { .append_vk_and_pub_input_vars::(&mut circuit, &vk_var, &input_fp_elem_vars) .unwrap(); - let challenge = transcript.get_and_append_challenge::(label).unwrap(); + let challenge = transcript.get_challenge::(label).unwrap(); let challenge_var = transcript_var - .get_and_append_challenge_var::(label, &mut circuit) + .get_challenge_var::(label, &mut circuit) .unwrap(); assert_eq!( diff --git a/plonk/src/constants.rs b/plonk/src/constants.rs index 0653d928b..7cbb32184 100644 --- a/plonk/src/constants.rs +++ b/plonk/src/constants.rs @@ -18,3 +18,6 @@ pub(crate) const EXTRA_TRANSCRIPT_MSG_LABEL: &[u8] = b"extra info"; pub(crate) const fn domain_size_ratio(n: usize, num_wire_types: usize) -> usize { (num_wire_types * (n + 1) + 2) / n + 1 } + +/// Keccak-256 have a 32 byte state size. +pub const KECCAK256_STATE_SIZE: usize = 32; diff --git a/plonk/src/proof_system/snark.rs b/plonk/src/proof_system/snark.rs index 66d08f160..1c92d60f8 100644 --- a/plonk/src/proof_system/snark.rs +++ b/plonk/src/proof_system/snark.rs @@ -255,7 +255,7 @@ where // Plookup: compute and interpolate the sorted concatenation of the (merged) // lookup table and the (merged) witness values if circuits.iter().any(|c| C::support_lookup(c)) { - challenges.tau = Some(transcript.get_and_append_challenge::(b"tau")?); + challenges.tau = Some(transcript.get_challenge::(b"tau")?); } else { challenges.tau = None; } @@ -284,8 +284,8 @@ where } // Round 2 - challenges.beta = transcript.get_and_append_challenge::(b"beta")?; - challenges.gamma = transcript.get_and_append_challenge::(b"gamma")?; + challenges.beta = transcript.get_challenge::(b"beta")?; + challenges.gamma = transcript.get_challenge::(b"gamma")?; let mut prod_perm_poly_comms_vec = vec![]; for i in 0..circuits.len() { let (prod_perm_poly_comm, prod_perm_poly) = @@ -318,7 +318,7 @@ where } // Round 3 - challenges.alpha = transcript.get_and_append_challenge::(b"alpha")?; + challenges.alpha = transcript.get_challenge::(b"alpha")?; let (split_quot_poly_comms, split_quot_polys) = prover.run_3rd_round( prng, &prove_keys[0].commit_key, @@ -330,7 +330,7 @@ where transcript.append_commitments(b"quot_poly_comms", &split_quot_poly_comms)?; // Round 4 - challenges.zeta = transcript.get_and_append_challenge::(b"zeta")?; + challenges.zeta = transcript.get_challenge::(b"zeta")?; let mut poly_evals_vec = vec![]; for i in 0..circuits.len() { let poly_evals = prover.compute_evaluations( @@ -389,7 +389,7 @@ where } // Round 5 - challenges.v = transcript.get_and_append_challenge::(b"v")?; + challenges.v = transcript.get_challenge::(b"v")?; let (opening_proof, shifted_opening_proof) = prover.compute_opening_proofs( &prove_keys[0].commit_key, prove_keys, diff --git a/plonk/src/proof_system/verifier.rs b/plonk/src/proof_system/verifier.rs index 3f6643b90..7d1b3cbf1 100644 --- a/plonk/src/proof_system/verifier.rs +++ b/plonk/src/proof_system/verifier.rs @@ -215,9 +215,9 @@ where // protocol transcript. This approach is more secure as `r` depends not only // on the proofs, but also the list of public inputs and verifying keys. for pcs_info in pcs_infos { - transcript.append_challenge::(b"u", &pcs_info.u)?; + transcript.append_field_elem::(b"u", &pcs_info.u)?; } - transcript.get_and_append_challenge::(b"r")? + transcript.get_challenge::(b"r")? }; // Compute A := A0 + r * A1 + ... + r^{m-1} * Am @@ -288,7 +288,7 @@ where transcript.append_commitments(b"witness_poly_comms", wires_poly_comms)?; } let tau = if verify_keys.iter().any(|vk| vk.plookup_vk.is_some()) { - Some(transcript.get_and_append_challenge::(b"tau")?) + Some(transcript.get_challenge::(b"tau")?) } else { None }; @@ -299,8 +299,8 @@ where } } - let beta = transcript.get_and_append_challenge::(b"beta")?; - let gamma = transcript.get_and_append_challenge::(b"gamma")?; + let beta = transcript.get_challenge::(b"beta")?; + let gamma = transcript.get_challenge::(b"gamma")?; for prod_perm_poly_comm in batch_proof.prod_perm_poly_comms_vec.iter() { transcript.append_commitment(b"perm_poly_comms", prod_perm_poly_comm)?; } @@ -311,9 +311,9 @@ where } } - let alpha = transcript.get_and_append_challenge::(b"alpha")?; + let alpha = transcript.get_challenge::(b"alpha")?; transcript.append_commitments(b"quot_poly_comms", &batch_proof.split_quot_poly_comms)?; - let zeta = transcript.get_and_append_challenge::(b"zeta")?; + let zeta = transcript.get_challenge::(b"zeta")?; for poly_evals in batch_proof.poly_evals_vec.iter() { transcript.append_proof_evaluations::(poly_evals)?; } @@ -323,10 +323,10 @@ where } } - let v = transcript.get_and_append_challenge::(b"v")?; + let v = transcript.get_challenge::(b"v")?; transcript.append_commitment(b"open_proof", &batch_proof.opening_proof)?; transcript.append_commitment(b"shifted_open_proof", &batch_proof.shifted_opening_proof)?; - let u = transcript.get_and_append_challenge::(b"u")?; + let u = transcript.get_challenge::(b"u")?; Ok(Challenges { tau, alpha, diff --git a/plonk/src/testing_apis.rs b/plonk/src/testing_apis.rs index c87492884..74aebacc1 100644 --- a/plonk/src/testing_apis.rs +++ b/plonk/src/testing_apis.rs @@ -12,6 +12,7 @@ #![allow(missing_docs)] use crate::{ + constants::KECCAK256_STATE_SIZE, errors::PlonkError, lagrange::LagrangeCoeffs, proof_system::{ @@ -379,12 +380,12 @@ where /// exposing the internal states for testing purposes impl SolidityTranscript { /// Create a new transcript from specific internal states. - pub fn from_internal(transcript: Vec) -> Self { - Self { transcript } + pub fn from_internal(state: [u8; KECCAK256_STATE_SIZE], transcript: Vec) -> Self { + Self { state, transcript } } /// Returns the internal states - pub fn internal(&self) -> Vec { - self.transcript.clone() + pub fn internal(&self) -> ([u8; KECCAK256_STATE_SIZE], Vec) { + (self.state.clone(), self.transcript.clone()) } } diff --git a/plonk/src/transcript/mod.rs b/plonk/src/transcript/mod.rs index ab455fe27..7162bb4ad 100644 --- a/plonk/src/transcript/mod.rs +++ b/plonk/src/transcript/mod.rs @@ -24,6 +24,7 @@ use ark_ec::{ short_weierstrass::{Affine, SWCurveConfig as SWParam}, }; use ark_ff::PrimeField; +use ark_std::vec::Vec; use jf_pcs::prelude::Commitment; use jf_utils::to_bytes; @@ -51,8 +52,7 @@ pub trait PlonkTranscript { E: Pairing>, P: SWParam, { - >::append_message( - self, + self.append_message( b"field size in bits", E::ScalarField::MODULUS_BIT_SIZE.to_le_bytes().as_ref(), )?; @@ -67,36 +67,18 @@ pub trait PlonkTranscript { vk.num_inputs.to_le_bytes().as_ref(), )?; - for ki in vk.k.iter() { - >::append_message( - self, - b"wire subsets separators", - &to_bytes!(ki)?, - )?; - } - for selector_com in vk.selector_comms.iter() { - >::append_message( - self, - b"selector commitments", - &to_bytes!(selector_com)?, - )?; - } - - for sigma_comms in vk.sigma_comms.iter() { - >::append_message( - self, - b"sigma commitments", - &to_bytes!(sigma_comms)?, - )?; - } + // include [x]_2 G2 point from SRS + // all G1 points from SRS are implicit reflected in committed polys + >::append_message( + self, + b"SRS G2 element", + &to_bytes!(&vk.open_key.powers_of_h[1])?, + )?; - for input in pub_input.iter() { - >::append_message( - self, - b"public input", - &to_bytes!(input)?, - )?; - } + self.append_field_elems::(b"wire subsets separators", &vk.k)?; + self.append_commitments(b"selector commitments", &vk.selector_comms)?; + self.append_commitments(b"sigma commitments", &vk.sigma_comms)?; + self.append_field_elems::(b"public input", pub_input)?; Ok(()) } @@ -133,83 +115,77 @@ pub trait PlonkTranscript { >::append_message(self, label, &to_bytes!(comm)?) } - /// Append a challenge to the transcript. - fn append_challenge( + /// Append a field element to the transcript. + fn append_field_elem( &mut self, label: &'static [u8], - challenge: &E::ScalarField, + field: &E::ScalarField, ) -> Result<(), PlonkError> where E: Pairing, { - >::append_message(self, label, &to_bytes!(challenge)?) + >::append_message(self, label, &to_bytes!(field)?) + } + + /// Append a list of field elements to the transcript + fn append_field_elems( + &mut self, + label: &'static [u8], + fields: &[E::ScalarField], + ) -> Result<(), PlonkError> + where + E: Pairing, + { + for f in fields { + self.append_field_elem::(label, f)?; + } + Ok(()) } /// Append a proof evaluation to the transcript. - fn append_proof_evaluations( + fn append_proof_evaluations>( &mut self, evals: &ProofEvaluations, ) -> Result<(), PlonkError> { - for w_eval in &evals.wires_evals { - >::append_message(self, b"wire_evals", &to_bytes!(w_eval)?)?; - } - for sigma_eval in &evals.wire_sigma_evals { - >::append_message( - self, - b"wire_sigma_evals", - &to_bytes!(sigma_eval)?, - )?; - } - >::append_message( - self, - b"perm_next_eval", - &to_bytes!(&evals.perm_next_eval)?, - ) + self.append_field_elems::(b"wire_evals", &evals.wires_evals)?; + self.append_field_elems::(b"wire_sigma_evals", &evals.wire_sigma_evals)?; + self.append_field_elem::(b"perm_next_eval", &evals.perm_next_eval) } /// Append the plookup evaluation to the transcript. - fn append_plookup_evaluations( + fn append_plookup_evaluations>( &mut self, evals: &PlookupEvaluations, ) -> Result<(), PlonkError> { - >::append_message( - self, - b"lookup_table_eval", - &to_bytes!(&evals.range_table_eval)?, - )?; - >::append_message( - self, - b"h_1_eval", - &to_bytes!(&evals.h_1_eval)?, - )?; - >::append_message( - self, - b"prod_next_eval", - &to_bytes!(&evals.prod_next_eval)?, - )?; - >::append_message( - self, - b"lookup_table_next_eval", - &to_bytes!(&evals.range_table_next_eval)?, - )?; - >::append_message( - self, - b"h_1_next_eval", - &to_bytes!(&evals.h_1_next_eval)?, - )?; - >::append_message( - self, - b"h_2_next_eval", - &to_bytes!(&evals.h_2_next_eval)?, - ) + self.append_field_elem::(b"lookup_table_eval", &evals.range_table_eval)?; + self.append_field_elem::(b"h_1_eval", &evals.h_1_eval)?; + self.append_field_elem::(b"prod_next_eval", &evals.prod_next_eval)?; + self.append_field_elem::(b"lookup_table_next_eval", &evals.range_table_next_eval)?; + self.append_field_elem::(b"h_1_next_eval", &evals.h_1_next_eval)?; + self.append_field_elem::(b"h_2_next_eval", &evals.h_2_next_eval) } - /// Generate the challenge for the current transcript, - /// and then append it to the transcript. - fn get_and_append_challenge( - &mut self, - label: &'static [u8], - ) -> Result + /// Generate a single challenge for the current round + fn get_challenge(&mut self, label: &'static [u8]) -> Result where E: Pairing; + + /// Generate multiple challenges for the current round + /// Implementers should be careful about domain separation for each + /// challenge The default implementation assume `self.get_challenge()` + /// already implements proper domain separation for each challenge + /// generation, thus simply call it multiple times. + fn get_n_challenges( + &mut self, + labels: &[&'static [u8]], + ) -> Result, PlonkError> + where + E: Pairing, + { + let mut challenges = Vec::new(); + for label in labels { + challenges.push(self.get_challenge::(label)?); + } + Ok(challenges) + } } diff --git a/plonk/src/transcript/rescue.rs b/plonk/src/transcript/rescue.rs index b2d8b6e86..a2928b8d0 100644 --- a/plonk/src/transcript/rescue.rs +++ b/plonk/src/transcript/rescue.rs @@ -33,7 +33,7 @@ use jf_utils::{bytes_to_field_elements, field_switching, fq_to_fr_with_mask}; /// /// 1. state: \[F: STATE_SIZE\] = hash(state|transcript) /// 2. challenge = state\[0\] -/// 3. transcript = vec!\[challenge\] +/// 3. transcript = vec!\[\] pub struct RescueTranscript where F: RescueParameter, @@ -123,9 +123,7 @@ where Ok(()) } - /// Append a challenge to the transcript. `_label` is omitted for - /// efficiency. - fn append_challenge( + fn append_field_elem( &mut self, _label: &'static [u8], challenge: &E::ScalarField, @@ -165,12 +163,8 @@ where } /// Generate the challenge for the current transcript, - /// and then append it to the transcript. `_label` is omitted for - /// efficiency. - fn get_and_append_challenge( - &mut self, - _label: &'static [u8], - ) -> Result + /// `_label` is omitted for efficiency. + fn get_challenge(&mut self, _label: &'static [u8]) -> Result where E: Pairing, { @@ -183,7 +177,6 @@ where let challenge = fq_to_fr_with_mask::(&tmp[0]); self.state.copy_from_slice(&tmp); self.transcript = Vec::new(); - self.transcript.push(field_switching(&challenge)); Ok(challenge) } diff --git a/plonk/src/transcript/solidity.rs b/plonk/src/transcript/solidity.rs index 7458ef116..c385a3204 100644 --- a/plonk/src/transcript/solidity.rs +++ b/plonk/src/transcript/solidity.rs @@ -7,8 +7,7 @@ //! This module implements solidity transcript. use super::PlonkTranscript; use crate::{ - errors::PlonkError, - proof_system::structs::{ProofEvaluations, VerifyingKey}, + constants::KECCAK256_STATE_SIZE, errors::PlonkError, proof_system::structs::VerifyingKey, }; use ark_ec::{ pairing::Pairing, @@ -18,19 +17,20 @@ use ark_ec::{ use ark_ff::{BigInteger, PrimeField}; use ark_std::vec::Vec; use jf_pcs::prelude::Commitment; +use jf_utils::to_bytes; use sha3::{Digest, Keccak256}; /// Transcript with `keccak256` hash function. /// -/// It is currently implemented simply as -/// - an append only vector of field elements +/// We append new elements to the transcript vector, +/// and when a challenge is generated, the state is updated and transcript is +/// emptied. /// -/// We keep appending new elements to the transcript vector, -/// and when a challenge is generated they are appended too. -/// -/// 1. challenge = hash(transcript) -/// 2. transcript = transcript || challenge +/// 1. state = hash(state | transcript) +/// 2. transcript = Vec::new() +/// 3. challenge = bytes_to_field(state) pub struct SolidityTranscript { + pub(crate) state: [u8; KECCAK256_STATE_SIZE], pub(crate) transcript: Vec, } @@ -38,6 +38,7 @@ impl PlonkTranscript for SolidityTranscript { /// Create a new plonk transcript. `label` is omitted for efficiency. fn new(_label: &'static [u8]) -> Self { SolidityTranscript { + state: [0u8; KECCAK256_STATE_SIZE], transcript: Vec::new(), } } @@ -75,14 +76,13 @@ impl PlonkTranscript for SolidityTranscript { } // override default implementation since we want to use BigEndian serialization - fn append_challenge( + fn append_field_elem( &mut self, label: &'static [u8], challenge: &E::ScalarField, ) -> Result<(), PlonkError> where E: Pairing, - E::ScalarField: PrimeField, { >::append_message( self, @@ -116,83 +116,52 @@ impl PlonkTranscript for SolidityTranscript { b"input size", vk.num_inputs.to_be_bytes().as_ref(), )?; - - for ki in vk.k.iter() { - >::append_message( - self, - b"wire subsets separators", - &ki.into_bigint().to_bytes_be(), - )?; - } - >::append_commitments( - self, - b"selector commitments", - &vk.selector_comms, - )?; - >::append_commitments( + // in EVM, memory word size is 32 bytes, the first 3 fields put onto the + // transcript occupies 4+8+8=20 bytes, thus to align with the memory + // boundray, we pad with 12 bytes of zeros. + >::append_message( self, - b"sigma commitments", - &vk.sigma_comms, + b"EVM word alignment padding", + &[0u8; 12], )?; - for input in pub_input.iter() { - >::append_message( - self, - b"public input", - &input.into_bigint().to_bytes_be(), - )?; - } - - Ok(()) - } - - fn append_proof_evaluations( - &mut self, - evals: &ProofEvaluations, - ) -> Result<(), PlonkError> - where - E::ScalarField: PrimeField, - { - for w_eval in &evals.wires_evals { - >::append_message( - self, - b"wire_evals", - &w_eval.into_bigint().to_bytes_be(), - )?; - } - for sigma_eval in &evals.wire_sigma_evals { - >::append_message( - self, - b"wire_sigma_evals", - &sigma_eval.into_bigint().to_bytes_be(), - )?; - } + // include [x]_2 G2 point from SRS + // all G1 points from SRS are implicit reflected in committed polys + // + // Since this is a fixed value, we don't need solidity-efficient serialization, + // we simply append the `to_bytes!()` which uses compressed, little-endian form + // instead of other proof-dependent field like number of public inputs or + // concrete polynomial commitments which uses uncompressed, big-endian + // form. >::append_message( self, - b"perm_next_eval", - &evals.perm_next_eval.into_bigint().to_bytes_be(), - ) + b"SRS G2 element", + &to_bytes!(&vk.open_key.powers_of_h[1])?, + )?; + + self.append_field_elems::(b"wire subsets separators", &vk.k)?; + self.append_commitments(b"selector commitments", &vk.selector_comms)?; + self.append_commitments(b"sigma commitments", &vk.sigma_comms)?; + self.append_field_elems::(b"public input", pub_input) } - /// Generate the challenge for the current transcript, - /// and then append it to the transcript. `_label` is omitted for - /// efficiency. - fn get_and_append_challenge( - &mut self, - label: &'static [u8], - ) -> Result + fn get_challenge(&mut self, _label: &'static [u8]) -> Result where E: Pairing, E::ScalarField: PrimeField, { + // 1. state = hash(state | transcript) let mut hasher = Keccak256::new(); + hasher.update(self.state); hasher.update(&self.transcript); let buf = hasher.finalize(); + self.state.copy_from_slice(&buf); - let challenge = E::ScalarField::from_be_bytes_mod_order(&buf); - >::append_challenge::(self, label, &challenge)?; + // 2. transcript = Vec::new() + self.transcript = Vec::new(); - Ok(challenge) + // 3. challenge = bytes_to_field(state) + Ok(E::ScalarField::from_be_bytes_mod_order(&buf)) } } diff --git a/plonk/src/transcript/standard.rs b/plonk/src/transcript/standard.rs index 6886998a4..97399f332 100644 --- a/plonk/src/transcript/standard.rs +++ b/plonk/src/transcript/standard.rs @@ -9,7 +9,6 @@ use super::PlonkTranscript; use crate::errors::PlonkError; use ark_ec::pairing::Pairing; use ark_ff::PrimeField; -use jf_utils::to_bytes; use merlin::Transcript; /// A wrapper of `merlin::Transcript`. @@ -28,19 +27,13 @@ impl PlonkTranscript for StandardTranscript { Ok(()) } - // generate the challenge for the current transcript - // and append it to the transcript - fn get_and_append_challenge( - &mut self, - label: &'static [u8], - ) -> Result + fn get_challenge(&mut self, label: &'static [u8]) -> Result where E: Pairing, { let mut buf = [0u8; 64]; self.0.challenge_bytes(label, &mut buf); let challenge = E::ScalarField::from_le_bytes_mod_order(&buf); - self.0.append_message(label, &to_bytes!(&challenge)?); Ok(challenge) } }