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

Revert bytecode storage update #646

Merged
merged 1 commit into from
Jan 30, 2024
Merged
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
14 changes: 11 additions & 3 deletions crates/ef-testing/src/evm_sequencer/account/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,9 @@ impl KakarotAccount {
};

// Initialize the bytecode storage var.
let mut bytecode_storage = code
.into_iter()
let mut bytecode_storage = split_bytecode_to_starkfelt(code)
.enumerate()
.map(|(i, byte)| (StorageKey::from(i as u64), StarkFelt::from(*byte)))
.map(|(i, bytes)| starknet_storage!("bytecode_", [StarkFelt::from(i as u32)], bytes))
.collect();
storage.append(&mut bytecode_storage);

Expand All @@ -91,3 +90,12 @@ impl KakarotAccount {
})
}
}

/// Splits a byte array into 16-byte chunks and converts each chunk to a StarkFelt.
pub fn split_bytecode_to_starkfelt(bytecode: &Bytes) -> impl Iterator<Item = StarkFelt> + '_ {
bytecode.chunks(16).map(|x| {
let mut storage_value = [0u8; 16];
storage_value[..x.len()].copy_from_slice(x);
StarkFelt::from(u128::from_be_bytes(storage_value))
})
}
25 changes: 14 additions & 11 deletions crates/ef-testing/src/evm_sequencer/evm_state/v0.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use blockifier::abi::abi_utils::{get_fee_token_var_address, get_storage_var_address};
use blockifier::abi::sierra_types::next_storage_key;
use blockifier::execution::errors::EntryPointExecutionError;
use blockifier::state::errors::StateError;
use blockifier::state::state_api::{State, StateReader, StateResult};
use blockifier::transaction::errors::TransactionExecutionError;
use blockifier::transaction::objects::{TransactionExecutionInfo, TransactionExecutionResult};
Expand All @@ -11,7 +10,6 @@ use sequencer::execution::Execution as _;
use sequencer::transaction::BroadcastedTransactionWrapper;
use starknet::core::types::{BroadcastedTransaction, FieldElement};
use starknet_api::hash::StarkFelt;
use starknet_api::state::StorageKey;

use super::Evm;
use crate::evm_sequencer::account::{AccountType, KakarotAccount};
Expand All @@ -22,7 +20,8 @@ use crate::evm_sequencer::constants::KAKAROT_ADDRESS;
use crate::evm_sequencer::constants::{CHAIN_ID, ETH_FEE_TOKEN_ADDRESS};
use crate::evm_sequencer::sequencer::KakarotSequencer;
use crate::evm_sequencer::utils::{
compute_starknet_address, split_u256, to_broadcasted_starknet_transaction,
compute_starknet_address, high_16_bytes_of_felt_to_bytes, split_u256,
to_broadcasted_starknet_transaction,
};

impl Evm for KakarotSequencer {
Expand Down Expand Up @@ -134,8 +133,7 @@ impl Evm for KakarotSequencer {

/// Returns the bytecode of the given address. For an EOA, the bytecode_len_ storage variable will return 0,
/// and the function will return an empty vector. For a contract account, the function will return the bytecode
/// stored in the bytecode_ storage variables. The function assumes that the bytecode is stored byte by byte,
/// starting from the storage key 0.
/// stored in the bytecode_ storage variables. The function assumes that the bytecode is stored in 16 byte big-endian chunks.
fn code_at(&mut self, evm_address: &Address) -> StateResult<Bytes> {
let starknet_address = compute_starknet_address(evm_address);

Expand All @@ -148,17 +146,22 @@ impl Evm for KakarotSequencer {
return Ok(Bytes::default());
}

// Assumes that the bytecode is stored in 16 byte chunks.
let num_chunks = bytecode_len / 16;
let mut bytecode: Vec<u8> = Vec::new();

for index in 0..bytecode_len {
let key = StorageKey::from(index);
for chunk_index in 0..num_chunks {
let key = get_storage_var_address("bytecode_", &[StarkFelt::from(chunk_index)]);
let code = (&mut self.state).get_storage_at(starknet_address.try_into()?, key)?;
let code: FieldElement = code.into();
bytecode.push(code.try_into().map_err(|_| {
StateError::StateReadError("FieldElement did not fit in u8".to_string())
})?)
bytecode.append(&mut high_16_bytes_of_felt_to_bytes(&code.into(), 16).to_vec());
}

let remainder = bytecode_len % 16;
let key = get_storage_var_address("bytecode_", &[StarkFelt::from(num_chunks)]);
let code = (&mut self.state).get_storage_at(starknet_address.try_into()?, key)?;
bytecode
.append(&mut high_16_bytes_of_felt_to_bytes(&code.into(), remainder as usize).to_vec());

Ok(Bytes::from(bytecode))
}

Expand Down
53 changes: 52 additions & 1 deletion crates/ef-testing/src/evm_sequencer/utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::constants::KAKAROT_ADDRESS;
use super::types::felt::FeltSequencer;
use bytes::BytesMut;
use reth_primitives::{Address, TransactionSigned, TxType};
use reth_primitives::{Address, Bytes, TransactionSigned, TxType};
use revm_primitives::U256;
use starknet::core::{
types::{BroadcastedInvokeTransaction, FieldElement},
Expand Down Expand Up @@ -57,6 +57,11 @@ pub fn split_u256(value: U256) -> [u128; 2] {
]
}

/// Converts the high 16 bytes of a FieldElement to a byte array.
pub fn high_16_bytes_of_felt_to_bytes(felt: &FieldElement, len: usize) -> Bytes {
Bytes::from(&felt.to_bytes_be()[16..len + 16])
}

/// Converts an signed transaction and a signature to a Starknet-rs transaction.
pub fn to_broadcasted_starknet_transaction(
transaction: &TransactionSigned,
Expand Down Expand Up @@ -127,3 +132,49 @@ pub fn to_broadcasted_starknet_transaction(

Ok(request)
}

#[cfg(test)]
mod tests {
use super::*;

macro_rules! test_felt_to_bytes {
($input: expr, $output: expr, $len: expr, $test_name: ident) => {
#[test]
fn $test_name() {
// Given
let felt = FieldElement::from_hex_be($input).unwrap();

// When
let bytes = high_16_bytes_of_felt_to_bytes(&felt, $len);

// Then
let expected = Bytes::from($output);
assert_eq!(bytes, expected);
}
};
}

test_felt_to_bytes!(
"0x1234567890abcdef1234567890abcdef",
vec![
0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab,
0xcd, 0xef
],
16,
test_felt_to_bytes_full
);

test_felt_to_bytes!(
"0x12345678900000000000000000000000",
vec![0x12, 0x34, 0x56, 0x78, 0x90],
5,
test_felt_to_bytes_partial
);

test_felt_to_bytes!(
"0x12345678900000000000000000000000",
vec![],
0,
test_felt_to_bytes_empty
);
}
Loading