From 4e64bdba9f5516bcde070c7087d06f149a0482bf Mon Sep 17 00:00:00 2001 From: Akase Cho Date: Fri, 21 Apr 2023 13:35:56 +0800 Subject: [PATCH] [refactor] refactor and add more helper in Bytecode (#1365) ### Description Refactor and add more helper functions to Bytecode: - Removed several functions such as `call`, `balance`, `mstore`, `calldatacopy`, and `return_bytecode` - Added `op_jumpdest` function - Implemented `impl_push_n` macro to generate functions for `op_push1` to `op_push32` - Implemented `impl_other_opcodes` macro to generate functions for various opcodes like `op_stop`, `op_add`, `op_mul`, `op_sub`, and so on - Renamed opcode helper functions to `op_{opcode}` for consistency and clarity ### Issue Link N/A ### Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update ### Contents - Removal of several functions - Addition of `op_jumpdest` function - Implementation of `impl_push_n` macro to generate functions for `op_push1` to `op_push32` - Implementation of `impl_other_opcodes` macro to generate functions for various opcodes - Renaming of opcode helper functions ### Rationale This refactor improves the code by removing unused functions, adding a new function, and implementing macros to generate functions for opcodes. The renaming of the opcode helper functions to `op_{opcode}` provides consistency and clarity to the codebase. ### How Has This Been Tested? https://github.com/scroll-tech/zkevm-circuits/actions/runs/4751119765 --- .../src/circuit_input_builder/tracer_tests.rs | 98 +++---- bus-mapping/src/evm/opcodes/balance.rs | 4 +- bus-mapping/src/evm/opcodes/calldatacopy.rs | 6 +- bus-mapping/src/evm/opcodes/logs.rs | 2 +- bus-mapping/src/evm/opcodes/sha3.rs | 4 +- eth-types/src/bytecode.rs | 267 +++++++++++++----- eth-types/src/evm_types/memory.rs | 2 +- mock/src/lib.rs | 4 +- .../src/evm_circuit/execution/balance.rs | 8 +- .../src/evm_circuit/execution/calldatacopy.rs | 2 +- .../src/evm_circuit/execution/dup.rs | 2 +- .../evm_circuit/execution/error_oog_call.rs | 2 +- .../execution/error_return_data_oo_bound.rs | 6 +- .../src/evm_circuit/execution/error_stack.rs | 2 +- .../src/evm_circuit/execution/logs.rs | 8 +- .../src/evm_circuit/execution/push.rs | 2 +- .../evm_circuit/execution/return_revert.rs | 4 +- .../evm_circuit/execution/returndatacopy.rs | 4 +- .../evm_circuit/execution/returndatasize.rs | 4 +- .../execution/signed_comparator.rs | 2 +- .../src/evm_circuit/execution/swap.rs | 2 +- zkevm-circuits/src/exp_circuit/test.rs | 6 +- zkevm-circuits/src/stats.rs | 2 +- 23 files changed, 268 insertions(+), 175 deletions(-) diff --git a/bus-mapping/src/circuit_input_builder/tracer_tests.rs b/bus-mapping/src/circuit_input_builder/tracer_tests.rs index 39dc4fbeb0..6fe834a612 100644 --- a/bus-mapping/src/circuit_input_builder/tracer_tests.rs +++ b/bus-mapping/src/circuit_input_builder/tracer_tests.rs @@ -357,8 +357,8 @@ fn tracer_err_address_collision() { // that outputs the same, which will lead to the same new // contract address. let code_creator = bytecode! { - .mstore(0x00, 0x00) - .return_bytecode(0x00, 0x01) + .op_mstore(0x00, 0x00) + .op_return(0x00, 0x01) }; // code_a calls code_b which executes code_creator in CREATE2 @@ -385,9 +385,7 @@ fn tracer_err_address_collision() { .chain(0u8..((32 - len % 32) as u8)) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - code_b.push(32, Word::from_big_endian(word)); - code_b.push(32, Word::from(index * 32)); - code_b.write_op(OpcodeId::MSTORE); + code_b.op_mstore(index * 32, Word::from_big_endian(word)); } let code_b_end = bytecode! { PUSH3(0x123456) // salt @@ -484,8 +482,8 @@ fn tracer_create_collision_free() { // that outputs not the same, which will lead to the different new // contract address. let code_creator = bytecode! { - .mstore(0x00, 0x00) - .return_bytecode(0x00, 0x01) + .op_mstore(0x00, 0x00) + .op_return(0x00, 0x01) }; // code_a calls code_b which executes code_creator in CREATE2 @@ -512,9 +510,7 @@ fn tracer_create_collision_free() { .chain(0u8..((32 - len % 32) as u8)) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - code_b.push(32, Word::from_big_endian(word)); - code_b.push(32, Word::from(index * 32)); - code_b.write_op(OpcodeId::MSTORE); + code_b.op_mstore(index * 32, Word::from_big_endian(word)); } let code_b_end = bytecode! { PUSH1(len) // length @@ -624,8 +620,8 @@ fn tracer_err_code_store_out_of_gas() { // exhaust the gas to store the code. let code_len = 0x100; let code_creator = bytecode! { - .mstore(code_len, Word::zero()) - .return_bytecode(0x00, code_len) + .op_mstore(code_len, Word::zero()) + .op_return(0x00, code_len) }; // code_a calls code_b which executes code_creator in CREATE @@ -652,9 +648,7 @@ fn tracer_err_code_store_out_of_gas() { .chain(0..(32 - len % 32) as u8) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - code_b.push(32, Word::from_big_endian(word)); - code_b.push(32, Word::from(index * 32)); - code_b.write_op(OpcodeId::MSTORE); + code_b.op_mstore(index * 32, Word::from_big_endian(word)); } let code_b_end = bytecode! { PUSH32(len) // length @@ -717,8 +711,8 @@ fn tracer_err_code_store_out_of_gas_tx_deploy() { // exhaust the gas to store the code. let code_len = 0x100; let code_creator = bytecode! { - .mstore(code_len, Word::zero()) - .return_bytecode(0x00, code_len) + .op_mstore(code_len, Word::zero()) + .op_return(0x00, code_len) }; // Get the execution steps from the external tracer @@ -778,8 +772,8 @@ fn tracer_err_invalid_code() { // code_creator outputs byte array that starts with 0xef, which is // invalid code. let code_creator = bytecode! { - .mstore(0x00, word!("0xef00000000000000000000000000000000000000000000000000000000000000")) - .return_bytecode(0x00, 0x01) + .op_mstore(0x00, word!("0xef00000000000000000000000000000000000000000000000000000000000000")) + .op_return(0x00, 0x01) }; // code_a calls code_b which executes code_creator in CREATE @@ -806,9 +800,7 @@ fn tracer_err_invalid_code() { .chain(0u8..((32 - len % 32) as u8)) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - code_b.push(32, Word::from_big_endian(word)); - code_b.push(32, Word::from(index * 32)); - code_b.write_op(OpcodeId::MSTORE); + code_b.op_mstore(index * 32, Word::from_big_endian(word)); } let code_b_end = bytecode! { PUSH1(len) // length @@ -880,8 +872,8 @@ fn tracer_err_max_code_size_exceeded() { // trigger the max code size limit. let code_len = 0x6000 + 1; let code_creator = bytecode! { - .mstore(code_len, Word::zero()) - .return_bytecode(0x00, code_len) + .op_mstore(code_len, Word::zero()) + .op_return(0x00, code_len) }; // code_a calls code_b which executes code_creator in CREATE @@ -908,9 +900,7 @@ fn tracer_err_max_code_size_exceeded() { .chain(0u8..((32 - len % 32) as u8)) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - code_b.push(32, Word::from_big_endian(word)); - code_b.push(32, Word::from(index * 32)); - code_b.write_op(OpcodeId::MSTORE); + code_b.op_mstore(index * 32, Word::from_big_endian(word)); } let code_b_end = bytecode! { PUSH32(len) // length @@ -973,8 +963,8 @@ fn tracer_err_max_code_size_exceeded_tx_deploy() { // trigger the max code size limit. let code_len = 0x6000 + 1; let code_creator = bytecode! { - .mstore(code_len, Word::zero()) - .return_bytecode(0x00, code_len) + .op_mstore(code_len, Word::zero()) + .op_return(0x00, code_len) }; // Get the execution steps from the external tracer @@ -1022,7 +1012,7 @@ fn tracer_err_max_code_size_exceeded_tx_deploy() { fn tracer_create_stop() { // code_creator doesn't output anything because it stops. let code_creator = bytecode! { - .mstore(0x00, word!("0xef00000000000000000000000000000000000000000000000000000000000000")) + .op_mstore(0x00, word!("0xef00000000000000000000000000000000000000000000000000000000000000")) PUSH1(0x01) // length PUSH1(0x00) // offset STOP @@ -1052,9 +1042,7 @@ fn tracer_create_stop() { .chain(0u8..((32 - len % 32) as u8)) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - code_b.push(32, Word::from_big_endian(word)); - code_b.push(32, Word::from(index * 32)); - code_b.write_op(OpcodeId::MSTORE); + code_b.op_mstore(index * 32, Word::from_big_endian(word)); } let code_b_end = bytecode! { PUSH1(len) // length @@ -1421,8 +1409,8 @@ fn tracer_err_return_data_out_of_bounds() { PUSH2(0xaa) }; let code_b = bytecode! { - .mstore(0x00, 0x42) - .return_bytecode(0x00, 0x01) + .op_mstore(0x00, 0x42) + .op_return(0x00, 0x01) }; // Get the execution steps from the external tracer let block: GethData = TestContext::<3, 2>::new_with_logger_config( @@ -1476,7 +1464,7 @@ fn tracer_err_gas_uint_overflow() { // MSTORE a value at an offset so high that the gast cost is big enough // to overflow an uint64 let code = bytecode! { - .mstore(0x100_0000_0000_0000_0000_u128, 0x42) + .op_mstore(0x100_0000_0000_0000_0000_u128, 0x42) }; let block: GethData = TestContext::<2, 1>::new_with_logger_config( None, @@ -1515,7 +1503,7 @@ fn tracer_err_gas_uint_overflow() { fn tracer_err_invalid_opcode() { // The second opcode is invalid (0x0f) let mut code = bytecode::Bytecode::default(); - code.write_op(OpcodeId::PC); + code.op_pc(); code.write(0x0f, true); let block: GethData = TestContext::<2, 1>::new_with_logger_config( None, @@ -1572,19 +1560,11 @@ fn tracer_err_write_protection(is_call: bool) { PUSH2(0xaa) }; - let mut code_b = bytecode! { - PUSH1(0x01) // value - PUSH1(0x02) // key - }; + let mut code_b = Bytecode::default(); if is_call { - code_b.push(1, Word::zero()); - code_b.push(1, Word::from(0x20)); - code_b.push(1, Word::from(0x10)); // value - code_b.push(32, *WORD_ADDR_B); // addr - code_b.push(32, Word::from(0x1000)); // gas - code_b.write_op(OpcodeId::CALL); + code_b.op_call(0x1000, *WORD_ADDR_B, 0x10, 0x20, 0, 0x02, 0x01); } else { - code_b.write_op(OpcodeId::SSTORE); + code_b.op_sstore(0x02, 0x01); } code_b.push(2, Word::from(0xbb)); @@ -1753,8 +1733,8 @@ fn tracer_err_stack_underflow() { fn create2_address() { // code_creator outputs 0x6050. let code_creator = bytecode! { - .mstore(0x00, word!("0x6050000000000000000000000000000000000000000000000000000000000000")) - .return_bytecode(0x00, 0x02) + .op_mstore(0x00, word!("0x6050000000000000000000000000000000000000000000000000000000000000")) + .op_return(0x00, 0x02) }; // code_a calls code_b which executes code_creator in CREATE @@ -1781,9 +1761,7 @@ fn create2_address() { .chain(0u8..((32 - len % 32) as u8)) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - code_b.push(32, Word::from_big_endian(word)); - code_b.push(32, Word::from(index * 32)); - code_b.write_op(OpcodeId::MSTORE); + code_b.op_mstore(index * 32, Word::from_big_endian(word)); } let code_b_end = bytecode! { PUSH3(0x123456) // salt @@ -1851,8 +1829,8 @@ fn create2_address() { fn create_address() { // code_creator outputs 0x6050. let code_creator = bytecode! { - .mstore(0x00, word!("0x6050000000000000000000000000000000000000000000000000000000000000")) - .return_bytecode(0x00, 0x02) + .op_mstore(0x00, word!("0x6050000000000000000000000000000000000000000000000000000000000000")) + .op_return(0x00, 0x02) }; // code_a calls code_b which executes code_creator in CREATE @@ -1879,9 +1857,7 @@ fn create_address() { .chain(0u8..((32 - len % 32) as u8)) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - code_b.push(32, Word::from_big_endian(word)); - code_b.push(32, Word::from(index * 32)); - code_b.write_op(OpcodeId::MSTORE); + code_b.op_mstore(index * 32, Word::from_big_endian(word)); } // We do CREATE 2 times to use a nonce != 0 in the second one. let code_b_end = bytecode! { @@ -1977,7 +1953,7 @@ fn test_gen_access_trace() { PUSH2(0xaa) }; let code_b = bytecode! { - .mstore(0x01, word!("0x1234567890000000000000000000abcdef000000000000000000112233445566")) + .op_mstore(0x01, word!("0x1234567890000000000000000000abcdef000000000000000000112233445566")) PUSH1(0x01) // value PUSH1(0x02) // key SSTORE @@ -2202,9 +2178,7 @@ fn test_gen_access_trace_create_push_call_stack() { .chain(0u8..((32 - len % 32) as u8)) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - code_b.push(32, Word::from_big_endian(word)); - code_b.push(32, Word::from(index * 32)); - code_b.write_op(OpcodeId::MSTORE); + code_b.op_mstore(index * 32, Word::from_big_endian(word)); } let code_b_end = bytecode! { PUSH1(len) // length diff --git a/bus-mapping/src/evm/opcodes/balance.rs b/bus-mapping/src/evm/opcodes/balance.rs index b30fd1acfc..1f58cf6712 100644 --- a/bus-mapping/src/evm/opcodes/balance.rs +++ b/bus-mapping/src/evm/opcodes/balance.rs @@ -125,12 +125,12 @@ mod balance_tests { let mut code = Bytecode::default(); if is_warm { code.append(&bytecode! { - .balance(address) + .op_balance(address) POP }); } code.append(&bytecode! { - .balance(address) + .op_balance(address) STOP }); diff --git a/bus-mapping/src/evm/opcodes/calldatacopy.rs b/bus-mapping/src/evm/opcodes/calldatacopy.rs index 2edd2879ba..04027f1c9a 100644 --- a/bus-mapping/src/evm/opcodes/calldatacopy.rs +++ b/bus-mapping/src/evm/opcodes/calldatacopy.rs @@ -202,7 +202,7 @@ mod calldatacopy_tests { let offset = 0x00usize; let copy_size = 0x10usize; let code_b = bytecode! { - .calldatacopy(dst_offset, offset, copy_size) + .op_calldatacopy(dst_offset, offset, copy_size) STOP }; @@ -378,7 +378,7 @@ mod calldatacopy_tests { // code B gets called by code A, so the call is an internal call. let code_b = bytecode! { - .calldatacopy(0x00usize, 0x00usize, 0x50usize) + .op_calldatacopy(0x00usize, 0x00usize, 0x50usize) STOP }; @@ -428,7 +428,7 @@ mod calldatacopy_tests { let calldata = vec![1, 3, 5, 7, 9, 2, 4, 6, 8]; let calldata_len = calldata.len(); let code = bytecode! { - .calldatacopy(dst_offset, offset, size) + .op_calldatacopy(dst_offset, offset, size) STOP }; diff --git a/bus-mapping/src/evm/opcodes/logs.rs b/bus-mapping/src/evm/opcodes/logs.rs index 3cf22faf95..aa68440c6d 100644 --- a/bus-mapping/src/evm/opcodes/logs.rs +++ b/bus-mapping/src/evm/opcodes/logs.rs @@ -252,7 +252,7 @@ mod log_tests { code.push(32, Word::from(msize)); code.push(32, Word::from(mstart)); code.write_op(cur_op_code); - code.write_op(OpcodeId::STOP); + code.op_stop(); // prepare memory data let pushdata = hex::decode("1234567890abcdef1234567890abcdef").unwrap(); diff --git a/bus-mapping/src/evm/opcodes/sha3.rs b/bus-mapping/src/evm/opcodes/sha3.rs index 75c2cf1a49..2179860d18 100644 --- a/bus-mapping/src/evm/opcodes/sha3.rs +++ b/bus-mapping/src/evm/opcodes/sha3.rs @@ -138,9 +138,7 @@ pub mod sha3_tests { mem_chunk.to_vec() }; memory.extend_from_slice(&mem_value); - code.push(32, Word::from_big_endian(&mem_value)); - code.push(32, 32 * i); - code.write_op(OpcodeId::MSTORE); + code.op_mstore(32 * i, Word::from_big_endian(&mem_value)); } // append SHA3 related opcodes at the tail end. let code_tail = bytecode! { diff --git a/eth-types/src/bytecode.rs b/eth-types/src/bytecode.rs index e62d71ec87..a72b30c682 100644 --- a/eth-types/src/bytecode.rs +++ b/eth-types/src/bytecode.rs @@ -149,76 +149,6 @@ impl Bytecode { self } - /// Call a contract - #[allow(clippy::too_many_arguments)] - pub fn call( - &mut self, - gas: T, - address: U, - value: V, - mem_in: W, - mem_in_size: X, - mem_out: Y, - mem_out_size: Z, - ) -> &mut Self { - self.append(&crate::bytecode! { - PUSH32(mem_out_size) - PUSH32(mem_out) - PUSH32(mem_in_size) - PUSH32(mem_in) - PUSH32(value) - PUSH32(address) - PUSH32(gas) - CALL - }); - self - } - - /// Balance - pub fn balance(&mut self, address: T) -> &mut Self { - self.append(&crate::bytecode! { - PUSH20(address) - BALANCE - }); - self - } - - /// mstore - pub fn mstore(&mut self, offset: T, value: U) -> &mut Self { - self.append(&crate::bytecode! { - PUSH32(value) - PUSH32(offset) - MSTORE - }); - self - } - - /// calldatacopy - pub fn calldatacopy( - &mut self, - dst_offset: T, - offset: U, - size: V, - ) -> &mut Self { - self.append(&crate::bytecode! { - PUSH32(size) - PUSH32(offset) - PUSH32(dst_offset) - CALLDATACOPY - }); - self - } - - /// return - pub fn return_bytecode(&mut self, offset: T, size: U) -> &mut Self { - self.append(&crate::bytecode! { - PUSH32(size) - PUSH32(offset) - RETURN - }); - self - } - /// Generate the diassembly pub fn disasm(&self) -> String { let mut asm = String::new(); @@ -255,6 +185,12 @@ impl Bytecode { pub fn iter(&self) -> BytecodeIterator<'_> { BytecodeIterator(self.code.iter()) } + + /// JUMPDEST opcode + pub fn op_jumpdest(&mut self) -> usize { + self.write_op(OpcodeId::JUMPDEST); + self.code.len() + } } /// An ASM entry @@ -402,6 +338,197 @@ macro_rules! bytecode_internal { }}; } +macro_rules! impl_push_n { + ($($push_n:ident, $n:expr)*) => { + #[allow(missing_docs)] + impl Bytecode { + $( + pub fn $push_n(&mut self, value: T) -> &mut Self { + self.push($n, value) + } + )* + } + }; +} + +impl_push_n! { + op_push1, 1 + op_push2, 2 + op_push3, 3 + op_push4, 4 + op_push5, 5 + op_push6, 6 + op_push7, 7 + op_push8, 8 + op_push9, 9 + op_push10, 10 + op_push11, 11 + op_push12, 12 + op_push13, 13 + op_push14, 14 + op_push15, 15 + op_push16, 16 + op_push17, 17 + op_push18, 18 + op_push19, 19 + op_push20, 20 + op_push21, 21 + op_push22, 22 + op_push23, 23 + op_push24, 24 + op_push25, 25 + op_push26, 26 + op_push27, 27 + op_push28, 28 + op_push29, 29 + op_push30, 30 + op_push31, 31 + op_push32, 32 +} + +macro_rules! impl_other_opcodes_inner { + ($self:ident, ) => {}; + ($self:ident, $arg:ident) => { + $self.op_push32($arg); + }; + ($self:ident, $arg:ident $($tail:ident)+) => { + impl_other_opcodes_inner!($self, $($tail)*); + $self.op_push32($arg); + } +} + +macro_rules! impl_other_opcodes { + ($(($op:ident, $x:ident $(, $arg:ident : $arg_ty:ident)*)),* $(,)?) => { + #[allow(missing_docs)] + #[allow(clippy::too_many_arguments)] + impl Bytecode { + $( + pub fn $op<$( + $arg_ty: ToWord, + )*>(&mut self, $($arg: $arg_ty),*) -> &mut Self { + impl_other_opcodes_inner!(self, $($arg)*); + self.write_op($crate::evm_types::OpcodeId::$x) + } + )* + } + }; +} + +impl_other_opcodes! { + (op_stop, STOP), + (op_add, ADD, a: A, b: B), + (op_mul, MUL, a: A, b: B), + (op_sub, SUB, a: A, b: B), + (op_div, DIV, a: A, b: B), + (op_sdiv, SDIV, a: A, b: B), + (op_mod, MOD, a: A, b: B), + (op_smod, SMOD, a: A, b: B), + (op_addmod, ADDMOD, a: A, b: B, n: N), + (op_mulmod, MULMOD, a: A, b: B, n: N), + (op_exp, EXP, a: A, exponent: B), + (op_signextend, SIGNEXTEND, b: A, x: B), + (op_lt, LT, a: A, b: B), + (op_gt, GT, a: A, b: B), + (op_slt, SLT, a: A, b: B), + (op_sgt, SGT, a: A, b: B), + (op_eq, EQ, a: A, b: B), + (op_iszero, ISZERO, a: A), + (op_and, AND, a: A, b: B), + (op_or, OR, a: A, b: B), + (op_xor, XOR, a: A, b: B), + (op_not, NOT, a: A), + (op_byte, BYTE, i: I, x: X), + (op_shl, SHL, shift: S, value: V), + (op_shr, SHR, shift: S, value: V), + (op_sar, SAR, shift: S, value: V), + (op_sha3, SHA3, offset: O, size: S), + (op_address, ADDRESS), + (op_balance, BALANCE, address: A), + (op_origin, ORIGIN), + (op_caller, CALLER), + (op_callvalue, CALLVALUE), + (op_calldataload, CALLDATALOAD, i: I), + (op_calldatasize, CALLDATASIZE), + (op_calldatacopy, CALLDATACOPY, dest_offset: D, offset: B, size: C), + (op_codesize, CODESIZE), + (op_codecopy, CODECOPY, dest_offset: D, offset: B, size: C), + (op_gasprice, GASPRICE), + (op_extcodesize, EXTCODESIZE, address: A), + (op_extcodecopy, EXTCODECOPY, address: A, dest_offset: D, offset: B, size: C), + (op_returndatasize, RETURNDATASIZE), + (op_returndatacopy, RETURNDATACOPY, dest_offset: D, offset: B, size: C), + (op_extcodehash, EXTCODEHASH, address: A), + (op_blockhash, BLOCKHASH, blocknumber: B), + (op_coinbase, COINBASE), + (op_timestamp, TIMESTAMP), + (op_number, NUMBER), + (op_prevrandao, DIFFICULTY), // alias for DIFFICULTY + (op_difficulty, DIFFICULTY), + (op_gaslimit, GASLIMIT), + (op_chainid, CHAINID), + (op_selfbalance, SELFBALANCE), + // (op_basefee, BASEFEE), ignored + (op_pop, POP), + (op_mload, MLOAD, offset: O), + (op_mstore, MSTORE, offset: O, value: V), + (op_mstore8, MSTORE8, offset: O, value: V), + (op_sload, SLOAD, offset: O), + (op_sstore, SSTORE, offset: O, value: V), + (op_jump, JUMP, counter: C), + (op_jumpi, JUMPI, counter: C), // branch not included + (op_pc, PC), + (op_msize, MSIZE), + (op_gas, GAS), + // (op_jumpdest, JUMPDEST), manually implemented + (op_dup1, DUP1), + (op_dup2, DUP2), + (op_dup3, DUP3), + (op_dup4, DUP4), + (op_dup5, DUP5), + (op_dup6, DUP6), + (op_dup7, DUP7), + (op_dup8, DUP8), + (op_dup9, DUP9), + (op_dup10, DUP10), + (op_dup11, DUP11), + (op_dup12, DUP12), + (op_dup13, DUP13), + (op_dup14, DUP14), + (op_dup15, DUP15), + (op_dup16, DUP16), + (op_swap1, SWAP1), + (op_swap2, SWAP2), + (op_swap3, SWAP3), + (op_swap4, SWAP4), + (op_swap5, SWAP5), + (op_swap6, SWAP6), + (op_swap7, SWAP7), + (op_swap8, SWAP8), + (op_swap9, SWAP9), + (op_swap10, SWAP10), + (op_swap11, SWAP11), + (op_swap12, SWAP12), + (op_swap13, SWAP13), + (op_swap14, SWAP14), + (op_swap15, SWAP15), + (op_swap16, SWAP16), + (op_log0, LOG0, offset: O, size: S), + (op_log1, LOG1, offset: O, size: S, topic1: T1), + (op_log2, LOG2, offset: O, size: S, topic1: T1, topic2: T2), + (op_log3, LOG3, offset: O, size: S, topic1: T1, topic2: T2, topic3: T3), + (op_log4, LOG4, offset: O, size: S, topic1: T1, topic2: T2, topic3: T3, topic4: T4), + (op_create, CREATE, value: V, offset: O, size: S), + (op_call, CALL, gas: G, address: A, value: V, args_offset: AO, args_size: AS, ret_offset: RO, ret_size: RS), + (op_callcode, CALLCODE, gas: G, address: A, value: V, args_offset: AO, args_size: AS, ret_offset: RO, ret_size: RS), + (op_return, RETURN, offset: O, size: S), + (op_delegatecall, DELEGATECALL, gas: G, address: A, args_offset: AO, args_size: AS, ret_offset: RO, ret_size: RS), + (op_create2, CREATE2, value: V, offset: O, size: SI, salt: SA), + (op_staticcall, STATICCALL, gas: G, address: A, args_offset: AO, args_size: AS, ret_offset: RO, ret_size: RS), + (op_revert, REVERT, offset: O, size: S), + // (op_invalid, INVALID), ignored + // (op_selfdestruct, SELFDESTRUCT), ignored +} + #[cfg(test)] mod tests { use super::*; diff --git a/eth-types/src/evm_types/memory.rs b/eth-types/src/evm_types/memory.rs index 7b0c599a8e..cb2d1f4fc9 100644 --- a/eth-types/src/evm_types/memory.rs +++ b/eth-types/src/evm_types/memory.rs @@ -336,7 +336,7 @@ impl Memory { self.extend_at_least(minimal_length); let mem_starts = dst_offset as usize; - let mem_ends = mem_starts + length as usize; + let mem_ends = mem_starts + length; let dst_slice = &mut self.0[mem_starts..mem_ends]; dst_slice.fill(0); let data_starts = data_offset as usize; diff --git a/mock/src/lib.rs b/mock/src/lib.rs index aad706f3e2..f190e0612c 100644 --- a/mock/src/lib.rs +++ b/mock/src/lib.rs @@ -129,11 +129,11 @@ impl Default for MockCallBytecodeParams { /// Generate mock EVM bytecode that performs a contract call pub fn generate_mock_call_bytecode(params: MockCallBytecodeParams) -> Bytecode { bytecode! { - .mstore( + .op_mstore( 0u64, Word::from_big_endian(¶ms.pushdata) ) - .call( + .op_call( params.gas, params.address, 0u64, diff --git a/zkevm-circuits/src/evm_circuit/execution/balance.rs b/zkevm-circuits/src/evm_circuit/execution/balance.rs index 04ed6277ca..eb4a6a0671 100644 --- a/zkevm-circuits/src/evm_circuit/execution/balance.rs +++ b/zkevm-circuits/src/evm_circuit/execution/balance.rs @@ -202,12 +202,12 @@ mod test { let mut code = Bytecode::default(); if is_warm { code.append(&bytecode! { - .balance(address) + .op_balance(address) POP }); } code.append(&bytecode! { - .balance(address) + .op_balance(address) STOP }); @@ -253,12 +253,12 @@ mod test { let mut code_b = Bytecode::default(); if is_warm { code_b.append(&bytecode! { - .balance(address) + .op_balance(address) POP }); } code_b.append(&bytecode! { - .balance(address) + .op_balance(address) STOP }); diff --git a/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs b/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs index 69433e3910..6b8b1c9e8d 100644 --- a/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/calldatacopy.rs @@ -307,7 +307,7 @@ mod test { // code B gets called by code A, so the call is an internal call. let code_b = bytecode! { - .calldatacopy(dst_offset, offset, length) + .op_calldatacopy(dst_offset, offset, length) STOP }; diff --git a/zkevm-circuits/src/evm_circuit/execution/dup.rs b/zkevm-circuits/src/evm_circuit/execution/dup.rs index f5fc855f07..cefb04b35c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/dup.rs +++ b/zkevm-circuits/src/evm_circuit/execution/dup.rs @@ -85,7 +85,7 @@ mod test { PUSH32(value) }; for _ in 0..n - 1 { - bytecode.write_op(OpcodeId::DUP1); + bytecode.op_dup1(); } bytecode.append(&bytecode! { .write_op(opcode) diff --git a/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs b/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs index f0a423df67..4b133d7677 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_oog_call.rs @@ -273,7 +273,7 @@ mod test { .write_op(opcode) PUSH1(0) PUSH1(0) - .write_op(OpcodeId::REVERT) + REVERT }); bytecode diff --git a/zkevm-circuits/src/evm_circuit/execution/error_return_data_oo_bound.rs b/zkevm-circuits/src/evm_circuit/execution/error_return_data_oo_bound.rs index 88c56218e7..6993a60709 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_return_data_oo_bound.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_return_data_oo_bound.rs @@ -204,7 +204,7 @@ mod test { if is_root { code_b.append(&bytecode! { - .return_bytecode(return_data_offset, return_data_size) + .op_return(return_data_offset, return_data_size) STOP }); } else { @@ -214,7 +214,7 @@ mod test { PUSH32(dest_offset) // memory offset RETURNDATACOPY // end for internal - .return_bytecode(return_data_offset, return_data_size) + .op_return(return_data_offset, return_data_size) STOP }); } @@ -242,7 +242,7 @@ mod test { }); } else { code_a.append(&bytecode! { - .return_bytecode(return_data_offset, return_data_size) + .op_return(return_data_offset, return_data_size) }); } diff --git a/zkevm-circuits/src/evm_circuit/execution/error_stack.rs b/zkevm-circuits/src/evm_circuit/execution/error_stack.rs index a8550c6e68..63111c4a10 100644 --- a/zkevm-circuits/src/evm_circuit/execution/error_stack.rs +++ b/zkevm-circuits/src/evm_circuit/execution/error_stack.rs @@ -131,7 +131,7 @@ mod test { } } // append final stop op code - bytecode.write_op(OpcodeId::STOP); + bytecode.op_stop(); CircuitTestBuilder::new_from_test_ctx( TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), diff --git a/zkevm-circuits/src/evm_circuit/execution/logs.rs b/zkevm-circuits/src/evm_circuit/execution/logs.rs index b82c3704e2..6e4889022a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/logs.rs +++ b/zkevm-circuits/src/evm_circuit/execution/logs.rs @@ -358,7 +358,7 @@ mod test { code.push(32, Word::from(mstart)); code.write_op(cur_op_code); if is_persistent { - code.write_op(OpcodeId::STOP); + code.op_stop(); } else { // make current call failed with false persistent code.write_op(OpcodeId::INVALID(0xfe)); @@ -415,7 +415,7 @@ mod test { code.push(32, Word::from(mstart)); code.write_op(cur_op_code); - code.write_op(OpcodeId::STOP); + code.op_stop(); code_prepare.append(&code); CircuitTestBuilder::new_from_test_ctx( @@ -430,9 +430,7 @@ mod test { // prepare memory data let mut code = Bytecode::default(); for (i, d) in data.chunks(32).enumerate() { - code.push(32, Word::from_big_endian(d)); - code.push(32, Word::from(offset + i * 32)); - code.write_op(OpcodeId::MSTORE); + code.op_mstore(offset + i * 32, Word::from_big_endian(d)); } code } diff --git a/zkevm-circuits/src/evm_circuit/execution/push.rs b/zkevm-circuits/src/evm_circuit/execution/push.rs index 7970c50eae..f2c28954bb 100644 --- a/zkevm-circuits/src/evm_circuit/execution/push.rs +++ b/zkevm-circuits/src/evm_circuit/execution/push.rs @@ -157,7 +157,7 @@ mod test { for b in bytes { bytecode.write(*b, false); } - bytecode.write_op(OpcodeId::STOP); + bytecode.op_stop(); CircuitTestBuilder::new_from_test_ctx( TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), diff --git a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs index d417a3590f..cf5d0e8d2c 100644 --- a/zkevm-circuits/src/evm_circuit/execution/return_revert.rs +++ b/zkevm-circuits/src/evm_circuit/execution/return_revert.rs @@ -602,9 +602,7 @@ mod test { .chain(0u8..((32 - initializer.len() % 32) as u8)) .collect(); for (index, word) in code_creator.chunks(32).enumerate() { - bytecode.push(32, Word::from_big_endian(word)); - bytecode.push(32, Word::from(index * 32)); - bytecode.write_op(OpcodeId::MSTORE); + bytecode.op_mstore(index * 32, Word::from_big_endian(word)); } bytecode.append(&bytecode! { PUSH3(0x123456) // salt diff --git a/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs b/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs index 706be81dea..4b4392ff2a 100644 --- a/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs +++ b/zkevm-circuits/src/evm_circuit/execution/returndatacopy.rs @@ -284,8 +284,8 @@ mod test { let return_offset = std::cmp::max((return_data_offset + return_data_size) as i64 - 32, 0) as usize; let code_b = bytecode! { - .mstore(return_offset, Word::from_big_endian(&rand_bytes(32))) - .return_bytecode(return_data_offset, return_data_size) + .op_mstore(return_offset, Word::from_big_endian(&rand_bytes(32))) + .op_return(return_data_offset, return_data_size) STOP }; diff --git a/zkevm-circuits/src/evm_circuit/execution/returndatasize.rs b/zkevm-circuits/src/evm_circuit/execution/returndatasize.rs index 766e8628ac..82bae82f6e 100644 --- a/zkevm-circuits/src/evm_circuit/execution/returndatasize.rs +++ b/zkevm-circuits/src/evm_circuit/execution/returndatasize.rs @@ -94,8 +94,8 @@ mod test { let (addr_a, addr_b) = (mock::MOCK_ACCOUNTS[0], mock::MOCK_ACCOUNTS[1]); let code_b = bytecode! { - .mstore(0, Word::from_big_endian(&rand_bytes(32))) - .return_bytecode(return_data_offset, return_data_size) + .op_mstore(0, Word::from_big_endian(&rand_bytes(32))) + .op_return(return_data_offset, return_data_size) STOP }; diff --git a/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs b/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs index 069e3ad740..52eb0f9ec8 100644 --- a/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs +++ b/zkevm-circuits/src/evm_circuit/execution/signed_comparator.rs @@ -230,7 +230,7 @@ mod test { bytecode.push(32, a); bytecode.write_op(opcode); } - bytecode.write_op(OpcodeId::STOP); + bytecode.op_stop(); CircuitTestBuilder::new_from_test_ctx( TestContext::<2, 1>::simple_ctx_with_bytecode(bytecode).unwrap(), diff --git a/zkevm-circuits/src/evm_circuit/execution/swap.rs b/zkevm-circuits/src/evm_circuit/execution/swap.rs index 55eb6f5556..5127fd2ad1 100644 --- a/zkevm-circuits/src/evm_circuit/execution/swap.rs +++ b/zkevm-circuits/src/evm_circuit/execution/swap.rs @@ -94,7 +94,7 @@ mod test { PUSH32(lhs) }; for _ in 0..n - 1 { - bytecode.write_op(OpcodeId::DUP1); + bytecode.op_dup1(); } bytecode.append(&bytecode! { PUSH32(rhs) diff --git a/zkevm-circuits/src/exp_circuit/test.rs b/zkevm-circuits/src/exp_circuit/test.rs index ecd032e1e5..ac168f7890 100644 --- a/zkevm-circuits/src/exp_circuit/test.rs +++ b/zkevm-circuits/src/exp_circuit/test.rs @@ -36,11 +36,9 @@ fn gen_code_single(base: Word, exponent: Word) -> Bytecode { fn gen_code_multiple(args: Vec<(Word, Word)>) -> Bytecode { let mut code = Bytecode::default(); for (base, exponent) in args.into_iter() { - code.push(32, exponent); - code.push(32, base); - code.write_op(OpcodeId::EXP); + code.op_exp(base, exponent); } - code.write_op(OpcodeId::STOP); + code.op_stop(); code } diff --git a/zkevm-circuits/src/stats.rs b/zkevm-circuits/src/stats.rs index 272bda9ed9..ed43527497 100644 --- a/zkevm-circuits/src/stats.rs +++ b/zkevm-circuits/src/stats.rs @@ -192,7 +192,7 @@ pub(crate) fn print_circuit_stats_by_states( code.write_op(opcode); let opcode_pc = code.code.len() - 1; // let opcode_step_index = (proxy_code.num_opcodes - 1 + code.num_opcodes) - 1; - code.write_op(OpcodeId::STOP); + code.op_stop(); let block: GethData = TestContext::<10, 1>::new( None, |accs| {