Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EELS scaffolding #83

Merged
merged 1 commit into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions cairo/ethereum/base_types.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from starkware.cairo.common.dict_access import DictAccess
from starkware.cairo.common.uint256 import Uint256

// Int types
struct bool {
value: felt,
}
struct U64 {
value: felt,
}
struct U128 {
value: felt,
}
struct Uint {
value: felt,
}
struct U256 {
value: Uint256*,
}

// Bytes types
struct Bytes0 {
value: felt,
}
struct Bytes8 {
value: felt,
}
struct Bytes20 {
value: felt,
}
struct Bytes32 {
value: Uint256*,
}
struct Bytes256 {
value: U128*,
}

// Iterables types
struct BytesStruct {
data: felt*,
len: felt,
}

struct Bytes {
value: BytesStruct*,
}
// Some parts of the exec spec use bytes, so just easier to copy/paste
using bytes = Bytes;

// In Cairo, tuples are not a first-class type, so we need to define a custom
// struct to represent a tuple of Bytes32.
struct TupleBytesStruct {
value: Bytes,
len: felt,
}

struct TupleBytes {
value: TupleBytesStruct*,
}

struct TupleBytes32Struct {
value: Bytes32,
len: felt,
}

struct TupleBytes32 {
value: TupleBytes32Struct*,
}
110 changes: 110 additions & 0 deletions cairo/ethereum/cancun/blocks.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from ethereum.base_types import (
U64,
U256,
Bytes,
Bytes8,
Bytes32,
Uint,
TupleBytes32,
bool,
TupleBytes,
)
from ethereum.cancun.fork_types import Address, Bloom, Root
from ethereum.crypto.hash import Hash32

struct WithdrawalStruct {
index: U64,
validator_index: U64,
address: Address,
amount: U256,
}

struct Withdrawal {
value: WithdrawalStruct*,
}

struct TupleWithdrawalStruct {
value: Withdrawal,
len: felt,
}

struct TupleWithdrawal {
value: TupleWithdrawalStruct*,
}

struct HeaderStruct {
parent_hash: Hash32,
ommers_hash: Hash32,
coinbase: Address,
state_root: Root,
transactions_root: Root,
receipt_root: Root,
bloom: Bloom,
difficulty: Uint,
number: Uint,
gas_limit: Uint,
gas_used: Uint,
timestamp: U256,
extra_data: Bytes,
prev_randao: Bytes32,
nonce: Bytes8,
base_fee_per_gas: Uint,
withdrawals_root: Root,
blob_gas_used: U64,
excess_blob_gas: U64,
parent_beacon_block_root: Root,
}
ClementWalter marked this conversation as resolved.
Show resolved Hide resolved

struct Header {
value: HeaderStruct*,
}

struct TupleHeaderStruct {
value: Header,
len: felt,
}

struct TupleHeader {
value: TupleHeaderStruct*,
}

struct BlockStruct {
header: Header,
transactions: TupleBytes,
ommers: TupleHeader,
withdrawals: TupleWithdrawal,
}

struct Block {
value: BlockStruct*,
}

struct LogStruct {
address: Address,
topics: TupleBytes32,
data: Bytes,
}

struct Log {
value: LogStruct*,
}

struct TupleLogStruct {
value: Log,
len: felt,
}

struct TupleLog {
value: TupleLogStruct*,
}

struct ReceiptStruct {
succeeded: bool,
cumulative_gas_used: Uint,
bloom: Bloom,
logs: TupleLog,
}

struct Receipt {
value: ReceiptStruct*,
}
18 changes: 18 additions & 0 deletions cairo/ethereum/cancun/fork_types.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from ethereum.crypto.hash import Hash32
from ethereum.base_types import Bytes20, Bytes256, Uint, U256, Bytes, bytes

using Address = Bytes20;
using Root = Hash32;
using VersionedHash = Hash32;

using Bloom = Bytes256;

struct AccountStruct {
nonce: Uint,
balance: U256,
code: bytes,
}

struct Account {
value: AccountStruct*,
}
6 changes: 6 additions & 0 deletions cairo/ethereum/cancun/transactions.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const TX_BASE_COST = 21000;
const TX_DATA_COST_PER_NON_ZERO = 16;
const TX_DATA_COST_PER_ZERO = 4;
const TX_CREATE_COST = 32000;
const TX_ACCESS_LIST_ADDRESS_COST = 2400;
const TX_ACCESS_LIST_STORAGE_KEY_COST = 1900;
3 changes: 3 additions & 0 deletions cairo/ethereum/crypto/hash.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from ethereum.base_types import Bytes32

using Hash32 = Bytes32;
48 changes: 48 additions & 0 deletions cairo/ethereum/utils/numeric.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from starkware.cairo.common.math_cmp import is_le

func min{range_check_ptr}(a: felt, b: felt) -> felt {
if (a == b) {
return a;
}

let res = is_le(a, b);
if (res == 1) {
return a;
}
return b;
}

