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] Precompile MODEXP #520

Merged
merged 69 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
e71851c
feat: preliminary work
roynalnaruto Jun 8, 2023
f525950
wip
roynalnaruto Jun 8, 2023
8bdaaf5
finish assignment to ecrecover
roynalnaruto Jun 9, 2023
11764fa
fix: input length may be different than call data length (for precomp…
roynalnaruto Jun 9, 2023
2176c44
fix: input bytes to ecrecover
roynalnaruto Jun 26, 2023
6ab87ea
minor edits
roynalnaruto Jun 26, 2023
ade3c99
modexp table
noel2004 May 30, 2023
6bbc644
wip
noel2004 Jun 15, 2023
0a4082d
add auxdata of modexp
noel2004 Jun 25, 2023
ad62cbf
assign in modexp gadget
noel2004 Jun 25, 2023
c9cc27d
wip: fix most constraint failure
noel2004 Jun 28, 2023
a6a531a
wip
noel2004 Jun 28, 2023
a567835
wip: fix constraints
noel2004 Jun 28, 2023
798cf69
Merge branch 'develop' into feat/ecrecover
roynalnaruto Jun 28, 2023
4bf677b
Merge remote-tracking branch 'main/feat/ecrecover' into feat/precompi…
noel2004 Jun 29, 2023
3e47f86
pass primary test
noel2004 Jun 29, 2023
8c36b29
optimize phase2 cell usage and add more tests
noel2004 Jun 30, 2023
d010625
add invalid detection and test
noel2004 Jul 2, 2023
13ac75c
wip: induce u256 modexp
noel2004 Jul 2, 2023
a39254e
modexp event
noel2004 Jul 2, 2023
01d5567
wip: induce modexp table to evm
noel2004 Jul 3, 2023
e647aa9
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 4, 2023
8fd7ad6
fix super circuit
noel2004 Jul 4, 2023
bb26c50
induce modexp table done
noel2004 Jul 5, 2023
b4310d8
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 5, 2023
b3c26ef
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 5, 2023
71e65a4
regression pass
noel2004 Jul 5, 2023
e927690
modexp circuit done
noel2004 Jul 5, 2023
ac12be0
wip: test modexp table lookup
noel2004 Jul 5, 2023
733d1b6
wip: testing modexp table lookup
noel2004 Jul 6, 2023
31f57c1
pass modexptable lookup
noel2004 Jul 6, 2023
1da8308
pass u256 modexp circuit
noel2004 Jul 6, 2023
fdf67e8
refine dependencies
noel2004 Jul 6, 2023
388c1b6
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 6, 2023
d05ed22
fix for merging develop
noel2004 Jul 6, 2023
b42bec9
add modexp into super circuit
noel2004 Jul 6, 2023
35f94d1
clippy
noel2004 Jul 7, 2023
24897b0
fmt
noel2004 Jul 7, 2023
7aa74be
disable ecrecover temporarily.
noel2004 Jul 7, 2023
c076ea0
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 7, 2023
8e5cb4a
post merging fixing
noel2004 Jul 7, 2023
62635f0
fmt and clippy
noel2004 Jul 7, 2023
8e68fb2
for invalid input
noel2004 Jul 9, 2023
55664f7
upgrade modexp circuit dep
noel2004 Jul 10, 2023
09d4a86
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 12, 2023
39299eb
fixes according to review
noel2004 Jul 12, 2023
2d71b36
fmt
noel2004 Jul 12, 2023
1606732
update dep, prune ff 0.13
noel2004 Jul 13, 2023
6687ef2
optimize by powofrand table
noel2004 Jul 13, 2023
b23ae25
constraint for nil output
noel2004 Jul 14, 2023
bfca828
reverse geth step error indication for precompile
noel2004 Jul 14, 2023
071bfef
trivial fix for invalid case
noel2004 Jul 14, 2023
2621de8
fmt
noel2004 Jul 14, 2023
4b69d20
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 14, 2023
d5fd268
error should not be throw for precompile failure
noel2004 Jul 22, 2023
ef1e94e
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 27, 2023
2c4be68
fix for merge
noel2004 Jul 27, 2023
f61ba9e
post-merge fixes for compile errors
noel2004 Jul 27, 2023
3355555
reverse throwing precompile error in get_step_err
noel2004 Jul 28, 2023
34b9d5b
fmt
noel2004 Jul 28, 2023
1871c45
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 28, 2023
f9d1578
clippy lint
noel2004 Jul 29, 2023
0cdd7c4
update `dev_load` of modexp table and some file structures
noel2004 Jul 29, 2023
938c7e2
resume size limit for modexp
noel2004 Jul 29, 2023
b51d1f7
refactor and support garbage bytes in input
noel2004 Jul 31, 2023
c89cacd
prune and lint
noel2004 Jul 31, 2023
d8e1ba8
Merge remote-tracking branch 'origin/develop' into feat/precompile-mo…
noel2004 Jul 31, 2023
91108c0
+ resume the precompile error detection. + trivial logs
noel2004 Jul 31, 2023
98a75b2
update modexp chip rows usage constant
noel2004 Aug 1, 2023
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
34 changes: 34 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ use ethers_core::{
};
use ethers_providers::JsonRpcClient;
pub use execution::{
CopyDataType, CopyEvent, CopyStep, ExecState, ExecStep, ExpEvent, ExpStep, NumberOrHash,
CopyDataType, CopyEvent, CopyStep, ExecState, ExecStep, ExpEvent, ExpStep, ModExpEvent,
NumberOrHash,
};
use hex::decode_to_slice;

Expand Down
7 changes: 7 additions & 0 deletions bus-mapping/src/circuit_input_builder/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use super::{
execution::ExecState, transaction::Transaction, CircuitsParams, CopyEvent, ExecStep, ExpEvent,
ModExpEvent,
};
use crate::{
operation::{OperationContainer, RWCounter},
Expand Down Expand Up @@ -155,6 +156,8 @@ pub struct Block {
pub sha3_inputs: Vec<Vec<u8>>,
/// IO to/from the precompile Ecrecover calls.
pub ecrecover_events: Vec<SignData>,
/// Params for the precompile Modexp calls.
pub modexp_events: Vec<ModExpEvent>,
/// Block-wise steps
pub block_steps: BlockSteps,
/// Exponentiation events in the block.
Expand Down Expand Up @@ -252,4 +255,8 @@ impl Block {
pub fn add_ecrecover_event(&mut self, event: SignData) {
self.ecrecover_events.push(event);
}
/// Push an modexp event to the block.
pub fn add_modexp_event(&mut self, event: ModExpEvent) {
self.modexp_events.push(event);
}
}
24 changes: 24 additions & 0 deletions bus-mapping/src/circuit_input_builder/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,3 +459,27 @@ impl Default for ExpEvent {
}
}
}

/// Event representating an exponentiation `a ^ b == d (mod m)` in precompile modexp.
#[derive(Clone, Debug)]
pub struct ModExpEvent {
/// Base `a` for the exponentiation.
pub base: Word,
/// Exponent `b` for the exponentiation.
pub exponent: Word,
/// Modulus `m`
pub modulus: Word,
/// Mod exponentiation result.
pub result: Word,
}

impl Default for ModExpEvent {
fn default() -> Self {
Self {
modulus: 1.into(),
base: Default::default(),
exponent: Default::default(),
result: Default::default(),
}
}
}
7 changes: 6 additions & 1 deletion 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,7 @@

use super::{
get_call_memory_offset_length, get_create_init_code, Block, BlockContext, Call, CallContext,
CallKind, CodeSource, CopyEvent, ExecState, ExecStep, ExpEvent, Transaction,
CallKind, CodeSource, CopyEvent, ExecState, ExecStep, ExpEvent, ModExpEvent, Transaction,
TransactionContext,
};
#[cfg(feature = "scroll")]
Expand Down Expand Up @@ -1313,6 +1313,11 @@ impl<'a> CircuitInputStateRef<'a> {
self.block.add_exp_event(event)
}

/// Push a modexp event to the state.
pub fn push_modexp(&mut self, event: ModExpEvent) {
self.block.add_modexp_event(event)
}

/// Push an ecrecover event to the state.
pub fn push_ecrecover(&mut self, event: SignData) {
self.block.add_ecrecover_event(event)
Expand Down
19 changes: 17 additions & 2 deletions bus-mapping/src/evm/opcodes/precompiles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use eth_types::{
use halo2_proofs::halo2curves::secp256k1::Fq;

use crate::{
circuit_input_builder::{Call, CircuitInputStateRef, ExecState, ExecStep},
circuit_input_builder::{Call, CircuitInputStateRef, ExecState, ExecStep, ModExpEvent},
operation::CallContextField,
precompile::{EcrecoverAuxData, PrecompileAuxData, PrecompileCalls},
precompile::{EcrecoverAuxData, ModExpAuxData, PrecompileAuxData, PrecompileCalls},
Error,
};

Expand Down Expand Up @@ -62,6 +62,21 @@ pub fn gen_associated_ops(
}

exec_step.aux_data = Some(PrecompileAuxData::Ecrecover(aux_data));
} else if precompile == PrecompileCalls::Modexp {
let aux_data = ModExpAuxData::new(
input_bytes.unwrap_or_default(),
output_bytes.unwrap_or_default(),
);
if aux_data.valid {
let event = ModExpEvent {
base: Word::from_big_endian(&aux_data.inputs[0]),
exponent: Word::from_big_endian(&aux_data.inputs[1]),
modulus: Word::from_big_endian(&aux_data.inputs[2]),
result: Word::from_big_endian(&aux_data.output),
};
state.push_modexp(event);
}
exec_step.aux_data = Some(PrecompileAuxData::Modexp(aux_data));
}

Ok(exec_step)
Expand Down
113 changes: 112 additions & 1 deletion bus-mapping/src/precompile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,22 @@ pub(crate) fn execute_precompiled(address: &Address, input: &[u8], gas: u64) ->
};

match precompile_fn(input, gas) {
Ok((gas_cost, return_value)) => (return_value, gas_cost),
Ok((gas_cost, return_value)) => {
match PrecompileCalls::from(address.0[19]) {
// FIXME: override the behavior of invalid input
PrecompileCalls::Modexp => {
let (input_valid, [_, _, modulus_len]) = ModExpAuxData::check_input(input);
if input_valid {
// detect some edge cases like modulus = 0
assert_eq!(modulus_len.as_usize(), return_value.len());
(return_value, gas_cost)
} else {
(vec![], gas)
}
}
_ => (return_value, gas_cost),
}
}
Err(_) => (vec![], gas),
}
}
Expand Down Expand Up @@ -115,6 +130,7 @@ impl PrecompileCalls {
match self {
Self::Ecrecover | Self::Bn128Add => Some(128),
Self::Bn128Mul => Some(96),
//Self::Modexp => Some(MODEXP_INPUT_LIMIT),
noel2004 marked this conversation as resolved.
Show resolved Hide resolved
_ => None,
}
}
Expand Down Expand Up @@ -166,11 +182,106 @@ impl EcrecoverAuxData {
}
}

