diff --git a/zkevm-circuits/src/evm_circuit/execution/precompiles/ec_pairing.rs b/zkevm-circuits/src/evm_circuit/execution/precompiles/ec_pairing.rs index 4360b3e864..9f44aeb035 100644 --- a/zkevm-circuits/src/evm_circuit/execution/precompiles/ec_pairing.rs +++ b/zkevm-circuits/src/evm_circuit/execution/precompiles/ec_pairing.rs @@ -37,7 +37,9 @@ pub struct EcPairingGadget { // 1. input_len > 4 * 192 // 2. input_len % 192 != 0 input_is_zero: IsZeroGadget, - input_lt_769: LtGadget, + + // call_data_len must less than 2^32. + input_lt_769: LtGadget, input_mod_192: Cell, input_div_192: Cell, input_mod_192_lt: LtGadget, @@ -294,6 +296,10 @@ impl ExecutionGadget for EcPairingGadget { // len(input) related assignment. self.input_is_zero .assign(region, offset, F::from(call.call_data_length))?; + log::trace!( + "assign ec pairing exec step: calldata_len = {}", + call.call_data_length + ); self.input_lt_769.assign( region, offset, @@ -429,13 +435,14 @@ impl ExecutionGadget for EcPairingGadget { #[cfg(test)] mod test { use bus_mapping::{ + circuit_input_builder::CircuitsParams, evm::{OpcodeId, PrecompileCallArgs}, precompile::PrecompileCalls, }; use eth_types::{bytecode, evm_types::GasCost, word, ToWord, Word}; use halo2_proofs::halo2curves::bn256::{G1Affine, G2Affine}; use itertools::Itertools; - use mock::TestContext; + use mock::{test_ctx::helpers::account_0_code_wallet_0_no_code, TestContext, MOCK_WALLETS}; use rayon::iter::{ParallelBridge, ParallelIterator}; use crate::test_util::CircuitTestBuilder; @@ -1047,6 +1054,23 @@ mod test { }, ] }; + static ref INVALID_LEN_TEST: Vec = { + vec![ + #[cfg(feature = "scroll")] + PrecompileCallArgs { + name: "ecPairing (invalid): len(input) > 768", + setup_code: bytecode! {}, + call_data_offset: 0x00.into(), + call_data_length: 0x10340.into(), + ret_offset: 0xC0.into(), + ret_size: 0x20.into(), + value: 1.into(), + address: PrecompileCalls::Bn128Pairing.address().to_word(), + gas: 12_000_000.into(), + ..Default::default() + }, + ] + }; } #[test] @@ -1094,4 +1118,42 @@ mod test { .run(); }) } + + #[test] + fn precompile_ec_pairing_invalid_len_test() { + let call_kinds = vec![ + OpcodeId::CALL, + OpcodeId::STATICCALL, + OpcodeId::DELEGATECALL, + OpcodeId::CALLCODE, + ]; + + INVALID_LEN_TEST + .iter() + .cartesian_product(&call_kinds) + .par_bridge() + .for_each(|(test_vector, &call_kind)| { + let bytecode = test_vector.with_call_op(call_kind); + + let test_ctx: TestContext<2, 1> = TestContext::new( + None, + account_0_code_wallet_0_no_code(bytecode), + |mut txs, accs| { + txs[0] + .from(MOCK_WALLETS[0].clone()) + .to(accs[0].address) + .gas(0x1200_0000.into()); + }, + |block, _txs| block.number(0xcafeu64), + ) + .unwrap(); + CircuitTestBuilder::new_from_test_ctx(test_ctx) + .params(CircuitsParams { + max_rws: 100_000, + max_copy_rows: 140_000, + ..CircuitsParams::default() + }) + .run() + }) + } }