Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
e3e1636
feat: simple muladd gadget
roynalnaruto Aug 17, 2022
48d4e0c
feat: muladd gadget fewer columns, more rows
roynalnaruto Aug 17, 2022
9112931
feat: basic structure of EXP and exp_table/circuit
roynalnaruto Aug 19, 2022
73b1b61
feat: bus-mapping for EXP with exponentiation by squaring steps
roynalnaruto Aug 19, 2022
e2ae4ae
fix: interface for exp table lookup
roynalnaruto Aug 19, 2022
ec4b1a8
feat: basic constraints for exp circuit, refactor circuit layout
roynalnaruto Aug 19, 2022
8cc8399
feat: additional constraints for exponentiation circuit
roynalnaruto Aug 19, 2022
12ff3e4
feat: assignments for exponentiation table
roynalnaruto Aug 19, 2022
42de4b0
fix: minor fixes in exp circuit and exp gadget. NOT TESTED
roynalnaruto Aug 20, 2022
fc0ad47
fix: handle exponent cases 0,1 and fix constraints for tests
roynalnaruto Aug 21, 2022
041b6a6
chore: comments and minor refactoring
roynalnaruto Aug 21, 2022
e261b30
fix: constraints for exponentiation circuit, first tests
roynalnaruto Aug 21, 2022
9f64709
test: more test cases for exp circuit
roynalnaruto Aug 22, 2022
a14a193
chore: add exp circuit/table to super circuit
roynalnaruto Aug 22, 2022
8096bfd
use array of 33 boolean cells to determine byte size of exponent
Aug 23, 2022
d1054fd
make clippy happy
roynalnaruto Aug 23, 2022
2770c12
fix: fetching most significant byte fixed, tests passing
roynalnaruto Aug 23, 2022
7ee096b
chore: refactor into byte size gadget
roynalnaruto Aug 23, 2022
5f980d8
chore: remove unnecessary LoC, some doc
roynalnaruto Aug 24, 2022
c51d055
fix: minor constraint fix, add constraints for multiplicand value
roynalnaruto Aug 24, 2022
6495457
chore: add a TODO
roynalnaruto Aug 24, 2022
e53fc52
fix: constraints to verify division by 2 was correct
roynalnaruto Aug 25, 2022
8c4967e
fix: updates based on recent upstream changes
roynalnaruto Sep 2, 2022
398a8f4
fix: add missing constraints for a and b (exp by squaring updates)
roynalnaruto Sep 6, 2022
25cfe1c
fix: intermediate steps generated in exp by squaring
roynalnaruto Sep 6, 2022
ab2b4c4
fix: ensure last step is included (verification through idx transition)
roynalnaruto Sep 7, 2022
94ab00a
feat: enforce is_last exists (additional lookup) and some TODOs
roynalnaruto Sep 7, 2022
834ff0e
chore: refactor constraint into the same condition
roynalnaruto Sep 8, 2022
bbe79bf
feat: add identifier (some todos)
roynalnaruto Sep 8, 2022
e9d4bda
feat: padding row at the end of exp trace
roynalnaruto Sep 9, 2022
8f5ba9a
feat: validate odd/even parity with conditional fixed lookup
roynalnaruto Sep 9, 2022
6aec502
fix: exponent hi was not taken into account for is_zero and is_one co…
roynalnaruto Sep 14, 2022
88eb8ff
fix: identifier | is_pad constraints, 2*n + k parity check using mul …
roynalnaruto Sep 14, 2022
c1be5e6
tests: add the previously failing test, verify that parity check is OK
roynalnaruto Sep 14, 2022
4a76a45
fix: remove redundant column (not used anymore)
roynalnaruto Sep 15, 2022
cf68169
chore: rename field to concise
roynalnaruto Sep 15, 2022
ca81b6c
fix: assignment to exp table matches exp circuit block assignment
roynalnaruto Sep 16, 2022
972573e
fix: is_pad added to lookup, no need for mul gadget in exp gadget
roynalnaruto Sep 16, 2022
1b1a3ed
fix: no overflow in parity check gadget
roynalnaruto Sep 16, 2022
7b6ea7e
fix: exp circuit layout
roynalnaruto Oct 13, 2022
feddd4f
fix: compilation after rebase
roynalnaruto Oct 13, 2022
e8246ce
fix negative tests
lispc Oct 19, 2022
0a9c5e6
remove redundant addition
roynalnaruto Oct 19, 2022
7e5c4f2
fix: c == 0 and is_last bool check
roynalnaruto Oct 20, 2022
184cb67
fix: comment on the correct line
roynalnaruto Oct 25, 2022
1f4b28f
fix: formatting
roynalnaruto Oct 25, 2022
952ff32
fix: uncomment tests
roynalnaruto Oct 26, 2022
621e0d2
refactoring for better encapsulation
roynalnaruto Oct 28, 2022
9b68cb3
fix: avoid conditional assignment
roynalnaruto Oct 28, 2022
e7a65f1
chore: rebase and fmt
roynalnaruto Oct 28, 2022
41ce51b
Merge branch 'main' into feat/exp
roynalnaruto Oct 29, 2022
5ac14ca
Merge branch 'main' into feat/exp
roynalnaruto Oct 31, 2022
2a555ba
fix: more efficient check for boolean formula
roynalnaruto Oct 31, 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
4 changes: 3 additions & 1 deletion bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ use core::fmt::Debug;
use eth_types::sign_types::{pk_bytes_le, pk_bytes_swap_endianness, SignData};
use eth_types::{self, geth_types, Address, GethExecStep, GethExecTrace, Word};
use ethers_providers::JsonRpcClient;
pub use execution::{CopyDataType, CopyEvent, CopyStep, ExecState, ExecStep, NumberOrHash};
pub use execution::{
CopyDataType, CopyEvent, CopyStep, ExecState, ExecStep, ExpEvent, ExpStep, NumberOrHash,
};
pub use input_state_ref::CircuitInputStateRef;
use itertools::Itertools;
use std::collections::HashMap;
Expand Down
15 changes: 12 additions & 3 deletions bus-mapping/src/circuit_input_builder/block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Block-related utility module