/// size limit of modexp
pub const MODEXP_SIZE_LIMIT: usize = 32;
/// size of input limit
pub const MODEXP_INPUT_LIMIT: usize = 192;

/// Auxiliary data for Modexp
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct ModExpAuxData {
/// The specified len of inputs: [base, exp, modulus]
pub input_lens: [Word; 3],
/// Input value [base, exp, modulus], limited to SIZE_LIMIT
pub inputs: [[u8; MODEXP_SIZE_LIMIT]; 3],
/// Input valid.
pub valid: bool,
/// len of output, limited to lens of moduls, but can be 0
pub output_len: usize,
/// output of modexp.
pub output: [u8; MODEXP_SIZE_LIMIT],
/// backup of input memory
pub input_memory: Vec<u8>,
/// backup of output memory
pub output_memory: Vec<u8>,
}

impl ModExpAuxData {
fn parse_memory_to_value(mem: &[u8]) -> [u8; MODEXP_SIZE_LIMIT] {
let mut value_bytes = [0u8; MODEXP_SIZE_LIMIT];
if !mem.is_empty() {
value_bytes.as_mut_slice()[(MODEXP_SIZE_LIMIT - mem.len())..].copy_from_slice(mem);
}
value_bytes
}

/// check input
pub fn check_input(input: &[u8]) -> (bool, [Word; 3]) {
let mut i = input.chunks(32);
let base_len = Word::from_big_endian(i.next().unwrap_or(&[]));
let exp_len = Word::from_big_endian(i.next().unwrap_or(&[]));
let modulus_len = Word::from_big_endian(i.next().unwrap_or(&[]));

let limit = Word::from(MODEXP_SIZE_LIMIT);

let input_valid = base_len <= limit && exp_len <= limit && modulus_len <= limit;

(input_valid, [base_len, exp_len, modulus_len])
}

/// Create a new instance of modexp auxiliary data.
pub fn new(mut mem_input: Vec<u8>, output: Vec<u8>) -> Self {
noel2004 marked this conversation as resolved.
Show resolved Hide resolved
let input_memory = mem_input.clone();
let output_memory = output.clone();

let (input_valid, [base_len, exp_len, modulus_len]) = Self::check_input(&mem_input);

let base_mem_len = if input_valid {
base_len.as_usize()
} else {
MODEXP_SIZE_LIMIT
};
let exp_mem_len = if input_valid {
exp_len.as_usize()
} else {
MODEXP_SIZE_LIMIT
};
let modulus_mem_len = if input_valid {
modulus_len.as_usize()
} else {
MODEXP_SIZE_LIMIT
};

mem_input.resize(96 + base_mem_len + exp_mem_len + modulus_mem_len, 0);
let mut cur_input_begin = &mem_input[96..];

let base = Self::parse_memory_to_value(&cur_input_begin[..base_mem_len]);
cur_input_begin = &cur_input_begin[base_mem_len..];
let exp = Self::parse_memory_to_value(&cur_input_begin[..exp_mem_len]);
cur_input_begin = &cur_input_begin[exp_mem_len..];
let modulus = Self::parse_memory_to_value(&cur_input_begin[..modulus_mem_len]);
noel2004 marked this conversation as resolved.
Show resolved Hide resolved
let output_len = output.len();
let output = Self::parse_memory_to_value(&output);

Self {
valid: input_valid,
input_lens: [base_len, exp_len, modulus_len],
inputs: [base, exp, modulus],
output,
output_len,
input_memory,
output_memory,
}
}
}

