From 8d464ea83e079924bdbb5fb2266bcfb3c6f77a47 Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Wed, 3 Aug 2022 07:45:38 +0800 Subject: [PATCH 1/3] Implement opcode `ADDRESS`. --- src/zkevm_specs/evm/execution/__init__.py | 2 + src/zkevm_specs/evm/execution/address.py | 24 ++++++++ tests/evm/test_address.py | 70 +++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 src/zkevm_specs/evm/execution/address.py create mode 100644 tests/evm/test_address.py diff --git a/src/zkevm_specs/evm/execution/__init__.py b/src/zkevm_specs/evm/execution/__init__.py index d1b4db432..005aa02e6 100644 --- a/src/zkevm_specs/evm/execution/__init__.py +++ b/src/zkevm_specs/evm/execution/__init__.py @@ -9,6 +9,7 @@ # Opcode's successful cases from .add_sub import * from .addmod import * +from .address import * from .mulmod import * from .block_ctx import * from .call import * @@ -47,6 +48,7 @@ ExecutionState.EndBlock: end_block, ExecutionState.ADD: add_sub, ExecutionState.ADDMOD: addmod, + ExecutionState.ADDRESS: address, ExecutionState.MULMOD: mulmod, ExecutionState.MUL: mul_div_mod, ExecutionState.NOT: not_opcode, diff --git a/src/zkevm_specs/evm/execution/address.py b/src/zkevm_specs/evm/execution/address.py new file mode 100644 index 000000000..63437de5c --- /dev/null +++ b/src/zkevm_specs/evm/execution/address.py @@ -0,0 +1,24 @@ +from ...util import N_BYTES_ACCOUNT_ADDRESS +from ..instruction import Instruction, Transition +from ..table import CallContextFieldTag +from ..opcode import Opcode + + +def address(instruction: Instruction): + opcode = instruction.opcode_lookup(True) + instruction.constrain_equal(opcode, Opcode.ADDRESS) + + # Get callee address from call context and compare with stack top after push. + instruction.constrain_equal( + instruction.call_context_lookup(CallContextFieldTag.CalleeAddress), + # NOTE: We can replace this with N_BYTES_WORD if we reuse the 32 byte RLC constraint in + # all places. See: https://github.com/privacy-scaling-explorations/zkevm-specs/issues/101 + instruction.rlc_to_fq(instruction.stack_push(), N_BYTES_ACCOUNT_ADDRESS), + ) + + instruction.step_state_transition_in_same_context( + opcode, + rw_counter=Transition.delta(2), + program_counter=Transition.delta(1), + stack_pointer=Transition.delta(-1), + ) diff --git a/tests/evm/test_address.py b/tests/evm/test_address.py new file mode 100644 index 000000000..8f4b7b1b0 --- /dev/null +++ b/tests/evm/test_address.py @@ -0,0 +1,70 @@ +import pytest + +from zkevm_specs.evm import ( + Bytecode, + CallContextFieldTag, + ExecutionState, + RWDictionary, + StepState, + Tables, + verify_steps, +) +from zkevm_specs.util import RLC, U160, rand_address, rand_fq + + +TESTING_DATA = ( + 0x00, + 0x10, + 0x030201, + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + rand_address(), +) + + +@pytest.mark.parametrize("address", TESTING_DATA) +def test_address(address: U160): + randomness = rand_fq() + + bytecode = Bytecode().address() + bytecode_hash = RLC(bytecode.hash(), randomness) + + tables = Tables( + block_table=set(), + tx_table=set(), + bytecode_table=set(bytecode.table_assignments(randomness)), + rw_table=set( + RWDictionary(9) + .call_context_read(1, CallContextFieldTag.CalleeAddress, address) + .stack_write(1, 1023, RLC(address, randomness)) + .rws + ), + ) + + verify_steps( + randomness=randomness, + tables=tables, + steps=[ + StepState( + execution_state=ExecutionState.ADDRESS, + rw_counter=9, + call_id=1, + is_root=True, + is_create=False, + code_hash=bytecode_hash, + program_counter=0, + stack_pointer=1024, + gas_left=2, + ), + StepState( + execution_state=ExecutionState.STOP, + rw_counter=11, + call_id=1, + is_root=True, + is_create=False, + code_hash=bytecode_hash, + program_counter=1, + stack_pointer=1023, + gas_left=0, + ), + ], + ) From 11b72d2401e2b4998c425345ecf931c4c60c1f20 Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Thu, 4 Aug 2022 08:40:36 +0800 Subject: [PATCH 2/3] Add Markdown doc for opcode `ADDRESS`. --- specs/opcode/30ADDRESS.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 specs/opcode/30ADDRESS.md diff --git a/specs/opcode/30ADDRESS.md b/specs/opcode/30ADDRESS.md new file mode 100644 index 000000000..a0e0f0277 --- /dev/null +++ b/specs/opcode/30ADDRESS.md @@ -0,0 +1,37 @@ +# ADDRESS opcode + +## Procedure + +The `ADDRESS` opcode gets the address of currently executing account. + +## EVM behaviour + +The `ADDRESS` opcode loads the callee address (20 bytes of data) from call +context, then pushes this address to the stack. + +## Circuit behaviour + +1. Construct call context table in rw table +2. Do busmapping lookup for call context callee read operation +3. Do busmapping lookup for stack write operation + +## Constraints + +1. opId = 0x30 +2. State transition: + - gc + 2 (1 stack write, 1 call context read) + - stack_pointer - 1 + - pc + 1 + - gas + 2 +3. Lookups: 2 + - `address` is in the rw table {call context, call ID, callee} + - `address` is on top of stack + +## Exceptions + +1. stack overflow: stack is full, stack pointer = 0 +2. out of gas: remaining gas is not enough + +## Code + +Please refer to `src/zkevm_specs/evm/execution/address.py`. From ddcc81a0d8820b86e1e5a739366cd472b3c23ee9 Mon Sep 17 00:00:00 2001 From: Steven Gu Date: Fri, 12 Aug 2022 17:04:49 +0800 Subject: [PATCH 3/3] Fixed to `gas - 2`. --- specs/opcode/30ADDRESS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/opcode/30ADDRESS.md b/specs/opcode/30ADDRESS.md index a0e0f0277..ec5a03773 100644 --- a/specs/opcode/30ADDRESS.md +++ b/specs/opcode/30ADDRESS.md @@ -22,7 +22,7 @@ context, then pushes this address to the stack. - gc + 2 (1 stack write, 1 call context read) - stack_pointer - 1 - pc + 1 - - gas + 2 + - gas - 2 3. Lookups: 2 - `address` is in the rw table {call context, call ID, callee} - `address` is on top of stack