Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ca2e17c
feat: Add `expressions` file for gadgets crate
CPerezz May 30, 2022
d2a156f
fixup
CPerezz May 30, 2022
37c4c01
add: Impl `Start Tag` gate config for Keccak circuit
CPerezz May 30, 2022
a5bc2f7
gadgets: Add `is_within_range` to gadget expressions mod
CPerezz May 31, 2022
3c9c5ce
gadgets: Add square_and_multiply to expressions mod
CPerezz May 31, 2022
6412b86
add: Finalize Continue state configure fn impl
CPerezz Jun 1, 2022
e0fc25c
add: End and Finalize state constraint exprs
CPerezz Jun 2, 2022
13043a6
add: Include bool_constraint expr and standarize state tag exprs
CPerezz Jun 6, 2022
ecbbff4
change: Allow BaseConversionConfig to use const-generics
CPerezz Jun 7, 2022
5ffd7a6
change: Refactor AbsorbConfig to perform base_conversion
CPerezz Jun 7, 2022
4fbf84f
chore: Rebase main mixing gate changes
CPerezz Jun 7, 2022
6961fe5
update: Update KeccakFConfig to config forwarding logic
CPerezz Jun 8, 2022
43a99ba
feat: Add RlcConfig and tests in keccak crate
CPerezz Jun 9, 2022
96480df
chore: Rebase into main keccakF config changes
CPerezz Jun 9, 2022
823a7c0
change: Create base conv tables in KeccakConfig and propagate
CPerezz Jun 13, 2022
a7d9c44
feat: Add PermutationInputs and NextInput helpers
CPerezz Jun 13, 2022
d52f6fe
fix: Update rlc config to return rlc in assign
CPerezz Jun 21, 2022
eb99f0d
fix: include rlc mod
CPerezz Jun 21, 2022
c0f197b
add: Finish tests for NextInput structure
CPerezz Jun 21, 2022
54fd225
change: Update padding Config
CPerezz Jun 28, 2022
64ab27c
feat: Add return-rlc variant for RlcConfig assignation
CPerezz Jun 28, 2022
00e722a
fix: Correct state tags passed to the permutation
CPerezz Jun 28, 2022
e689e6a
feat: Add hash and permutation assignment functions
CPerezz Jun 28, 2022
6ffbf94
fix: Rebase Absorb to main
CPerezz Jun 30, 2022
c38d296
fix: Rebase Mixing and keccakF to main
CPerezz Jun 30, 2022
ea24fa8
Merge branch 'main' into keccak_final_assembly
CPerezz Jun 30, 2022
70be930
fix: Update RLC test to constraint rlc result
CPerezz Jun 30, 2022
95ef037
chore: Update circuit KeccakConfig to latest rebase
CPerezz Jun 30, 2022
b2c533c
tmp benchmark
CPerezz Jun 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 41 additions & 84 deletions circuit-benchmarks/src/keccak_permutation.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
//! Evm circuit benchmarks

use eth_types::Field;
use halo2_proofs::{
circuit::{AssignedCell, Layouter, SimpleFloorPlanner},
circuit::{floor_planner::V1, AssignedCell, Layouter},
plonk::{Circuit, ConstraintSystem, Error},
};
use keccak256::{
common::NEXT_INPUTS_LANES, keccak_arith::KeccakFArith, permutation::circuit::KeccakFConfig,
};
use keccak256::{circuit::KeccakConfig, common::NEXT_INPUTS_LANES, keccak_arith::KeccakFArith};

