Skip to content

Commit

Permalink
Migrate gadgets from zkevm-circuits mod to it'w own crate (scroll-tec…
Browse files Browse the repository at this point in the history
…h#457)

* Migrate gadgets from zkevm-circuits mod to it'w own crate

* add: Include `gadgets` as workspace member

* update: Include `gadgets` into workflows config

Resolves: scroll-tech#444
  • Loading branch information
CPerezz authored Apr 13, 2022
1 parent 29ccd5f commit f96b07d
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 82 deletions.
3 changes: 3 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ crate-eth-types:
- eth-types/**/*
crate-external-tracer:
- external-tracer/**/*
crate-gadgets:
- gadgets/**/*
crate-geth-utils:
- geth-utils/**/*
crate-integration-tests:
Expand All @@ -30,6 +32,7 @@ T-opcode:
"zkevm-circuits/src/evm_circuit/execution/**/*",
"bus-mapping/src/evm/opcodes/**/*",
]

# Add 'T-bench' to any changes related to benchmarks in `circuit-benchmarks`.
T-bench:
- circuit-benchmarks/**/*
2 changes: 2 additions & 0 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ categories:
label: "crate-eth-types"
- title: "Changes in external-tracer"
label: "crate-external-tracer"
- title: "Changes in gadgets"
label: "crate-gadgets"
- title: "Changes in geth-utils"
label: "crate-geth-utils"
- title: "Changes in integration-tests"
Expand Down
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"bus-mapping",
"keccak256",
"geth-utils",
"gadgets",
"integration-tests",
"circuit-benchmarks",
"eth-types",
Expand Down
1 change: 1 addition & 0 deletions gadgets/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
17 changes: 17 additions & 0 deletions gadgets/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "gadgets"
version = "0.1.0"
edition = "2021"
authors = ["The appliedzkp team"]

[dependencies]
ff = "0.11"
halo2_proofs = { git = "https://github.com/appliedzkp/halo2.git", tag = "v2022_03_06" }
pairing = { git = 'https://github.com/appliedzkp/pairing', package = "pairing_bn256" }
sha3 = "0.7.2"
eth-types = { path = "../eth-types" }
digest = "0.7.6"