/// Auxiliary data attached to an internal state for precompile verification.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PrecompileAuxData {
/// Ecrecover.
Ecrecover(EcrecoverAuxData),
/// Modexp.
Modexp(ModExpAuxData),
}

impl Default for PrecompileAuxData {
Expand Down
1 change: 1 addition & 0 deletions eth-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ impl fmt::Debug for GethExecStep {
.field("op", &self.op)
.field("gas", &format_args!("{}", self.gas.0))
.field("gas_cost", &format_args!("{}", self.gas_cost.0))
.field("refund", &format_args!("{}", self.refund.0))
.field("depth", &self.depth)
.field("error", &self.error)
.field("stack", &self.stack)
Expand Down
1 change: 1 addition & 0 deletions zkevm-circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ serde_json = "1.0.78"

hash-circuit = { package = "poseidon-circuit", git = "https://github.com/scroll-tech/poseidon-circuit.git", branch = "scroll-dev-0619", features=['short']}
#mpt-circuits = { package = "halo2-mpt-circuits", path = "../../mpt-circuit" }
misc-precompiled-circuit = { package = "rmd160-circuits", git = "https://github.com/scroll-tech/misc-precompiled-circuit.git", branch = "integration" }

halo2-base = { git = "https://github.com/scroll-tech/halo2-lib", branch = "develop", default-features=false, features=["halo2-pse","display"] }
halo2-ecc = { git = "https://github.com/scroll-tech/halo2-lib", branch = "develop", default-features=false, features=["halo2-pse","display"] }
Expand Down
Loading