Skip to content

Commit

Permalink
upgrade "misc-precompiled-circuits" and handle modexp invalid len in …
Browse files Browse the repository at this point in the history
…bus-mapping (#830)

* tag modexp circuit

* try fix native reminder

* fix divmod

* update MODEXPCONFIG_EACH_CHIP_ROWS

* fix fmt

* update assert_eq and refactor tests

* fix test: enlarge keccak rows

* add invalid input testcase in modexp

* fix sub with overflow if modexp input bytes len greater than 192

---------

Co-authored-by: DreamWuGit <[email protected]>
Co-authored-by: kunxian xia <[email protected]>
  • Loading branch information
3 people authored Aug 29, 2023
1 parent 7c48935 commit 517127f
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 54 deletions.
36 changes: 18 additions & 18 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion zkevm-circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.78"

hash-circuit = { package = "poseidon-circuit", git = "https://github.com/scroll-tech/poseidon-circuit.git", branch = "scroll-dev-0723"}
misc-precompiled-circuit = { package = "rmd160-circuits", git = "https://github.com/scroll-tech/misc-precompiled-circuit.git", branch = "integration" }
misc-precompiled-circuit = { package = "misc-precompiled-circuit", git = "https://github.com/scroll-tech/misc-precompiled-circuit.git", tag = "v0.1.0" }

halo2-base = { git = "https://github.com/scroll-tech/halo2-lib", tag = "v0.1.1", default-features=false, features=["halo2-pse","display"] }
halo2-ecc = { git = "https://github.com/scroll-tech/halo2-lib", tag = "v0.1.1", default-features=false, features=["halo2-pse","display"] }
Expand Down
47 changes: 46 additions & 1 deletion zkevm-circuits/src/evm_circuit/execution/precompiles/modexp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,10 +881,18 @@ impl<F: Field> ExecutionGadget<F> for ModExpGadget<F> {
.keccak_input()
.map(|randomness| rlc::value(data.input_memory.iter().rev(), randomness));

// if the input to modexp has more than 192 bytes, then we only keep the first 192 bytes
// and discard the remaining bytes
let input_len_limit = INPUT_LIMIT as u64;
let n_padded_zeros = if call.call_data_length > input_len_limit {
0
} else {
input_len_limit - call.call_data_length
};
let n_padded_zeroes_pow = region
.challenges()
.keccak_input()
.map(|r| r.pow(&[INPUT_LIMIT as u64 - call.call_data_length, 0, 0, 0]));
.map(|r| r.pow(&[n_padded_zeros, 0, 0, 0]));

let output_rlc = region
.challenges()
Expand Down Expand Up @@ -1286,6 +1294,43 @@ mod test {
gas: 100000.into(),
..Default::default()
},
PrecompileCallArgs {
name: "modexp length too large invalid",
setup_code: bytecode! {
// Base size
PUSH1(0x21)
PUSH1(0x00)
MSTORE
// Esize
PUSH1(0x21)
PUSH1(0x20)
MSTORE
// Msize
PUSH1(0x21)
PUSH1(0x40)
MSTORE
// B, E and M
PUSH32(word!("0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed"))
PUSH1(0x60)
MSTORE
PUSH32(word!("0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2"))
PUSH1(0x80)
MSTORE
PUSH32(word!("0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"))
PUSH1(0xa0)
MSTORE
PUSH32(word!("0x08090A0000000000000000000000000000000000000000000000000000000000"))
PUSH1(0xc0)
MSTORE
},
call_data_offset: 0x0.into(),
call_data_length: 0xc3.into(),
ret_offset: 0xe0.into(),
ret_size: 0x21.into(),
address: PrecompileCalls::Modexp.address().to_word(),
gas: 1000.into(),
..Default::default()
},
]
};
}
Expand Down
50 changes: 20 additions & 30 deletions zkevm-circuits/src/modexp_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ impl ModExpCircuitConfig {
self.modexp_table.modulus,
&event.modulus,
)?;

let ret = modexp_chip.mod_exp(
region,
range_check_chip,
Expand Down Expand Up @@ -128,7 +127,7 @@ impl ModExpCircuitConfig {
}
}

const MODEXPCONFIG_EACH_CHIP_ROWS: usize = 24576;
const MODEXPCONFIG_EACH_CHIP_ROWS: usize = 31235;

