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

[feat] Keccak Coprocessor Leaf Circuit #130

Merged
merged 19 commits into from
Sep 9, 2023
Merged
Show file tree
Hide file tree
Changes from 18 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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ resolver = "2"

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

Expand Down
1 change: 1 addition & 0 deletions halo2-base/src/gates/circuit/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ impl<F: ScalarField> BaseCircuitBuilder<F> {
for lm in &mut self.lookup_manager {
lm.clear();
}
self.assigned_instances.iter_mut().for_each(|c| c.clear());
}

/// Returns a mutable reference to the [Context] of a gate thread. Spawns a new thread for the given phase, if none exists.
Expand Down
7 changes: 7 additions & 0 deletions halo2-base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use std::any::TypeId;

use getset::CopyGetters;
use itertools::Itertools;
// Different memory allocator options:
#[cfg(feature = "jemallocator")]
use jemallocator::Jemalloc;
Expand Down Expand Up @@ -445,6 +446,12 @@ impl<F: ScalarField> Context<F> {
self.last().unwrap()
}

/// Assigns a list of constant values and returns the corresponding assigned cells.
/// * `c`: the list of constant values to be assigned
pub fn load_constants(&mut self, c: &[F]) -> Vec<AssignedValue<F>> {
c.iter().map(|v| self.load_constant(*v)).collect_vec()
}

/// Assigns the 0 value to a new cell or returns a previously assigned zero cell from `zero_cell`.
pub fn load_zero(&mut self) -> AssignedValue<F> {
if let Some(zcell) = &self.zero_cell {
Expand Down
21 changes: 13 additions & 8 deletions halo2-base/src/poseidon/hasher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ impl<F: ScalarField, const T: usize, const RATE: usize> PoseidonHasher<F, T, RAT
self.consts.get_or_init(|| PoseidonHasherConsts::<F, T, RATE>::new(ctx, gate, &self.spec));
}

/// Clear all consts.
pub fn clear(&mut self) {
self.consts.take();
}

fn empty_hash(&self) -> &AssignedValue<F> {
self.consts.get().unwrap().empty_hash()
}
Expand Down Expand Up @@ -187,21 +192,21 @@ impl<F: ScalarField, const T: usize, const RATE: usize> PoseidonHasher<F, T, RAT
pub fn hash_fix_len_array(
&self,
ctx: &mut Context<F>,
range: &impl RangeInstructions<F>,
gate: &impl GateInstructions<F>,
inputs: &[AssignedValue<F>],
) -> AssignedValue<F>
where
F: BigPrimeField,
{
let mut state = self.init_state().clone();
fix_len_array_squeeze(ctx, range.gate(), inputs, &mut state, &self.spec)
fix_len_array_squeeze(ctx, gate, inputs, &mut state, &self.spec)
}

/// Constrains and returns hashes of inputs in a compact format. Length of `compact_inputs` should be determined at compile time.
pub fn hash_compact_input(
&self,
ctx: &mut Context<F>,
range: &impl RangeInstructions<F>,
gate: &impl GateInstructions<F>,
compact_inputs: &[PoseidonCompactInput<F, RATE>],
) -> Vec<PoseidonCompactOutput<F>>
where
Expand All @@ -212,18 +217,18 @@ impl<F: ScalarField, const T: usize, const RATE: usize> PoseidonHasher<F, T, RAT
for input in compact_inputs {
// Assume this is the last row of a logical input:
// Depending on if len == RATE.
let is_full = range.gate().is_equal(ctx, input.len, Constant(F::from(RATE as u64)));
let is_full = gate.is_equal(ctx, input.len, Constant(F::from(RATE as u64)));
// Case 1: if len != RATE.
state.permutation(ctx, range.gate(), &input.inputs, Some(input.len), &self.spec);
state.permutation(ctx, gate, &input.inputs, Some(input.len), &self.spec);
// Case 2: if len == RATE, an extra permuation is needed for squeeze.
let mut state_2 = state.clone();
state_2.permutation(ctx, range.gate(), &[], None, &self.spec);
state_2.permutation(ctx, gate, &[], None, &self.spec);
// Select the result of case 1/2 depending on if len == RATE.
let hash = range.gate().select(ctx, state_2.s[1], state.s[1], is_full);
let hash = gate.select(ctx, state_2.s[1], state.s[1], is_full);
outputs.push(PoseidonCompactOutput { hash, is_final: input.is_final });
// Reset state to init_state if this is the end of a logical input.
// TODO: skip this if this is the last row.
state.select(ctx, range.gate(), input.is_final, self.init_state());
state.select(ctx, gate, input.is_final, self.init_state());
}
outputs
}
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/poseidon/hasher/tests/hasher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ fn hasher_compact_inputs_compatiblity_verification<
let native_result = native_sponge.squeeze();
native_results.push(native_result);
}
let compact_outputs = hasher.hash_compact_input(ctx, range, &compact_inputs);
let compact_outputs = hasher.hash_compact_input(ctx, range.gate(), &compact_inputs);
let mut output_offset = 0;
for (compact_output, compact_input) in compact_outputs.iter().zip(compact_inputs) {
// into() doesn't work if ! is in the beginning in the bool expression...
Expand Down
2 changes: 1 addition & 1 deletion halo2-base/src/poseidon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl<'a, F: ScalarField, const T: usize, const RATE: usize> PoseidonInstructions
{
self.hasher.hash_fix_len_array(
ctx,
self.range_chip,
self.range_chip.gate(),
inputs.bytes().map(|sb| *sb.as_ref()).as_ref(),
)
}
Expand Down
14 changes: 13 additions & 1 deletion halo2-base/src/virtual_region/copy_constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,21 @@ impl<F: Field + Ord> CopyConstraintManager<F> {
/// Adds external raw Halo2 cell to `self.assigned_advices` and returns a new virtual cell that can be
/// used as a tag (but will not be re-assigned). The returned [ContextCell] will have `type_id` the `TypeId::of::<Cell>()`.
pub fn load_external_cell(&mut self, cell: Cell) -> ContextCell {
self.load_external_cell_impl(Some(cell))
}

/// Mock to load an external cell for base circuit simulation. If any mock external cell is loaded, calling [assign_raw] will panic.
pub fn mock_external_assigned(&mut self, v: F) -> AssignedValue<F> {
let context_cell = self.load_external_cell_impl(None);
AssignedValue { value: Assigned::Trivial(v), cell: Some(context_cell) }
}

fn load_external_cell_impl(&mut self, cell: Option<Cell>) -> ContextCell {
let context_cell = ContextCell::new(TypeId::of::<Cell>(), 0, self.external_cell_count);
self.external_cell_count += 1;
self.assigned_advices.insert(context_cell, cell);
if let Some(cell) = cell {
self.assigned_advices.insert(context_cell, cell);
}
context_cell
}

Expand Down
6 changes: 5 additions & 1 deletion hashes/zkevm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ itertools = "0.11"
lazy_static = "1.4"
log = "0.4"
num-bigint = { version = "0.4" }
halo2-base = { path = "../../halo2-base", default-features = false }
halo2-base = { path = "../../halo2-base", default-features = false, features = [
"test-utils",
] }
rayon = "1.7"
sha3 = "0.10.8"
pse-poseidon = { git = "https://github.com/axiom-crypto/pse-poseidon.git" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pse-poseidon should only be in dev-dependencies, do not include in production

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

encode is currently only used for testing, so this is ok. but maybe later I'll change encode to a feature that enables snark-verifier import

getset = "0.1.2"

[dev-dependencies]
criterion = "0.3"
Expand Down
Loading
Loading