Skip to content

Commit

Permalink
Merge branch 'feat/eels-stack' into feat/memory
Browse files Browse the repository at this point in the history
  • Loading branch information
enitrat committed Dec 20, 2024
2 parents feee5d8 + dc351fa commit 6267f66
Show file tree
Hide file tree
Showing 15 changed files with 305 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/trunk_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- run: rustup update
- name: Rust cache
Expand Down
32 changes: 16 additions & 16 deletions .trunk/trunk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml
version: 0.1
cli:
version: 1.22.7
version: 1.22.8
# Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins)
plugins:
sources:
- id: trunk
ref: v1.6.4
ref: v1.6.6
uri: https://github.com/trunk-io/plugins
# Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes)
runtimes:
enabled:
- [email protected]
- node@18.12.1
- node@18.20.5
- [email protected]
downloads:
- name: rust
Expand Down Expand Up @@ -61,28 +61,28 @@ lint:
read_output_from: stdout
run_linter_from: workspace
enabled:
- cspell@8.15.4
- cspell@8.17.1
- [email protected]
- [email protected].3
- [email protected].4
- [email protected]
- cairo@SYSTEM
- rustfmt@2024-10-31
- clippy@2024-10-31
- [email protected].269
- rustfmt@1.65.0
- clippy@1.65.0
- [email protected].342
- git-diff-check
- [email protected].0
- [email protected].1-beta
- [email protected]
- markdownlint@0.42.0
- [email protected].0
- [email protected].2
- prettier@3.3.3
- ruff@0.7.1
- markdownlint@0.43.0
- [email protected].2
- [email protected].3
- prettier@3.4.2
- ruff@0.8.3
- [email protected]
- [email protected]
- solidity@SYSTEM
- [email protected]
- trivy@0.56.2
- trufflehog@3.82.13
- trivy@0.58.0
- trufflehog@3.87.2
- [email protected]

actions:
Expand Down
17 changes: 16 additions & 1 deletion cairo/ethereum/cancun/fork_types.cairo
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
from starkware.cairo.common.alloc import alloc

from ethereum_types.bytes import Bytes20, Bytes256, Bytes, BytesStruct
from ethereum_types.numeric import Uint, U256, U256Struct
from ethereum_types.numeric import Uint, U256, U256Struct, bool
from ethereum.crypto.hash import Hash32

using Address = Bytes20;

struct SetAddressDictAccess {
key: Address,
prev_value: bool,
new_value: bool,
}

struct SetAddressStruct {
dict_ptr_start: SetAddressDictAccess*,
dict_ptr: SetAddressDictAccess*,
}

struct SetAddress {
value: SetAddressStruct*,
}
using Root = Hash32;

using VersionedHash = Hash32;
Expand Down
35 changes: 33 additions & 2 deletions cairo/ethereum/cancun/utils/address.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,42 @@ from starkware.cairo.common.cairo_builtins import BitwiseBuiltin, KeccakBuiltin
from starkware.cairo.common.math_cmp import is_nn, is_not_zero

from ethereum_types.bytes import Bytes32, Bytes, BytesStruct
from ethereum_types.numeric import Uint
from ethereum_types.numeric import Uint, UnionUintU256
from ethereum.cancun.fork_types import Address
from ethereum.crypto.hash import keccak256
from ethereum.utils.numeric import divmod
from src.utils.bytes import felt_to_bytes20_little, felt_to_bytes, uint256_to_bytes32_little

from src.utils.bytes import (
felt_to_bytes20_little,
bytes_to_felt,
felt_to_bytes,
uint256_to_bytes32_little,
)

func to_address{range_check_ptr}(data: UnionUintU256) -> Address {
alloc_locals;
let (local bytes_data) = alloc();

if (cast(data.value.uint, felt) != 0) {
felt_to_bytes20_little(bytes_data, data.value.uint.value);
let res = bytes_to_felt(20, bytes_data);
tempvar address = Address(res);
return address;
}

if (cast(data.value.u256.value, felt) != 0) {
uint256_to_bytes32_little(bytes_data, [data.value.u256.value]);
let res = bytes_to_felt(20, bytes_data);
tempvar address = Address(res);
return address;
}

with_attr error_message("Type not valid") {
assert 0 = 1;
tempvar address = Address(0);
return address;
}
}