/// ModExp circuit for precompile modexp
#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -180,6 +179,7 @@ impl<F: Field> SubCircuit<F> for ModExpCircuit<F> {
|| "modexp circuit",
|mut region| {
range_chip.initialize(&mut region)?;
let modexp_count = self.0.len();
let mut calc_offset = 0;
for (n, event) in self.0.iter().enumerate() {
calc_offset = config.assign_group(
Expand All @@ -191,6 +191,8 @@ impl<F: Field> SubCircuit<F> for ModExpCircuit<F> {
&mut range_chip,
)?;
}

assert_eq!(calc_offset, MODEXPCONFIG_EACH_CHIP_ROWS * modexp_count);
Ok(())
},
)?;
Expand All @@ -203,6 +205,7 @@ impl<F: Field> SubCircuit<F> for ModExpCircuit<F> {
mod test {
use super::*;
use crate::util::MockChallenges;
use eth_types::U256;
use halo2_proofs::{
circuit::SimpleFloorPlanner,
dev::MockProver,
Expand Down Expand Up @@ -239,51 +242,38 @@ mod test {

#[test]
fn test_modexp_circuit_00() {
let base = Word::from(1u128);
let exp = Word::from(2u128);
let modulus = Word::from(7u128);
let (_, result) = base.pow(exp).div_mod(modulus);
let event1 = BigModExp {
base,
exponent: exp,
modulus,
result,
};
let event1 = construct_modexp(Word::from(1u128), Word::from(3u128), Word::from(7u128));

let test_circuit = ModExpCircuit(vec![event1], Default::default());
let prover = MockProver::run(16, &test_circuit, vec![]).unwrap();
assert_eq!(prover.verify(), Ok(()));
}

#[test]
fn test_modexp_circuit_01() {
let base = Word::from(1u128);
let exp = Word::from(2u128);
let modulus = Word::from(7u128);
let (_, result) = base.pow(exp).div_mod(modulus);
let event1 = BigModExp {
base,
exponent: exp,
modulus,
result,
};
let event1 = construct_modexp(Word::from(1u128), Word::from(2u128), Word::from(7u128));

let test_circuit = ModExpCircuit(vec![event1], Default::default());
let prover = MockProver::run(16, &test_circuit, vec![]).unwrap();
assert_eq!(prover.verify(), Ok(()));
}
#[test]
fn test_modexp_circuit_02() {
let base = Word::from(2u128);
let exp = Word::from(2u128);
let modulus = Word::from(7u128);
let event1 = construct_modexp(Word::from(2u128), Word::from(2u128), Word::from(7u128));
let event2 = construct_modexp(Word::from(3u128), Word::from(21u128), Word::from(78u128));

let test_circuit = ModExpCircuit(vec![event1, event2], Default::default());
let prover = MockProver::run(17, &test_circuit, vec![]).unwrap();
assert_eq!(prover.verify(), Ok(()));
}

fn construct_modexp(base: U256, exp: U256, modulus: U256) -> BigModExp {
let (_, result) = base.pow(exp).div_mod(modulus);
let event1 = BigModExp {
BigModExp {
base,
exponent: exp,
modulus,
result,
};
let test_circuit = ModExpCircuit(vec![event1], Default::default());
let prover = MockProver::run(16, &test_circuit, vec![]).unwrap();
assert_eq!(prover.verify(), Ok(()));
}
}
}
2 changes: 1 addition & 1 deletion zkevm-circuits/src/super_circuit/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ fn serial_test_super_circuit_ec_ops_txs() {
max_evm_rows: 0,
// modexp ref this to decide its ability, we
// need at least one (~25000 rows)
max_keccak_rows: 30000,
max_keccak_rows: 40000,
max_inner_blocks: MAX_INNER_BLOCKS,
max_exp_steps: 256,
max_rlp_rows: 800,
Expand Down
7 changes: 4 additions & 3 deletions zkevm-circuits/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2619,10 +2619,11 @@ impl ModExpTable {
/// helper for obtain the modulus of a U256 in Fr
pub fn native_u256<F: Field>(word: &Word) -> F {
let minus1 = -F::one();
let (div, _) = word.div_mod(Word::from_little_endian(minus1.to_repr().as_ref()));
let div = div.checked_add(Word::from(1u64)).unwrap();
let div = Word::from_little_endian(minus1.to_repr().as_ref()) + Word::from(1u64);
let (_, remainder) = word.div_mod(div);

let mut bytes = [0u8; 64];
div.to_little_endian(&mut bytes[..32]);
remainder.to_little_endian(&mut bytes[..32]);
F::from_bytes_wide(&bytes)
}

Expand Down

0 comments on commit 517127f

Please sign in to comment.