Skip to content

Commit 517127f

Browse files
lispcDreamWuGitkunxian-xia
authored
upgrade "misc-precompiled-circuits" and handle modexp invalid len in 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]>
1 parent 7c48935 commit 517127f

File tree

6 files changed

+90
-54
lines changed

6 files changed

+90
-54
lines changed

Cargo.lock

+18-18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

zkevm-circuits/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ serde = { version = "1.0", features = ["derive"] }
3333
serde_json = "1.0.78"
3434

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

3838
halo2-base = { git = "https://github.com/scroll-tech/halo2-lib", tag = "v0.1.1", default-features=false, features=["halo2-pse","display"] }
3939
halo2-ecc = { git = "https://github.com/scroll-tech/halo2-lib", tag = "v0.1.1", default-features=false, features=["halo2-pse","display"] }

zkevm-circuits/src/evm_circuit/execution/precompiles/modexp.rs

+46-1
Original file line numberDiff line numberDiff line change
@@ -881,10 +881,18 @@ impl<F: Field> ExecutionGadget<F> for ModExpGadget<F> {
881881
.keccak_input()
882882
.map(|randomness| rlc::value(data.input_memory.iter().rev(), randomness));
883883

884+
// if the input to modexp has more than 192 bytes, then we only keep the first 192 bytes
885+
// and discard the remaining bytes
886+
let input_len_limit = INPUT_LIMIT as u64;
887+
let n_padded_zeros = if call.call_data_length > input_len_limit {
888+
0
889+
} else {
890+
input_len_limit - call.call_data_length
891+
};
884892
let n_padded_zeroes_pow = region
885893
.challenges()
886894
.keccak_input()
887-
.map(|r| r.pow(&[INPUT_LIMIT as u64 - call.call_data_length, 0, 0, 0]));
895+
.map(|r| r.pow(&[n_padded_zeros, 0, 0, 0]));
888896

889897
let output_rlc = region
890898
.challenges()
@@ -1286,6 +1294,43 @@ mod test {
12861294
gas: 100000.into(),
12871295
..Default::default()
12881296
},
1297+
PrecompileCallArgs {
1298+
name: "modexp length too large invalid",
1299+
setup_code: bytecode! {
1300+
// Base size
1301+
PUSH1(0x21)
1302+
PUSH1(0x00)
1303+
MSTORE
1304+
// Esize
1305+
PUSH1(0x21)
1306+
PUSH1(0x20)
1307+
MSTORE
1308+
// Msize
1309+
PUSH1(0x21)
1310+
PUSH1(0x40)
1311+
MSTORE
1312+
// B, E and M
1313+
PUSH32(word!("0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed"))
1314+
PUSH1(0x60)
1315+
MSTORE
1316+
PUSH32(word!("0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2"))
1317+
PUSH1(0x80)
1318+
MSTORE
1319+
PUSH32(word!("0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"))
1320+
PUSH1(0xa0)
1321+
MSTORE
1322+
PUSH32(word!("0x08090A0000000000000000000000000000000000000000000000000000000000"))
1323+
PUSH1(0xc0)
1324+
MSTORE
1325+
},
1326+
call_data_offset: 0x0.into(),
1327+
call_data_length: 0xc3.into(),
1328+
ret_offset: 0xe0.into(),
1329+
ret_size: 0x21.into(),
1330+
address: PrecompileCalls::Modexp.address().to_word(),
1331+
gas: 1000.into(),
1332+
..Default::default()
1333+
},
12891334
]
12901335
};
12911336
}

zkevm-circuits/src/modexp_circuit.rs

+20-30
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ impl ModExpCircuitConfig {
6363
self.modexp_table.modulus,
6464
&event.modulus,
6565
)?;
66-
6766
let ret = modexp_chip.mod_exp(
6867
region,
6968
range_check_chip,
@@ -128,7 +127,7 @@ impl ModExpCircuitConfig {
128127
}
129128
}
130129

131-
const MODEXPCONFIG_EACH_CHIP_ROWS: usize = 24576;
130+
const MODEXPCONFIG_EACH_CHIP_ROWS: usize = 31235;
132131