func compute_contract_address{
range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: KeccakBuiltin*
Expand Down
9 changes: 9 additions & 0 deletions cairo/ethereum/cancun/vm/exceptions.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from ethereum_types.bytes import BytesStruct

struct StackUnderflowError {
value: BytesStruct*,
}

struct StackOverflowError {
value: BytesStruct*,
}
64 changes: 64 additions & 0 deletions cairo/ethereum/cancun/vm/stack.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from ethereum_types.numeric import U256, U256Struct
from ethereum_types.bytes import BytesStruct
from starkware.cairo.common.dict import DictAccess, dict_read, dict_write
from ethereum.cancun.vm.exceptions import StackOverflowError, StackUnderflowError

struct Stack {
value: StackStruct*,
}

struct StackStruct {
dict_ptr_start: StackDictAccess*,
dict_ptr: StackDictAccess*,
len: felt,
}

struct StackDictAccess {
key: felt,
prev_value: U256,
new_value: U256,
}

const STACK_MAX_SIZE = 1024;

func pop{stack: Stack}() -> (U256, StackUnderflowError) {
alloc_locals;
let len = stack.value.len;
if (len == 0) {
tempvar err = StackUnderflowError(new BytesStruct(cast(0, felt*), 0));
let val = U256(cast(0, U256Struct*));
return (val, err);
}

let dict_ptr = cast(stack.value.dict_ptr, DictAccess*);
with dict_ptr {
let (pointer) = dict_read(len - 1);
}
let new_dict_ptr = cast(dict_ptr, StackDictAccess*);

tempvar stack = Stack(new StackStruct(stack.value.dict_ptr_start, new_dict_ptr, len - 1));
tempvar value = U256(cast(pointer, U256Struct*));

let ok_ = StackUnderflowError(cast(0, BytesStruct*));
return (value, ok_);
}

func push{stack: Stack}(value: U256) -> StackOverflowError {
alloc_locals;
let len = stack.value.len;
if (len == STACK_MAX_SIZE) {
tempvar err = StackOverflowError(new BytesStruct(cast(0, felt*), 0));
return err;
}

let dict_ptr = cast(stack.value.dict_ptr, DictAccess*);
with dict_ptr {
dict_write(len, cast(value.value, felt));
}
let new_dict_ptr = cast(dict_ptr, StackDictAccess*);

tempvar stack = Stack(new StackStruct(stack.value.dict_ptr_start, new_dict_ptr, len + 1));
let ok_ = StackOverflowError(cast(0, BytesStruct*));

return ok_;
}
9 changes: 9 additions & 0 deletions cairo/ethereum_types/numeric.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ struct U256 {
value: U256Struct*,
}

struct UnionUintU256Enum {
uint: Uint*,
u256: U256,
}

struct UnionUintU256 {
value: UnionUintU256Enum*,
}

struct SetUintDictAccess {
key: Uint,
prev_value: bool,
Expand Down
2 changes: 1 addition & 1 deletion cairo/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ profile = "black"
src_paths = ["src", "tests"]

[tool.uv.sources]
ethereum = { git = "https://github.com/ethereum/execution-specs.git", rev = "1adcc1bfe774798bcacc685aebc17bd9935078c3" }
ethereum = { git = "https://github.com/kkrt-labs/execution-specs.git", branch = "dev/change-type-branch-nodes" }

[build-system]
requires = ["hatchling"]
Expand Down
10 changes: 9 additions & 1 deletion cairo/tests/ethereum/cancun/utils/test_address.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
from typing import Union

from ethereum_types.bytes import Bytes32
from ethereum_types.numeric import Uint
from ethereum_types.numeric import U256, Uint
from hypothesis import given

from ethereum.cancun.fork_types import Address
from ethereum.cancun.utils.address import (
compute_contract_address,
compute_create2_contract_address,
to_address,
)


class TestAddress:

@given(data=...)
def test_to_address(self, cairo_run, data: Union[Uint, U256]):
assert to_address(data) == cairo_run("to_address", data)

@given(address=..., nonce=...)
def test_compute_contract_address(self, cairo_run, address: Address, nonce: Uint):
assert compute_contract_address(address, nonce) == cairo_run(
Expand Down
40 changes: 40 additions & 0 deletions cairo/tests/ethereum/cancun/vm/test_stack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from typing import List

import pytest
from ethereum_types.numeric import U256
from hypothesis import assume, given

from ethereum.cancun.vm.exceptions import StackOverflowError, StackUnderflowError
from ethereum.cancun.vm.stack import pop, push


class TestStack:
def test_pop_underflow(self, cairo_run):
stack = []
with pytest.raises(StackUnderflowError):
cairo_run("pop", stack)
with pytest.raises(StackUnderflowError):
pop(stack)

@given(stack=...)
def test_pop_success(self, cairo_run, stack: List[U256]):
assume(len(stack) > 0)

(new_stack_cairo, popped_value_cairo) = cairo_run("pop", stack)
popped_value_py = pop(stack)
assert new_stack_cairo == stack
assert popped_value_cairo == popped_value_py

@given(value=...)
def test_push_overflow(self, cairo_run, value: U256):
stack = [U256(0)] * 1024
with pytest.raises(StackOverflowError):
cairo_run("push", stack, value)
with pytest.raises(StackOverflowError):
push(stack, value)

@given(stack=..., value=...)
def test_push_success(self, cairo_run, stack: List[U256], value: U256):
new_stack_cairo = cairo_run("push", stack, value)
push(stack, value)
assert new_stack_cairo == stack
5 changes: 3 additions & 2 deletions cairo/tests/fixtures/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from tests.utils.args_gen import to_cairo_type, to_python_type
from tests.utils.hints import debug_info, get_op, oracle
from tests.utils.reporting import profile_from_tracer_data
from tests.utils.serde import Serde
from tests.utils.serde import NO_ERROR_FLAG, Serde

logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
Expand Down Expand Up @@ -332,12 +332,13 @@ def _factory(entrypoint, *args, **kwargs):
final_output = serde.serialize_list(output_ptr)

cumulative_retdata_offsets = serde.get_offsets(return_data_types)
function_output = [
unfiltered_output = [
serde.serialize(return_data_type, runner.vm.run_context.ap, offset)
for offset, return_data_type in zip(
cumulative_retdata_offsets, return_data_types
)
]
function_output = [x for x in unfiltered_output if x is not NO_ERROR_FLAG]

if final_output is not None:
if len(function_output) > 0:
Expand Down
5 changes: 4 additions & 1 deletion cairo/tests/test_serde.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Mapping, Optional, Set, Tuple, Type, Union
from typing import Annotated, Any, Mapping, Optional, Set, Tuple, Type, Union

import pytest
from ethereum_types.bytes import Bytes, Bytes0, Bytes8, Bytes20, Bytes32, Bytes256
Expand Down Expand Up @@ -168,6 +168,9 @@ def test_type(
Tuple[Mapping[Bytes, Bytes], ...],
Set[Uint],
Mapping[Address, Account],
Union[Uint, U256],
Set[Address],
Annotated[Tuple[VersionedHash, ...], 16],
],
):
assume(no_empty_sequence(b))
Expand Down
Loading

0 comments on commit 6267f66

Please sign in to comment.