Skip to content

Commit

Permalink
update bytecode packing (#648)
Browse files Browse the repository at this point in the history
  • Loading branch information
greged93 authored Feb 1, 2024
1 parent 9688354 commit b646e7b
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 57 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ jobs:
GITHUB_TOKEN: ${{ github.token }}
- name: run tests v0
run: |
set -o pipefail
make vm-tests-v0-ci | tee test_v0.out
- name: run tests v1
run: |
make vm-tests-v1-ci | tee test_v1.out
set +o pipefail
- name: Retrieve ef-tests execution resources
run: python scripts/compute_resources.py
env:
Expand Down
27 changes: 27 additions & 0 deletions crates/ef-testing/src/evm_sequencer/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use starknet_api::{
hash::StarkFelt,
state::StorageKey,
};
use starknet_crypto::FieldElement;

#[macro_export]
macro_rules! starknet_storage {
Expand Down Expand Up @@ -77,3 +78,29 @@ pub mod kkrt_account {
}
}
}

/// Splits a byte array into 31-byte chunks and converts each chunk to a StarkFelt.
pub fn split_bytecode_to_starkfelt(bytecode: &[u8]) -> impl Iterator<Item = StarkFelt> + '_ {
bytecode.chunks(31).filter_map(|bytes| {
let f = FieldElement::from_byte_slice_be(bytes);
f.map(StarkFelt::from).ok()
})
}

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

#[test]
fn test_split_bytecode_to_starkfelt() {
// Given
let bytes = Bytes::from([0x01, 0x02, 0x03, 0x04, 0x05]);

// When
let result: Vec<_> = split_bytecode_to_starkfelt(&bytes).collect();

// Then
assert_eq!(result, vec![StarkFelt::from(0x0102030405u64)]);
}
}
13 changes: 2 additions & 11 deletions crates/ef-testing/src/evm_sequencer/account/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use starknet_api::{
StarknetApiError,
};

use super::{AccountType, KakarotAccount};
use super::{split_bytecode_to_starkfelt, AccountType, KakarotAccount};
use crate::evm_sequencer::{
constants::{
kkrt_constants_v0::{CONTRACT_ACCOUNT_CLASS_HASH, EOA_CLASS_HASH},
Expand Down Expand Up @@ -64,7 +64,7 @@ impl KakarotAccount {
// Initialize the bytecode storage var.
let mut bytecode_storage = split_bytecode_to_starkfelt(code)
.enumerate()
.map(|(i, bytes)| starknet_storage!("bytecode_", [StarkFelt::from(i as u32)], bytes))
.map(|(i, bytes)| (StorageKey::from(i as u32), bytes))
.collect();
storage.append(&mut bytecode_storage);

Expand All @@ -90,12 +90,3 @@ 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))
})
}
24 changes: 1 addition & 23 deletions crates/ef-testing/src/evm_sequencer/account/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use starknet_api::{
};
use starknet_crypto::{poseidon_hash_many, FieldElement};

use super::split_bytecode_to_starkfelt;
use super::{AccountType, KakarotAccount};
use crate::evm_sequencer::{
constants::CHAIN_ID,
Expand Down Expand Up @@ -131,26 +132,3 @@ impl KakarotAccount {
})
}
}

fn split_bytecode_to_starkfelt(bytecode: &[u8]) -> impl Iterator<Item = StarkFelt> + '_ {
bytecode
.chunks(31)
.map(|bytes| StarkFelt::from(FieldElement::from_byte_slice_be(bytes).unwrap()))
}

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

#[test]
fn test_split_bytecode_to_starkfelt() {
// Given
let bytes = Bytes::from([0x01, 0x02, 0x03, 0x04, 0x05]);

// When
let result: Vec<_> = split_bytecode_to_starkfelt(&bytes).collect();

// Then
assert_eq!(result, vec![StarkFelt::from(0x0102030405u64)]);
}
}
21 changes: 10 additions & 11 deletions crates/ef-testing/src/evm_sequencer/evm_state/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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 @@ -20,8 +21,7 @@ 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, high_16_bytes_of_felt_to_bytes, split_u256,
to_broadcasted_starknet_transaction,
compute_starknet_address, felt_to_bytes, split_u256, to_broadcasted_starknet_transaction,
};

impl Evm for KakarotSequencer {
Expand Down Expand Up @@ -133,7 +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 in 16 byte big-endian chunks.
/// stored in the bytecode_ storage variables. The function assumes that the bytecode is stored in 31 byte big-endian chunks.
fn code_at(&mut self, evm_address: &Address) -> StateResult<Bytes> {
let starknet_address = compute_starknet_address(evm_address);

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

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

for chunk_index in 0..num_chunks {
let key = get_storage_var_address("bytecode_", &[StarkFelt::from(chunk_index)]);
let key = StorageKey::from(chunk_index);
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(), 16).to_vec());
bytecode.append(&mut felt_to_bytes(&code.into(), 1).to_vec());
}

let remainder = bytecode_len % 16;
let key = get_storage_var_address("bytecode_", &[StarkFelt::from(num_chunks)]);
let remainder = bytecode_len % 31;
let key = StorageKey::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());
bytecode.append(&mut felt_to_bytes(&code.into(), (32 - remainder) as usize).to_vec());

Ok(Bytes::from(bytecode))
}
Expand Down
25 changes: 13 additions & 12 deletions crates/ef-testing/src/evm_sequencer/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ 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 a FieldElement to a byte array.
pub fn felt_to_bytes(felt: &FieldElement, start: usize) -> Bytes {
Bytes::from(&felt.to_bytes_be()[start..])
}

/// Converts an signed transaction and a signature to a Starknet-rs transaction.
Expand Down Expand Up @@ -138,14 +138,14 @@ mod tests {
use super::*;

macro_rules! test_felt_to_bytes {
($input: expr, $output: expr, $len: expr, $test_name: ident) => {
($input: expr, $output: expr, $start: 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);
let bytes = felt_to_bytes(&felt, $start);

// Then
let expected = Bytes::from($output);
Expand All @@ -155,26 +155,27 @@ mod tests {
}

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

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

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

0 comments on commit b646e7b

Please sign in to comment.