diff --git a/cairo/src/account.cairo b/cairo/src/account.cairo index 25c35b2..a4c82da 100644 --- a/cairo/src/account.cairo +++ b/cairo/src/account.cairo @@ -29,7 +29,7 @@ namespace Account { // @dev This is used to initialize a new, empty account in the state // @dev when an account is part of a transaction, but was never interacted with before. // @return The new account - func new_empty() -> model.Account* { + func default() -> model.Account* { let (code) = alloc(); tempvar empty_code_hash = new Uint256( low=Constants.EMPTY_CODE_HASH_LOW, high=Constants.EMPTY_CODE_HASH_HIGH diff --git a/cairo/src/state.cairo b/cairo/src/state.cairo index b8f2d8c..f88396d 100644 --- a/cairo/src/state.cairo +++ b/cairo/src/state.cairo @@ -89,7 +89,7 @@ namespace State { } // Initialize a new account, empty otherwise - let account = Account.new_empty(); + let account = Account.default(); dict_write{dict_ptr=accounts}(key=evm_address, new_value=cast(account, felt)); tempvar state = new model.State( accounts_start=state.accounts_start, diff --git a/cairo/tests/src/test_account.cairo b/cairo/tests/src/test_account.cairo index dd72b7f..99f089a 100644 --- a/cairo/tests/src/test_account.cairo +++ b/cairo/tests/src/test_account.cairo @@ -7,8 +7,9 @@ from starkware.cairo.common.uint256 import Uint256, assert_uint256_eq from starkware.cairo.common.dict_access import DictAccess from starkware.cairo.common.memcpy import memcpy +from ethereum.base_types import U256 from src.model import model -from src.account import Account +from src.account import Account, Internals from tests.utils.helpers import TestHelpers func test__init__should_return_account_with_default_dict_as_storage{}() { @@ -185,3 +186,8 @@ func test__compute_code_hash{ // Then return result; } + +func test___storage_addr{pedersen_ptr: HashBuiltin*}(key: U256) -> felt { + let (res) = Internals._storage_addr(key.value); + return res; +} diff --git a/cairo/tests/src/test_account.py b/cairo/tests/src/test_account.py index 396274b..30342e7 100644 --- a/cairo/tests/src/test_account.py +++ b/cairo/tests/src/test_account.py @@ -3,7 +3,9 @@ from hypothesis import given from hypothesis.strategies import binary +from ethereum.base_types import U256 from src.utils.uint256 import int_to_uint256 +from tests.utils.helpers import get_internal_storage_key class TestAccount: @@ -60,3 +62,10 @@ def test_should_compute_code_hash(self, cairo_run, bytecode): output = cairo_run("test__compute_code_hash", code=bytecode) code_hash = int.from_bytes(keccak(bytecode), byteorder="big") assert output["low"] + 2**128 * output["high"] == code_hash + + class TestInternals: + @given(key=...) + def test_should_compute_storage_address(self, cairo_run, key: U256): + assert get_internal_storage_key(key) == cairo_run( + "test___storage_addr", key + ) diff --git a/cairo/tests/src/test_state.py b/cairo/tests/src/test_state.py index 6feb634..fffc0c9 100644 --- a/cairo/tests/src/test_state.py +++ b/cairo/tests/src/test_state.py @@ -1,6 +1,7 @@ from ethereum.cancun.fork_types import EMPTY_ACCOUNT from ethereum.crypto.hash import keccak256 from tests.utils.constants import OTHER, OWNER +from tests.utils.helpers import get_internal_storage_key from tests.utils.models import State @@ -47,7 +48,10 @@ def test_should_return_account_when_account_in_state(self, cairo_run): ), "balance": initial_state[OWNER]["balance"], "nonce": initial_state[OWNER]["nonce"], - "storage": initial_state[OWNER]["storage"], + "storage": { + get_internal_storage_key(k): v + for k, v in initial_state[OWNER]["storage"].items() + }, "transient_storage": {}, "valid_jumpdests": {}, "selfdestruct": 0, @@ -55,7 +59,7 @@ def test_should_return_account_when_account_in_state(self, cairo_run): } assert account == expected - def test_should_return_new_empty_account_when_account_not_in_state( + def test_should_return_default_account_when_account_not_in_state( self, cairo_run ): account = cairo_run( diff --git a/cairo/tests/utils/helpers.py b/cairo/tests/utils/helpers.py index 86a92a2..e8b00d5 100644 --- a/cairo/tests/utils/helpers.py +++ b/cairo/tests/utils/helpers.py @@ -1,5 +1,4 @@ import random -from collections import defaultdict from textwrap import wrap from typing import Iterable, List, Tuple, Union @@ -10,6 +9,7 @@ from eth_utils import decode_hex, keccak, to_checksum_address from starkware.cairo.lang.vm.crypto import pedersen_hash +from ethereum.base_types import U256 from src.utils.uint256 import int_to_uint256 from tests.utils.parsers import to_bytes, to_int @@ -93,10 +93,6 @@ def ec_sign( ) -def pack_64_bits_little(input: List[int]): - return sum([x * 256**i for (i, x) in enumerate(input)]) - - def flatten(data): result = [] @@ -125,21 +121,6 @@ def flatten_tx_access_list(access_list): return result -def merge_access_list(access_list): - """ - Merge all entries of the access list to get one entry per account with all its storage keys. - """ - merged_list = defaultdict(set) - for access in access_list: - merged_list[access["address"]] = merged_list[access["address"]].union( - { - pedersen_hash(*int_to_uint256(int(key, 16))) - for key in access["storageKeys"] - } - ) - return merged_list - - def pack_calldata(data: bytes) -> List[int]: """ Pack the incoming calldata bytes 31-bytes at a time in big-endian order. @@ -150,3 +131,8 @@ def pack_calldata(data: bytes) -> List[int]: """ return [len(data), *[int(chunk, 16) for chunk in wrap(data.hex(), 2 * 31)]] + + +def get_internal_storage_key(key: U256) -> int: + low, high = int_to_uint256(key) + return pedersen_hash(low, high)