From 5ac6e5708a1bb02c3678164d52734d49de316c2b Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Mon, 6 Jan 2025 14:49:10 -0500 Subject: [PATCH 1/6] refactor: store genesis in ChainSpec as its JSON repr --- Cargo.lock | 1 + crates/katana/chain-spec/Cargo.toml | 3 + crates/katana/chain-spec/src/lib.rs | 97 ++++++++++++-------- crates/katana/primitives/src/genesis/json.rs | 96 +++++++++++++++++++ crates/katana/primitives/src/genesis/mod.rs | 1 - 5 files changed, 157 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40cf285b3e..8607ae25c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8491,6 +8491,7 @@ dependencies = [ "serde", "serde_json", "starknet 0.12.0", + "tempfile", "url", ] diff --git a/crates/katana/chain-spec/Cargo.toml b/crates/katana/chain-spec/Cargo.toml index 96ae05dcaf..294e94dd32 100644 --- a/crates/katana/chain-spec/Cargo.toml +++ b/crates/katana/chain-spec/Cargo.toml @@ -16,5 +16,8 @@ serde_json.workspace = true starknet.workspace = true url.workspace = true +[dev-dependencies] +tempfile.workspace = true + [features] controller = [ "katana-primitives/controller" ] diff --git a/crates/katana/chain-spec/src/lib.rs b/crates/katana/chain-spec/src/lib.rs index 3da189d86f..86c2ade3bf 100644 --- a/crates/katana/chain-spec/src/lib.rs +++ b/crates/katana/chain-spec/src/lib.rs @@ -10,20 +10,21 @@ use katana_primitives::chain::ChainId; use katana_primitives::class::ClassHash; use katana_primitives::contract::ContractAddress; use katana_primitives::da::L1DataAvailabilityMode; +use katana_primitives::genesis::Genesis; use katana_primitives::genesis::allocation::{DevAllocationsGenerator, GenesisAllocation}; use katana_primitives::genesis::constant::{ - get_fee_token_balance_base_storage_address, DEFAULT_ACCOUNT_CLASS_PUBKEY_STORAGE_SLOT, - DEFAULT_ETH_FEE_TOKEN_ADDRESS, DEFAULT_LEGACY_ERC20_CLASS, DEFAULT_LEGACY_ERC20_CLASS_HASH, - DEFAULT_LEGACY_UDC_CLASS, DEFAULT_LEGACY_UDC_CLASS_HASH, - DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, DEFAULT_PREFUNDED_ACCOUNT_BALANCE, - DEFAULT_STRK_FEE_TOKEN_ADDRESS, DEFAULT_UDC_ADDRESS, ERC20_DECIMAL_STORAGE_SLOT, - ERC20_NAME_STORAGE_SLOT, ERC20_SYMBOL_STORAGE_SLOT, ERC20_TOTAL_SUPPLY_STORAGE_SLOT, + DEFAULT_ACCOUNT_CLASS_PUBKEY_STORAGE_SLOT, DEFAULT_ETH_FEE_TOKEN_ADDRESS, + DEFAULT_LEGACY_ERC20_CLASS, DEFAULT_LEGACY_ERC20_CLASS_HASH, DEFAULT_LEGACY_UDC_CLASS, + DEFAULT_LEGACY_UDC_CLASS_HASH, DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, + DEFAULT_PREFUNDED_ACCOUNT_BALANCE, DEFAULT_STRK_FEE_TOKEN_ADDRESS, DEFAULT_UDC_ADDRESS, + ERC20_DECIMAL_STORAGE_SLOT, ERC20_NAME_STORAGE_SLOT, ERC20_SYMBOL_STORAGE_SLOT, + ERC20_TOTAL_SUPPLY_STORAGE_SLOT, get_fee_token_balance_base_storage_address, }; -use katana_primitives::genesis::Genesis; +use katana_primitives::genesis::json::GenesisJson; use katana_primitives::state::StateUpdatesWithClasses; use katana_primitives::utils::split_u256; -use katana_primitives::version::{ProtocolVersion, CURRENT_STARKNET_VERSION}; -use katana_primitives::{eth, Felt}; +use katana_primitives::version::{CURRENT_STARKNET_VERSION, ProtocolVersion}; +use katana_primitives::{Felt, eth}; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use starknet::core::utils::cairo_short_string_to_felt; @@ -31,6 +32,7 @@ use url::Url; /// The rollup chain specification. #[derive(Debug, Clone)] +#[cfg_attr(test, derive(PartialEq))] pub struct ChainSpec { /// The rollup network chain id. pub id: ChainId, @@ -54,6 +56,7 @@ pub struct ChainSpec { /// supported on Starknet. // TODO: include both l1 and l2 addresses #[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(test, derive(PartialEq))] pub struct FeeContracts { /// L2 ETH fee token address. Used for paying pre-V3 transactions. pub eth: ContractAddress, @@ -62,6 +65,7 @@ pub struct FeeContracts { } #[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(test, derive(PartialEq))] #[serde(tag = "type", rename_all = "camelCase")] pub enum SettlementLayer { Ethereum { @@ -103,7 +107,10 @@ impl ChainSpec { let cs = serde_json::from_str::(&content)?; let file = File::open(&cs.genesis).context("failed to open genesis file")?; - let genesis: Genesis = serde_json::from_reader(BufReader::new(file))?; + + // the genesis file is stored as its JSON representation + let genesis_json: GenesisJson = serde_json::from_reader(BufReader::new(file))?; + let genesis = Genesis::try_from(genesis_json)?; Ok(Self { genesis, @@ -127,8 +134,11 @@ impl ChainSpec { fee_contracts: self.fee_contracts, }; + // convert the genesis to its JSON representation and store it + let genesis_json = GenesisJson::try_from(self.genesis)?; + serde_json::to_writer_pretty(File::create(cfg_path)?, &stored)?; - serde_json::to_writer_pretty(File::create(stored.genesis)?, &self.genesis)?; + serde_json::to_writer_pretty(File::create(stored.genesis)?, &genesis_json)?; Ok(()) } @@ -350,6 +360,7 @@ mod tests { use katana_primitives::address; use katana_primitives::block::{Block, GasPrices, Header}; use katana_primitives::da::L1DataAvailabilityMode; + use katana_primitives::genesis::GenesisClass; use katana_primitives::genesis::allocation::{ GenesisAccount, GenesisAccountAlloc, GenesisContractAlloc, }; @@ -361,46 +372,52 @@ mod tests { DEFAULT_LEGACY_ERC20_CLASS, DEFAULT_LEGACY_ERC20_COMPILED_CLASS_HASH, DEFAULT_LEGACY_UDC_CLASS, DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, }; - use katana_primitives::genesis::GenesisClass; use katana_primitives::version::CURRENT_STARKNET_VERSION; use starknet::macros::felt; use super::*; + #[test] + fn chainspec_load_store_rt() { + let chainspec = ChainSpec::default(); + + // Create a temporary file and store the ChainSpec + let temp = tempfile::NamedTempFile::new().unwrap(); + chainspec.clone().store(temp.path()).unwrap(); + + // Load the ChainSpec back from the file + let loaded_chainspec = ChainSpec::load(temp.path()).unwrap(); + + // Assert that the loaded ChainSpec matches the original + assert_eq!(chainspec.id, loaded_chainspec.id); + assert_eq!(chainspec.version, loaded_chainspec.version); + assert_eq!(chainspec.settlement, loaded_chainspec.settlement); + assert_eq!(chainspec.fee_contracts, loaded_chainspec.fee_contracts); + assert_eq!(chainspec.genesis, loaded_chainspec.genesis); + } + #[test] fn genesis_block_and_state_updates() { // setup initial states to test let classes = BTreeMap::from([ - ( - DEFAULT_LEGACY_UDC_CLASS_HASH, - GenesisClass { - class: DEFAULT_LEGACY_UDC_CLASS.clone().into(), - compiled_class_hash: DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, - }, - ), - ( - DEFAULT_LEGACY_ERC20_CLASS_HASH, - GenesisClass { - class: DEFAULT_LEGACY_ERC20_CLASS.clone().into(), - compiled_class_hash: DEFAULT_LEGACY_ERC20_COMPILED_CLASS_HASH, - }, - ), - ( - DEFAULT_ACCOUNT_CLASS_HASH, - GenesisClass { - compiled_class_hash: DEFAULT_ACCOUNT_COMPILED_CLASS_HASH, - class: DEFAULT_ACCOUNT_CLASS.clone().into(), - }, - ), + (DEFAULT_LEGACY_UDC_CLASS_HASH, GenesisClass { + class: DEFAULT_LEGACY_UDC_CLASS.clone().into(), + compiled_class_hash: DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, + }), + (DEFAULT_LEGACY_ERC20_CLASS_HASH, GenesisClass { + class: DEFAULT_LEGACY_ERC20_CLASS.clone().into(), + compiled_class_hash: DEFAULT_LEGACY_ERC20_COMPILED_CLASS_HASH, + }), + (DEFAULT_ACCOUNT_CLASS_HASH, GenesisClass { + compiled_class_hash: DEFAULT_ACCOUNT_COMPILED_CLASS_HASH, + class: DEFAULT_ACCOUNT_CLASS.clone().into(), + }), #[cfg(feature = "controller")] - ( - CONTROLLER_CLASS_HASH, - GenesisClass { - compiled_class_hash: CONTROLLER_CLASS_HASH, - class: CONTROLLER_ACCOUNT_CLASS.clone().into(), - }, - ), + (CONTROLLER_CLASS_HASH, GenesisClass { + compiled_class_hash: CONTROLLER_CLASS_HASH, + class: CONTROLLER_ACCOUNT_CLASS.clone().into(), + }), ]); let allocations = [ diff --git a/crates/katana/primitives/src/genesis/json.rs b/crates/katana/primitives/src/genesis/json.rs index 837a6ae107..e8e8f8b8e2 100644 --- a/crates/katana/primitives/src/genesis/json.rs +++ b/crates/katana/primitives/src/genesis/json.rs @@ -473,6 +473,86 @@ impl TryFrom for Genesis { } } +impl TryFrom for GenesisJson { + type Error = GenesisJsonError; + + fn try_from(value: Genesis) -> Result { + let mut contracts = BTreeMap::new(); + let mut accounts = BTreeMap::new(); + let mut classes = Vec::new(); + + for (hash, class) in value.classes { + // Convert the class to an artifact Value + let artifact = match &*class.class { + ContractClass::Legacy(casm) => serde_json::to_value(casm)?, + ContractClass::Class(sierra) => serde_json::to_value(sierra)?, + }; + + classes.push(GenesisClassJson { + class: PathOrFullArtifact::Artifact(artifact), + class_hash: Some(hash), + name: None, + }); + } + + for (address, allocation) in value.allocations { + match allocation { + GenesisAllocation::Account(account) => match account { + GenesisAccountAlloc::Account(acc) => { + accounts.insert( + address, + GenesisAccountJson { + nonce: acc.nonce, + private_key: None, + storage: acc.storage, + balance: acc.balance, + public_key: acc.public_key, + class: Some(ClassNameOrHash::Hash(acc.class_hash)), + }, + ); + } + GenesisAccountAlloc::DevAccount(dev_acc) => { + accounts.insert( + address, + GenesisAccountJson { + nonce: dev_acc.inner.nonce, + balance: dev_acc.inner.balance, + storage: dev_acc.inner.storage, + public_key: dev_acc.inner.public_key, + private_key: Some(dev_acc.private_key), + class: Some(ClassNameOrHash::Hash(dev_acc.inner.class_hash)), + }, + ); + } + }, + GenesisAllocation::Contract(contract) => { + contracts.insert( + address, + GenesisContractJson { + nonce: contract.nonce, + balance: contract.balance, + storage: contract.storage, + class: contract.class_hash.map(ClassNameOrHash::Hash), + }, + ); + } + } + } + + Ok(GenesisJson { + parent_hash: value.parent_hash, + state_root: value.state_root, + number: value.number, + timestamp: value.timestamp, + sequencer_address: value.sequencer_address, + gas_prices: value.gas_prices, + classes, + accounts, + contracts, + }) + } +} + impl FromStr for GenesisJson { type Err = GenesisJsonError; fn from_str(s: &str) -> Result { @@ -858,6 +938,22 @@ mod tests { } } + // We don't care what the intermediate JSON format looks like as long as the + // conversion back and forth between GenesisJson and Genesis results in equivalent Genesis + // structs + #[test] + fn genesis_conversion_rt() { + let path = PathBuf::from("./src/genesis/test-genesis.json"); + + let json = GenesisJson::load(path).unwrap(); + let genesis = Genesis::try_from(json.clone()).unwrap(); + + let json_again = GenesisJson::try_from(genesis.clone()).unwrap(); + let genesis_again = Genesis::try_from(json_again.clone()).unwrap(); + + similar_asserts::assert_eq!(genesis, genesis_again); + } + #[test] fn default_genesis_try_from_json() { let json = r#" diff --git a/crates/katana/primitives/src/genesis/mod.rs b/crates/katana/primitives/src/genesis/mod.rs index a057b2d734..582b354fe0 100644 --- a/crates/katana/primitives/src/genesis/mod.rs +++ b/crates/katana/primitives/src/genesis/mod.rs @@ -40,7 +40,6 @@ impl core::fmt::Debug for GenesisClass { } /// Genesis block configuration. -#[serde_with::serde_as] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Genesis { /// The genesis block parent hash. From 874c2783af8089496cc16cf7beb9262b5896bc5c Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Mon, 6 Jan 2025 15:35:43 -0500 Subject: [PATCH 2/6] use similar_asserts for easier debugging --- Cargo.lock | 1 + crates/katana/chain-spec/Cargo.toml | 1 + crates/katana/chain-spec/src/lib.rs | 24 ++---------------------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8607ae25c0..99a02c4b0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8490,6 +8490,7 @@ dependencies = [ "lazy_static", "serde", "serde_json", + "similar-asserts", "starknet 0.12.0", "tempfile", "url", diff --git a/crates/katana/chain-spec/Cargo.toml b/crates/katana/chain-spec/Cargo.toml index 294e94dd32..6657aeb3e5 100644 --- a/crates/katana/chain-spec/Cargo.toml +++ b/crates/katana/chain-spec/Cargo.toml @@ -17,6 +17,7 @@ starknet.workspace = true url.workspace = true [dev-dependencies] +similar-asserts.workspace = true tempfile.workspace = true [features] diff --git a/crates/katana/chain-spec/src/lib.rs b/crates/katana/chain-spec/src/lib.rs index 86c2ade3bf..5d9d059a70 100644 --- a/crates/katana/chain-spec/src/lib.rs +++ b/crates/katana/chain-spec/src/lib.rs @@ -388,12 +388,7 @@ mod tests { // Load the ChainSpec back from the file let loaded_chainspec = ChainSpec::load(temp.path()).unwrap(); - // Assert that the loaded ChainSpec matches the original - assert_eq!(chainspec.id, loaded_chainspec.id); - assert_eq!(chainspec.version, loaded_chainspec.version); - assert_eq!(chainspec.settlement, loaded_chainspec.settlement); - assert_eq!(chainspec.fee_contracts, loaded_chainspec.fee_contracts); - assert_eq!(chainspec.genesis, loaded_chainspec.genesis); + similar_asserts::assert_eq!(chainspec, loaded_chainspec); } #[test] @@ -505,22 +500,7 @@ mod tests { let actual_block = chain_spec.block(); let actual_state_updates = chain_spec.state_updates(); - // assert individual fields of the block - - assert_eq!(actual_block.header.number, expected_block.header.number); - assert_eq!(actual_block.header.timestamp, expected_block.header.timestamp); - assert_eq!(actual_block.header.parent_hash, expected_block.header.parent_hash); - assert_eq!(actual_block.header.sequencer_address, expected_block.header.sequencer_address); - assert_eq!(actual_block.header.l1_gas_prices, expected_block.header.l1_gas_prices); - assert_eq!( - actual_block.header.l1_data_gas_prices, - expected_block.header.l1_data_gas_prices - ); - assert_eq!(actual_block.header.l1_da_mode, expected_block.header.l1_da_mode); - assert_eq!(actual_block.header.protocol_version, expected_block.header.protocol_version); - assert_eq!(actual_block.header.transaction_count, expected_block.header.transaction_count); - assert_eq!(actual_block.header.events_count, expected_block.header.events_count); - assert_eq!(actual_block.body, expected_block.body); + similar_asserts::assert_eq!(actual_block, expected_block); if cfg!(feature = "controller") { assert!(actual_state_updates.classes.len() == 4); From 08f4c3da9f5be3c3265a2f6e73ffd3b1c5f4b195 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Tue, 7 Jan 2025 11:54:09 -0500 Subject: [PATCH 3/6] refactor: simplify genesis class parsing logic --- crates/katana/primitives/src/class.rs | 4 ++ crates/katana/primitives/src/genesis/json.rs | 60 +++++++++----------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/crates/katana/primitives/src/class.rs b/crates/katana/primitives/src/class.rs index fcf25e62c0..5a8c127922 100644 --- a/crates/katana/primitives/src/class.rs +++ b/crates/katana/primitives/src/class.rs @@ -28,6 +28,10 @@ pub enum ContractClassCompilationError { SierraCompilation(#[from] StarknetSierraCompilationError), } +// NOTE: +// Ideally, we can implement this enum as an untagged `serde` enum, so that we can deserialize from +// the raw JSON class artifact directly into this (ie +// `serde_json::from_str::(json)`). But that is not possible due to a limitation with untagged enums derivation (see https://github.com/serde-rs/serde/pull/2781). #[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] diff --git a/crates/katana/primitives/src/genesis/json.rs b/crates/katana/primitives/src/genesis/json.rs index e8e8f8b8e2..0e37a5dffa 100644 --- a/crates/katana/primitives/src/genesis/json.rs +++ b/crates/katana/primitives/src/genesis/json.rs @@ -13,13 +13,11 @@ use std::sync::Arc; use alloy_primitives::U256; use base64::prelude::*; use katana_cairo::cairo_vm::types::errors::program_errors::ProgramError; -use katana_cairo::lang::starknet_classes::casm_contract_class::StarknetSierraCompilationError; use serde::de::value::MapAccessDeserializer; use serde::de::Visitor; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; -use starknet::core::types::contract::legacy::LegacyContractClass; -use starknet::core::types::contract::{ComputeClassHashError, JsonError}; +use starknet::core::types::contract::JsonError; use super::allocation::{ DevGenesisAccount, GenesisAccount, GenesisAccountAlloc, GenesisContractAlloc, @@ -31,10 +29,12 @@ use super::constant::{ }; use super::{Genesis, GenesisAllocation}; use crate::block::{BlockHash, BlockNumber, GasPrices}; -use crate::class::{ClassHash, ContractClass, SierraContractClass}; +use crate::class::{ + ClassHash, ComputeClassHashError, ContractClass, ContractClassCompilationError, + LegacyContractClass, SierraContractClass, +}; use crate::contract::{ContractAddress, StorageKey, StorageValue}; use crate::genesis::GenesisClass; -use crate::utils::class::{parse_compiled_class_v1, parse_deprecated_compiled_class}; use crate::Felt; type Object = Map; @@ -175,9 +175,6 @@ pub enum GenesisJsonError { #[error(transparent)] ComputeClassHash(#[from] ComputeClassHashError), - #[error(transparent)] - SierraCompilation(#[from] StarknetSierraCompilationError), - #[error(transparent)] ProgramError(#[from] ProgramError), @@ -202,6 +199,9 @@ pub enum GenesisJsonError { #[error("Class name '{0}' not found in the genesis classes")] UnknownClassName(String), + #[error(transparent)] + ContractClassCompilation(#[from] ContractClassCompilationError), + #[error(transparent)] Other(#[from] anyhow::Error), } @@ -309,36 +309,28 @@ impl TryFrom for Genesis { } }; - let sierra = serde_json::from_value::(artifact.clone()); - - let (class_hash, compiled_class_hash, class) = match sierra { - Ok(sierra) => { - let casm = parse_compiled_class_v1(artifact)?; + let (class_hash, compiled_class_hash, class) = + match serde_json::from_value::(artifact.clone()) { + Ok(class) => { + let class = ContractClass::Class(class); + let class_hash = + if let Some(hash) = class_hash { hash } else { class.class_hash()? }; + let compiled_hash = class.clone().compile()?.class_hash()?; - // check if the class hash is provided, otherwise compute it from the - // artifacts - let class = ContractClass::Class(sierra); - let class_hash = class_hash - .unwrap_or_else(|| class.class_hash().expect("failed to compute hash")); - let compiled_hash = casm.compiled_class_hash(); - - (class_hash, compiled_hash, Arc::new(class)) - } + (class_hash, compiled_hash, Arc::new(class)) + } - // if the artifact is not a sierra contract, we check if it's a legacy contract - Err(_) => { - let casm = parse_deprecated_compiled_class(artifact.clone())?; + // if the artifact is not a sierra contract, we check if it's a legacy contract + Err(_) => { + let class = serde_json::from_value::(artifact)?; - let class_hash = if let Some(class_hash) = class_hash { - class_hash - } else { - let casm: LegacyContractClass = serde_json::from_value(artifact.clone())?; - casm.class_hash()? - }; + let class = ContractClass::Legacy(class); + let class_hash = + if let Some(hash) = class_hash { hash } else { class.class_hash()? }; - (class_hash, class_hash, Arc::new(ContractClass::Legacy(casm))) - } - }; + (class_hash, class_hash, Arc::new(class)) + } + }; // if the class has a name, we add it to the lookup table to use later when we're // parsing the contracts From b02659dae361fcacede574f44c3419a06e66dabd Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Tue, 7 Jan 2025 13:05:53 -0500 Subject: [PATCH 4/6] fix: compute controller compiled hash --- crates/katana/primitives/src/genesis/json.rs | 28 ++++++++++++-------- crates/katana/primitives/src/genesis/mod.rs | 7 ++++- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/crates/katana/primitives/src/genesis/json.rs b/crates/katana/primitives/src/genesis/json.rs index 0e37a5dffa..f790dd7c7e 100644 --- a/crates/katana/primitives/src/genesis/json.rs +++ b/crates/katana/primitives/src/genesis/json.rs @@ -286,16 +286,22 @@ impl TryFrom for Genesis { let mut classes: BTreeMap = BTreeMap::new(); #[cfg(feature = "controller")] - // Merely a band aid fix for now. - // Adding this by default so that we can support mounting the genesis file from k8s - // ConfigMap when we embed the Controller class, and its capacity is only limited to 1MiB. - classes.insert( - CONTROLLER_CLASS_HASH, - GenesisClass { - class: CONTROLLER_ACCOUNT_CLASS.clone().into(), - compiled_class_hash: CONTROLLER_CLASS_HASH, - }, - ); + { + // Merely a band aid fix for now. + // Adding this by default so that we can support mounting the genesis file from k8s + // ConfigMap when we embed the Controller class, and its capacity is only limited to + // 1MiB. + classes.insert( + CONTROLLER_CLASS_HASH, + GenesisClass { + class: CONTROLLER_ACCOUNT_CLASS.clone().into(), + compiled_class_hash: CONTROLLER_ACCOUNT_CLASS + .clone() + .compile()? + .class_hash()?, + }, + ); + } for entry in value.classes { let GenesisClassJson { class, class_hash, name } = entry; @@ -471,7 +477,7 @@ impl TryFrom for GenesisJson { fn try_from(value: Genesis) -> Result { let mut contracts = BTreeMap::new(); let mut accounts = BTreeMap::new(); - let mut classes = Vec::new(); + let mut classes = Vec::with_capacity(value.classes.len()); for (hash, class) in value.classes { // Convert the class to an artifact Value diff --git a/crates/katana/primitives/src/genesis/mod.rs b/crates/katana/primitives/src/genesis/mod.rs index 582b354fe0..17597bb2f3 100644 --- a/crates/katana/primitives/src/genesis/mod.rs +++ b/crates/katana/primitives/src/genesis/mod.rs @@ -127,7 +127,12 @@ impl Default for Genesis { ( CONTROLLER_CLASS_HASH, GenesisClass { - compiled_class_hash: CONTROLLER_CLASS_HASH, + compiled_class_hash: CONTROLLER_ACCOUNT_CLASS + .clone() + .compile() + .expect("failed to compile") + .class_hash() + .expect("failed to compute class hash"), class: CONTROLLER_ACCOUNT_CLASS.clone().into(), }, ), From 684fcfa531ddfc32b17df28827ae16a7c1ee608e Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Tue, 7 Jan 2025 13:11:35 -0500 Subject: [PATCH 5/6] fmt --- crates/katana/chain-spec/src/lib.rs | 64 +++++++++++++++++------------ 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/crates/katana/chain-spec/src/lib.rs b/crates/katana/chain-spec/src/lib.rs index 5d9d059a70..c2d4939cc1 100644 --- a/crates/katana/chain-spec/src/lib.rs +++ b/crates/katana/chain-spec/src/lib.rs @@ -10,21 +10,21 @@ use katana_primitives::chain::ChainId; use katana_primitives::class::ClassHash; use katana_primitives::contract::ContractAddress; use katana_primitives::da::L1DataAvailabilityMode; -use katana_primitives::genesis::Genesis; use katana_primitives::genesis::allocation::{DevAllocationsGenerator, GenesisAllocation}; use katana_primitives::genesis::constant::{ - DEFAULT_ACCOUNT_CLASS_PUBKEY_STORAGE_SLOT, DEFAULT_ETH_FEE_TOKEN_ADDRESS, - DEFAULT_LEGACY_ERC20_CLASS, DEFAULT_LEGACY_ERC20_CLASS_HASH, DEFAULT_LEGACY_UDC_CLASS, - DEFAULT_LEGACY_UDC_CLASS_HASH, DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, - DEFAULT_PREFUNDED_ACCOUNT_BALANCE, DEFAULT_STRK_FEE_TOKEN_ADDRESS, DEFAULT_UDC_ADDRESS, - ERC20_DECIMAL_STORAGE_SLOT, ERC20_NAME_STORAGE_SLOT, ERC20_SYMBOL_STORAGE_SLOT, - ERC20_TOTAL_SUPPLY_STORAGE_SLOT, get_fee_token_balance_base_storage_address, + get_fee_token_balance_base_storage_address, DEFAULT_ACCOUNT_CLASS_PUBKEY_STORAGE_SLOT, + DEFAULT_ETH_FEE_TOKEN_ADDRESS, DEFAULT_LEGACY_ERC20_CLASS, DEFAULT_LEGACY_ERC20_CLASS_HASH, + DEFAULT_LEGACY_UDC_CLASS, DEFAULT_LEGACY_UDC_CLASS_HASH, + DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, DEFAULT_PREFUNDED_ACCOUNT_BALANCE, + DEFAULT_STRK_FEE_TOKEN_ADDRESS, DEFAULT_UDC_ADDRESS, ERC20_DECIMAL_STORAGE_SLOT, + ERC20_NAME_STORAGE_SLOT, ERC20_SYMBOL_STORAGE_SLOT, ERC20_TOTAL_SUPPLY_STORAGE_SLOT, }; use katana_primitives::genesis::json::GenesisJson; +use katana_primitives::genesis::Genesis; use katana_primitives::state::StateUpdatesWithClasses; use katana_primitives::utils::split_u256; -use katana_primitives::version::{CURRENT_STARKNET_VERSION, ProtocolVersion}; -use katana_primitives::{Felt, eth}; +use katana_primitives::version::{ProtocolVersion, CURRENT_STARKNET_VERSION}; +use katana_primitives::{eth, Felt}; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use starknet::core::utils::cairo_short_string_to_felt; @@ -360,7 +360,6 @@ mod tests { use katana_primitives::address; use katana_primitives::block::{Block, GasPrices, Header}; use katana_primitives::da::L1DataAvailabilityMode; - use katana_primitives::genesis::GenesisClass; use katana_primitives::genesis::allocation::{ GenesisAccount, GenesisAccountAlloc, GenesisContractAlloc, }; @@ -372,6 +371,7 @@ mod tests { DEFAULT_LEGACY_ERC20_CLASS, DEFAULT_LEGACY_ERC20_COMPILED_CLASS_HASH, DEFAULT_LEGACY_UDC_CLASS, DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, }; + use katana_primitives::genesis::GenesisClass; use katana_primitives::version::CURRENT_STARKNET_VERSION; use starknet::macros::felt; @@ -396,23 +396,35 @@ mod tests { // setup initial states to test let classes = BTreeMap::from([ - (DEFAULT_LEGACY_UDC_CLASS_HASH, GenesisClass { - class: DEFAULT_LEGACY_UDC_CLASS.clone().into(), - compiled_class_hash: DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, - }), - (DEFAULT_LEGACY_ERC20_CLASS_HASH, GenesisClass { - class: DEFAULT_LEGACY_ERC20_CLASS.clone().into(), - compiled_class_hash: DEFAULT_LEGACY_ERC20_COMPILED_CLASS_HASH, - }), - (DEFAULT_ACCOUNT_CLASS_HASH, GenesisClass { - compiled_class_hash: DEFAULT_ACCOUNT_COMPILED_CLASS_HASH, - class: DEFAULT_ACCOUNT_CLASS.clone().into(), - }), + ( + DEFAULT_LEGACY_UDC_CLASS_HASH, + GenesisClass { + class: DEFAULT_LEGACY_UDC_CLASS.clone().into(), + compiled_class_hash: DEFAULT_LEGACY_UDC_COMPILED_CLASS_HASH, + }, + ), + ( + DEFAULT_LEGACY_ERC20_CLASS_HASH, + GenesisClass { + class: DEFAULT_LEGACY_ERC20_CLASS.clone().into(), + compiled_class_hash: DEFAULT_LEGACY_ERC20_COMPILED_CLASS_HASH, + }, + ), + ( + DEFAULT_ACCOUNT_CLASS_HASH, + GenesisClass { + compiled_class_hash: DEFAULT_ACCOUNT_COMPILED_CLASS_HASH, + class: DEFAULT_ACCOUNT_CLASS.clone().into(), + }, + ), #[cfg(feature = "controller")] - (CONTROLLER_CLASS_HASH, GenesisClass { - compiled_class_hash: CONTROLLER_CLASS_HASH, - class: CONTROLLER_ACCOUNT_CLASS.clone().into(), - }), + ( + CONTROLLER_CLASS_HASH, + GenesisClass { + compiled_class_hash: CONTROLLER_CLASS_HASH, + class: CONTROLLER_ACCOUNT_CLASS.clone().into(), + }, + ), ]); let allocations = [ From 1c78d17544ea8439ff5994fd3ab292d874d3c854 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Tue, 7 Jan 2025 13:29:55 -0500 Subject: [PATCH 6/6] fix test --- crates/katana/primitives/src/genesis/json.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/katana/primitives/src/genesis/json.rs b/crates/katana/primitives/src/genesis/json.rs index f790dd7c7e..927d739dd1 100644 --- a/crates/katana/primitives/src/genesis/json.rs +++ b/crates/katana/primitives/src/genesis/json.rs @@ -807,8 +807,13 @@ mod tests { ( CONTROLLER_CLASS_HASH, GenesisClass { - compiled_class_hash: CONTROLLER_CLASS_HASH, class: CONTROLLER_ACCOUNT_CLASS.clone().into(), + compiled_class_hash: CONTROLLER_ACCOUNT_CLASS + .clone() + .compile() + .unwrap() + .class_hash() + .unwrap(), }, ), ]); @@ -998,7 +1003,12 @@ mod tests { CONTROLLER_CLASS_HASH, GenesisClass { class: CONTROLLER_ACCOUNT_CLASS.clone().into(), - compiled_class_hash: CONTROLLER_CLASS_HASH, + compiled_class_hash: CONTROLLER_ACCOUNT_CLASS + .clone() + .compile() + .unwrap() + .class_hash() + .unwrap(), }, ), ]);