Skip to content

Commit

Permalink
feat: refactor Kakarot Sequencer API (#651)
Browse files Browse the repository at this point in the history
* refactor code to make API useable outside of ef-tests

* fix trunk

* fix CI

* fix CI

* fix comments

* clean the code
  • Loading branch information
greged93 authored Feb 6, 2024
1 parent a693bce commit 97f50f1
Show file tree
Hide file tree
Showing 14 changed files with 493 additions and 285 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/trunk-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
toolchain: 1.75.0
override: true
components: clippy
- uses: Swatinem/rust-cache@v2
Expand Down
14 changes: 2 additions & 12 deletions crates/ef-testing/src/evm_sequencer/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ pub mod v0;
#[cfg(feature = "v1")]
pub mod v1;

use starknet_api::{
core::{ContractAddress, Nonce},
hash::StarkFelt,
state::StorageKey,
};
use starknet_api::{core::Nonce, hash::StarkFelt, state::StorageKey};
use starknet_crypto::FieldElement;

#[macro_export]
Expand Down Expand Up @@ -35,7 +31,6 @@ macro_rules! starknet_storage {
#[allow(dead_code)]
#[derive(Debug, Clone, Default)]
pub struct KakarotAccount {
pub(crate) starknet_address: ContractAddress,
pub(crate) evm_address: StarkFelt,
pub(crate) nonce: Nonce,
pub(crate) storage: Vec<(StorageKey, StarkFelt)>,
Expand All @@ -54,11 +49,7 @@ pub enum AccountType {
pub mod kkrt_account {
use super::{AccountType, KakarotAccount};
use reth_primitives::{Address, Bytes, U256};
use starknet_api::{
core::{ContractAddress, Nonce},
hash::StarkFelt,
StarknetApiError,
};
use starknet_api::{core::Nonce, hash::StarkFelt, StarknetApiError};

impl KakarotAccount {
pub fn new(
Expand All @@ -68,7 +59,6 @@ pub mod kkrt_account {
_evm_storage: &[(U256, U256)],
) -> Result<Self, StarknetApiError> {
Ok(Self {
starknet_address: ContractAddress::default(),
evm_address: StarkFelt::default(),
nonce: Nonce::default(),
storage: vec![],
Expand Down
33 changes: 8 additions & 25 deletions crates/ef-testing/src/evm_sequencer/account/v0.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
use blockifier::abi::{abi_utils::get_storage_var_address, sierra_types::next_storage_key};
use reth_primitives::{Address, Bytes, U256};
use starknet_api::{
core::{ContractAddress, Nonce},
hash::StarkFelt,
state::StorageKey,
StarknetApiError,
};
use starknet_api::{core::Nonce, hash::StarkFelt, state::StorageKey, StarknetApiError};

use super::{split_bytecode_to_starkfelt, AccountType, KakarotAccount};
use crate::evm_sequencer::{
constants::{
kkrt_constants_v0::{CONTRACT_ACCOUNT_CLASS_HASH, EOA_CLASS_HASH},
KAKAROT_ADDRESS,
},
types::felt::FeltSequencer,
utils::{compute_starknet_address, split_u256},
};
use crate::evm_sequencer::{types::felt::FeltSequencer, utils::split_u256};
use crate::starknet_storage;

impl KakarotAccount {
Expand All @@ -31,32 +19,23 @@ impl KakarotAccount {
}
})?);

let starknet_address = compute_starknet_address(evm_address);
let starknet_address = ContractAddress::try_from(starknet_address)?;

let evm_address = TryInto::<FeltSequencer>::try_into(*evm_address)
.unwrap() // infallible
.into();

let mut storage = vec![
starknet_storage!("evm_address", evm_address),
starknet_storage!("is_initialized_", 1u8),
starknet_storage!("Ownable_owner", *KAKAROT_ADDRESS.0.key()),
starknet_storage!("bytecode_len_", code.len() as u32),
starknet_storage!("kakarot_address", *KAKAROT_ADDRESS.0.key()),
];

// Initialize the implementation and nonce based on account type.
// The account is an EOA if it has no bytecode and no storage (or all storage is zero).
let has_code_or_storage = !code.is_empty() || evm_storage.iter().any(|x| x.1 != U256::ZERO);
let account_type = if !has_code_or_storage {
storage.push(starknet_storage!("_implementation", EOA_CLASS_HASH.0));
AccountType::EOA
} else {
storage.append(&mut vec![
starknet_storage!("nonce", nonce),
starknet_storage!("_implementation", CONTRACT_ACCOUNT_CLASS_HASH.0),
]);
storage.append(&mut vec![starknet_storage!("nonce", nonce)]);
AccountType::Contract
};

Expand All @@ -83,9 +62,13 @@ impl KakarotAccount {
Ok(Self {
account_type,
storage,
starknet_address,
evm_address,
nonce: Nonce(nonce),
})
}

pub fn evm_address(&self) -> Address {
let evm_address = &self.evm_address.bytes()[12..];
Address::from_slice(evm_address)
}
}
31 changes: 9 additions & 22 deletions crates/ef-testing/src/evm_sequencer/account/v1.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use blockifier::abi::abi_utils::get_storage_var_address;
use reth_primitives::{Address, Bytes, U256};
use starknet_api::{
core::{ContractAddress, Nonce, PatriciaKey},
core::{Nonce, PatriciaKey},
hash::StarkFelt,
state::StorageKey,
StarknetApiError,
Expand All @@ -10,16 +10,9 @@ use starknet_crypto::{poseidon_hash_many, FieldElement};

use super::split_bytecode_to_starkfelt;
use super::{AccountType, KakarotAccount};
use crate::evm_sequencer::{
constants::CHAIN_ID,
types::felt::FeltSequencer,
utils::{compute_starknet_address, split_u256},
};
use crate::evm_sequencer::{types::felt::FeltSequencer, utils::split_u256};
use crate::{
evm_sequencer::{
constants::KAKAROT_ADDRESS,
evm_state::v1::{compute_storage_base_address, offset_storage_key},
},
evm_sequencer::evm_state::v1::{compute_storage_base_address, offset_storage_key},
starknet_storage,
};

Expand All @@ -36,26 +29,16 @@ impl KakarotAccount {
}
})?);

let starknet_address = compute_starknet_address(evm_address);
let starknet_address = ContractAddress::try_from(starknet_address)?;

let evm_address = TryInto::<FeltSequencer>::try_into(*evm_address)
.unwrap() // infallible
.into();

let mut storage = vec![
starknet_storage!("kakarot_core_address", *KAKAROT_ADDRESS.0.key()),
starknet_storage!("evm_address", evm_address),
];
let mut storage = vec![starknet_storage!("evm_address", evm_address)];

// Initialize the implementation and nonce based on account type.
// The account is an EOA if it has no bytecode and no storage (or all storage is zero).
let has_code_or_storage = !code.is_empty() || evm_storage.iter().any(|x| x.1 != U256::ZERO);
let account_type = if !has_code_or_storage {
storage.push((
get_storage_var_address("chain_id", &[]),
StarkFelt::from(*CHAIN_ID),
));
AccountType::EOA
} else {
storage.push(starknet_storage!("contract_account_nonce", nonce));
Expand Down Expand Up @@ -125,9 +108,13 @@ impl KakarotAccount {
Ok(Self {
account_type,
storage,
starknet_address,
evm_address,
nonce: Nonce(nonce),
})
}

pub fn evm_address(&self) -> Address {
let evm_address = &self.evm_address.bytes()[12..];
Address::from_slice(evm_address)
}
}
71 changes: 37 additions & 34 deletions crates/ef-testing/src/evm_sequencer/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,44 +59,47 @@ lazy_static! {
}

#[cfg(feature = "v0")]
pub mod kkrt_constants_v0 {
use super::*;

lazy_static! {
// Main contract classes v0
pub static ref KAKAROT_CLASS: LegacyContractClass = load_legacy_contract_class("../../build/v0/kakarot.json").expect("Failed to load Kakarot contract class");
pub static ref CONTRACT_ACCOUNT_CLASS: LegacyContractClass = load_legacy_contract_class("../../build/v0/contract_account.json").expect("Failed to load ContractAccount contract class");
pub static ref EOA_CLASS: LegacyContractClass = load_legacy_contract_class("../../build/v0/externally_owned_account.json").expect("Failed to load EOA contract class");
pub static ref PROXY_CLASS: LegacyContractClass = load_legacy_contract_class("../../build/v0/proxy.json").expect("Failed to load Proxy contract class");

// Main class hashes
pub static ref KAKAROT_CLASS_HASH: ClassHash = ClassHash(KAKAROT_CLASS.class_hash().unwrap().into());
pub static ref CONTRACT_ACCOUNT_CLASS_HASH: ClassHash = ClassHash(CONTRACT_ACCOUNT_CLASS.class_hash().unwrap().into());
pub static ref EOA_CLASS_HASH: ClassHash = ClassHash(EOA_CLASS.class_hash().unwrap().into());
pub static ref PROXY_CLASS_HASH: ClassHash = ClassHash(PROXY_CLASS.class_hash().unwrap().into());
}
lazy_static! {
// Main contract classes v0
pub static ref KAKAROT_CLASS: LegacyContractClass = load_legacy_contract_class("../../build/v0/kakarot.json").expect("Failed to load Kakarot contract class");
pub static ref CONTRACT_ACCOUNT_CLASS: LegacyContractClass = load_legacy_contract_class("../../build/v0/contract_account.json").expect("Failed to load ContractAccount contract class");
pub static ref EOA_CLASS: LegacyContractClass = load_legacy_contract_class("../../build/v0/externally_owned_account.json").expect("Failed to load EOA contract class");
pub static ref PROXY_CLASS: LegacyContractClass = load_legacy_contract_class("../../build/v0/proxy.json").expect("Failed to load Proxy contract class");

// Main class hashes
pub static ref KAKAROT_CLASS_HASH: ClassHash = ClassHash(KAKAROT_CLASS.class_hash().unwrap().into());
pub static ref CONTRACT_ACCOUNT_CLASS_HASH: ClassHash = ClassHash(CONTRACT_ACCOUNT_CLASS.class_hash().unwrap().into());
pub static ref EOA_CLASS_HASH: ClassHash = ClassHash(EOA_CLASS.class_hash().unwrap().into());
pub static ref PROXY_CLASS_HASH: ClassHash = ClassHash(PROXY_CLASS.class_hash().unwrap().into());
}

#[cfg(feature = "v1")]
pub mod kkrt_constants_v1 {
use super::*;
lazy_static! {
// Main contract classes v1
pub static ref KAKAROT_CLASS: CompiledClass = load_contract_class("../../build/v1/kakarot.json").expect("Failed to load Kakarot contract class");
pub static ref CONTRACT_ACCOUNT_CLASS: CompiledClass = load_contract_class("../../build/v1/contract_account.json").expect("Failed to load ContractAccount contract class");
pub static ref EOA_CLASS: CompiledClass = load_contract_class("../../build/v1/externally_owned_account.json").expect("Failed to load EOA contract class");
pub static ref UNINITIALIZED_ACCOUNT_CLASS: CompiledClass = load_contract_class("../../build/v1/uninitialized_account.json").expect("Failed to load uninitialized account contract class");

// Main class hashes
pub static ref KAKAROT_CLASS_HASH: ClassHash = ClassHash(KAKAROT_CLASS.class_hash().unwrap().into());
pub static ref CONTRACT_ACCOUNT_CLASS_HASH: ClassHash = ClassHash(CONTRACT_ACCOUNT_CLASS.class_hash().unwrap().into());
pub static ref EOA_CLASS_HASH: ClassHash = ClassHash(EOA_CLASS.class_hash().unwrap().into());
pub static ref UNINITIALIZED_ACCOUNT_CLASS_HASH: ClassHash = ClassHash(UNINITIALIZED_ACCOUNT_CLASS.class_hash().unwrap().into());
pub static ref PROXY_CLASS_HASH: ClassHash = *UNINITIALIZED_ACCOUNT_CLASS_HASH;

// v1 constants
pub static ref DEPLOY_FEE: StarkFelt = StarkFelt::from(0xabde1_u128);
}

lazy_static! {
// Main contract classes v1
pub static ref KAKAROT_CLASS: CompiledClass = load_contract_class("../../build/v1/kakarot.json").expect("Failed to load Kakarot contract class");
pub static ref CONTRACT_ACCOUNT_CLASS: CompiledClass = load_contract_class("../../build/v1/contract_account.json").expect("Failed to load ContractAccount contract class");
pub static ref EOA_CLASS: CompiledClass = load_contract_class("../../build/v1/externally_owned_account.json").expect("Failed to load EOA contract class");
pub static ref UNINITIALIZED_ACCOUNT_CLASS: CompiledClass = load_contract_class("../../build/v1/uninitialized_account.json").expect("Failed to load uninitialized account contract class");

// Main class hashes
pub static ref KAKAROT_CLASS_HASH: ClassHash = ClassHash(KAKAROT_CLASS.class_hash().unwrap().into());
pub static ref CONTRACT_ACCOUNT_CLASS_HASH: ClassHash = ClassHash(CONTRACT_ACCOUNT_CLASS.class_hash().unwrap().into());
pub static ref EOA_CLASS_HASH: ClassHash = ClassHash(EOA_CLASS.class_hash().unwrap().into());
pub static ref UNINITIALIZED_ACCOUNT_CLASS_HASH: ClassHash = ClassHash(UNINITIALIZED_ACCOUNT_CLASS.class_hash().unwrap().into());

// v1 constants
pub static ref DEPLOY_FEE: StarkFelt = StarkFelt::from(0xabde1_u128);
}
#[cfg(not(any(feature = "v0", feature = "v1")))]
lazy_static! {
pub static ref CONTRACT_ACCOUNT_CLASS_HASH: ClassHash =
panic!("Contract account class hash not defined, use features flag \"v0\" or \"v1\"");
pub static ref EOA_CLASS_HASH: ClassHash =
panic!("EOA class hash not defined, use features flag \"v0\" or \"v1\"");
pub static ref PROXY_CLASS_HASH: ClassHash =
panic!("Proxy class hash not defined, use features flag \"v0\" or \"v1\"");
}

#[cfg(test)]
Expand Down
Loading

0 comments on commit 97f50f1

Please sign in to comment.