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

feat: use lazy static and clone to init sequencer #609

Merged
merged 4 commits into from
Dec 7, 2023
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: 4 additions & 10 deletions crates/ef-testing/src/evm_sequencer/evm_state/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,25 +201,19 @@ impl Evm for KakarotSequencer {
#[cfg(test)]
mod tests {
use super::*;
use crate::evm_sequencer::{
constants::{
tests::{PRIVATE_KEY, PUBLIC_KEY, TEST_CONTRACT_ADDRESS},
CHAIN_ID,
},
sequencer::InitializeSequencer,
use crate::evm_sequencer::constants::{
tests::{PRIVATE_KEY, PUBLIC_KEY, TEST_CONTRACT_ADDRESS},
CHAIN_ID,
};
use blockifier::{abi::abi_utils::get_storage_var_address, state::state_api::StateReader};
use reth_primitives::{sign_message, AccessList, Signature, TransactionSigned, TxEip1559};
use revm_primitives::B256;
use sequencer::state::State as SequencerState;
use starknet_api::hash::StarkFelt;

#[test]
fn test_execute_simple_contract() {
// Given
let sequencer =
crate::evm_sequencer::sequencer::KakarotSequencer::new(SequencerState::default());
let mut sequencer = sequencer.initialize().unwrap();
let mut sequencer = crate::evm_sequencer::sequencer::KakarotSequencer::new();

let mut transaction = TransactionSigned {
hash: B256::default(),
Expand Down
15 changes: 5 additions & 10 deletions crates/ef-testing/src/evm_sequencer/evm_state/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,16 +269,12 @@ pub(crate) fn offset_storage_base_address(base_address: StorageKey, offset: i64)
#[cfg(test)]
mod tests {
use super::*;
use crate::evm_sequencer::{
constants::{
tests::{PRIVATE_KEY, PUBLIC_KEY, TEST_CONTRACT_ADDRESS},
CHAIN_ID,
},
sequencer::InitializeSequencer,
use crate::evm_sequencer::constants::{
tests::{PRIVATE_KEY, PUBLIC_KEY, TEST_CONTRACT_ADDRESS},
CHAIN_ID,
};
use reth_primitives::{sign_message, AccessList, Signature, TransactionSigned, TxEip1559};
use revm_primitives::B256;
use sequencer::state::State as SequencerState;
use starknet::core::types::FieldElement;
use starknet_api::hash::StarkFelt;

Expand All @@ -305,7 +301,7 @@ mod tests {
#[test]
fn test_store_bytecode() {
// Given
let mut sequencer = KakarotSequencer::new(SequencerState::default());
let mut sequencer = KakarotSequencer::new();
let bytecode = Bytes::from(vec![
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
Expand All @@ -331,8 +327,7 @@ mod tests {
#[test]
fn test_execute_simple_contract() {
// Given
let sequencer = KakarotSequencer::new(SequencerState::default());
let mut sequencer = sequencer.initialize().unwrap();
let mut sequencer = KakarotSequencer::new();

let mut transaction = TransactionSigned {
hash: B256::default(),
Expand Down
37 changes: 0 additions & 37 deletions crates/ef-testing/src/evm_sequencer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,3 @@ pub mod evm_state;
pub mod sequencer;
pub mod types;
pub mod utils;

use blockifier::state::errors::StateError;
use cairo_vm::types::errors::program_errors::ProgramError;

use self::types::contract_class::ContractClassConversionError;
use thiserror::Error;

type InitializationResult<T> = Result<T, InitializationError>;

#[derive(Debug, Error)]
pub enum InitializationError {
#[error(transparent)]
ClassConversionError(#[from] ContractClassConversionError),
#[error(transparent)]
ProgramError(#[from] ProgramError),
#[error(transparent)]
StateError(#[from] StateError),
}

#[cfg(test)]
mod tests {
use crate::evm_sequencer::sequencer::{InitializeSequencer, KakarotSequencer};
use ::sequencer::state::State;

#[test]
fn test_initialize() {
// Given
let state = State::default();
let sequencer = KakarotSequencer::new(state);

// When
let result = sequencer.initialize();

// Then
assert!(result.is_ok());
}
}
37 changes: 18 additions & 19 deletions crates/ef-testing/src/evm_sequencer/sequencer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,29 @@ use blockifier::transaction::{
};
use sequencer::{execution::Execution, sequencer::Sequencer, state::State};

use super::{constants::BLOCK_CONTEXT, InitializationResult};

/// Sequencer initialization interface. Initializes the sequencer state
/// by setting contract, its storage, declares all necessary classes and
/// deploys the fee token contract.
/// Default implementation is used when no feature flag is enabled.
pub trait InitializeSequencer {
fn initialize(self) -> InitializationResult<Self>
where
Self: Sized,
{
panic!("Not implemented, use features flag \"v0\" or \"v1\"")
}
}

#[cfg(not(any(feature = "v0", feature = "v1")))]
impl InitializeSequencer for KakarotSequencer {}
use super::constants::BLOCK_CONTEXT;

/// Kakarot wrapper around a sequencer.
#[derive(Clone)]
pub(crate) struct KakarotSequencer(Sequencer<State>);

impl KakarotSequencer {
pub fn new(state: State) -> Self {
let sequencer = Sequencer::new(BLOCK_CONTEXT.clone(), state);
pub fn new() -> Self {
let initial_state = {
#[cfg(feature = "v0")]
{
v0::INITIAL_SEQUENCER_STATE.clone()
}
#[cfg(feature = "v1")]
{
v1::INITIAL_SEQUENCER_STATE.clone()
}
#[cfg(not(any(feature = "v0", feature = "v1")))]
greged93 marked this conversation as resolved.
Show resolved Hide resolved
{
State::default()
}
};
let sequencer = Sequencer::new(BLOCK_CONTEXT.clone(), initial_state);
Self(sequencer)
}
}
Expand Down
49 changes: 24 additions & 25 deletions crates/ef-testing/src/evm_sequencer/sequencer/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use blockifier::{
execution::contract_class::{ContractClass, ContractClassV0},
};
use cairo_vm::types::errors::program_errors::ProgramError;
use lazy_static::lazy_static;
use starknet::core::types::contract::legacy::LegacyContractClass;

use crate::evm_sequencer::{
Expand All @@ -18,13 +19,13 @@ use crate::evm_sequencer::{
ETH_FEE_TOKEN_ADDRESS, FEE_TOKEN_CLASS, FEE_TOKEN_CLASS_HASH, KAKAROT_ADDRESS,
KAKAROT_OWNER_ADDRESS,
},
InitializationError,
};
use sequencer::state::State as SequencerState;

use super::{InitializationResult, InitializeSequencer, KakarotSequencer};
lazy_static! {
pub static ref INITIAL_SEQUENCER_STATE: SequencerState = {
let mut state = SequencerState::default();

impl InitializeSequencer for KakarotSequencer {
fn initialize(mut self) -> InitializationResult<Self> {
let storage = [
("Ownable_owner", *KAKAROT_OWNER_ADDRESS.0.key()),
("native_token_address", *ETH_FEE_TOKEN_ADDRESS.0.key()),
Expand All @@ -35,37 +36,35 @@ impl InitializeSequencer for KakarotSequencer {

// Write all the storage vars to the sequencer state.
for (k, v) in storage {
(&mut self.state).set_storage_at(*KAKAROT_ADDRESS, get_storage_var_address(k, &[]), v);
(&mut state).set_storage_at(*KAKAROT_ADDRESS, get_storage_var_address(k, &[]), v);
}

// Write the kakarot class and class hash.
(&mut self.state).set_class_hash_at(*KAKAROT_ADDRESS, *KAKAROT_CLASS_HASH)?;
(&mut self.state)
.set_contract_class(&KAKAROT_CLASS_HASH, convert_contract_class(&KAKAROT_CLASS)?)?;
(&mut state).set_class_hash_at(*KAKAROT_ADDRESS, *KAKAROT_CLASS_HASH).expect("Failed to set kakarot class hash");
(&mut state)
.set_contract_class(&KAKAROT_CLASS_HASH, convert_contract_class(&KAKAROT_CLASS).expect("Failed to convert KAKAROT CLASS to contract class")).expect("Failed to set kakarot contract class");

// Write proxy, eoa, contract account and erc20 classes and class hashes.
(&mut self.state)
.set_contract_class(&PROXY_CLASS_HASH, convert_contract_class(&PROXY_CLASS)?)?;
(&mut self.state).set_contract_class(
(&mut state)
.set_contract_class(&PROXY_CLASS_HASH, convert_contract_class(&PROXY_CLASS).expect("Failed to convert PROXY CLASS to contract class")).expect("Failed to set proxy contract class");
(&mut state).set_contract_class(
&CONTRACT_ACCOUNT_CLASS_HASH,
convert_contract_class(&CONTRACT_ACCOUNT_CLASS)?,
)?;
(&mut self.state)
.set_contract_class(&EOA_CLASS_HASH, convert_contract_class(&EOA_CLASS)?)?;
(&mut self.state).set_contract_class(
convert_contract_class(&CONTRACT_ACCOUNT_CLASS).expect("Failed to convert CONTRACT ACCOUNT CLASS to contract class"),
).expect("Failed to set contract account class");
(&mut state)
.set_contract_class(&EOA_CLASS_HASH, convert_contract_class(&EOA_CLASS).expect("Failed to convert EOA CLASS to contract class")).expect("Failed to set eoa contract class");
(&mut state).set_contract_class(
&FEE_TOKEN_CLASS_HASH,
convert_contract_class(&FEE_TOKEN_CLASS)?,
)?;
(&mut self.state).set_class_hash_at(*ETH_FEE_TOKEN_ADDRESS, *FEE_TOKEN_CLASS_HASH)?;
convert_contract_class(&FEE_TOKEN_CLASS).expect("Failed to convert FEE TOKEN CLASS to contract class"),
).expect("Failed to set sequencer contract class");
(&mut state).set_class_hash_at(*ETH_FEE_TOKEN_ADDRESS, *FEE_TOKEN_CLASS_HASH).expect("Failed to set fee token class hash");

Ok(self)
}
state
};
}

fn convert_contract_class(
class: &LegacyContractClass,
) -> Result<ContractClass, InitializationError> {
Result::<ContractClass, InitializationError>::Ok(ContractClass::V0(
fn convert_contract_class(class: &LegacyContractClass) -> Result<ContractClass, eyre::Error> {
Result::<ContractClass, eyre::Error>::Ok(ContractClass::V0(
ContractClassV0::try_from_json_string(
&serde_json::to_string(class).map_err(ProgramError::Parse)?,
)?,
Expand Down
59 changes: 30 additions & 29 deletions crates/ef-testing/src/evm_sequencer/sequencer/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use blockifier::{
};
use cairo_lang_starknet::casm_contract_class::CasmContractClass;
use cairo_vm::types::errors::program_errors::ProgramError;
use starknet::core::types::contract::CompiledClass;
use lazy_static::lazy_static;
use starknet::core::types::contract::{legacy::LegacyContractClass, CompiledClass};
use starknet_api::hash::StarkFelt;

use crate::evm_sequencer::{
Expand All @@ -19,16 +20,13 @@ use crate::evm_sequencer::{
KAKAROT_OWNER_ADDRESS,
},
types::contract_class::CasmContractClassWrapper,
InitializationError, InitializationResult,
};
use sequencer::state::State as SequencerState;

use super::{InitializeSequencer, KakarotSequencer};
lazy_static! {
pub static ref INITIAL_SEQUENCER_STATE: SequencerState = {
let mut state = SequencerState::default();

impl InitializeSequencer for KakarotSequencer {
fn initialize(mut self) -> InitializationResult<Self>
where
Self: Sized,
{
let storage = [
("owner", *KAKAROT_OWNER_ADDRESS.0.key()),
("chain_id", StarkFelt::from(*CHAIN_ID)),
Expand All @@ -41,39 +39,42 @@ impl InitializeSequencer for KakarotSequencer {

// Write all the storage vars to the sequencer state.
for (k, v) in storage {
(&mut self.state).set_storage_at(*KAKAROT_ADDRESS, get_storage_var_address(k, &[]), v);
(&mut state).set_storage_at(*KAKAROT_ADDRESS, get_storage_var_address(k, &[]), v);
}

// Write the kakarot class and class hash.
(&mut self.state).set_class_hash_at(*KAKAROT_ADDRESS, *KAKAROT_CLASS_HASH)?;
(&mut self.state)
.set_contract_class(&KAKAROT_CLASS_HASH, convert_contract_class(&KAKAROT_CLASS)?)?;
(&mut state).set_class_hash_at(*KAKAROT_ADDRESS, *KAKAROT_CLASS_HASH).expect("Failed to set kakarot class hash");
(&mut state)
.set_contract_class(&KAKAROT_CLASS_HASH, convert_contract_class(&KAKAROT_CLASS).expect("Failed to convert KAKAROT CLASS to contract class")).expect("Failed to set kakarot contract class");

// Write eoa, contract account and uninitialized account.
(&mut self.state).set_contract_class(
(&mut state).set_contract_class(
&CONTRACT_ACCOUNT_CLASS_HASH,
convert_contract_class(&CONTRACT_ACCOUNT_CLASS)?,
)?;
(&mut self.state)
.set_contract_class(&EOA_CLASS_HASH, convert_contract_class(&EOA_CLASS)?)?;
(&mut self.state).set_contract_class(
convert_contract_class(&CONTRACT_ACCOUNT_CLASS).expect("Failed to convert CONTRACT ACCOUNT CLASS to contract class"),
).expect("Failed to set contract account class");
(&mut state)
.set_contract_class(&EOA_CLASS_HASH, convert_contract_class(&EOA_CLASS).expect("Failed to convert EOA CLASS to contract class")).expect("Failed to set eoa contract class");
(&mut state).set_contract_class(
&UNINITIALIZED_ACCOUNT_CLASS_HASH,
convert_contract_class(&UNINITIALIZED_ACCOUNT_CLASS)?,
)?;
convert_contract_class(&UNINITIALIZED_ACCOUNT_CLASS).expect("Failed to convert UNINITIALIZED ACCOUNT CLASS to contract class"),
).expect("Failed to set uninitialized account class");

(&mut self.state).set_contract_class(
let convert_class = |class: &LegacyContractClass| -> Result<ContractClass, eyre::Error> {
greged93 marked this conversation as resolved.
Show resolved Hide resolved
Ok(ContractClass::V0(ContractClassV0::try_from_json_string(
&serde_json::to_string(&class).map_err(ProgramError::Parse)?,
)?))
};
(&mut state).set_contract_class(
&FEE_TOKEN_CLASS_HASH,
ContractClass::V0(ContractClassV0::try_from_json_string(
&serde_json::to_string(&*FEE_TOKEN_CLASS).map_err(ProgramError::Parse)?,
)?),
)?;
(&mut self.state).set_class_hash_at(*ETH_FEE_TOKEN_ADDRESS, *FEE_TOKEN_CLASS_HASH)?;
convert_class(&FEE_TOKEN_CLASS).expect("Failed to convert FEE TOKEN CLASS to contract class"),
).expect("Failed to set fee token contract class");
(&mut state).set_class_hash_at(*ETH_FEE_TOKEN_ADDRESS, *FEE_TOKEN_CLASS_HASH).expect("Failed to set fee token class hash");

Ok(self)
}
state
};
}

fn convert_contract_class(class: &CompiledClass) -> Result<ContractClass, InitializationError> {
fn convert_contract_class(class: &CompiledClass) -> Result<ContractClass, eyre::Error> {
let casm_contract_class = CasmContractClassWrapper::try_from(class)?;
let casm_contract_class: CasmContractClass = casm_contract_class.into();
Ok(ContractClass::V1(ContractClassV1::try_from(
Expand Down
9 changes: 2 additions & 7 deletions crates/ef-testing/src/models/case.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// Inspired by https://github.com/paradigmxyz/reth/tree/main/testing/ef-tests

use super::error::RunnerError;
use super::result::log_execution_result;
use crate::evm_sequencer::evm_state::Evm;
use crate::evm_sequencer::sequencer::{InitializeSequencer, KakarotSequencer};
use crate::evm_sequencer::sequencer::KakarotSequencer;
use crate::{
evm_sequencer::{account::KakarotAccount, constants::CHAIN_ID},
traits::Case,
Expand All @@ -17,7 +16,6 @@ use ethers_signers::{LocalWallet, Signer};
use reth_primitives::{sign_message, SealedBlock};
use reth_rlp::Decodable as _;
use revm_primitives::B256;
use sequencer::state::State as SequencerState;

#[derive(Debug)]
pub struct BlockchainTestCase {
Expand Down Expand Up @@ -192,15 +190,12 @@ impl BlockchainTestCase {
#[async_trait]
impl Case for BlockchainTestCase {
fn run(&self) -> Result<(), RunnerError> {
let sequencer = KakarotSequencer::new(SequencerState::default());
let mut sequencer = sequencer.initialize()?;
let mut sequencer = KakarotSequencer::new();

self.handle_pre_state(&mut sequencer)?;

// handle transaction
self.handle_transaction(&mut sequencer)?;

// handle post state
self.handle_post_state(&mut sequencer)?;
Ok(())
}
Expand Down
5 changes: 0 additions & 5 deletions crates/ef-testing/src/models/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ use starknet::{
};
use starknet_api::StarknetApiError;

use crate::evm_sequencer::InitializationError;

/// Error type based off <https://github.com/paradigmxyz/reth/blob/main/testing/ef-tests/src/result.rs>
#[derive(Debug, thiserror::Error)]
pub enum RunnerError {
Expand All @@ -29,9 +27,6 @@ pub enum RunnerError {
/// The specific error
error: String,
},
/// Sequencer initialization error
#[error("An error occurred while initializing the sequencer: {0}")]
InitializationError(#[from] InitializationError),
/// Sequencer error
#[error("An error occurred while running the sequencer: {0}")]
SequencerError(#[from] StateError),
Expand Down
1 change: 1 addition & 0 deletions crates/sequencer/src/sequencer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use starknet_api::core::ContractAddress;
/// must implement State and `StateReader`. The `for` keyword
/// indicates that the bound must hold for any lifetime 'any.
/// For more details, check out [rust-lang docs](https://doc.rust-lang.org/nomicon/hrtb.html)
#[derive(Clone)]
pub struct Sequencer<S>
where
for<'any> &'any mut S: State + StateReader,
Expand Down
Loading