[dev-dependencies]
rand_xorshift = "0.3"
rand = "0.8"
52 changes: 23 additions & 29 deletions zkevm-circuits/src/gadget/evm_word.rs → gadgets/src/evm_word.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! In the zkevm circuit, this `encode(word)` expression will not be directly
//! looked up. Instead, it will be folded into the bus mapping lookup.
use crate::gadget::Variable;
use crate::Variable;
use digest::{FixedOutput, Input};
use eth_types::Field;
use halo2_proofs::{
Expand All @@ -20,9 +20,9 @@ use std::convert::TryInto;
#[cfg(test)]
use halo2_proofs::circuit::Layouter;

// r = hash([0, 1, ..., 255])
// TODO: Move into crate-level `constants` file.
pub(crate) fn r<F: Field>() -> F {
/// r = hash([0, 1, ..., 255])
pub fn r<F: Field>() -> F {
let mut hasher = Keccak256::new();
for byte in 0..=u8::MAX {
hasher.process(&[byte]);
Expand All @@ -32,46 +32,40 @@ pub(crate) fn r<F: Field>() -> F {
F::from_bytes_wide(&r)
}

// Returns encoding of big-endian representation of a 256-bit word.
pub(crate) fn encode<F: Field>(vals: impl Iterator<Item = u8>, r: F) -> F {
/// Returns encoding of big-endian representation of a 256-bit word.
pub fn encode<F: Field>(vals: impl Iterator<Item = u8>, r: F) -> F {
vals.fold(F::zero(), |acc, val| {
let byte = F::from(val as u64);
acc * r + byte
})
}

/// A 256-bit word represented in the circuit as 32 bytes.
pub(crate) struct Word<F: Field>([Variable<u8, F>; 32]);

impl<F: Field> Word<F> {
fn encoded_val(&self, r: F) -> Option<F> {
if self.0[0].value.is_some() {
let val = self.0.iter().rev().map(|var| var.value.unwrap());
let val = encode(val, r);
Some(val)
} else {
None
}
}
}
pub struct Word<F: Field>([Variable<u8, F>; 32]);

#[allow(dead_code)]
/// Configuration structure used to constraint. generate and assign an EVM Word
/// inside a circuit.
#[derive(Clone, Debug)]
pub(crate) struct WordConfig<F: Field> {
// Randomness used to compress the word encoding.
pub struct WordConfig<F: Field> {
/// Randomness used to compress the word encoding.
r: F,
// Selector to toggle the word encoding gate.
/// Selector to toggle the word encoding gate.
// TODO: This may be replaced by a synthetic selector.
pub q_encode: Selector,
// Advice columns used to witness the byte representation of the word.
pub bytes: [Column<Advice>; 32],
// Fixed column containing all possible 8-bit values. This is used in
// a lookup argument to range-constrain each byte.
pub byte_lookup: Column<Fixed>,
// Expression representing `encode(word)`.
pub encode_word_expr: Expression<F>,
q_encode: Selector,
/// Advice columns used to witness the byte representation of the word.
bytes: [Column<Advice>; 32],
/// Fixed column containing all possible 8-bit values. This is used in
/// a lookup argument to range-constrain each byte.
byte_lookup: Column<Fixed>,
/// Expression representing `encode(word)`.
encode_word_expr: Expression<F>,
}

impl<F: Field> WordConfig<F> {
/// Sets up the configuration of the config by creating the required columns
/// & selectors and defining the constraints that take part when using a
/// Word.
pub fn configure(
meta: &mut ConstraintSystem<F>,
r: F,
Expand Down
48 changes: 34 additions & 14 deletions zkevm-circuits/src/gadget/is_zero.rs → gadgets/src/is_zero.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
//! IsZero gadget works as follows:
//!
//! Given a `value` to be checked if it is zero:
//! - witnesses `inv0(value)`, where `inv0(x)` is 0 when `x` = 0, and
//! `1/x` otherwise
use halo2_proofs::{
circuit::{Chip, Region},
plonk::{Advice, Column, ConstraintSystem, Error, Expression, VirtualCells},
Expand All @@ -6,7 +12,9 @@ use halo2_proofs::{
use pairing::arithmetic::FieldExt;
use std::array;

pub(crate) trait IsZeroInstruction<F: FieldExt> {
/// Trait that needs to be implemented for any gadget or circuit that wants to
/// implement `IsZero`.
pub trait IsZeroInstruction<F: FieldExt> {
/// Given a `value` to be checked if it is zero:
/// - witnesses `inv0(value)`, where `inv0(x)` is 0 when `x` = 0, and
/// `1/x` otherwise
Expand All @@ -18,19 +26,41 @@ pub(crate) trait IsZeroInstruction<F: FieldExt> {
) -> Result<(), Error>;
}

/// Config struct representing the required fields for an `IsZero` config to
/// exist.
#[derive(Clone, Debug)]
pub(crate) struct IsZeroConfig<F> {
pub struct IsZeroConfig<F> {
/// Modular inverse of the value.
pub value_inv: Column<Advice>,
/// This can be used directly for custom gate at the offset if `is_zero` is
/// called, it will be 1 if `value` is zero, and 0 otherwise.
pub is_zero_expression: Expression<F>,
}

pub(crate) struct IsZeroChip<F> {
/// Wrapper arround [`IsZeroConfig`] for which [`Chip`] is implemented.
pub struct IsZeroChip<F> {
config: IsZeroConfig<F>,
}

impl<F: FieldExt> IsZeroChip<F> {
#[rustfmt::skip]
/// Sets up the configuration of the chip by creating the required columns
/// and defining the constraints that take part when using `is_zero` gate.
///
/// Truth table of iz_zero gate:
/// +----+-------+-----------+-----------------------+---------------------------------+-------------------------------------+
/// | ok | value | value_inv | 1 - value ⋅ value_inv | value ⋅ (1 - value ⋅
/// value_inv) | value_inv ⋅ (1 - value ⋅ value_inv) |
/// +----+-------+-----------+-----------------------+---------------------------------+-------------------------------------+
/// | V | 0 | 0 | 1 | 0
/// | 0 | | | 0 | x | 1
/// | 0 | x |
/// | | x | 0 | 1 | x
/// | 0 | | V | x | 1/x | 0
/// | 0 | 0 |
/// | | x | y | 1 - xy | x(1 - xy)
/// | y(1 - xy) |
/// +----+-------+-----------+-----------------------+---------------------------------+-------------------------------------+
pub fn configure(
meta: &mut ConstraintSystem<F>,
q_enable: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression<F>,
Expand All @@ -40,17 +70,6 @@ impl<F: FieldExt> IsZeroChip<F> {
// dummy initialization
let mut is_zero_expression = Expression::Constant(F::zero());

#[rustfmt::skip]
// Truth table of iz_zero gate:
// +----+-------+-----------+-----------------------+---------------------------------+-------------------------------------+
// | ok | value | value_inv | 1 - value ⋅ value_inv | value ⋅ (1 - value ⋅ value_inv) | value_inv ⋅ (1 - value ⋅ value_inv) |
// +----+-------+-----------+-----------------------+---------------------------------+-------------------------------------+
// | V | 0 | 0 | 1 | 0 | 0 |
// | | 0 | x | 1 | 0 | x |
// | | x | 0 | 1 | x | 0 |
// | V | x | 1/x | 0 | 0 | 0 |
// | | x | y | 1 - xy | x(1 - xy) | y(1 - xy) |
// +----+-------+-----------+-----------------------+---------------------------------+-------------------------------------+
meta.create_gate("is_zero gate", |meta| {
let q_enable = q_enable(meta);

Expand All @@ -77,6 +96,7 @@ impl<F: FieldExt> IsZeroChip<F> {
}
}

/// Given an `IsZeroConfig`, construct the chip.
pub fn construct(config: IsZeroConfig<F>) -> Self {
IsZeroChip { config }
}
Expand Down
33 changes: 33 additions & 0 deletions gadgets/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//! # ZKEVM-Gadgets
//!
//! A collection of reusable gadgets for the zk_evm circuits.
#![cfg_attr(docsrs, feature(doc_cfg))]
// We want to have UPPERCASE idents sometimes.
#![allow(clippy::upper_case_acronyms)]
// Catch documentation errors caused by code changes.
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(missing_docs)]
#![deny(unsafe_code)]
#![deny(clippy::debug_assert_with_mut_call)]

pub mod evm_word;
pub mod is_zero;
pub mod monotone;

use halo2_proofs::circuit::AssignedCell;
use pairing::arithmetic::FieldExt;

#[allow(dead_code)]
/// An assigned cell in the circuit.
#[derive(Clone, Debug)]
pub struct Variable<T, F: FieldExt> {
assig_cell: AssignedCell<F, F>,
value: Option<T>,
}

impl<T, F: FieldExt> Variable<T, F> {
pub(crate) fn new(assig_cell: AssignedCell<F, F>, value: Option<T>) -> Self {
Self { assig_cell, value }
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! # Monotone mod
//! Monotone gadget helps to check if an advice column is monotonically
//! increasing within a range. With strict enabled, it disallows equality of two
//! cell.
use halo2_proofs::{
circuit::{Chip, Layouter},
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Fixed, VirtualCells},
Expand All @@ -6,6 +10,7 @@ use halo2_proofs::{
use pairing::arithmetic::FieldExt;
use std::{marker::PhantomData, u64};

#[allow(dead_code)]
#[derive(Clone, Debug)]
pub(crate) struct MonotoneConfig {
range_table: Column<Fixed>,
Expand All @@ -19,6 +24,7 @@ pub(crate) struct MonotoneChip<F, const RANGE: usize, const INCR: bool, const ST
_marker: PhantomData<F>,
}

#[allow(dead_code)]
impl<F: FieldExt, const RANGE: usize, const INCR: bool, const STRICT: bool>
MonotoneChip<F, RANGE, INCR, STRICT>
{
Expand Down
4 changes: 2 additions & 2 deletions zkevm-circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ sha3 = "0.7.2"
digest = "0.7.6"
array-init = "2.0.0"
paste = "1.0"
bus-mapping = { path = "../bus-mapping"}
bus-mapping = { path = "../bus-mapping" }
eth-types = { path = "../eth-types" }
gadgets = { path = "../gadgets" }
ethers-core = "0.6"
serde_json = "1.0.66"
rand_xorshift = "0.3"
rand = "0.8"
itertools = "0.10.3"
lazy_static = "1.4"
keccak256 = { path = "../keccak256"}

log = "0.4.14"
env_logger = "0.9"

Expand Down
8 changes: 4 additions & 4 deletions zkevm-circuits/src/bytecode_circuit/bytecode_unroller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ use crate::{
RandomLinearCombination,
},
},
gadget::{
evm_word::encode,
is_zero::{IsZeroChip, IsZeroConfig, IsZeroInstruction},
},
util::Expr,
};
use bus_mapping::evm::OpcodeId;
use eth_types::Field;
use gadgets::{
evm_word::encode,
is_zero::{IsZeroChip, IsZeroConfig, IsZeroInstruction},
};
use halo2_proofs::{
circuit::{Layouter, Region},
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Fixed, Selector, VirtualCells},
Expand Down
20 changes: 0 additions & 20 deletions zkevm-circuits/src/gadget.rs

This file was deleted.

1 change: 0 additions & 1 deletion zkevm-circuits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

pub mod bytecode_circuit;
pub mod evm_circuit;
pub mod gadget;
pub mod rw_table;
pub mod state_circuit;
#[cfg(test)]
Expand Down
Loading

0 comments on commit f96b07d

Please sign in to comment.