use super::{execution::ExecState, transaction::Transaction, CircuitsParams, CopyEvent, ExecStep};
use super::{
execution::ExecState, transaction::Transaction, CircuitsParams, CopyEvent, ExecStep, ExpEvent,
};
use crate::{
operation::{OperationContainer, RWCounter},
Error,
Expand Down Expand Up @@ -79,6 +81,8 @@ pub struct Block {
pub copy_events: Vec<CopyEvent>,
/// Inputs to the SHA3 opcode
pub sha3_inputs: Vec<Vec<u8>>,
/// Exponentiation events in the block.
pub exp_events: Vec<ExpEvent>,
code: HashMap<Hash, Vec<u8>>,
/// Circuits Setup Paramteres
pub circuits_params: CircuitsParams,
Expand Down Expand Up @@ -127,6 +131,7 @@ impl Block {
},
},
copy_events: Vec::new(),
exp_events: Vec::new(),
code: HashMap::new(),
sha3_inputs: Vec::new(),
circuits_params,
Expand All @@ -146,7 +151,11 @@ impl Block {

impl Block {
/// Push a copy event to the block.
pub fn add_copy_event(&mut self, copy: CopyEvent) {
self.copy_events.push(copy);
pub fn add_copy_event(&mut self, event: CopyEvent) {
self.copy_events.push(event);
}
/// Push an exponentiation event to the block.
pub fn add_exp_event(&mut self, event: ExpEvent) {
self.exp_events.push(event);
}
}
38 changes: 37 additions & 1 deletion bus-mapping/src/circuit_input_builder/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
};
use eth_types::{
evm_types::{Gas, GasCost, OpcodeId, ProgramCounter},
GethExecStep, H256,
GethExecStep, Word, H256,
};
use gadgets::impl_expr;
use halo2_proofs::plonk::Expression;
Expand Down Expand Up @@ -262,3 +262,39 @@ impl CopyEvent {
source_rw_increase + destination_rw_increase
}
}

/// Intermediary multiplication step, representing `a * b == d (mod 2^256)`
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ExpStep {
/// First multiplicand.
pub a: Word,
/// Second multiplicand.
pub b: Word,
/// Multiplication result.
pub d: Word,
}

impl From<(Word, Word, Word)> for ExpStep {
fn from(values: (Word, Word, Word)) -> Self {
Self {
a: values.0,
b: values.1,
d: values.2,
}
}
}

/// Event representating an exponentiation `a ^ b == d (mod 2^256)`.
#[derive(Clone, Debug)]
pub struct ExpEvent {
/// Identifier for the exponentiation trace.
pub identifier: usize,
/// Base `a` for the exponentiation.
pub base: Word,
/// Exponent `b` for the exponentiation.
pub exponent: Word,
/// Exponentiation result.
pub exponentiation: Word,
/// Intermediate multiplication results.
pub steps: Vec<ExpStep>,
}
12 changes: 9 additions & 3 deletions bus-mapping/src/circuit_input_builder/input_state_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

use super::{
get_call_memory_offset_length, get_create_init_code, Block, BlockContext, Call, CallContext,
CallKind, CodeSource, CopyEvent, ExecState, ExecStep, Transaction, TransactionContext,
CallKind, CodeSource, CopyEvent, ExecState, ExecStep, ExpEvent, Transaction,
TransactionContext,
};
use crate::{
error::{get_step_reported_error, ExecError},
Expand Down Expand Up @@ -924,8 +925,13 @@ impl<'a> CircuitInputStateRef<'a> {
}

/// Push a copy event to the state.
pub fn push_copy(&mut self, copy: CopyEvent) {
self.block.add_copy_event(copy);
pub fn push_copy(&mut self, event: CopyEvent) {
self.block.add_copy_event(event);
}

/// Push a exponentiation event to the state.
pub fn push_exponentiation(&mut self, event: ExpEvent) {
self.block.add_exp_event(event)
}

pub(crate) fn get_step_err(
Expand Down
4 changes: 3 additions & 1 deletion bus-mapping/src/evm/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ mod codecopy;
mod codesize;
mod create;
mod dup;
mod exp;
mod extcodecopy;
mod extcodehash;
mod extcodesize;
Expand Down Expand Up @@ -67,6 +68,7 @@ use codecopy::Codecopy;
use codesize::Codesize;
use create::DummyCreate;
use dup::Dup;
use exp::Exponentiation;
use extcodecopy::Extcodecopy;
use extcodehash::Extcodehash;
use extcodesize::Extcodesize;
Expand Down Expand Up @@ -133,7 +135,6 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps {
OpcodeId::SMOD => StackOnlyOpcode::<2, 1>::gen_associated_ops,
OpcodeId::ADDMOD => StackOnlyOpcode::<3, 1>::gen_associated_ops,
OpcodeId::MULMOD => StackOnlyOpcode::<3, 1>::gen_associated_ops,
OpcodeId::EXP => StackOnlyOpcode::<2, 1>::gen_associated_ops,
OpcodeId::SIGNEXTEND => StackOnlyOpcode::<2, 1>::gen_associated_ops,
OpcodeId::LT => StackOnlyOpcode::<2, 1>::gen_associated_ops,
OpcodeId::GT => StackOnlyOpcode::<2, 1>::gen_associated_ops,
Expand Down Expand Up @@ -161,6 +162,7 @@ fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps {
OpcodeId::GASPRICE => GasPrice::gen_associated_ops,
OpcodeId::CODECOPY => Codecopy::gen_associated_ops,
OpcodeId::CODESIZE => Codesize::gen_associated_ops,
OpcodeId::EXP => Exponentiation::gen_associated_ops,
OpcodeId::EXTCODESIZE => Extcodesize::gen_associated_ops,
OpcodeId::EXTCODECOPY => Extcodecopy::gen_associated_ops,
OpcodeId::RETURNDATASIZE => Returndatasize::gen_associated_ops,
Expand Down
103 changes: 103 additions & 0 deletions bus-mapping/src/evm/opcodes/exp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use crate::{
circuit_input_builder::{CircuitInputStateRef, ExecStep, ExpEvent, ExpStep},
Error,
};
use eth_types::{GethExecStep, U256};

use super::Opcode;

#[derive(Clone, Copy, Debug)]
pub(crate) struct Exponentiation;

fn exp_by_squaring(base: U256, exponent: U256, steps: &mut Vec<ExpStep>) -> U256 {
if exponent.is_zero() {
return U256::one();
}
if exponent == U256::one() {
return base;
}

let (exponent_div2, odd) = exponent.div_mod(U256::from(2));
let exp1 = exp_by_squaring(base, exponent_div2, steps);
let (exp2, _) = exp1.overflowing_mul(exp1);
steps.push((exp1, exp1, exp2).into());

if odd.is_zero() {
// exponent is even
exp2
} else {
// exponent is odd
let (exp, _) = base.overflowing_mul(exp2);
steps.push((exp2, base, exp).into());
exp
}
}

impl Opcode for Exponentiation {
fn gen_associated_ops(
state: &mut CircuitInputStateRef,
geth_steps: &[GethExecStep],
) -> Result<Vec<ExecStep>, Error> {
let geth_step = &geth_steps[0];
let mut exec_step = state.new_step(geth_step)?;

let base = geth_step.stack.nth_last(0)?;
state.stack_read(&mut exec_step, geth_step.stack.nth_last_filled(0), base)?;
let exponent = geth_step.stack.nth_last(1)?;
state.stack_read(&mut exec_step, geth_step.stack.nth_last_filled(1), exponent)?;

let (exponentiation, _) = base.overflowing_pow(exponent);
state.stack_write(
&mut exec_step,
geth_steps[1].stack.last_filled(),
exponentiation,
)?;

let mut steps = Vec::new();
let exponentiation_calc = exp_by_squaring(base, exponent, &mut steps);
debug_assert_eq!(exponentiation, exponentiation_calc);
state.push_exponentiation(ExpEvent {
identifier: state.block_ctx.rwc.0,
base,
exponent,
exponentiation,
steps,
});

Ok(vec![exec_step])
}
}

#[cfg(test)]
mod tests {
use eth_types::U256;

use super::exp_by_squaring;

#[test]
fn test_exp_by_squaring() {
let mut steps = Vec::new();
let exp = exp_by_squaring(23u64.into(), 123u64.into(), &mut steps);
assert_eq!(
exp,
U256::from_dec_str(
"87180413255890732361416772728849128389641993872302935967571352892955279939527"
)
.unwrap()
);

let mut steps = Vec::new();
let exp = exp_by_squaring(3u64.into(), 13u64.into(), &mut steps);
assert_eq!(exp, 1594323u64.into());
assert_eq!(
steps,
vec![
(3.into(), 3.into(), 9.into()).into(),
(9.into(), 3.into(), 27.into()).into(),
(27.into(), 27.into(), 729.into()).into(),
(729.into(), 729.into(), 531441.into()).into(),
(531441.into(), 3.into(), 1594323.into()).into(),
]
);
}
}
2 changes: 2 additions & 0 deletions circuit-benchmarks/src/evm_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl<F: Field> Circuit<F> for TestCircuit<F> {
let block_table = BlockTable::construct(meta);
let copy_table = [(); 11].map(|_| meta.advice_column());
let keccak_table = [(); 4].map(|_| meta.advice_column());
let exp_table = [(); 9].map(|_| meta.advice_column());
// Use constant expression to mock constant instance column for a more
// reasonable benchmark.
let power_of_randomness = [(); 31].map(|_| Expression::Constant(F::one()));
Expand All @@ -41,6 +42,7 @@ impl<F: Field> Circuit<F> for TestCircuit<F> {
&block_table,
&copy_table,
&keccak_table,
&exp_table,
)
}

Expand Down
1 change: 1 addition & 0 deletions gadgets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod evm_word;
pub mod is_zero;
pub mod less_than;
pub mod monotone;
pub mod mul_add;
pub mod util;

use eth_types::Field;
Expand Down
Loading