From c3d8a977ab74e559017aa4bc57821d0e281e9b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Walter?= Date: Tue, 21 Nov 2023 18:14:18 +0100 Subject: [PATCH] Use evm address as key in state --- src/data_availability/starknet.cairo | 34 +++++++++++-------- src/kakarot/evm.cairo | 2 +- .../instructions/system_operations.cairo | 7 ++-- src/kakarot/library.cairo | 6 ++-- src/kakarot/state.cairo | 14 ++++---- .../test_environmental_information.cairo | 9 ++--- .../instructions/test_system_operations.cairo | 21 ++++++------ 7 files changed, 50 insertions(+), 43 deletions(-) diff --git a/src/data_availability/starknet.cairo b/src/data_availability/starknet.cairo index 294a300e4..da713d417 100644 --- a/src/data_availability/starknet.cairo +++ b/src/data_availability/starknet.cairo @@ -6,9 +6,7 @@ from starkware.cairo.common.alloc import alloc from starkware.cairo.common.bool import FALSE from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.dict_access import DictAccess -from starkware.cairo.common.hash import hash2 from starkware.cairo.common.uint256 import Uint256 -from starkware.starknet.common.storage import normalize_address from starkware.starknet.common.syscalls import ( emit_event, get_contract_address, @@ -73,6 +71,25 @@ namespace Starknet { evm_to_starknet_address.write(evm_address, starknet_address); return (account_address=starknet_address); } + + // @notice Return the bytecode of a given account + // @dev Return empty if the account is not deployed + // @param evm_address The address of the account + // @return bytecode_len The len of the bytecode + // @return bytecode The bytecode + func get_bytecode{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( + evm_address: felt + ) -> (bytecode_len: felt, bytecode: felt*) { + let (starknet_address) = evm_to_starknet_address.read(evm_address); + + if (starknet_address == 0) { + let (bytecode: felt*) = alloc(); + return (0, bytecode); + } + + let (bytecode_len, bytecode) = IAccount.bytecode(starknet_address); + return (bytecode_len, bytecode); + } } namespace Internals { @@ -88,7 +105,7 @@ namespace Internals { return (); } - let starknet_address = accounts_start.key; + let (starknet_address) = Account.compute_starknet_address(accounts_start.key); let account = cast(accounts_start.new_value, Account.Summary*); _commit_account(account, starknet_address); @@ -216,15 +233,4 @@ namespace Internals { return _save_storage(starknet_address, storage_start + DictAccess.SIZE, storage_end); } - - // @notice Compute the storage address of the given key when the storage var interface is - // storage_(key: Uint256) - // @dev Just the generated addr method when compiling the contract_account - func _storage_addr{pedersen_ptr: HashBuiltin*, range_check_ptr}(key: Uint256*) -> (res: felt) { - let res = 1510236440068827666686527023008568026372765124888307403567795291192307314167; - let (res) = hash2{hash_ptr=pedersen_ptr}(res, cast(key, felt*)[0]); - let (res) = hash2{hash_ptr=pedersen_ptr}(res, cast(key, felt*)[1]); - let (res) = normalize_address(addr=res); - return (res=res); - } } diff --git a/src/kakarot/evm.cairo b/src/kakarot/evm.cairo index 39cca3096..753dd22a6 100644 --- a/src/kakarot/evm.cairo +++ b/src/kakarot/evm.cairo @@ -740,7 +740,7 @@ namespace EVM { let (state, success) = State.add_transfer(state, transfer); // Check collision - let account = Account.fetch_or_create(address); + let (state, account) = State.get_account(state, address); let code_or_nonce = Account.has_code_or_nonce(account); let is_collision = code_or_nonce * is_deploy_tx; // Nonce is set to 1 in case of deploy_tx diff --git a/src/kakarot/instructions/system_operations.cairo b/src/kakarot/instructions/system_operations.cairo index 66ac356e7..45d275f21 100644 --- a/src/kakarot/instructions/system_operations.cairo +++ b/src/kakarot/instructions/system_operations.cairo @@ -766,7 +766,7 @@ namespace CreateHelper { self=ctx.memory, element_len=size.low, element=bytecode, offset=offset.low ); - // Get new account address + // Get target account let (state, evm_contract_address) = get_evm_address( ctx.state, ctx.call_context.address, popped_len, popped, size.low, bytecode ); @@ -774,9 +774,8 @@ namespace CreateHelper { tempvar address = new model.Address(starknet_contract_address, evm_contract_address); // Create Account with empty bytecode - let account = Account.fetch_or_create(address); + let (state, account) = State.get_account(state, address); let is_collision = Account.has_code_or_nonce(account); - let account = Account.set_nonce(account, 1); // Update calling context before creating sub context let ctx = ExecutionContext.update_memory(ctx, memory); @@ -790,6 +789,8 @@ namespace CreateHelper { // Create sub context with copied state let state = State.copy(ctx.state); + let (state, account) = State.get_account(state, address); + let account = Account.set_nonce(account, 1); let state = State.set_account(state, address, account); let (calldata: felt*) = alloc(); tempvar call_context: model.CallContext* = new model.CallContext( diff --git a/src/kakarot/library.cairo b/src/kakarot/library.cairo index 58cc583a4..6d1b87b3e 100644 --- a/src/kakarot/library.cairo +++ b/src/kakarot/library.cairo @@ -93,14 +93,14 @@ namespace Kakarot { let is_regular_tx = is_not_zero(to); let is_deploy_tx = 1 - is_regular_tx; - let account = Account.fetch_or_create(address); + let (bytecode_len, bytecode) = Starknet.get_bytecode(address.evm); let summary = EVM.execute( address, is_deploy_tx, origin_address, - account.code_len, - account.code, + bytecode_len, + bytecode, data_len, data, value, diff --git a/src/kakarot/state.cairo b/src/kakarot/state.cairo index f5b435a57..600e7262f 100644 --- a/src/kakarot/state.cairo +++ b/src/kakarot/state.cairo @@ -102,7 +102,7 @@ namespace State { ) -> (model.State*, model.Account*) { alloc_locals; let accounts = self.accounts; - let (pointer) = dict_read{dict_ptr=accounts}(key=address.starknet); + let (pointer) = dict_read{dict_ptr=accounts}(key=address.evm); // Return from local storage if found if (pointer != 0) { @@ -120,7 +120,7 @@ namespace State { // Otherwise read values from contract storage local accounts: DictAccess* = accounts; let account = Account.fetch_or_create(address); - dict_write{dict_ptr=accounts}(key=address.starknet, new_value=cast(account, felt)); + dict_write{dict_ptr=accounts}(key=address.evm, new_value=cast(account, felt)); tempvar state = new model.State( accounts_start=self.accounts_start, accounts=accounts, @@ -141,7 +141,7 @@ namespace State { self: model.State*, address: model.Address*, account: model.Account* ) -> model.State* { let accounts = self.accounts; - dict_write{dict_ptr=accounts}(key=address.starknet, new_value=cast(account, felt)); + dict_write{dict_ptr=accounts}(key=address.evm, new_value=cast(account, felt)); return new model.State( accounts_start=self.accounts_start, accounts=accounts, @@ -231,10 +231,8 @@ namespace State { let recipient = Account.set_balance(recipient, &recipient_balance_new); let accounts = self.accounts; - dict_write{dict_ptr=accounts}(key=transfer.sender.starknet, new_value=cast(sender, felt)); - dict_write{dict_ptr=accounts}( - key=transfer.recipient.starknet, new_value=cast(recipient, felt) - ); + dict_write{dict_ptr=accounts}(key=transfer.sender.evm, new_value=cast(sender, felt)); + dict_write{dict_ptr=accounts}(key=transfer.recipient.evm, new_value=cast(recipient, felt)); assert self.transfers[self.transfers_len] = transfer; tempvar state = new model.State( @@ -256,7 +254,7 @@ namespace State { self: model.State*, address: model.Address* ) -> (state: model.State*, balance: Uint256) { let accounts = self.accounts; - let (pointer) = dict_read{dict_ptr=accounts}(key=address.starknet); + let (pointer) = dict_read{dict_ptr=accounts}(key=address.evm); tempvar self = new model.State( accounts_start=self.accounts_start, accounts=accounts, diff --git a/tests/src/kakarot/instructions/test_environmental_information.cairo b/tests/src/kakarot/instructions/test_environmental_information.cairo index 1960ae406..b49f59d17 100644 --- a/tests/src/kakarot/instructions/test_environmental_information.cairo +++ b/tests/src/kakarot/instructions/test_environmental_information.cairo @@ -15,6 +15,7 @@ from starkware.starknet.common.syscalls import get_contract_address from openzeppelin.token.erc20.library import ERC20 // Local dependencies +from data_availability.starknet import Starknet from kakarot.account import Account from kakarot.constants import Constants from kakarot.storages import ( @@ -123,7 +124,7 @@ func test__exec_extcodesize__should_handle_address_with_no_code{ let (contract_account_class_hash_) = contract_account_class_hash.read(); let (evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (local starknet_contract_address) = Account.deploy( + let (local starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, evm_contract_address ); let address = Helpers.to_uint256(evm_contract_address); @@ -159,7 +160,7 @@ func test__exec_extcodecopy__should_handle_address_with_code{ let (contract_account_class_hash_) = contract_account_class_hash.read(); let (evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (local starknet_contract_address) = Account.deploy( + let (local starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, evm_contract_address ); IContractAccount.write_bytecode(starknet_contract_address, bytecode_len, bytecode); @@ -211,7 +212,7 @@ func test__exec_extcodecopy__should_handle_address_with_no_code{ let (contract_account_class_hash_) = contract_account_class_hash.read(); let (evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (local starknet_contract_address) = Account.deploy( + let (local starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, evm_contract_address ); let evm_contract_address_uint256 = Helpers.to_uint256(evm_contract_address); @@ -387,7 +388,7 @@ func test__exec_extcodehash__should_handle_address_with_code{ let (contract_account_class_hash_) = contract_account_class_hash.read(); let (evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (local starknet_contract_address) = Account.deploy( + let (local starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, evm_contract_address ); IContractAccount.write_bytecode(starknet_contract_address, bytecode_len, bytecode); diff --git a/tests/src/kakarot/instructions/test_system_operations.cairo b/tests/src/kakarot/instructions/test_system_operations.cairo index c3f481f9c..298380ab8 100644 --- a/tests/src/kakarot/instructions/test_system_operations.cairo +++ b/tests/src/kakarot/instructions/test_system_operations.cairo @@ -15,6 +15,7 @@ from starkware.starknet.common.syscalls import deploy, get_contract_address from openzeppelin.token.erc20.library import ERC20 // Local dependencies +from data_availability.starknet import Starknet from kakarot.constants import Constants from kakarot.storages import ( native_token_address, @@ -170,11 +171,11 @@ func test__exec_call__should_return_a_new_context_based_on_calling_ctx_stack{ let (contract_account_class_hash_) = contract_account_class_hash.read(); let (caller_evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (caller_starknet_contract_address) = Account.deploy( + let (caller_starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, caller_evm_contract_address ); let (callee_evm_contract_address) = CreateHelper.get_create_address(1, 0); - let (callee_starknet_contract_address) = Account.deploy( + let (callee_starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, callee_evm_contract_address ); @@ -258,14 +259,14 @@ func test__exec_call__should_transfer_value{ let (contract_account_class_hash_) = contract_account_class_hash.read(); let (caller_evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (caller_starknet_contract_address) = Account.deploy( + let (caller_starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, caller_evm_contract_address ); tempvar caller_address = new model.Address( caller_starknet_contract_address, caller_evm_contract_address ); let (callee_evm_contract_address) = CreateHelper.get_create_address(1, 0); - let (callee_starknet_contract_address) = Account.deploy( + let (callee_starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, callee_evm_contract_address ); tempvar callee_address = new model.Address( @@ -327,11 +328,11 @@ func test__exec_callcode__should_return_a_new_context_based_on_calling_ctx_stack let (contract_account_class_hash_) = contract_account_class_hash.read(); let (caller_evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (caller_starknet_contract_address) = Account.deploy( + let (caller_starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, caller_evm_contract_address ); let (callee_evm_contract_address) = CreateHelper.get_create_address(1, 0); - let (_) = Account.deploy(contract_account_class_hash_, callee_evm_contract_address); + let (_) = Starknet.deploy(contract_account_class_hash_, callee_evm_contract_address); // Fill the stack with input data let stack: model.Stack* = Stack.init(); @@ -407,14 +408,14 @@ func test__exec_callcode__should_transfer_value{ let (contract_account_class_hash_) = contract_account_class_hash.read(); let (caller_evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (caller_starknet_contract_address) = Account.deploy( + let (caller_starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, caller_evm_contract_address ); tempvar caller_address = new model.Address( caller_starknet_contract_address, caller_evm_contract_address ); let (callee_evm_contract_address) = CreateHelper.get_create_address(1, 0); - let (callee_starknet_contract_address) = Account.deploy( + let (callee_starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, callee_evm_contract_address ); tempvar callee_address = new model.Address( @@ -476,7 +477,7 @@ func test__exec_staticcall__should_return_a_new_context_based_on_calling_ctx_sta let (contract_account_class_hash_) = contract_account_class_hash.read(); let (evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (local starknet_contract_address) = Account.deploy( + let (local starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, evm_contract_address ); @@ -550,7 +551,7 @@ func test__exec_delegatecall__should_return_a_new_context_based_on_calling_ctx_s let (contract_account_class_hash_) = contract_account_class_hash.read(); let (evm_contract_address) = CreateHelper.get_create_address(0, 0); - let (local starknet_contract_address) = Account.deploy( + let (local starknet_contract_address) = Starknet.deploy( contract_account_class_hash_, evm_contract_address );