Skip to content

Commit

Permalink
feat: cache code_hash (#930)
Browse files Browse the repository at this point in the history
  • Loading branch information
obatirou authored Sep 12, 2024
1 parent c66fe80 commit f14fd32
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 60 deletions.
1 change: 1 addition & 0 deletions crates/contracts/src/account_contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ pub mod AccountContract {
}

fn set_code_hash(ref self: ContractState, code_hash: u256) {
self.ownable.assert_only_owner();
self.Account_code_hash.write(code_hash);
}

Expand Down
14 changes: 13 additions & 1 deletion crates/contracts/tests/test_kakarot_core.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ use snforge_utils::snforge_utils::{
EventsFilterBuilderTrait, ContractEvents, ContractEventsTrait, store_evm
};
use starknet::storage::StorageTrait;
use utils::constants::EMPTY_KECCAK;
use utils::eth_transaction::common::{TxKind, TxKindTrait};
use utils::eth_transaction::legacy::TxLegacy;
use utils::eth_transaction::transaction::{Transaction, TransactionTrait};
use utils::helpers::U8SpanExTrait;
use utils::helpers::{EthAddressExTrait, u256_to_bytes_array};

#[test]
Expand Down Expand Up @@ -281,16 +283,26 @@ fn test_process_transaction() {
test_utils::register_account(eoa_evm_address, eoa_starknet_address);
start_mock_call::<u256>(eoa_starknet_address, selector!("get_nonce"), 0);
start_mock_call::<Span<u8>>(eoa_starknet_address, selector!("bytecode"), [].span());
start_mock_call::<u256>(eoa_starknet_address, selector!("get_code_hash"), EMPTY_KECCAK);

let contract_evm_address = test_utils::other_evm_address();
let contract_starknet_address = utils::helpers::compute_starknet_address(
test_address(), contract_evm_address, test_utils::uninitialized_account()
);
test_utils::register_account(contract_evm_address, contract_starknet_address);
start_mock_call::<u256>(contract_starknet_address, selector!("get_nonce"), 1);
let counter_evm_bytecode = counter_evm_bytecode();
start_mock_call::<
Span<u8>
>(contract_starknet_address, selector!("bytecode"), counter_evm_bytecode());
>(contract_starknet_address, selector!("bytecode"), counter_evm_bytecode);

start_mock_call::<
u256
>(
contract_starknet_address,
selector!("get_code_hash"),
counter_evm_bytecode.compute_keccak256_hash()
);
start_mock_call::<u256>(contract_starknet_address, selector!("storage"), 0);

let nonce = 0;
Expand Down
29 changes: 22 additions & 7 deletions crates/evm/src/backend/starknet_backend.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,8 @@ fn commit_account(self: @Account, ref state: State) {
//committed.
if self.is_created() {
starknet_account.write_bytecode(self.bytecode());
starknet_account.set_code_hash(self.code_hash());
//TODO: save valid jumpdests https://github.com/kkrt-labs/kakarot-ssj/issues/839
//TODO: set code hash https://github.com/kkrt-labs/kakarot-ssj/issues/840
}
return;
}
Expand Down Expand Up @@ -255,6 +255,7 @@ mod tests {
};
use snforge_std::{test_address, start_mock_call, get_class_hash};
use snforge_utils::snforge_utils::{assert_not_called, assert_called};
use utils::helpers::U8SpanExTrait;
use utils::helpers::compute_starknet_address;

#[test]
Expand Down Expand Up @@ -293,10 +294,16 @@ mod tests {
let mut state: State = Default::default();

// When
let bytecode = [0x1].span();
let code_hash = bytecode.compute_keccak256_hash();
let mut account = Account {
address: Address { evm: evm_address, starknet: starknet_address }, nonce: 420, code: [
0x1
].span(), balance: 0, selfdestruct: false, is_created: true,
address: Address { evm: evm_address, starknet: starknet_address },
nonce: 420,
code: bytecode,
code_hash: code_hash,
balance: 0,
selfdestruct: false,
is_created: true,
};
state.set_account(account);

Expand Down Expand Up @@ -324,21 +331,29 @@ mod tests {
register_account(evm_address, starknet_address);

let mut state: State = Default::default();
let bytecode = [0x1].span();
let code_hash = bytecode.compute_keccak256_hash();
let mut account = Account {
address: Address { evm: evm_address, starknet: starknet_address }, nonce: 420, code: [
0x1
].span(), balance: 0, selfdestruct: false, is_created: true,
address: Address { evm: evm_address, starknet: starknet_address },
nonce: 420,
code: bytecode,
code_hash: code_hash,
balance: 0,
selfdestruct: false,
is_created: true,
};
state.set_account(account);

start_mock_call::<()>(starknet_address, selector!("write_bytecode"), ());
start_mock_call::<()>(starknet_address, selector!("set_code_hash"), ());
start_mock_call::<()>(starknet_address, selector!("set_nonce"), ());
starknet_backend::commit(ref state).expect('commitment failed');

// Then the account should have a new code.
//TODO(starknet-foundry): we should be able to assert this has been called with specific
//data, to pass in mock_call
assert_called(starknet_address, selector!("write_bytecode"));
assert_called(starknet_address, selector!("set_code_hash"));
assert_called(starknet_address, selector!("set_nonce"));
}

Expand Down
2 changes: 2 additions & 0 deletions crates/evm/src/instructions/block_information.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ mod tests {
use evm::state::StateTrait;
use evm::test_utils::{VMBuilderTrait, gas_price, setup_test_environment};
use snforge_std::{start_cheat_block_number_global, start_cheat_block_timestamp_global};
use utils::constants::EMPTY_KECCAK;
use utils::constants;
use utils::traits::{EthAddressIntoU256};

Expand Down Expand Up @@ -268,6 +269,7 @@ mod tests {
balance: 400,
nonce: 0,
code: [].span(),
code_hash: EMPTY_KECCAK,
selfdestruct: false,
is_created: true,
};
Expand Down
51 changes: 32 additions & 19 deletions crates/evm/src/instructions/environmental_information.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use evm::model::vm::{VM, VMTrait};
use evm::model::{AddressTrait};
use evm::stack::StackTrait;
use evm::state::StateTrait;
use utils::constants::EMPTY_KECCAK;
use utils::helpers::{ceil32, load_word, U8SpanExTrait};
use utils::helpers::{ceil32, load_word};
use utils::set::SetTrait;
use utils::traits::{EthAddressIntoU256};

Expand Down Expand Up @@ -280,15 +279,7 @@ pub impl EnvironmentInformationImpl of EnvironmentInformationTrait {
|| (!account.has_code_or_nonce() && account.balance.is_zero()) {
return self.stack.push(0);
}
let bytecode = account.code;

if bytecode.is_empty() {
return self.stack.push(EMPTY_KECCAK);
}

// `cairo_keccak` takes in an array of little-endian u64s
let hash = bytecode.compute_keccak256_hash();
self.stack.push(hash)
self.stack.push(account.code_hash)
}
}

Expand Down Expand Up @@ -320,10 +311,12 @@ mod tests {
use evm::state::StateTrait;
use evm::test_utils::{VMBuilderTrait, origin, callvalue, gas_price};
use snforge_std::test_address;
use utils::helpers::{u256_to_bytes_array, ArrayExtTrait, compute_starknet_address};
use utils::constants::EMPTY_KECCAK;
use utils::helpers::{
u256_to_bytes_array, ArrayExtTrait, compute_starknet_address, U8SpanExTrait
};
use utils::traits::{EthAddressIntoU256};

const EMPTY_KECCAK: u256 = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

mod test_internals {
use evm::memory::MemoryTrait;
Expand Down Expand Up @@ -411,6 +404,7 @@ mod tests {
balance: 400,
nonce: 0,
code: [].span(),
code_hash: EMPTY_KECCAK,
selfdestruct: false,
is_created: true,
};
Expand Down Expand Up @@ -823,6 +817,7 @@ mod tests {
balance: 1,
nonce: 1,
code: [].span(),
code_hash: EMPTY_KECCAK,
selfdestruct: false,
is_created: true,
};
Expand All @@ -840,10 +835,16 @@ mod tests {
fn test_exec_extcodesize_should_push_bytecode_len() {
// Given
let mut vm = VMBuilderTrait::new_with_presets().build();
let bytecode = [0xff; 350].span();
let code_hash = bytecode.compute_keccak256_hash();
let account = Account {
address: vm.message().target, balance: 1, nonce: 1, code: [
0xff
; 350].span(), selfdestruct: false, is_created: true,
address: vm.message().target,
balance: 1,
nonce: 1,
code: bytecode,
code_hash,
selfdestruct: false,
is_created: true,
};
vm.env.state.set_account(account);
vm.stack.push(account.address.evm.into()).expect('push failed');
Expand All @@ -863,11 +864,14 @@ mod tests {
fn test_exec_extcodecopy_should_copy_code_of_input_account() {
// Given
let mut vm = VMBuilderTrait::new_with_presets().build();
let bytecode = counter_evm_bytecode();
let code_hash = bytecode.compute_keccak256_hash();
let account = Account {
address: vm.message().target,
balance: 1,
nonce: 1,
code: counter_evm_bytecode(),
code: bytecode,
code_hash,
selfdestruct: false,
is_created: true,
};
Expand Down Expand Up @@ -895,11 +899,14 @@ mod tests {
fn test_exec_extcodecopy_ca_offset_out_of_bounds_should_return_zeroes() {
// Given
let mut vm = VMBuilderTrait::new_with_presets().build();
let bytecode = counter_evm_bytecode();
let code_hash = bytecode.compute_keccak256_hash();
let account = Account {
address: vm.message().target,
balance: 1,
nonce: 1,
code: counter_evm_bytecode(),
code: bytecode,
code_hash,
selfdestruct: false,
is_created: true,
};
Expand Down Expand Up @@ -1054,6 +1061,7 @@ mod tests {
balance: 1,
nonce: 0,
code: [].span(),
code_hash: EMPTY_KECCAK,
selfdestruct: false,
is_created: true,
};
Expand All @@ -1076,6 +1084,7 @@ mod tests {
balance: 0,
nonce: 0,
code: [].span(),
code_hash: EMPTY_KECCAK,
selfdestruct: false,
is_created: true,
};
Expand All @@ -1098,6 +1107,7 @@ mod tests {
balance: 1,
nonce: 1,
code: [].span(),
code_hash: EMPTY_KECCAK,
selfdestruct: false,
is_created: true,
};
Expand All @@ -1115,11 +1125,14 @@ mod tests {
fn test_exec_extcodehash_with_bytecode() {
// Given
let mut vm = VMBuilderTrait::new_with_presets().build();
let bytecode = counter_evm_bytecode();
let code_hash = bytecode.compute_keccak256_hash();
let account = Account {
address: vm.message().target,
balance: 1,
nonce: 1,
code: counter_evm_bytecode(),
code: bytecode,
code_hash,
selfdestruct: false,
is_created: true,
};
Expand Down
26 changes: 20 additions & 6 deletions crates/evm/src/instructions/memory_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ mod tests {
native_token
};
use snforge_std::{test_address, start_mock_call};
use utils::constants::EMPTY_KECCAK;
use utils::helpers::U8SpanExTrait;
use utils::helpers::compute_starknet_address;

#[test]
Expand Down Expand Up @@ -808,10 +810,16 @@ mod tests {
let starknet_address = compute_starknet_address(
test_address, evm_address, uninitialized_account()
);
let bytecode = [0xab, 0xcd, 0xef].span();
let code_hash = bytecode.compute_keccak256_hash();
let account = Account {
address: Address { evm: evm_address, starknet: starknet_address }, code: [
0xab, 0xcd, 0xef
].span(), nonce: 1, balance: 0, selfdestruct: false, is_created: false,
address: Address { evm: evm_address, starknet: starknet_address },
code: bytecode,
code_hash: code_hash,
nonce: 1,
balance: 0,
selfdestruct: false,
is_created: false,
};
vm.env.state.set_account(account);

Expand Down Expand Up @@ -861,10 +869,16 @@ mod tests {
let starknet_address = compute_starknet_address(
test_address, evm_address, uninitialized_account()
);
let bytecode = [0xab, 0xcd, 0xef].span();
let code_hash = bytecode.compute_keccak256_hash();
let account = Account {
address: Address { evm: evm_address, starknet: starknet_address }, code: [
0xab, 0xcd, 0xef
].span(), nonce: 1, balance: 0, selfdestruct: false, is_created: false,
address: Address { evm: evm_address, starknet: starknet_address },
code: bytecode,
code_hash: code_hash,
nonce: 1,
balance: 0,
selfdestruct: false,
is_created: false,
};
let key: u256 = 0x100000000000000000000000000000001;
let value: u256 = 0xABDE1E11A5;
Expand Down
Loading

0 comments on commit f14fd32

Please sign in to comment.