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

wip: environment instructions #490

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
330 changes: 330 additions & 0 deletions cairo/ethereum/cancun/vm/instructions/environment.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin, PoseidonBuiltin

Check failure on line 1 in cairo/ethereum/cancun/vm/instructions/environment.cairo

View workflow job for this annotation

GitHub Actions / Trunk Check

cairo

Incorrect formatting, autoformat by running 'trunk fmt'
from starkware.cairo.common.registers import get_fp_and_pc
from starkware.cairo.common.dict_access import DictAccess

from ethereum_types.numeric import U256, U256Struct, Uint, UnionUintU256, UnionUintU256Enum
from ethereum.cancun.fork_types import Address, SetAddress, SetAddressStruct, SetAddressDictAccess
from ethereum.cancun.vm import Evm, EvmImpl, EnvImpl
from ethereum.cancun.vm.exceptions import ExceptionalHalt
from ethereum.cancun.vm.gas import charge_gas, GasConstants
from ethereum.cancun.vm.stack import Stack, push, pop
from ethereum.cancun.state import get_account
from ethereum.cancun.utils.address import to_address

from ethereum.utils.numeric import U256_be_from_address
from src.utils.bytes import felt_to_bytes20_little
from src.utils.dict import hashdict_read, hashdict_write

// @notice Pushes the address of the current executing account to the stack.
func address{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;

// GAS
let err = charge_gas(Uint(GasConstants.GAS_BASE));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
with stack {
let address_u256 = U256_be_from_address(evm.value.message.value.current_target);
let err = push(address_u256);
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}

func balance{range_check_ptr, poseidon_ptr: PoseidonBuiltin*, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;
with stack {
let (address_u256, err) = pop();
if (cast(err, felt) != 0) {
return err;
}
}

let fp_and_pc = get_fp_and_pc();
local __fp__: felt* = fp_and_pc.fp_val;

// GAS
let accessed_addresses = evm.value.accessed_addresses;
let dict_ptr = cast(accessed_addresses.value.dict_ptr, DictAccess*);
tempvar address_u256_ = UnionUintU256(new UnionUintU256Enum(cast(0, Uint*), address_u256));
let address_ = to_address(address_u256_);
tempvar address = new Address(address_.value);
with dict_ptr {
let (is_present) = hashdict_read(1, &address.value);
if (is_present == 0) {
// If the entry is not in the accessed storage keys, add it
hashdict_write(1, &address.value, 1);
tempvar poseidon_ptr = poseidon_ptr;
tempvar dict_ptr = dict_ptr;
} else {
tempvar poseidon_ptr = poseidon_ptr;
tempvar dict_ptr = dict_ptr;
}
}
let poseidon_ptr = cast([ap - 2], PoseidonBuiltin*);
let new_dict_ptr = cast([ap - 1], SetAddressDictAccess*);
tempvar new_accessed_addresses = SetAddress(
new SetAddressStruct(
evm.value.accessed_addresses.value.dict_ptr_start, new_dict_ptr
),
);
EvmImpl.set_accessed_addresses(new_accessed_addresses);


let access_gas_cost = (is_present * GasConstants.GAS_WARM_ACCESS) + (1 - is_present) *
GasConstants.GAS_COLD_ACCOUNT_ACCESS;
let err = charge_gas(Uint(access_gas_cost));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
with stack {
let err = push(evm.value.message.value.value);
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}


func origin{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;

// GAS
let err = charge_gas(Uint(GasConstants.GAS_BASE));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
with stack {
let origin_u256 = U256_be_from_address(evm.value.env.value.origin);

let err = push(origin_u256);
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}

// @notice Push the address of the caller onto the stack
func caller{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;

// GAS
let err = charge_gas(Uint(GasConstants.GAS_BASE));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
with stack {
let caller_u256 = U256_be_from_address(evm.value.message.value.caller);
let err = push(caller_u256);
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}

// @notice Push the value (in wei) sent with the call onto the stack
func callvalue{range_check_ptr, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;

// GAS
let err = charge_gas(Uint(GasConstants.GAS_BASE));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
with stack {
let err = push(evm.value.message.value.value);
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}

// @notice Push the size of code running in current environment onto the stack
func codesize{range_check_ptr, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;

// GAS
let err = charge_gas(Uint(GasConstants.GAS_BASE));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
with stack {
// max codesize is 24kb
tempvar code_len = U256(new U256Struct(evm.value.code.value.len, 0));
let err = push(code_len);
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}

// @notice Push the gas price used in current environment onto the stack
func gasprice{range_check_ptr, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;

// GAS
let err = charge_gas(Uint(GasConstants.GAS_BASE));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
with stack {
// gas price is a u64
tempvar gas_price = U256(new U256Struct(evm.value.env.value.gas_price.value, 0));
let err = push(gas_price);
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}

// @notice Push the size of the return data buffer onto the stack
func returndatasize{range_check_ptr, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;

// GAS
let err = charge_gas(Uint(GasConstants.GAS_BASE));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
with stack {
// any returndata bigger would produce an OOG upstream.
let err = push(U256(new U256Struct(evm.value.return_data.value.len, 0)));
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}

// @notice Push the balance of the current address to the stack
func self_balance{range_check_ptr, poseidon_ptr: PoseidonBuiltin*, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;

// GAS
let err = charge_gas(Uint(GasConstants.GAS_FAST_STEP));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
let state = evm.value.env.value.state;
let account = get_account{state=state}(evm.value.message.value.current_target);
let env = evm.value.env;
EnvImpl.set_state{env=env}(state);
EvmImpl.set_env(env);

with stack {
let err = push(account.value.balance);
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}

// @notice Push the base fee of the current block onto the stack
func base_fee{range_check_ptr, evm: Evm}() -> ExceptionalHalt* {
alloc_locals;
// STACK
let stack = evm.value.stack;

// GAS
let err = charge_gas(Uint(GasConstants.GAS_BASE));
if (cast(err, felt) != 0) {
return err;
}

// OPERATION
with stack {
// base fee is a u64
tempvar base_fee = U256(new U256Struct(evm.value.env.value.base_fee_per_gas.value, 0));
let err = push(base_fee);
if (cast(err, felt) != 0) {
return err;
}
}

// PROGRAM COUNTER
EvmImpl.set_pc_stack(Uint(evm.value.pc.value + 1), stack);
let ok = cast(0, ExceptionalHalt*);
return ok;
}
10 changes: 9 additions & 1 deletion cairo/ethereum/utils/numeric.cairo
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from starkware.cairo.common.math_cmp import is_le, is_not_zero

Check failure on line 1 in cairo/ethereum/utils/numeric.cairo

View workflow job for this annotation

GitHub Actions / Trunk Check

cairo

Incorrect formatting, autoformat by running 'trunk fmt'
from starkware.cairo.common.uint256 import uint256_reverse_endian
from ethereum_types.numeric import Uint, U256, U256Struct, bool
from ethereum_types.bytes import Bytes32, Bytes32Struct
from ethereum_types.bytes import Bytes32, Bytes32Struct, Bytes20
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin

from starkware.cairo.common.math import split_felt

func min{range_check_ptr}(a: felt, b: felt) -> felt {
alloc_locals;

Expand Down Expand Up @@ -148,3 +150,9 @@
tempvar res = bool(0);
return res;
}


func U256_be_from_address{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(address: Bytes20) -> U256 {
//TODO
return res;
}
Loading
Loading