Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
Add spec for CALLER opcode (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
ed255 authored Jan 14, 2022
1 parent 7e05f75 commit ffcc929
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 0 deletions.
37 changes: 37 additions & 0 deletions specs/opcode/33CALLER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# CALLER opcode

## Procedure

The `CALLER` opcode gets the caller address (msg.caller) from the current call.

## EVM behaviour

The `CALLER` opcode loads an `address` (20 bytes of data) from call context,
then pushes the `address` to the stack.

## Circuit behaviour

1. Construct call context table in rw table
2. Do busmapping lookup for stack write operation
3. Do busmapping lookup for call context caller read operation

## Constraints

1. opId = 0x33
2. State transition:
- gc + 2 (1 stack write, 1 call context read)
- stack_pointer - 1
- pc + 1
- gas + 2
3. Lookups: 2
- `address` is on top of stack
- `address` is in the rw table {call context, call ID, caller}

## 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/caller.py`.
1 change: 1 addition & 0 deletions src/zkevm_specs/evm/execution/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
from .jump import *
from .jumpi import *
from .block_coinbase import *
from .caller import *

# Error cases
27 changes: 27 additions & 0 deletions src/zkevm_specs/evm/execution/caller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from ..instruction import Instruction, Transition
from ..table import CallContextFieldTag
from ..opcode import Opcode


def caller(instruction: Instruction):
opcode = instruction.opcode_lookup(True)
instruction.constrain_equal(opcode, Opcode.CALLER)
address = instruction.stack_push()

# check [rw_table, call_context] table for caller address
instruction.constrain_equal(
address,
instruction.bytes_to_rlc(
instruction.int_to_bytes(
instruction.call_context_lookup(CallContextFieldTag.CallerAddress),
20,
)
),
)

instruction.constrain_same_context_state_transition(
opcode,
rw_counter=Transition.delta(2),
program_counter=Transition.delta(1),
stack_pointer=Transition.delta(-1),
)
3 changes: 3 additions & 0 deletions src/zkevm_specs/evm/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
jump,
jumpi,
coinbase,
caller,
)
from .execution_state import ExecutionState
from .instruction import Instruction
Expand Down Expand Up @@ -51,6 +52,8 @@ def verify_step(
jumpi(instruction)
elif instruction.curr.execution_state == ExecutionState.COINBASE:
coinbase(instruction)
elif instruction.curr.execution_state == ExecutionState.CALLER:
caller(instruction)
# Error cases
else:
raise NotImplementedError
Expand Down
67 changes: 67 additions & 0 deletions tests/evm/test_caller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import pytest

from zkevm_specs.evm import (
ExecutionState,
StepState,
Opcode,
verify_steps,
Tables,
RWTableTag,
RW,
CallContextFieldTag,
Bytecode,
)
from zkevm_specs.util import RLCStore, U160


TESTING_DATA = ((Opcode.CALLER, 0x030201),)


@pytest.mark.parametrize("opcode, address", TESTING_DATA)
def test_caller(opcode: Opcode, address: U160):
rlc_store = RLCStore()

caller_rlc = rlc_store.to_rlc(address.to_bytes(20, "little"))

bytecode = Bytecode(f"{opcode.hex()}00")
bytecode_hash = rlc_store.to_rlc(bytecode.hash, 32)
tables = Tables(
block_table=set(),
tx_table=set(),
bytecode_table=set(bytecode.table_assignments(rlc_store)),
rw_table=set(
[
(9, RW.Write, RWTableTag.Stack, 1, 1023, caller_rlc, 0, 0),
(10, RW.Read, RWTableTag.CallContext, 1, CallContextFieldTag.CallerAddress, address, 0, 0),
]
),
)

verify_steps(
rlc_store=rlc_store,
tables=tables,
steps=[
StepState(
execution_state=ExecutionState.CALLER,
rw_counter=9,
call_id=1,
is_root=True,
is_create=False,
opcode_source=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,
opcode_source=bytecode_hash,
program_counter=1,
stack_pointer=1023,
gas_left=0,
),
],
)

0 comments on commit ffcc929

Please sign in to comment.