From 314a5845b7c750fbfc4b347b35d705c7ab0daf45 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 29 Dec 2021 16:41:43 +0100 Subject: [PATCH] Use outer hash in Challenger --- plonky2/src/fri/commitment.rs | 2 +- plonky2/src/fri/prover.rs | 8 ++--- plonky2/src/iop/challenger.rs | 4 +-- plonky2/src/plonk/config.rs | 52 +++++++++++++++++++++++------ plonky2/src/plonk/get_challenges.rs | 2 +- plonky2/src/plonk/prover.rs | 2 +- 6 files changed, 51 insertions(+), 19 deletions(-) diff --git a/plonky2/src/fri/commitment.rs b/plonky2/src/fri/commitment.rs index 52ed0645..cd61a3c2 100644 --- a/plonky2/src/fri/commitment.rs +++ b/plonky2/src/fri/commitment.rs @@ -135,7 +135,7 @@ impl, C: GenericConfig, const D: usize> pub(crate) fn open_plonk( commitments: &[&Self; 4], zeta: F::Extension, - challenger: &mut Challenger, + challenger: &mut Challenger, common_data: &CommonCircuitData, timing: &mut TimingTree, ) -> (FriProof, OpeningSet) { diff --git a/plonky2/src/fri/prover.rs b/plonky2/src/fri/prover.rs index 20c4f133..21311939 100644 --- a/plonky2/src/fri/prover.rs +++ b/plonky2/src/fri/prover.rs @@ -21,7 +21,7 @@ pub fn fri_proof, C: GenericConfig, const lde_polynomial_coeffs: PolynomialCoeffs, // Evaluation of the polynomial on the large domain. lde_polynomial_values: PolynomialValues, - challenger: &mut Challenger, + challenger: &mut Challenger, common_data: &CommonCircuitData, timing: &mut TimingTree, ) -> FriProof { @@ -63,7 +63,7 @@ pub fn fri_proof, C: GenericConfig, const fn fri_committed_trees, C: GenericConfig, const D: usize>( mut coeffs: PolynomialCoeffs, mut values: PolynomialValues, - challenger: &mut Challenger, + challenger: &mut Challenger, common_data: &CommonCircuitData, ) -> ( Vec>, @@ -140,7 +140,7 @@ fn fri_prover_query_rounds< >( initial_merkle_trees: &[&MerkleTree], trees: &[MerkleTree], - challenger: &mut Challenger, + challenger: &mut Challenger, n: usize, common_data: &CommonCircuitData, ) -> Vec> { @@ -156,7 +156,7 @@ fn fri_prover_query_round< >( initial_merkle_trees: &[&MerkleTree], trees: &[MerkleTree], - challenger: &mut Challenger, + challenger: &mut Challenger, n: usize, common_data: &CommonCircuitData, ) -> FriQueryRound { diff --git a/plonky2/src/iop/challenger.rs b/plonky2/src/iop/challenger.rs index a97cb5f1..b8ca4fb7 100644 --- a/plonky2/src/iop/challenger.rs +++ b/plonky2/src/iop/challenger.rs @@ -15,7 +15,7 @@ use crate::plonk::proof::{OpeningSet, OpeningSetTarget}; /// Observes prover messages, and generates challenges by hashing the transcript, a la Fiat-Shamir. #[derive(Clone)] -pub struct Challenger> { +pub struct Challenger> { sponge_state: [F; SPONGE_WIDTH], input_buffer: Vec, output_buffer: Vec, @@ -30,7 +30,7 @@ pub struct Challenger> { /// design, but it can be viewed as a duplex sponge whose inputs are sometimes zero (when we perform /// multiple squeezes) and whose outputs are sometimes ignored (when we perform multiple /// absorptions). Thus the security properties of a duplex sponge still apply to our design. -impl> Challenger { +impl> Challenger { pub fn new() -> Challenger { Challenger { sponge_state: [F::ZERO; SPONGE_WIDTH], diff --git a/plonky2/src/plonk/config.rs b/plonky2/src/plonk/config.rs index 252e8e3a..3c204a16 100644 --- a/plonky2/src/plonk/config.rs +++ b/plonky2/src/plonk/config.rs @@ -34,6 +34,9 @@ pub trait Hasher: Sized + Clone + Debug + Eq + PartialEq { const HASH_SIZE: usize; type Hash: GenericHashOut; + /// Permutation used in the sponge construction. + type Permutation: PlonkyPermutation; + fn hash(input: Vec, pad: bool) -> Self::Hash; fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash; } @@ -43,8 +46,6 @@ pub trait AlgebraicHasher: Hasher> { // TODO: Adding a `const WIDTH: usize` here yields a compiler error down the line. // Maybe try again in a while. - /// Permutation used in the sponge construction. - type Permutation: PlonkyPermutation; /// Circuit to conditionally swap two chunks of the inputs (useful in verifying Merkle proofs), /// then apply the permutation. fn permute_swapped( @@ -62,19 +63,18 @@ pub struct PoseidonHash; impl Hasher for PoseidonHash { const HASH_SIZE: usize = 4 * 8; type Hash = HashOut; + type Permutation = PoseidonPermutation; fn hash(input: Vec, pad: bool) -> Self::Hash { - hash_n_to_hash::>::Permutation>(input, pad) + hash_n_to_hash::(input, pad) } fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash { - compress::>::Permutation>(left, right) + compress::(left, right) } } impl AlgebraicHasher for PoseidonHash { - type Permutation = PoseidonPermutation; - fn permute_swapped( inputs: [Target; SPONGE_WIDTH], swap: BoolTarget, @@ -111,19 +111,18 @@ pub struct GMiMCHash; impl Hasher for GMiMCHash { const HASH_SIZE: usize = 4 * 8; type Hash = HashOut; + type Permutation = GMiMCPermutation; fn hash(input: Vec, pad: bool) -> Self::Hash { - hash_n_to_hash::>::Permutation>(input, pad) + hash_n_to_hash::(input, pad) } fn two_to_one(left: Self::Hash, right: Self::Hash) -> Self::Hash { - compress::>::Permutation>(left, right) + compress::(left, right) } } impl AlgebraicHasher for GMiMCHash { - type Permutation = GMiMCPermutation; - fn permute_swapped( inputs: [Target; SPONGE_WIDTH], swap: BoolTarget, @@ -155,12 +154,45 @@ impl AlgebraicHasher for GMiMCHash { } } +/// Keccak-256 permutation used in the challenger. +pub struct KeccakPermutation; +impl PlonkyPermutation for KeccakPermutation { + fn permute(input: [F; SPONGE_WIDTH]) -> [F; SPONGE_WIDTH] { + // Fill a byte array with the little-endian representation of the field array. + let mut buffer = [0u8; SPONGE_WIDTH * std::mem::size_of::()]; + for i in 0..SPONGE_WIDTH { + buffer[i * std::mem::size_of::()..(i + 1) * std::mem::size_of::()] + .copy_from_slice(&input[i].to_canonical_u64().to_le_bytes()); + } + // Concatenate `H(input), H(H(input)), H(H(H(input)))`. + let permutated_input_bytes = { + let mut ans = [0u8; 96]; + ans[0..32].copy_from_slice(&keccak(buffer).0); + ans[32..64].copy_from_slice(&keccak(keccak(buffer).0).0); + ans[64..96].copy_from_slice(&keccak(keccak(keccak(buffer).0).0).0); + ans + }; + // Write the hashed byte array to a field array. + let mut permutated_input = [F::ZERO; SPONGE_WIDTH]; + for i in 0..SPONGE_WIDTH { + permutated_input[i] = F::from_noncanonical_u64(u64::from_le_bytes( + permutated_input_bytes + [i * std::mem::size_of::()..(i + 1) * std::mem::size_of::()] + .try_into() + .unwrap(), + )); + } + permutated_input + } +} + /// Keccak-256 hash function. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct KeccakHash; impl Hasher for KeccakHash { const HASH_SIZE: usize = N; type Hash = BytesHash; + type Permutation = KeccakPermutation; fn hash(input: Vec, _pad: bool) -> Self::Hash { let mut buffer = Buffer::new(Vec::new()); diff --git a/plonky2/src/plonk/get_challenges.rs b/plonky2/src/plonk/get_challenges.rs index 12c069a0..4e90e27b 100644 --- a/plonky2/src/plonk/get_challenges.rs +++ b/plonky2/src/plonk/get_challenges.rs @@ -32,7 +32,7 @@ fn get_challenges, C: GenericConfig, cons let num_fri_queries = config.fri_config.num_query_rounds; let lde_size = common_data.lde_size(); - let mut challenger = Challenger::::new(); + let mut challenger = Challenger::::new(); // Observe the instance. challenger.observe_hash::(common_data.circuit_digest); diff --git a/plonky2/src/plonk/prover.rs b/plonky2/src/plonk/prover.rs index 1ae85f34..169f78bb 100644 --- a/plonky2/src/plonk/prover.rs +++ b/plonky2/src/plonk/prover.rs @@ -79,7 +79,7 @@ pub(crate) fn prove, C: GenericConfig, co ) ); - let mut challenger = Challenger::new(); + let mut challenger = Challenger::::new(); // Observe the instance. challenger.observe_hash::(common_data.circuit_digest);