// @dev Inlined version of unsigned_div_rem
// Returns q and r such that:
// 0 <= q < rc_bound, 0 <= r < div and value = q * div + r.
//
// Assumption: 0 < div <= PRIME / rc_bound.
// Prover assumption: value / div < rc_bound.
//
// The value of div is restricted to make sure there is no overflow.
// q * div + r < (q + 1) * div <= rc_bound * (PRIME / rc_bound) = PRIME.
func divmod{range_check_ptr}(value, div) -> (q: felt, r: felt) {
let r = [range_check_ptr];
let q = [range_check_ptr + 1];
let range_check_ptr = range_check_ptr + 2;
%{
from starkware.cairo.common.math_utils import assert_integer
assert_integer(ids.div)
assert 0 < ids.div <= PRIME // range_check_builtin.bound, \
f'div={hex(ids.div)} is out of the valid range.'
ids.q, ids.r = divmod(ids.value, ids.div)
%}

// equivalent to assert_le(r, div - 1);
tempvar a = div - 1 - r;
%{
from starkware.cairo.common.math_utils import assert_integer
assert_integer(ids.a)
assert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'
%}
a = [range_check_ptr];
let range_check_ptr = range_check_ptr + 1;

assert value = q * div + r;
return (q, r);
}
22 changes: 22 additions & 0 deletions cairo/tests/ethereum/utils/test_numeric.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from ethereum.utils.numeric import min, divmod

func test_min{range_check_ptr}() -> felt {
tempvar a;
tempvar b;
%{
ids.a = program_input["a"]
ids.b = program_input["b"]
%}

return min(a, b);
}

func test_divmod{range_check_ptr}() -> (q: felt, r: felt) {
tempvar value;
tempvar div;
%{
ids.value = program_input["value"]
ids.div = program_input["div"]
%}
return divmod(value, div);
}
20 changes: 20 additions & 0 deletions cairo/tests/ethereum/utils/test_numeric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from hypothesis import given
from hypothesis import strategies as st
from starkware.cairo.lang.instances import PRIME

from tests.utils.strategies import uint128


class TestNumeric:
@given(a=uint128, b=uint128)
def test_min(self, cairo_run, a, b):
assert min(a, b) == cairo_run("test_min", a=a, b=b)

@given(
value=uint128,
div=st.integers(min_value=1, max_value=PRIME // (2**128 - 1) - 1),
)
def test_divmod(self, cairo_run, value, div):
ClementWalter marked this conversation as resolved.
Show resolved Hide resolved
assert list(divmod(value, div)) == cairo_run(
"test_divmod", value=value, div=div
)
14 changes: 1 addition & 13 deletions cairo/tests/fixtures/data.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from tests.utils.models import Account, Block, State
from tests.utils.models import Block, State


@pytest.fixture
Expand Down Expand Up @@ -63,18 +63,6 @@ def block():
)


@pytest.fixture
def account():
return Account.model_validate(
{
"balance": "0x00",
"code": "0x7fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf5f527fc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf6020527fe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff60405260786040356020355f35608a565b5f515f55602051600155604051600255005b5e56",
"nonce": "0x01",
"storage": {"0x1": "0xabde1"},
}
)


@pytest.fixture
def state():
return State.model_validate(
Expand Down
20 changes: 12 additions & 8 deletions cairo/tests/fixtures/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import pytest
import starkware.cairo.lang.instances as LAYOUTS
from starkware.cairo.common.dict import DictManager
from starkware.cairo.lang.cairo_constants import DEFAULT_PRIME
from starkware.cairo.lang.compiler.cairo_compile import compile_cairo, get_module_reader
from starkware.cairo.lang.compiler.preprocessor.default_pass_manager import (
Expand All @@ -24,9 +25,8 @@
from starkware.cairo.lang.vm.memory_segments import FIRST_MEMORY_ADDR as PROGRAM_BASE
from starkware.cairo.lang.vm.utils import RunResources

from tests.utils.constants import Opcodes
from tests.utils.coverage import VmWithCoverage
from tests.utils.hints import implement_hints
from tests.utils.hints import gen_arg, implement_hints
from tests.utils.reporting import profile_from_tracer_data
from tests.utils.serde import Serde

Expand Down Expand Up @@ -115,7 +115,7 @@ def _factory(entrypoint, **kwargs):
proof_mode=request.config.getoption("proof_mode"),
allow_missing_builtins=False,
)
serde = Serde(runner)
serde = Serde(runner.segments, cairo_program)

runner.program_base = runner.segments.add()
runner.execution_base = runner.segments.add()
Expand Down Expand Up @@ -156,11 +156,13 @@ def _factory(entrypoint, **kwargs):
)
runner.initial_fp = runner.initial_ap = runner.execution_base + len(stack)

dict_manager = DictManager()

runner.initialize_vm(
hint_locals={"program_input": kwargs},
static_locals={
"serde": serde,
"Opcodes": Opcodes,
hint_locals={
"program_input": kwargs,
"__dict_manager": dict_manager,
"gen_arg": gen_arg(dict_manager, runner.segments),
},
vm_class=VmWithCoverage,
)
Expand Down Expand Up @@ -261,7 +263,9 @@ def _factory(entrypoint, **kwargs):
final_output = None
if add_output:
final_output = serde.serialize_list(output_ptr)
function_output = serde.serialize(return_data.cairo_type)
function_output = serde.serialize(
return_data.cairo_type, runner.vm.run_context.ap
)
if final_output is not None:
function_output = (
function_output
Expand Down
Loading
Loading