Skip to content

Commit

Permalink
feat(katana): implement Arbitrary trait for all db types (#2568)
Browse files Browse the repository at this point in the history
implement the [`Arbitray`](https://docs.rs/arbitrary/latest/arbitrary/trait.Arbitrary.html) trait for all types that are used in the database. this is for generating random values  of all the database types. helpful for 

due to Rust's orphan rule, there are some types that we use from external crate (mainly `starknet-rs`) that don't implement the trait, so we can't directly derive it. to get around this, the simplest solution is to just own the types and define it ourselves. this approach requires that we do more marshalling between our primitives types to the rpc types (rpc we mostly use types from starknet-rs). which is not the most elegant solution. i think eventually we probably should not rely on external crate for our rpc types and maintain them ourselves for more flexibility (if the changes that we need cant be included upstream).

the idea for this PR, is to use this for generating bunch of random values for all db types and use them in a benchmark. 

---

test db needs to be updated because of the we define the [`ExecutionResources`](https://github.com/dojoengine/dojo/blob/a4ee208b517daead41ac1a6b855af3abb03294c3/crates/katana/primitives/src/trace.rs#L12-L20) and it doesn't serde into the same format as the one we used before (from the [cairo-vm](https://github.com/dojoengine/dojo/blob/a4ee208b517daead41ac1a6b855af3abb03294c3/crates/katana/primitives/src/trace.rs#L12-L20))

i would prefer to keep the breaking serde, mainly because it doesnt de/serialize the `builtin_instance_counter` as raw strings of the builtin names. therefore more storage optimized. we're still using the builin name types from cairo-vm anyway so marshalling between them is straightforward as we dont need to convert the individual map entry.

though this changes break the db format, as we already bumped it at #2560, and it hasnt been included in a release yet, theres no need to bump it again.
  • Loading branch information
kariy authored Oct 22, 2024
1 parent 59c6dcf commit 81b6fa7
Show file tree
Hide file tree
Showing 37 changed files with 377 additions and 87 deletions.
40 changes: 40 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ sozo-signers = { path = "crates/sozo/signers" }
sozo-walnut = { path = "crates/sozo/walnut" }

anyhow = "1.0.89"
arbitrary = { version = "1.3.2", features = [ "derive" ] }
assert_fs = "1.1"
assert_matches = "1.5.0"
async-trait = "0.1.82"
Expand Down Expand Up @@ -244,4 +245,4 @@ alloy-transport = { version = "0.3", default-features = false }

starknet = "0.12.0"
starknet-crypto = "0.7.1"
starknet-types-core = "0.1.6"
starknet-types-core = { version = "0.1.6", features = [ "arbitrary" ] }
5 changes: 5 additions & 0 deletions crates/katana/cairo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@ cairo-lang-starknet-classes = "2.7.0"
cairo-lang-utils = "2.7.0"
cairo-vm = "1.0.1"
starknet_api = { git = "https://github.com/dojoengine/sequencer", tag = "v0.8.0-rc3.2" }

[features]
# Some types that we used from cairo-vm implements the `Arbitrary` trait,
# only under the `test_utils` feature. So we expose through this feature.
cairo-vm-test-utils = [ "cairo-vm/test_utils" ]
11 changes: 8 additions & 3 deletions crates/katana/core/src/backend/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use katana_primitives::block::{
BlockHashOrNumber, BlockIdOrTag, FinalityStatus, SealedBlockWithStatus,
};
use katana_primitives::chain_spec::ChainSpec;
use katana_primitives::da::L1DataAvailabilityMode;
use katana_primitives::state::StateUpdatesWithDeclaredClasses;
use katana_primitives::version::ProtocolVersion;
use katana_provider::providers::db::DbProvider;
Expand Down Expand Up @@ -182,7 +183,12 @@ impl Blockchain {
forked_block.l1_data_gas_price.price_in_wei.to_u128().expect("should fit in u128");
block.header.l1_data_gas_prices.strk =
forked_block.l1_data_gas_price.price_in_fri.to_u128().expect("should fit in u128");
block.header.l1_da_mode = forked_block.l1_da_mode;
block.header.l1_da_mode = match forked_block.l1_da_mode {
starknet::core::types::L1DataAvailabilityMode::Blob => L1DataAvailabilityMode::Blob,
starknet::core::types::L1DataAvailabilityMode::Calldata => {
L1DataAvailabilityMode::Calldata
}
};

let block = block.seal_with_hash_and_status(forked_block.block_hash, status);
let state_updates = chain.state_updates();
Expand Down Expand Up @@ -216,7 +222,7 @@ mod tests {
Block, FinalityStatus, GasPrices, Header, SealedBlockWithStatus,
};
use katana_primitives::da::L1DataAvailabilityMode;
use katana_primitives::fee::TxFeeInfo;
use katana_primitives::fee::{PriceUnit, TxFeeInfo};
use katana_primitives::genesis::constant::{
DEFAULT_ETH_FEE_TOKEN_ADDRESS, DEFAULT_LEGACY_ERC20_CASM, DEFAULT_LEGACY_ERC20_CLASS_HASH,
DEFAULT_LEGACY_UDC_CASM, DEFAULT_LEGACY_UDC_CLASS_HASH, DEFAULT_UDC_ADDRESS,
Expand All @@ -232,7 +238,6 @@ mod tests {
};
use katana_provider::traits::state::StateFactoryProvider;
use katana_provider::traits::transaction::{TransactionProvider, TransactionTraceProvider};
use starknet::core::types::PriceUnit;
use starknet::macros::felt;

use super::Blockchain;
Expand Down
27 changes: 19 additions & 8 deletions crates/katana/executor/src/implementation/blockifier/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,14 @@ use katana_cairo::starknet_api::transaction::{
};
use katana_primitives::chain::NamedChainId;
use katana_primitives::env::{BlockEnv, CfgEnv};
use katana_primitives::fee::TxFeeInfo;
use katana_primitives::fee::{PriceUnit, TxFeeInfo};
use katana_primitives::state::{StateUpdates, StateUpdatesWithDeclaredClasses};
use katana_primitives::trace::{L1Gas, TxExecInfo, TxResources};
use katana_primitives::transaction::{
DeclareTx, DeployAccountTx, ExecutableTx, ExecutableTxWithHash, InvokeTx, TxType,
};
use katana_primitives::{class, event, message, trace, Felt};
use katana_provider::traits::contract::ContractClassProvider;
use starknet::core::types::PriceUnit;
use starknet::core::utils::parse_cairo_short_string;

use super::state::{CachedState, StateDb};
Expand Down Expand Up @@ -480,15 +479,15 @@ pub(super) fn state_update_from_cached_state<S: StateDb>(
}
}

fn to_api_da_mode(mode: starknet::core::types::DataAvailabilityMode) -> DataAvailabilityMode {
fn to_api_da_mode(mode: katana_primitives::da::DataAvailabilityMode) -> DataAvailabilityMode {
match mode {
starknet::core::types::DataAvailabilityMode::L1 => DataAvailabilityMode::L1,
starknet::core::types::DataAvailabilityMode::L2 => DataAvailabilityMode::L2,
katana_primitives::da::DataAvailabilityMode::L1 => DataAvailabilityMode::L1,
katana_primitives::da::DataAvailabilityMode::L2 => DataAvailabilityMode::L2,
}
}

fn to_api_resource_bounds(
resource_bounds: starknet::core::types::ResourceBoundsMapping,
resource_bounds: katana_primitives::fee::ResourceBoundsMapping,
) -> ResourceBoundsMapping {
let l1_gas = ResourceBounds {
max_amount: resource_bounds.l1_gas.max_amount,
Expand Down Expand Up @@ -572,7 +571,9 @@ pub fn to_exec_info(exec_info: TransactionExecutionInfo, r#type: TxType) -> TxEx
actual_fee: exec_info.transaction_receipt.fee.0,
revert_error: exec_info.revert_error.clone(),
actual_resources: TxResources {
vm_resources: exec_info.transaction_receipt.resources.vm_resources,
vm_resources: to_execution_resources(
exec_info.transaction_receipt.resources.vm_resources,
),
n_reverted_steps: exec_info.transaction_receipt.resources.n_reverted_steps,
data_availability: L1Gas {
l1_gas: exec_info.transaction_receipt.da_gas.l1_data_gas,
Expand Down Expand Up @@ -626,7 +627,7 @@ fn to_call_info(call: CallInfo) -> trace::CallInfo {
entry_point_type,
calldata,
retdata,
execution_resources: call.resources,
execution_resources: to_execution_resources(call.resources),
events,
l2_to_l1_messages: l1_msg,
storage_read_values,
Expand Down Expand Up @@ -655,6 +656,16 @@ fn to_l2_l1_messages(
message::OrderedL2ToL1Message { order, from_address, to_address, payload }
}

fn to_execution_resources(
resources: ExecutionResources,
) -> katana_primitives::trace::ExecutionResources {
katana_primitives::trace::ExecutionResources {
n_steps: resources.n_steps,
n_memory_holes: resources.n_memory_holes,
builtin_instance_counter: resources.builtin_instance_counter,
}
}

#[cfg(test)]
mod tests {

Expand Down
2 changes: 1 addition & 1 deletion crates/katana/executor/tests/simulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use fixtures::{executor_factory, state_provider};
use katana_executor::{ExecutionOutput, ExecutorFactory, SimulationFlag};
use katana_primitives::block::GasPrices;
use katana_primitives::env::BlockEnv;
use katana_primitives::fee::PriceUnit;
use katana_primitives::transaction::ExecutableTxWithHash;
use katana_provider::traits::state::StateProvider;
use rstest_reuse::{self, *};
use starknet::core::types::PriceUnit;
use starknet::macros::felt;

#[rstest::fixture]
Expand Down
13 changes: 11 additions & 2 deletions crates/katana/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
katana-cairo.workspace = true

anyhow.workspace = true
arbitrary = { workspace = true, optional = true }
base64.workspace = true
derive_more.workspace = true
lazy_static.workspace = true
Expand All @@ -18,11 +21,11 @@ serde_json.workspace = true
serde_with.workspace = true
starknet.workspace = true
starknet-crypto.workspace = true
starknet-types-core.workspace = true
thiserror.workspace = true

alloy-primitives.workspace = true
alloy-primitives = { workspace = true, features = [ "arbitrary" ] }
flate2 = { workspace = true, optional = true }
katana-cairo.workspace = true
num-bigint = "0.4.6"

[dev-dependencies]
Expand All @@ -34,6 +37,12 @@ similar-asserts.workspace = true
[features]
default = [ "serde" ]

arbitrary = [
"alloy-primitives/arbitrary",
"dep:arbitrary",
# See the comment in katana-cairo/Cargo.toml for why this is needed.
"katana-cairo/cairo-vm-test-utils",
]
controller = [ ]
rpc = [ "dep:flate2" ]
serde = [ "alloy-primitives/serde" ]
Expand Down
3 changes: 3 additions & 0 deletions crates/katana/primitives/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub type BlockHash = Felt;

/// Finality status of a canonical block.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FinalityStatus {
AcceptedOnL2,
Expand All @@ -55,6 +56,7 @@ pub struct PartialHeader {
// TODO: change names to wei and fri
/// The L1 gas prices.
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "UPPERCASE"))]
pub struct GasPrices {
Expand All @@ -73,6 +75,7 @@ impl GasPrices {

/// Represents a block header.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Header {
pub parent_hash: BlockHash,
Expand Down
2 changes: 2 additions & 0 deletions crates/katana/primitives/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{Felt, FromStrError};

/// Known chain ids that has been assigned a name.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum NamedChainId {
Mainnet,
Expand Down Expand Up @@ -72,6 +73,7 @@ impl TryFrom<Felt> for NamedChainId {

/// Represents a chain id.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ChainId {
/// A chain id with a known chain name.
Expand Down
4 changes: 2 additions & 2 deletions crates/katana/primitives/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ use std::collections::BTreeMap;

use alloy_primitives::U256;
use lazy_static::lazy_static;
use starknet::core::types::L1DataAvailabilityMode;
use starknet::core::utils::cairo_short_string_to_felt;
use starknet_crypto::Felt;

use crate::block::{Block, Header};
use crate::chain::ChainId;
use crate::class::ClassHash;
use crate::contract::ContractAddress;
use crate::da::L1DataAvailabilityMode;
use crate::genesis::allocation::{DevAllocationsGenerator, GenesisAllocation};
use crate::genesis::constant::{
get_fee_token_balance_base_storage_address, DEFAULT_ACCOUNT_CLASS_PUBKEY_STORAGE_SLOT,
Expand Down Expand Up @@ -225,12 +225,12 @@ mod tests {
use std::str::FromStr;

use alloy_primitives::U256;
use starknet::core::types::L1DataAvailabilityMode;
use starknet::macros::felt;

use super::*;
use crate::address;
use crate::block::{Block, GasPrices, Header};
use crate::da::L1DataAvailabilityMode;
use crate::genesis::allocation::{GenesisAccount, GenesisAccountAlloc, GenesisContractAlloc};
#[cfg(feature = "slot")]
use crate::genesis::constant::{
Expand Down
2 changes: 2 additions & 0 deletions crates/katana/primitives/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub type Nonce = Felt;

/// Represents a contract address.
#[derive(Default, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ContractAddress(pub Felt);

Expand Down Expand Up @@ -72,6 +73,7 @@ macro_rules! address {

/// Represents a generic contract instance information.
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "arbitrary", derive(::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct GenericContractInfo {
/// The nonce of the contract.
Expand Down
Loading

0 comments on commit 81b6fa7

Please sign in to comment.