Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chore] Reorg Folder Structure of hashes/zkevm #118

Merged
merged 4 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 4 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
[workspace]
members = [
"halo2-base",
"halo2-ecc",
"hashes/zkevm-keccak",
]
members = ["halo2-base", "halo2-ecc", "hashes/zkevm"]
resolver = "2"

[profile.dev]
opt-level = 3
debug = 1 # change to 0 or 2 for more or less debug info
debug = 1 # change to 0 or 2 for more or less debug info
overflow-checks = true
incremental = true

Expand All @@ -29,7 +25,7 @@ codegen-units = 16
opt-level = 3
debug = false
debug-assertions = false
lto = "fat"
lto = "fat"
# `codegen-units = 1` can lead to WORSE performance - always bench to find best profile for your machine!
# codegen-units = 1
panic = "unwind"
Expand All @@ -38,4 +34,4 @@ incremental = false
# For performance profiling
[profile.flamegraph]
inherits = "release"
debug = true
debug = true
7 changes: 4 additions & 3 deletions halo2-base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,9 @@ impl<F: ScalarField> Context<F> {
/// The `MockProver` will print out the row, column where it fails, so it serves as a debugging "break point"
/// so you can add to your code to search for where the actual constraint failure occurs.
pub fn debug_assert_false(&mut self) {
let three = self.load_witness(F::from(3));
let four = self.load_witness(F::from(4));
self.constrain_equal(&three, &four);
use rand_chacha::rand_core::OsRng;
let rand1 = self.load_witness(F::random(OsRng));
let rand2 = self.load_witness(F::random(OsRng));
self.constrain_equal(&rand1, &rand2);
}
}
2 changes: 1 addition & 1 deletion hashes/zkevm-keccak/Cargo.toml → hashes/zkevm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "zkevm-keccak"
name = "zkevm-hashes"
version = "0.1.1"
edition = "2021"
license = "MIT OR Apache-2.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@ use super::util::{
constraint_builder::BaseConstraintBuilder,
eth_types::Field,
expression::{and, not, select, Expr},
field_xor, get_absorb_positions, get_num_bits_per_lookup, into_bits, load_lookup_table,
load_normalize_table, load_pack_table, pack, pack_u64, pack_with_base, rotate, scatter,
target_part_sizes, to_bytes, unpack, CHI_BASE_LOOKUP_TABLE, NUM_BYTES_PER_WORD, NUM_ROUNDS,
NUM_WORDS_TO_ABSORB, NUM_WORDS_TO_SQUEEZE, RATE, RATE_IN_BITS, RHO_MATRIX, ROUND_CST,
};
use crate::halo2_proofs::{
circuit::{Layouter, Region, Value},
halo2curves::ff::PrimeField,
plonk::{
Advice, Challenge, Column, ConstraintSystem, Error, Expression, Fixed, SecondPhase,
TableColumn, VirtualCells,
use crate::{
halo2_proofs::{
circuit::{Layouter, Region, Value},
halo2curves::ff::PrimeField,
plonk::{
Advice, Challenge, Column, ConstraintSystem, Error, Expression, Fixed, SecondPhase,
TableColumn, VirtualCells,
},
poly::Rotation,
},
poly::Rotation,
util::expression::sum,
};
use halo2_base::halo2_proofs::{circuit::AssignedCell, plonk::Assigned};
use itertools::Itertools;
Expand All @@ -24,6 +23,14 @@ use std::marker::PhantomData;

#[cfg(test)]
mod tests;
pub mod util;

use util::{
field_xor, get_absorb_positions, get_num_bits_per_lookup, into_bits, load_lookup_table,
load_normalize_table, load_pack_table, pack, pack_u64, pack_with_base, rotate, scatter,
target_part_sizes, to_bytes, unpack, CHI_BASE_LOOKUP_TABLE, NUM_BYTES_PER_WORD, NUM_ROUNDS,
NUM_WORDS_TO_ABSORB, NUM_WORDS_TO_SQUEEZE, RATE, RATE_IN_BITS, RHO_MATRIX, ROUND_CST,
};

const MAX_DEGREE: usize = 3;
const ABSORB_LOOKUP_RANGE: usize = 3;
Expand Down Expand Up @@ -88,8 +95,7 @@ pub struct KeccakRow<F: PrimeField> {
round_cst: F,
is_final: bool,
cell_values: Vec<F>,
// We have no need for length as RLC equality checks length implicitly
// length: usize,
length: usize,
// SecondPhase values will be assigned separately
// data_rlc: Value<F>,
// hash_rlc: Value<F>,
Expand All @@ -100,14 +106,14 @@ impl<F: PrimeField> KeccakRow<F> {
(0..num_rows)
.map(|idx| KeccakRow {
q_enable: idx == 0,
// q_enable_row: true,
q_round: false,
q_absorb: idx == 0,
q_round_last: false,
q_padding: false,
q_padding_last: false,
round_cst: F::ZERO,
is_final: false,
length: 0usize,
cell_values: Vec::new(),
})
.collect()
Expand Down Expand Up @@ -354,24 +360,21 @@ pub struct KeccakTable {
/// Byte array input as `RLC(reversed(input))`
pub input_rlc: Column<Advice>, // RLC of input bytes
// Byte array input length
// pub input_len: Column<Advice>,
pub input_len: Column<Advice>,
/// RLC of the hash result
pub output_rlc: Column<Advice>, // RLC of hash of input bytes
}

impl KeccakTable {
/// Construct a new KeccakTable
pub fn construct<F: Field>(meta: &mut ConstraintSystem<F>) -> Self {
let input_len = meta.advice_column();
let input_rlc = meta.advice_column_in(SecondPhase);
let output_rlc = meta.advice_column_in(SecondPhase);
meta.enable_equality(input_len);
meta.enable_equality(input_rlc);
meta.enable_equality(output_rlc);
Self {
is_enabled: meta.advice_column(),
input_rlc,
// input_len: meta.advice_column(),
output_rlc,
}
Self { is_enabled: meta.advice_column(), input_rlc, input_len, output_rlc }
}
}

Expand Down Expand Up @@ -423,9 +426,9 @@ pub fn assign_fixed_custom<F: Field>(

/// Recombines parts back together
mod decode {
use super::util::BIT_COUNT;
use super::{Expr, Part, PartValue, PrimeField};
use crate::halo2_proofs::plonk::Expression;
use crate::util::BIT_COUNT;

pub(crate) fn expr<F: PrimeField>(parts: Vec<Part<F>>) -> Expression<F> {
parts.iter().rev().fold(0.expr(), |acc, part| {
Expand All @@ -442,12 +445,12 @@ mod decode {

/// Splits a word into parts
mod split {
use super::util::{pack, pack_part, unpack, WordParts};
use super::{
decode, BaseConstraintBuilder, CellManager, Expr, Field, KeccakRegion, Part, PartValue,
PrimeField,
};
use crate::halo2_proofs::plonk::{ConstraintSystem, Expression};
use crate::util::{pack, pack_part, unpack, WordParts};

#[allow(clippy::too_many_arguments)]
pub(crate) fn expr<F: PrimeField>(
Expand Down Expand Up @@ -515,13 +518,12 @@ mod split {
// table layout in `output_cells` regardless of rotation.
mod split_uniform {
use super::{
decode, target_part_sizes, BaseConstraintBuilder, Cell, CellManager, Expr, KeccakRegion,
Part, PartValue, PrimeField,
decode, target_part_sizes,
util::{pack, pack_part, rotate, rotate_rev, unpack, WordParts, BIT_SIZE},
BaseConstraintBuilder, Cell, CellManager, Expr, KeccakRegion, Part, PartValue, PrimeField,
};
use crate::halo2_proofs::plonk::{ConstraintSystem, Expression};
use crate::util::{
eth_types::Field, pack, pack_part, rotate, rotate_rev, unpack, WordParts, BIT_SIZE,
};
use crate::util::eth_types::Field;

#[allow(clippy::too_many_arguments)]
pub(crate) fn expr<F: PrimeField>(
Expand Down Expand Up @@ -743,9 +745,9 @@ mod transform {

// Transfroms values to cells
mod transform_to {
use super::util::{pack, to_bytes, unpack};
use super::{Cell, Expr, Field, KeccakRegion, Part, PartValue, PrimeField};
use crate::halo2_proofs::plonk::{ConstraintSystem, TableColumn};
use crate::util::{pack, to_bytes, unpack};

#[allow(clippy::too_many_arguments)]
pub(crate) fn expr<F: PrimeField>(
Expand Down Expand Up @@ -820,7 +822,6 @@ pub struct KeccakConfigParams {
pub struct KeccakCircuitConfig<F> {
challenge: Challenge,
q_enable: Column<Fixed>,
// q_enable_row: Column<Fixed>,
q_first: Column<Fixed>,
q_round: Column<Fixed>,
q_absorb: Column<Fixed>,
Expand Down Expand Up @@ -869,7 +870,7 @@ impl<F: Field> KeccakCircuitConfig<F> {
let keccak_table = KeccakTable::construct(meta);

let is_final = keccak_table.is_enabled;
// let length = keccak_table.input_len;
let input_len = keccak_table.input_len;
let data_rlc = keccak_table.input_rlc;
let hash_rlc = keccak_table.output_rlc;

Expand Down Expand Up @@ -1451,15 +1452,26 @@ impl<F: Field> KeccakCircuitConfig<F> {
// TODO: there is probably a way to only require NUM_BYTES_PER_WORD instead of
// NUM_BYTES_PER_WORD + 1 rows per round, but for simplicity and to keep the
// gate degree at 3, we just do the obvious thing for now Input data rlc
meta.create_gate("data rlc", |meta| {
meta.create_gate("length and data rlc", |meta| {
let mut cb = BaseConstraintBuilder::new(MAX_DEGREE);

let q_padding = meta.query_fixed(q_padding, Rotation::cur());
let start_new_hash_prev = start_new_hash(meta, Rotation(-(num_rows_per_round as i32)));
let length_prev = meta.query_advice(input_len, Rotation(-(num_rows_per_round as i32)));
let length = meta.query_advice(input_len, Rotation::cur());
let data_rlc_prev = meta.query_advice(data_rlc, Rotation(-(num_rows_per_round as i32)));

// Update the length/data_rlc on rows where we absorb data
cb.condition(q_padding.expr(), |cb| {
// Length increases by the number of bytes that aren't padding
cb.require_equal(
"update length",
length.clone(),
length_prev.clone() * not::expr(start_new_hash_prev.expr())
+ sum::expr(
is_paddings.iter().map(|is_padding| not::expr(is_padding.expr())),
),
);
let challenge_expr = meta.query_challenge(challenge);
// Use intermediate cells to keep the degree low
let mut new_data_rlc =
Expand Down Expand Up @@ -1498,6 +1510,7 @@ impl<F: Field> KeccakCircuitConfig<F> {
not::expr(q_padding),
]),
|cb| {
cb.require_equal("length equality check", length, length_prev);
cb.require_equal(
"data_rlc equality check",
meta.query_advice(data_rlc, Rotation::cur()),
Expand Down Expand Up @@ -1530,7 +1543,6 @@ impl<F: Field> KeccakCircuitConfig<F> {
KeccakCircuitConfig {
challenge,
q_enable,
// q_enable_row,
q_first,
q_round,
q_absorb,
Expand All @@ -1552,13 +1564,26 @@ impl<F: Field> KeccakCircuitConfig<F> {
}

impl<F: Field> KeccakCircuitConfig<F> {
pub fn assign(&self, region: &mut Region<'_, F>, witness: &[KeccakRow<F>]) {
for (offset, keccak_row) in witness.iter().enumerate() {
self.set_row(region, offset, keccak_row);
}
/// Returns vector of `length`s for assigned rows
pub fn assign<'v>(
&self,
region: &mut Region<F>,
witness: &[KeccakRow<F>],
) -> Vec<KeccakAssignedValue<'v, F>> {
witness
.iter()
.enumerate()
.map(|(offset, keccak_row)| self.set_row(region, offset, keccak_row))
.collect()
}

pub fn set_row(&self, region: &mut Region<'_, F>, offset: usize, row: &KeccakRow<F>) {
/// Output is `length` at that row
pub fn set_row<'v>(
&self,
region: &mut Region<F>,
offset: usize,
row: &KeccakRow<F>,
) -> KeccakAssignedValue<'v, F> {
// Fixed selectors
for (_, column, value) in &[
("q_enable", self.q_enable, F::from(row.q_enable)),
Expand All @@ -1572,12 +1597,14 @@ impl<F: Field> KeccakCircuitConfig<F> {
assign_fixed_custom(region, *column, offset, *value);
}

assign_advice_custom(
region,
self.keccak_table.is_enabled,
offset,
Value::known(F::from(row.is_final)),
);
// Keccak data
let [_is_final, length] = [
("is_final", self.keccak_table.is_enabled, F::from(row.is_final)),
("length", self.keccak_table.input_len, F::from(row.length as u64)),
]
.map(|(_name, column, value)| {
assign_advice_custom(region, column, offset, Value::known(value))
});

// Cell values
row.cell_values.iter().zip(self.cell_manager.columns()).for_each(|(bit, column)| {
Expand All @@ -1586,6 +1613,8 @@ impl<F: Field> KeccakCircuitConfig<F> {

// Round constant
assign_fixed_custom(region, self.round_cst, offset, row.round_cst);

length
}

pub fn load_aux_tables(&self, layouter: &mut impl Layouter<F>, k: u32) -> Result<(), Error> {
Expand Down Expand Up @@ -1670,11 +1699,15 @@ pub fn keccak_phase0<F: Field>(
}
bits.push(1);

// running length of absorbed input in bytes
let mut length = 0;
let chunks = bits.chunks(RATE_IN_BITS);
let num_chunks = chunks.len();

let mut cell_managers = Vec::with_capacity(NUM_ROUNDS + 1);
let mut regions = Vec::with_capacity(NUM_ROUNDS + 1);
// keeps track of running lengths over all rounds in an absorb step
let mut round_lengths = Vec::with_capacity(NUM_ROUNDS + 1);
let mut hash_words = [F::ZERO; NUM_WORDS_TO_SQUEEZE];

for (idx, chunk) in chunks.enumerate() {
Expand All @@ -1692,6 +1725,7 @@ pub fn keccak_phase0<F: Field>(
// better memory management to clear already allocated Vecs
cell_managers.clear();
regions.clear();
round_lengths.clear();

for round in 0..NUM_ROUNDS + 1 {
let mut cell_manager = CellManager::new(num_rows_per_round);
Expand Down Expand Up @@ -1750,7 +1784,12 @@ pub fn keccak_phase0<F: Field>(
if round < NUM_WORDS_TO_ABSORB {
for (padding_idx, is_padding) in is_paddings.iter().enumerate() {
let byte_idx = round * NUM_BYTES_PER_WORD + padding_idx;
let padding = is_final_block && byte_idx >= num_bytes_in_last_block;
let padding = if is_final_block && byte_idx >= num_bytes_in_last_block {
true
} else {
length += 1;
false
};
is_padding.assign(&mut region, 0, F::from(padding));
}
}
Expand Down Expand Up @@ -1901,6 +1940,8 @@ pub fn keccak_phase0<F: Field>(
*hash_word = a[0];
}

round_lengths.push(length);

cell_managers.push(cell_manager);
regions.push(region);
}
Expand Down Expand Up @@ -1936,6 +1977,7 @@ pub fn keccak_phase0<F: Field>(
q_padding_last: row_idx == 0 && round == NUM_WORDS_TO_ABSORB - 1,
round_cst,
is_final: is_final_block && round == NUM_ROUNDS && row_idx == 0,
length: round_lengths[round],
cell_values: regions[round].rows.get(row_idx).unwrap_or(&vec![]).clone(),
});
#[cfg(debug_assertions)]
Expand Down Expand Up @@ -1965,7 +2007,7 @@ pub fn keccak_phase0<F: Field>(
})
.collect::<Vec<_>>();
debug!("hash: {:x?}", &(hash_bytes[0..4].concat()));
// debug!("data rlc: {:x?}", data_rlc);
assert_eq!(length, bytes.len());
}
}

Expand Down
Loading