133132
/// ModExp circuit for precompile modexp
134133
#[derive(Clone, Debug, Default)]
@@ -180,6 +179,7 @@ impl<F: Field> SubCircuit<F> for ModExpCircuit<F> {
180179
|| "modexp circuit",
181180
|mut region| {
182181
range_chip.initialize(&mut region)?;
182+
let modexp_count = self.0.len();
183183
let mut calc_offset = 0;
184184
for (n, event) in self.0.iter().enumerate() {
185185
calc_offset = config.assign_group(
@@ -191,6 +191,8 @@ impl<F: Field> SubCircuit<F> for ModExpCircuit<F> {
191191
&mut range_chip,
192192
)?;
193193
}
194+
195+
assert_eq!(calc_offset, MODEXPCONFIG_EACH_CHIP_ROWS * modexp_count);
194196
Ok(())
195197
},
196198
)?;
@@ -203,6 +205,7 @@ impl<F: Field> SubCircuit<F> for ModExpCircuit<F> {
203205
mod test {
204206
use super::*;
205207
use crate::util::MockChallenges;
208+
use eth_types::U256;
206209
use halo2_proofs::{
207210
circuit::SimpleFloorPlanner,
208211
dev::MockProver,
@@ -239,51 +242,38 @@ mod test {
239242

240243
#[test]
241244
fn test_modexp_circuit_00() {
242-
let base = Word::from(1u128);
243-
let exp = Word::from(2u128);
244-
let modulus = Word::from(7u128);
245-
let (_, result) = base.pow(exp).div_mod(modulus);
246-
let event1 = BigModExp {
247-
base,
248-
exponent: exp,
249-
modulus,
250-
result,
251-
};
245+
let event1 = construct_modexp(Word::from(1u128), Word::from(3u128), Word::from(7u128));
246+
252247
let test_circuit = ModExpCircuit(vec![event1], Default::default());
253248
let prover = MockProver::run(16, &test_circuit, vec![]).unwrap();
254249
assert_eq!(prover.verify(), Ok(()));
255250
}
256251

257252
#[test]
258253
fn test_modexp_circuit_01() {
259-
let base = Word::from(1u128);
260-
let exp = Word::from(2u128);
261-
let modulus = Word::from(7u128);
262-
let (_, result) = base.pow(exp).div_mod(modulus);
263-
let event1 = BigModExp {
264-
base,
265-
exponent: exp,
266-
modulus,
267-
result,
268-
};
254+
let event1 = construct_modexp(Word::from(1u128), Word::from(2u128), Word::from(7u128));
255+
269256
let test_circuit = ModExpCircuit(vec![event1], Default::default());
270257
let prover = MockProver::run(16, &test_circuit, vec![]).unwrap();
271258
assert_eq!(prover.verify(), Ok(()));
272259
}
273260
#[test]
274261
fn test_modexp_circuit_02() {
275-
let base = Word::from(2u128);
276-
let exp = Word::from(2u128);
277-
let modulus = Word::from(7u128);
262+
let event1 = construct_modexp(Word::from(2u128), Word::from(2u128), Word::from(7u128));
263+
let event2 = construct_modexp(Word::from(3u128), Word::from(21u128), Word::from(78u128));
264+
265+
let test_circuit = ModExpCircuit(vec![event1, event2], Default::default());
266+
let prover = MockProver::run(17, &test_circuit, vec![]).unwrap();
267+
assert_eq!(prover.verify(), Ok(()));
268+
}
269+
270+
fn construct_modexp(base: U256, exp: U256, modulus: U256) -> BigModExp {
278271
let (_, result) = base.pow(exp).div_mod(modulus);
279-
let event1 = BigModExp {
272+
BigModExp {
280273
base,
281274
exponent: exp,
282275
modulus,
283276
result,
284-
};
285-
let test_circuit = ModExpCircuit(vec![event1], Default::default());
286-
let prover = MockProver::run(16, &test_circuit, vec![]).unwrap();
287-
assert_eq!(prover.verify(), Ok(()));
277+
}
288278
}
289279
}

zkevm-circuits/src/super_circuit/test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ fn serial_test_super_circuit_ec_ops_txs() {
606606
max_evm_rows: 0,
607607
// modexp ref this to decide its ability, we
608608
// need at least one (~25000 rows)
609-
max_keccak_rows: 30000,
609+
max_keccak_rows: 40000,
610610
max_inner_blocks: MAX_INNER_BLOCKS,
611611
max_exp_steps: 256,
612612
max_rlp_rows: 800,

zkevm-circuits/src/table.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -2619,10 +2619,11 @@ impl ModExpTable {
26192619
/// helper for obtain the modulus of a U256 in Fr
26202620
pub fn native_u256<F: Field>(word: &Word) -> F {
26212621
let minus1 = -F::one();
2622-
let (div, _) = word.div_mod(Word::from_little_endian(minus1.to_repr().as_ref()));
2623-
let div = div.checked_add(Word::from(1u64)).unwrap();
2622+
let div = Word::from_little_endian(minus1.to_repr().as_ref()) + Word::from(1u64);
2623+
let (_, remainder) = word.div_mod(div);
2624+
26242625
let mut bytes = [0u8; 64];
2625-
div.to_little_endian(&mut bytes[..32]);
2626+
remainder.to_little_endian(&mut bytes[..32]);
26262627
F::from_bytes_wide(&bytes)
26272628
}
26282629

0 commit comments

Comments
 (0)