From e65e2693cc36fdedfd930d44bf8897a70f07bc9f Mon Sep 17 00:00:00 2001 From: lightsing Date: Fri, 11 Nov 2022 22:37:00 +0800 Subject: [PATCH 1/3] add specs --- specs/error_state/ErrorDepth.md | 51 ++++++++++++++++++++ src/zkevm_specs/evm/execution/error_depth.py | 39 +++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 specs/error_state/ErrorDepth.md create mode 100644 src/zkevm_specs/evm/execution/error_depth.py diff --git a/specs/error_state/ErrorDepth.md b/specs/error_state/ErrorDepth.md new file mode 100644 index 000000000..c3b3aeb27 --- /dev/null +++ b/specs/error_state/ErrorDepth.md @@ -0,0 +1,51 @@ +# ErrorDepth state + +## Procedure +For CALL-family codes this type of error occurs when causing a callstack overflow. + +### EVM behavior +1. Fail the call attempt resulting in pushing `0` into stack +2. Continue the execution of current context + +### Constraints +1. Current opcode must be CALL-family codes. +2. `depth == 1025`. +3. The next step with `0` on stack top. + +### Lookups +- 1 Call Context lookup `CallContextFieldTag.Depth` +- 1 Stack push lookup + +## Code + +Please refer to `src/zkevm_specs/evm/execution/error_depth.py`. + +### Solidity Code to trigger ErrorDepth +```solidity +PUSH32 0x7f602060006000376000600060206000600060003561ffff5a03f10000000000 +PUSH1 0x0 +MSTORE +PUSH32 0x0060005260206000F30000000000000000000000000000000000000000000000 +PUSH1 0x20 +MSTORE + +PUSH1 0x40 +PUSH1 0x0 +PUSH1 0x0 +CREATE + +DUP1 +PUSH1 0x40 +MSTORE + +PUSH1 0x0 // retSize +PUSH1 0x0 // retOffset +PUSH1 0x20 // argSize +PUSH1 0x40 // argOffset +PUSH1 0x0 // Value +DUP6 +PUSH2 0xFF +GAS +SUB +CALL +``` \ No newline at end of file diff --git a/src/zkevm_specs/evm/execution/error_depth.py b/src/zkevm_specs/evm/execution/error_depth.py new file mode 100644 index 000000000..14f5ff5a7 --- /dev/null +++ b/src/zkevm_specs/evm/execution/error_depth.py @@ -0,0 +1,39 @@ +from ...util import FQ +from ..instruction import Instruction, Transition +from ..opcode import Opcode +from ..table import CallContextFieldTag + + +def error_depth(instruction: Instruction): + opcode = instruction.opcode_lookup(True) + # current executing op code must be CALL-family + instruction.constrain_in( + opcode, + [FQ(Opcode.CALL), FQ(Opcode.CALLCODE), FQ(Opcode.DELEGATECALL), FQ(Opcode.STATICCALL)] + ) + + is_call, is_callcode, is_delegatecall, is_staticcall = instruction.multiple_select( + opcode, (Opcode.CALL, Opcode.CALLCODE, Opcode.DELEGATECALL, Opcode.STATICCALL) + ) + + stack_delta = 0 + if is_call or is_callcode: + stack_delta -= 7 + elif is_delegatecall or is_delegatecall: + stack_delta -= 6 + + # next step must have zero on stack top + is_zero = instruction.stack_push() + stack_delta += 1 + instruction.constrain_equal(is_zero, FQ(0)) + + # check the call depth + depth = instruction.call_context_lookup(CallContextFieldTag.Depth) + instruction.constrain_equal(depth, FQ(1025)) + + instruction.step_state_transition_in_same_context( + opcode, + rw_counter=Transition.delta(2), + program_counter=Transition.delta(1), + stack_pointer=Transition.delta(stack_delta) + ) From 56769005082256e550c40de56dec2de483e28c12 Mon Sep 17 00:00:00 2001 From: lightsing Date: Thu, 17 Nov 2022 17:23:39 +0800 Subject: [PATCH 2/3] add test --- src/zkevm_specs/evm/execution/__init__.py | 2 + tests/evm/test_depth.py | 74 +++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 tests/evm/test_depth.py diff --git a/src/zkevm_specs/evm/execution/__init__.py b/src/zkevm_specs/evm/execution/__init__.py index f44ba2965..4d8d3aea0 100644 --- a/src/zkevm_specs/evm/execution/__init__.py +++ b/src/zkevm_specs/evm/execution/__init__.py @@ -48,6 +48,7 @@ from .extcodecopy import * from .oog_constant import * from .error_Invalid_jump import * +from .error_depth import * EXECUTION_STATE_IMPL: Dict[ExecutionState, Callable] = { @@ -95,4 +96,5 @@ ExecutionState.RETURN: return_, ExecutionState.ErrorOutOfGasConstant: oog_constant, ExecutionState.ErrorInvalidJump: invalid_jump, + ExecutionState.ErrorDepth: error_depth, } diff --git a/tests/evm/test_depth.py b/tests/evm/test_depth.py new file mode 100644 index 000000000..5c3e675cd --- /dev/null +++ b/tests/evm/test_depth.py @@ -0,0 +1,74 @@ +import pytest +from collections import namedtuple +from itertools import chain + +from zkevm_specs.evm import ( + Block, + Bytecode, + CallContextFieldTag, + ExecutionState, + Opcode, + RWDictionary, + StepState, + Tables, + Transaction, + verify_steps, +) +from zkevm_specs.util import rand_fq, RLC + +CallContext = namedtuple( + "CallContext", + [ + "is_root", + "is_create", + "program_counter", + "stack_pointer", + "gas_left", + "memory_size", + "reversible_write_counter", + ], + defaults=[True, False, 232, 1023, 5000, 0, 0], +) + +BYTECODE = Bytecode().call() +TESTING_DATA_IS_ROOT = ((Transaction(), BYTECODE),) + + +@pytest.mark.parametrize("tx, bytecode", TESTING_DATA_IS_ROOT) +def test_depth(tx: Transaction, bytecode: Bytecode): + randomness = rand_fq() + + block = Block() + + bytecode_hash = RLC(bytecode.hash(), randomness) + + tables = Tables( + block_table=set(block.table_assignments(randomness)), + tx_table=set( + chain( + tx.table_assignments(randomness), + Transaction(id=tx.id + 1).table_assignments(randomness), + ) + ), + bytecode_table=set(bytecode.table_assignments(randomness)), + rw_table=set(RWDictionary(24).call_context_read(1, CallContextFieldTag.IsSuccess, 0).rws), + ) + + verify_steps( + randomness=randomness, + tables=tables, + steps=[ + StepState( + execution_state=ExecutionState.ErrorDepth, + rw_counter=24, + call_id=1, + is_root=True, + is_create=False, + code_hash=bytecode_hash, + program_counter=0, + stack_pointer=1023, + gas_left=2, + reversible_write_counter=2, + ) + ], + ) From 3c070bc73419a1bbc5c5c507fd08083e4e5d9112 Mon Sep 17 00:00:00 2001 From: lightsing Date: Thu, 17 Nov 2022 17:29:40 +0800 Subject: [PATCH 3/3] fix call_context_read --- tests/evm/test_depth.py | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/tests/evm/test_depth.py b/tests/evm/test_depth.py index 5c3e675cd..3c5e80c08 100644 --- a/tests/evm/test_depth.py +++ b/tests/evm/test_depth.py @@ -16,20 +16,6 @@ ) from zkevm_specs.util import rand_fq, RLC -CallContext = namedtuple( - "CallContext", - [ - "is_root", - "is_create", - "program_counter", - "stack_pointer", - "gas_left", - "memory_size", - "reversible_write_counter", - ], - defaults=[True, False, 232, 1023, 5000, 0, 0], -) - BYTECODE = Bytecode().call() TESTING_DATA_IS_ROOT = ((Transaction(), BYTECODE),) @@ -51,7 +37,11 @@ def test_depth(tx: Transaction, bytecode: Bytecode): ) ), bytecode_table=set(bytecode.table_assignments(randomness)), - rw_table=set(RWDictionary(24).call_context_read(1, CallContextFieldTag.IsSuccess, 0).rws), + rw_table=set( + RWDictionary(24) + .call_context_read(1, CallContextFieldTag.Depth, 1025) + .rws + ), ) verify_steps(