Skip to content

Commit

Permalink
refactor(katana): rpc class types improvements (#2712)
Browse files Browse the repository at this point in the history
the goal is to reduce the steps in converting from rpc to primitives types for classes. currently we rely on starknet-rs for rpc types, while using cairo-lang types for internal usages (ie execution). this required a very ugly ceremony for conversion as they don't share the same types (only Felt!). so the current approach is to convert the starknet-rs types to serde_json::Value first and deserialize it to the cairo-lang types. This is damn slow!!

so im solving this by defining the rpc types ourselves using the same internal types (for the inner fields) as cairo-lang's. so we don't need to perform any conversions from rpc -> internal. i also replace any usages of starknet-rs class types in the db and go fully with cairo-lang as the primitives types.
  • Loading branch information
kariy authored Nov 22, 2024
1 parent b55f1fc commit c5a4eaf
Show file tree
Hide file tree
Showing 29 changed files with 580 additions and 173 deletions.
8 changes: 6 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 12 additions & 14 deletions crates/katana/executor/src/implementation/blockifier/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ impl<S: StateDb> StateReader for CachedState<S> {
mod tests {

use blockifier::state::state_api::{State, StateReader};
use katana_primitives::class::{CompiledClass, FlattenedSierraClass};
use katana_primitives::class::CompiledClass;
use katana_primitives::contract::ContractAddress;
use katana_primitives::genesis::constant::{
DEFAULT_ACCOUNT_CLASS, DEFAULT_ACCOUNT_CLASS_CASM, DEFAULT_LEGACY_ERC20_CLASS,
Expand All @@ -258,11 +258,11 @@ mod tests {
use super::{CachedState, *};
use crate::StateProviderDb;

fn new_sierra_class() -> (FlattenedSierraClass, CompiledClass) {
fn new_sierra_class() -> (ContractClass, CompiledClass) {
let json = include_str!("../../../../contracts/build/cairo1_contract.json");
let artifact = serde_json::from_str(json).unwrap();
let compiled_class = parse_compiled_class(artifact).unwrap();
let sierra_class = parse_sierra_class(json).unwrap().flatten().unwrap();
let sierra_class = parse_sierra_class(json).unwrap();
(sierra_class, compiled_class)
}

Expand All @@ -273,9 +273,9 @@ mod tests {
let storage_value = felt!("0x2");
let class_hash = felt!("0x123");
let compiled_hash = felt!("0x456");
let class = ContractClass::Class(DEFAULT_ACCOUNT_CLASS.clone().flatten().unwrap());
let class = DEFAULT_ACCOUNT_CLASS.clone();
let compiled_class = DEFAULT_ACCOUNT_CLASS_CASM.clone();
let legacy_class_hash = felt!("0x111");
let legacy_class_hash = felt!("0x445");
let legacy_class = DEFAULT_LEGACY_ERC20_CLASS.clone();

let provider = katana_provider::test_utils::test_provider();
Expand All @@ -285,7 +285,8 @@ mod tests {
provider.set_compiled_class_hash_of_class_hash(class_hash, compiled_hash).unwrap();
provider.set_class(class_hash, class).unwrap();
provider.set_compiled_class(class_hash, compiled_class).unwrap();
provider.set_class(legacy_class_hash, legacy_class).unwrap();
provider.set_class(legacy_class_hash, legacy_class.clone()).unwrap();
provider.set_compiled_class(legacy_class_hash, legacy_class.compile().unwrap()).unwrap();

provider.latest().unwrap()
}
Expand All @@ -296,7 +297,7 @@ mod tests {
let cached_state = CachedState::new(StateProviderDb::new(state));

let address = address!("0x67");
let legacy_class_hash = felt!("0x111");
let legacy_class_hash = felt!("0x445");
let storage_key = felt!("0x1");

let api_address = utils::to_blk_address(address);
Expand Down Expand Up @@ -397,15 +398,15 @@ mod tests {

let declared_classes = &mut lock.declared_classes;
declared_classes.insert(new_legacy_class_hash, new_legacy_class.clone());
declared_classes.insert(new_class_hash, ContractClass::Class(new_sierra_class.clone()));
declared_classes.insert(new_class_hash, new_sierra_class.clone());
}

// assert that can fetch data from the underlyign state provider
let sp: Box<dyn StateProvider> = Box::new(cached_state);

let address = address!("0x67");
let class_hash = felt!("0x123");
let legacy_class_hash = felt!("0x111");
let legacy_class_hash = felt!("0x445");

let actual_class_hash = sp.class_hash_of_contract(address)?;
let actual_nonce = sp.nonce(address)?;
Expand All @@ -420,10 +421,7 @@ mod tests {
assert_eq!(actual_storage_value, Some(felt!("0x2")));
assert_eq!(actual_compiled_hash, Some(felt!("0x456")));
assert_eq!(actual_compiled_class, Some(DEFAULT_ACCOUNT_CLASS_CASM.clone()));
assert_eq!(
actual_class,
Some(ContractClass::Class(DEFAULT_ACCOUNT_CLASS.clone().flatten()?))
);
assert_eq!(actual_class, Some(DEFAULT_ACCOUNT_CLASS.clone()));
assert_eq!(actual_legacy_class, Some(DEFAULT_LEGACY_ERC20_CLASS.clone()));

// assert that can fetch data native to the cached state from the state provider
Expand Down Expand Up @@ -451,7 +449,7 @@ mod tests {
"data should be in cached state"
);
assert_eq!(actual_new_compiled_class, Some(new_compiled_sierra_class));
assert_eq!(actual_new_class, Some(ContractClass::Class(new_sierra_class)));
assert_eq!(actual_new_class, Some(new_sierra_class));
assert_eq!(actual_new_compiled_hash, Some(new_compiled_hash));
assert_eq!(actual_legacy_class, Some(new_legacy_class.clone()));
assert_eq!(
Expand Down
4 changes: 2 additions & 2 deletions crates/katana/executor/tests/fixtures/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ pub fn contract_class() -> (CompiledClass, ContractClass) {
let json = include_str!("contract.json");
let artifact = serde_json::from_str(json).unwrap();

let sierra = parse_sierra_class(json).unwrap().flatten().unwrap();
let class = parse_sierra_class(json).unwrap();
let compiled = parse_compiled_class(artifact).unwrap();

(compiled, ContractClass::Class(sierra))
(compiled, class)
}

#[rstest::fixture]
Expand Down
1 change: 1 addition & 0 deletions crates/katana/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ thiserror.workspace = true
alloy-primitives = { workspace = true, features = [ "arbitrary" ] }
flate2.workspace = true
num-bigint = "0.4.6"
serde_json_pythonic = "0.1.2"

[dev-dependencies]
assert_matches.workspace = true
Expand Down
13 changes: 4 additions & 9 deletions crates/katana/primitives/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ mod tests {
use super::*;
use crate::address;
use crate::block::{Block, GasPrices, Header};
use crate::class::ContractClass;
use crate::da::L1DataAvailabilityMode;
use crate::genesis::allocation::{GenesisAccount, GenesisAccountAlloc, GenesisContractAlloc};
#[cfg(feature = "slot")]
Expand Down Expand Up @@ -290,19 +289,15 @@ mod tests {
DEFAULT_ACCOUNT_CLASS_HASH,
GenesisClass {
compiled_class_hash: DEFAULT_ACCOUNT_COMPILED_CLASS_HASH,
class: ContractClass::Class(DEFAULT_ACCOUNT_CLASS.clone().flatten().unwrap())
.into(),
class: DEFAULT_ACCOUNT_CLASS.clone().into(),
},
),
#[cfg(feature = "slot")]
(
CONTROLLER_CLASS_HASH,
GenesisClass {
compiled_class_hash: CONTROLLER_CLASS_HASH,
class: ContractClass::Class(
CONTROLLER_ACCOUNT_CLASS.clone().flatten().unwrap(),
)
.into(),
class: CONTROLLER_ACCOUNT_CLASS.clone().into(),
},
),
]);
Expand Down Expand Up @@ -478,7 +473,7 @@ mod tests {

assert_eq!(
actual_state_updates.classes.get(&DEFAULT_ACCOUNT_CLASS_HASH),
Some(&ContractClass::Class(DEFAULT_ACCOUNT_CLASS.clone().flatten().unwrap())),
Some(&*DEFAULT_ACCOUNT_CLASS),
"The default oz account contract sierra class should be declared"
);

Expand All @@ -492,7 +487,7 @@ mod tests {

assert_eq!(
actual_state_updates.classes.get(&CONTROLLER_CLASS_HASH),
Some(&ContractClass::Class(CONTROLLER_ACCOUNT_CLASS.clone().flatten().unwrap())),
Some(&*CONTROLLER_ACCOUNT_CLASS),
"The controller account contract sierra class should be declared"
);
}
Expand Down
Loading

0 comments on commit c5a4eaf

Please sign in to comment.