Skip to content

Commit

Permalink
Serde into ethereum types
Browse files Browse the repository at this point in the history
  • Loading branch information
ClementWalter committed Nov 11, 2024
1 parent 4dd2a38 commit dda8791
Show file tree
Hide file tree
Showing 29 changed files with 1,054 additions and 504 deletions.
74 changes: 58 additions & 16 deletions cairo/ethereum/base_types.cairo
Original file line number Diff line number Diff line change
@@ -1,26 +1,68 @@
from starkware.cairo.common.dict_access import DictAccess
from starkware.cairo.common.uint256 import Uint256

struct Bytes {
// 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,
}

using bool = felt;
using U64 = felt;
using U128 = felt;
using U256 = Uint256;
using Uint = felt;

using Bytes0 = felt;
using Bytes8 = felt;
using Bytes20 = felt;
using Bytes32 = Uint256;
using Bytes256 = felt*;
struct Bytes {
value: BytesStruct*,
}
// Some parts of the exec spec use bytes, so just easier to copy/paste
using bytes = Bytes;

using Dict = DictAccess;
using List = felt*;
using Set = felt*;
using Tuple = felt*;
// 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*,
}
95 changes: 76 additions & 19 deletions cairo/ethereum/cancun/blocks.cairo
Original file line number Diff line number Diff line change
@@ -1,21 +1,44 @@
from ethereum.base_types import U64, U256, Bytes, Bytes8, Bytes32, Uint, Tuple, bool
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 Withdrawal {
struct WithdrawalStruct {
index: U64,
validator_index: U64,
address: Address,
amount: U256*,
amount: U256,
}

struct Header {
parent_hash: Hash32*,
ommers_hash: Hash32*,
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*,
state_root: Root,
transactions_root: Root,
receipt_root: Root,
bloom: Bloom,
difficulty: Uint,
number: Uint,
Expand All @@ -26,28 +49,62 @@ struct Header {
prev_randao: Bytes32,
nonce: Bytes8,
base_fee_per_gas: Uint,
withdrawals_root: Root*,
withdrawals_root: Root,
blob_gas_used: U64,
excess_blob_gas: U64,
parent_beacon_block_root: Root*,
parent_beacon_block_root: Root,
}

struct Block {
struct Header {
value: HeaderStruct*,
}

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

struct TupleHeader {
value: TupleHeaderStruct*,
}

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

struct Log {
struct Block {
value: BlockStruct*,
}

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

struct Receipt {
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: Tuple,
logs: TupleLog,
}

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

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

using Bloom = Bytes256;

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

EMPTY_ACCOUNT:
dw 0; // nonce
dw 0; // balance
dw 0; // code

// @notice See .venv/lib/python3.10/site-packages/ethereum/cancun/fork_types.py
// for the reference implementation of this function.
// TODO: Implement this function.
func encode_account(raw_account_data: Account*, storage_root: Root*) -> bytes* {
return storage_root;
struct Account {
value: AccountStruct*,
}
9 changes: 0 additions & 9 deletions cairo/ethereum/cancun/state.cairo

This file was deleted.

9 changes: 0 additions & 9 deletions cairo/ethereum/cancun/trie.cairo

This file was deleted.

58 changes: 15 additions & 43 deletions cairo/ethereum/cancun/fork.cairo → cairo/programs/fork.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,32 @@ from starkware.cairo.common.uint256 import Uint256
from starkware.cairo.common.math import unsigned_div_rem, split_felt
from starkware.cairo.common.math_cmp import is_nn
from starkware.cairo.common.bool import FALSE
from starkware.cairo.common.alloc import alloc

from ethereum.cancun.transactions import (
from src.model import model
from src.utils.array import count_not_zero
from src.gas import Gas
from src.utils.transaction import (
TX_DATA_COST_PER_ZERO,
TX_DATA_COST_PER_NON_ZERO,
TX_CREATE_COST,
TX_BASE_COST,
TX_ACCESS_LIST_ADDRESS_COST,
TX_ACCESS_LIST_STORAGE_KEY_COST,
)
from ethereum.crypto.hash import Hash32
from ethereum.base_types import U64, U128, U256, Bytes, Uint
from ethereum.cancun.blocks import Block
from ethereum.cancun.state import State
from ethereum.utils.numeric import min

from src.model import model
from src.utils.array import count_not_zero
from src.gas import Gas
using Uint128 = felt;
using Uint64 = felt;

const BASE_FEE_MAX_CHANGE_DENOMINATOR = 8;
const ELASTICITY_MULTIPLIER = 2;
const GAS_LIMIT_ADJUSTMENT_FACTOR = 1024;
const GAS_LIMIT_MINIMUM = 5000;
const BASE_FEE_MAX_CHANGE_DENOMINATOR = 8;
const EMPTY_OMMER_HASH_LOW = 0xd312451b948a7413f0a142fd40d49347;
const EMPTY_OMMER_HASH_HIGH = 0x1dcc4de8dec75d7aab85b567b6ccd41a;
const SYSTEM_ADDRESS = 0xfffffffffffffffffffffffffffffffffffffffe;
const BEACON_ROOTS_ADDRESS = 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02;
const SYSTEM_TRANSACTION_GAS = 30000000;
const MAX_BLOB_GAS_PER_BLOCK = 786432;
const VERSIONED_HASH_VERSION_KZG = 1;

struct BlockChain {
blocks_len: felt,
blocks: Block*,
state: State*,
chain_id: U64,
}

func apply_fork(old: BlockChain*) -> BlockChain* {
return old;
}

func get_last_256_block_hashes{range_check_ptr}(chain: BlockChain*) -> Hash32* {
alloc_locals;
let (local recent_block_hashes: Hash32*) = alloc();
let blocks_len = min(chain.blocks_len, 256);
let index = chain.blocks_len - blocks_len;

return recent_block_hashes;

// TODO: Implements
}

// @notice See https://github.com/ethereum/execution-specs/blob/master/src/ethereum/cancun/fork.py#L1118-L1154
// @dev We use the U128 alias to strenghten the fact that these felts should have been range_checked before
func check_gas_limit{range_check_ptr}(gas_limit: U64, parent_gas_limit: U64) {
// @dev We use the Uint128 alias to strenghten the fact that these felts should have been range_checked before
func check_gas_limit{range_check_ptr}(gas_limit: Uint64, parent_gas_limit: Uint64) {
let (max_adjustment_delta, _) = unsigned_div_rem(parent_gas_limit, GAS_LIMIT_ADJUSTMENT_FACTOR);

with_attr error_message("InvalidBlock") {
Expand All @@ -74,10 +43,13 @@ func check_gas_limit{range_check_ptr}(gas_limit: U64, parent_gas_limit: U64) {
}

// @notice See https://github.com/ethereum/execution-specs/blob/master/src/ethereum/cancun/fork.py#L226-L285
// @dev We use the U64 alias to strenghten the fact that these felts should have been range_checked before
// @dev We use the Uint64 alias to strenghten the fact that these felts should have been range_checked before
func calculate_base_fee_per_gas{range_check_ptr}(
block_gas_limit: U64, parent_gas_limit: U64, parent_gas_used: U64, parent_base_fee_per_gas: U64
) -> U128 {
block_gas_limit: Uint64,
parent_gas_limit: Uint64,
parent_gas_used: Uint64,
parent_base_fee_per_gas: Uint64,
) -> Uint128 {
let (parent_gas_target, _) = unsigned_div_rem(parent_gas_limit, ELASTICITY_MULTIPLIER);

check_gas_limit(block_gas_limit, parent_gas_limit);
Expand Down
Loading

0 comments on commit dda8791

Please sign in to comment.