#[derive(Default, Clone)]
struct KeccakRoundTestCircuit<F> {
in_state: [F; 25],
out_state: [F; 25],
next_mixing: Option<[F; NEXT_INPUTS_LANES]>,
is_mixing: bool,
struct KeccakTestCircuit {
input: Vec<Vec<u8>>,
output: [u8; 32],
}

impl<F: Field> Circuit<F> for KeccakRoundTestCircuit<F> {
type Config = KeccakFConfig<F>;
type FloorPlanner = SimpleFloorPlanner;
impl<F: Field> Circuit<F> for KeccakTestCircuit {
type Config = KeccakConfig<F>;
type FloorPlanner = V1;

fn without_witnesses(&self) -> Self {
Self::default()
self.clone()
}

fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
Expand All @@ -36,36 +31,11 @@ impl<F: Field> Circuit<F> for KeccakRoundTestCircuit<F> {
) -> Result<(), Error> {
// Load the table
config.load(&mut layouter)?;
let offset: usize = 0;

let in_state = layouter.assign_region(
|| "Keccak round witnes & flag assignment",
|mut region| {
// Witness `state`
let in_state: [AssignedCell<F, F>; 25] = {
let mut state: Vec<AssignedCell<F, F>> = Vec::with_capacity(25);
for (idx, val) in self.in_state.iter().enumerate() {
let cell = region.assign_advice(
|| "witness input state",
config.state[idx],
offset,
|| Ok(*val),
)?;
state.push(cell)
}
state.try_into().unwrap()
};
Ok(in_state)
},
)?;

config.assign_all(
&mut layouter,
in_state,
self.out_state,
self.is_mixing,
self.next_mixing,
)?;
let mut config = config.clone();

for input in self.input.iter() {
config.assign_hash(&mut layouter, input.as_slice(), self.output)?;
}
Ok(())
}
}
Expand Down Expand Up @@ -93,42 +63,34 @@ mod tests {

#[test]
fn bench_keccak_round() {
let in_state: State = [
[1, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
let input = vec![
vec![
65u8, 108, 105, 99, 101, 32, 119, 97, 115, 32, 98, 101, 103, 105, 110, 110, 105,
110, 103, 32, 116, 111, 32, 103, 101, 116, 32, 118, 101, 114, 121, 32, 116, 105,
114, 101, 100, 32, 111, 102, 32, 115, 105, 116, 116, 105, 110, 103, 32, 98, 121,
32, 104, 101, 114, 32, 115, 105, 115, 116, 101, 114, 32, 111, 110, 32, 116, 104,
101, 32, 98, 97, 110, 107, 44, 32, 97, 110, 100, 32, 111, 102, 32, 104, 97, 118,
105, 110, 103, 32, 110, 111, 116, 104, 105, 110, 103, 32, 116, 111, 32, 100, 111,
58, 32, 111, 110, 99, 101, 32, 111, 114, 32, 116, 119, 105, 99, 101, 32, 115, 104,
101, 32, 104, 97, 100, 32, 112, 101, 101, 112, 101, 100, 32, 105, 110, 116, 111,
32, 116, 104, 101, 32, 98, 111, 111, 107, 32, 104, 101, 114, 32, 115, 105, 115,
116, 101, 114, 32, 119, 97, 115, 32, 114, 101, 97, 100, 105, 110, 103, 44, 32, 98,
117, 116, 32, 105, 116, 32, 104, 97, 100, 32, 110, 111, 32, 112, 105, 99, 116, 117,
114, 101, 115, 32, 111, 114, 32, 99, 111, 110, 118, 101, 114, 115, 97, 116, 105,
111, 110, 115, 32, 105, 110, 32, 105, 116, 44, 32, 97, 110, 100, 32, 119, 104, 97,
116, 32, 105, 115, 32, 116, 104, 101, 32, 117, 115, 101, 32, 111, 102, 32, 97, 32,
98, 111, 111, 107, 44, 32, 116, 104, 111, 117, 103, 104, 116, 32, 65, 108, 105, 99,
101, 32, 119, 105, 116, 104, 111, 117, 116, 32, 112, 105, 99, 116, 117, 114, 101,
115, 32, 111, 114, 32, 99, 111, 110, 118, 101, 114, 115, 97, 116, 105, 111, 110,
115, 63,
];
3000
];

let next_input: State = [
[2, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
let output = [
60u8, 227, 142, 8, 143, 135, 108, 85, 13, 254, 190, 58, 30, 106, 153, 194, 188, 6, 208,
49, 16, 102, 150, 120, 100, 130, 224, 177, 64, 98, 53, 252,
];

let mut in_state_biguint = StateBigInt::default();

// Generate in_state as `[Fr;25]`
let mut in_state_fp: [Fr; 25] = [Fr::zero(); 25];
for (x, y) in (0..5).cartesian_product(0..5) {
in_state_fp[5 * x + y] = biguint_to_f(&convert_b2_to_b13(in_state[x][y]));
in_state_biguint[(x, y)] = convert_b2_to_b13(in_state[x][y]);
}

// Compute out_state_mix
let mut out_state_mix = in_state_biguint.clone();
KeccakFArith::permute_and_absorb(&mut out_state_mix, Some(&next_input));

// Compute out_state_non_mix
let mut out_state_non_mix = in_state_biguint.clone();
KeccakFArith::permute_and_absorb(&mut out_state_non_mix, None);

// Generate out_state as `[Fr;25]`
let out_state_non_mix: [Fr; 25] = state_bigint_to_field(out_state_non_mix);

let constants_b13: Vec<Fr> = ROUND_CONSTANTS
.iter()
.map(|num| biguint_to_f(&convert_b2_to_b13(*num)))
Expand All @@ -140,12 +102,7 @@ mod tests {
.collect();

// Build the circuit
let circuit = KeccakRoundTestCircuit::<Fr> {
in_state: in_state_fp,
out_state: out_state_non_mix,
next_mixing: None,
is_mixing: false,
};
let circuit = KeccakTestCircuit { input, output };

let degree: u32 = var("DEGREE")
.expect("No DEGREE env var was provided")
Expand Down Expand Up @@ -196,7 +153,7 @@ mod tests {
&verifier_params,
pk.get_vk(),
strategy,
&[&[constants_b9.as_slice(), constants_b13.as_slice()]],
&[],
&mut verifier_transcript,
)
.unwrap();
Expand Down
199 changes: 199 additions & 0 deletions circuit-benchmarks/src/keccak_permutation_old.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
//! Evm circuit benchmarks

use eth_types::Field;
use halo2_proofs::{
circuit::{AssignedCell, Layouter, SimpleFloorPlanner},
plonk::{Circuit, ConstraintSystem, Error},
};
use keccak256::{
common::NEXT_INPUTS_LANES, keccak_arith::KeccakFArith, permutation::circuit::KeccakFConfig,
};

#[derive(Default, Clone)]
struct KeccakRoundTestCircuit<F> {
in_state: [F; 25],
out_state: [F; 25],
next_mixing: Option<[F; NEXT_INPUTS_LANES]>,
is_mixing: bool,
}

impl<F: Field> Circuit<F> for KeccakRoundTestCircuit<F> {
type Config = KeccakFConfig<F>;
type FloorPlanner = SimpleFloorPlanner;

fn without_witnesses(&self) -> Self {
Self::default()
}

fn configure(meta: &mut ConstraintSystem<F>) -> Self::Config {
Self::Config::configure(meta)
}

fn synthesize(
&self,
config: Self::Config,
mut layouter: impl Layouter<F>,
) -> Result<(), Error> {
// Load the table
config.load(&mut layouter)?;
let offset: usize = 0;

let in_state = layouter.assign_region(
|| "Keccak round witnes & flag assignment",
|mut region| {
// Witness `state`
let in_state: [AssignedCell<F, F>; 25] = {
let mut state: Vec<AssignedCell<F, F>> = Vec::with_capacity(25);
for (idx, val) in self.in_state.iter().enumerate() {
let cell = region.assign_advice(
|| "witness input state",
config.state[idx],
offset,
|| Ok(*val),
)?;
state.push(cell)
}
state.try_into().unwrap()
};
Ok(in_state)
},
)?;

config.assign_permutation(&mut layouter, in_state, self.is_mixing, self.next_mixing)?;
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
use ark_std::{end_timer, start_timer};
use halo2_proofs::plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, SingleVerifier};
use halo2_proofs::{
pairing::bn256::{Bn256, Fr, G1Affine},
poly::commitment::{Params, ParamsVerifier},
transcript::{Blake2bRead, Blake2bWrite, Challenge255},
};
use itertools::Itertools;
use keccak256::common::PERMUTATION;
use keccak256::{
arith_helpers::*,
common::{State, ROUND_CONSTANTS},
gate_helpers::biguint_to_f,
};
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::env::var;

#[test]
fn bench_keccak_round() {
let in_state: State = [
[1, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
];

let next_input: State = [
[2, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
];

let mut in_state_biguint = StateBigInt::default();

// Generate in_state as `[Fr;25]`
let mut in_state_fp: [Fr; 25] = [Fr::zero(); 25];
for (x, y) in (0..5).cartesian_product(0..5) {
in_state_fp[5 * x + y] = biguint_to_f(&convert_b2_to_b13(in_state[x][y]));
in_state_biguint[(x, y)] = convert_b2_to_b13(in_state[x][y]);
}

// Compute out_state_mix
let mut out_state_mix = in_state_biguint.clone();
KeccakFArith::permute_and_absorb(&mut out_state_mix, Some(next_input));

// Compute out_state_non_mix
let mut out_state_non_mix = in_state_biguint.clone();
KeccakFArith::permute_and_absorb(&mut out_state_non_mix, None);

// Generate out_state as `[Fr;25]`
let out_state_non_mix: [Fr; 25] = state_bigint_to_field(out_state_non_mix);

let constants_b13: Vec<Fr> = ROUND_CONSTANTS
.iter()
.map(|num| biguint_to_f(&convert_b2_to_b13(*num)))
.collect();

let constants_b9: Vec<Fr> = ROUND_CONSTANTS
.iter()
.map(|num| biguint_to_f(&convert_b2_to_b9(*num)))
.collect();

// Build the circuit
let circuit = KeccakRoundTestCircuit::<Fr> {
in_state: in_state_fp,
out_state: out_state_non_mix,
next_mixing: None,
is_mixing: false,
};

let degree: u32 = var("DEGREE")
.expect("No DEGREE env var was provided")
.parse()
.expect("Cannot parse DEGREE env var as u32");

let rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
0xbc, 0xe5,
]);

// Bench setup generation
let setup_message = format!("Setup generation with degree = {}", degree);
let start1 = start_timer!(|| setup_message);
let general_params: Params<G1Affine> = Params::<G1Affine>::unsafe_setup::<Bn256>(degree);
end_timer!(start1);

let vk = keygen_vk(&general_params, &circuit).unwrap();
let pk = keygen_pk(&general_params, vk, &circuit).unwrap();

// Prove
let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]);

// Bench proof generation time
let proof_message = format!("EVM Proof generation with {} rows", degree);
let start2 = start_timer!(|| proof_message);
create_proof(
&general_params,
&pk,
&[circuit],
&[&[constants_b9.as_slice(), constants_b13.as_slice()]],
rng,
&mut transcript,
)
.unwrap();
let proof = transcript.finalize();
end_timer!(start2);

// Verify
let verifier_params: ParamsVerifier<Bn256> =
general_params.verifier(PERMUTATION * 2).unwrap();
let mut verifier_transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]);
let strategy = SingleVerifier::new(&verifier_params);

// Bench verification time
let start3 = start_timer!(|| "EVM Proof verification");
verify_proof(
&verifier_params,
pk.get_vk(),
strategy,
&[&[constants_b9.as_slice(), constants_b13.as_slice()]],
&mut verifier_transcript,
)
.unwrap();
end_timer!(start3);
}
}
4 changes: 4 additions & 0 deletions circuit-benchmarks/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ pub mod state_circuit;
#[cfg(feature = "benches")]
pub mod bench_params;

// #[cfg(test)]
// #[cfg(feature = "benches")]
// pub mod keccak_permutation;

#[cfg(test)]
#[cfg(feature = "benches")]
pub mod keccak_permutation;
Expand Down
Loading