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

Commit

Permalink
spec for opcode COINBASE (#83)
Browse files Browse the repository at this point in the history
* update as dependency pr changed

* remove '/'

* some minor fix

* tweak doc

* fix rebase error

* lint

* lint

* update doc

* Apply suggestions from code review

Co-authored-by: Chih Cheng Liang <chihchengliang@gmail.com>

* change to use raw value into block

Co-authored-by: Dream Wu <wwuwwei@126.com>
Co-authored-by: Haichen Shen <shenhaichen@gmail.com>
Co-authored-by: Chih Cheng Liang <chihchengliang@gmail.com>
  • Loading branch information
4 people authored Jan 12, 2022
1 parent e3c7885 commit 2fd3a29
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 2 deletions.
39 changes: 39 additions & 0 deletions specs/opcode/41COINBASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Coinbase op code

## Procedure

The `COINBASE` opcode get the coinbase address from current block and push to the stack

## EVM behavior

The `COINBASE` opcode loads an `address` (20 bytes of data) from block context.
then push the `address` to the stack.

## Circuit behavior

1. construct block context table
2. do busmapping lookup for stack write operation
3. other implicit check: bytes length

## Constraints

1. opId = 0x41
2. State transition:
- gc + 1 (1 stack write)
- stack_pointer - 1
- pc + 1
- gas + 2
3. Lookups: 2
- `address` is on the top of stack
- `address` is in the block context table
4. Others:
- `address` is 20 bytes length

## 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/coinbase.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 @@ -5,5 +5,6 @@
from .push import *
from .jump import *
from .jumpi import *
from .block_coinbase import *

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


def coinbase(instruction: Instruction):
opcode = instruction.opcode_lookup(True)
instruction.constrain_equal(opcode, Opcode.COINBASE)
address = instruction.stack_push()
# in real circuit also check address raw data is 160 bit length (20 bytes)
# check block table for coinbase address
instruction.constrain_equal(
address,
instruction.bytes_to_rlc(instruction.int_to_bytes(instruction.block_lookup(BlockContextFieldTag.Coinbase), 20)),
)

instruction.constrain_same_context_state_transition(
opcode,
rw_counter=Transition.delta(1),
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 @@ -7,6 +7,7 @@
push,
jump,
jumpi,
coinbase,
)
from .execution_state import ExecutionState
from .instruction import Instruction
Expand Down Expand Up @@ -48,6 +49,8 @@ def verify_step(
jump(instruction)
elif instruction.curr.execution_state == ExecutionState.JUMPI:
jumpi(instruction)
elif instruction.curr.execution_state == ExecutionState.COINBASE:
coinbase(instruction)
# Error cases
else:
raise NotImplementedError
Expand Down
4 changes: 2 additions & 2 deletions src/zkevm_specs/evm/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Block:
coinbase: U160
gas_limit: U64
block_number: U256
time: U256
time: U64
difficulty: U256
base_fee: U256

Expand All @@ -34,7 +34,7 @@ def __init__(
coinbase: U160 = 0x10,
gas_limit: U64 = int(15e6),
block_number: U256 = 0,
time: U256 = 0,
time: U64 = 0,
difficulty: U256 = 0,
base_fee: U256 = int(1e9),
history_hashes: Sequence[U256] = [],
Expand Down
67 changes: 67 additions & 0 deletions tests/evm/test_coinbase.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,
Block,
Bytecode,
)
from zkevm_specs.util import RLCStore, U160


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


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

coinbase_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)
block = Block(address)
tables = Tables(
block_table=set(block.table_assignments(rlc_store)),
tx_table=set(),
bytecode_table=set(bytecode.table_assignments(rlc_store)),
rw_table=set(
[
(9, RW.Write, RWTableTag.Stack, 1, 1023, coinbase_rlc, 0, 0),
]
),
)

verify_steps(
rlc_store=rlc_store,
tables=tables,
steps=[
StepState(
execution_state=ExecutionState.COINBASE,
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=10,
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 2fd3a29

Please sign in to comment.