Skip to content

Commit

Permalink
Refactor Katana to using the new executor traits (#1563)
Browse files Browse the repository at this point in the history
integrate the new executor traits introduced in #1561 to katana
  • Loading branch information
kariy authored Feb 29, 2024
1 parent 1213ab1 commit d5841e1
Show file tree
Hide file tree
Showing 30 changed files with 750 additions and 1,518 deletions.
6 changes: 4 additions & 2 deletions Cargo.lock

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

6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ members = [
"crates/katana/storage/codecs/derive",
"crates/katana/storage/db",
"crates/katana/storage/provider",
"crates/katana/tasks",
"crates/metrics",
"crates/saya/core",
"crates/sozo/signers",
Expand Down Expand Up @@ -68,16 +69,17 @@ dojo-world = { path = "crates/dojo-world" }
# katana
katana-codecs = { path = "crates/katana/storage/codecs" }
katana-codecs-derive = { path = "crates/katana/storage/codecs/derive" }
katana-core = { path = "crates/katana/core" }
katana-core = { path = "crates/katana/core", default-features = false }
katana-db = { path = "crates/katana/storage/db" }
katana-executor = { path = "crates/katana/executor" }
katana-executor = { path = "crates/katana/executor", default-features = false }
katana-primitives = { path = "crates/katana/primitives" }
katana-provider = { path = "crates/katana/storage/provider" }
katana-rpc = { path = "crates/katana/rpc/rpc" }
katana-rpc-api = { path = "crates/katana/rpc/rpc-api" }
katana-rpc-types = { path = "crates/katana/rpc/rpc-types" }
katana-rpc-types-builder = { path = "crates/katana/rpc/rpc-types-builder" }
katana-runner = { path = "crates/katana/runner" }
katana-tasks = { path = "crates/katana/tasks" }

# torii
torii-client = { path = "crates/torii/client" }
Expand Down
1 change: 1 addition & 0 deletions bin/katana/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ clap_complete.workspace = true
common.workspace = true
console.workspace = true
katana-core.workspace = true
katana-executor.workspace = true
katana-primitives.workspace = true
katana-rpc-api.workspace = true
katana-rpc.workspace = true
Expand Down
28 changes: 27 additions & 1 deletion bin/katana/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ use std::sync::Arc;
use clap::{CommandFactory, Parser};
use clap_complete::{generate, Shell};
use console::Style;
use katana_core::constants::MAX_RECURSION_DEPTH;
use katana_core::env::get_default_vm_resource_fee_cost;
use katana_core::sequencer::KatanaSequencer;
use katana_executor::SimulationFlag;
use katana_primitives::class::ClassHash;
use katana_primitives::contract::ContractAddress;
use katana_primitives::env::{CfgEnv, FeeTokenAddressses};
use katana_primitives::genesis::allocation::GenesisAccountAlloc;
use katana_primitives::genesis::Genesis;
use katana_rpc::{spawn, NodeHandle};
Expand Down Expand Up @@ -39,7 +43,29 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let sequencer_config = args.sequencer_config();
let starknet_config = args.starknet_config();

let sequencer = Arc::new(KatanaSequencer::new(sequencer_config, starknet_config).await?);
let cfg_env = CfgEnv {
chain_id: starknet_config.env.chain_id,
vm_resource_fee_cost: get_default_vm_resource_fee_cost(),
invoke_tx_max_n_steps: starknet_config.env.invoke_max_steps,
validate_max_n_steps: starknet_config.env.validate_max_steps,
max_recursion_depth: MAX_RECURSION_DEPTH,
fee_token_addresses: FeeTokenAddressses {
eth: starknet_config.genesis.fee_token.address,
strk: Default::default(),
},
};

let simulation_flags = SimulationFlag {
skip_validate: starknet_config.disable_validate,
skip_fee_transfer: starknet_config.disable_fee,
..Default::default()
};

use katana_executor::implementation::blockifier::BlockifierFactory;
let executor_factory = BlockifierFactory::new(cfg_env, simulation_flags);

let sequencer =
Arc::new(KatanaSequencer::new(executor_factory, sequencer_config, starknet_config).await?);
let NodeHandle { addr, handle, .. } = spawn(Arc::clone(&sequencer), server_config).await?;

if !args.silent {
Expand Down
1 change: 1 addition & 0 deletions crates/dojo-test-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dojo-lang = { path = "../dojo-lang" }
dojo-world = { path = "../dojo-world", features = [ "manifest", "migration" ] }
jsonrpsee = { version = "0.16.2", features = [ "server" ] }
katana-core = { path = "../katana/core" }
katana-executor = { workspace = true, features = [ "blockifier" ] }
katana-primitives = { path = "../katana/primitives" }
katana-rpc = { path = "../katana/rpc/rpc" }
katana-rpc-api = { path = "../katana/rpc/rpc-api" }
Expand Down
29 changes: 27 additions & 2 deletions crates/dojo-test-utils/src/sequencer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ use std::sync::Arc;

use jsonrpsee::core::Error;
pub use katana_core::backend::config::{Environment, StarknetConfig};
use katana_core::constants::MAX_RECURSION_DEPTH;
use katana_core::env::get_default_vm_resource_fee_cost;
use katana_core::sequencer::KatanaSequencer;
pub use katana_core::sequencer::SequencerConfig;
use katana_executor::implementation::blockifier::BlockifierFactory;
use katana_executor::SimulationFlag;
use katana_primitives::chain::ChainId;
use katana_primitives::env::{CfgEnv, FeeTokenAddressses};
use katana_rpc::config::ServerConfig;
use katana_rpc::{spawn, NodeHandle};
use katana_rpc_api::ApiKind;
Expand All @@ -26,13 +31,33 @@ pub struct TestSequencer {
url: Url,
handle: NodeHandle,
account: TestAccount,
pub sequencer: Arc<KatanaSequencer>,
pub sequencer: Arc<KatanaSequencer<BlockifierFactory>>,
}

impl TestSequencer {
pub async fn start(config: SequencerConfig, starknet_config: StarknetConfig) -> Self {
let cfg_env = CfgEnv {
chain_id: starknet_config.env.chain_id,
vm_resource_fee_cost: get_default_vm_resource_fee_cost(),
invoke_tx_max_n_steps: starknet_config.env.invoke_max_steps,
validate_max_n_steps: starknet_config.env.validate_max_steps,
max_recursion_depth: MAX_RECURSION_DEPTH,
fee_token_addresses: FeeTokenAddressses {
eth: starknet_config.genesis.fee_token.address,
strk: Default::default(),
},
};

let simulation_flags = SimulationFlag {
skip_validate: starknet_config.disable_validate,
skip_fee_transfer: starknet_config.disable_fee,
..Default::default()
};

let executor_factory = BlockifierFactory::new(cfg_env, simulation_flags);

let sequencer = Arc::new(
KatanaSequencer::new(config, starknet_config)
KatanaSequencer::new(executor_factory, config, starknet_config)
.await
.expect("Failed to create sequencer"),
);
Expand Down
8 changes: 5 additions & 3 deletions crates/katana/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ version.workspace = true

[dependencies]
katana-db = { path = "../storage/db" }
katana-executor = { path = "../executor" }
katana-executor.workspace = true
katana-primitives = { path = "../primitives" }
katana-provider = { path = "../storage/provider" }
katana-tasks.workspace = true

anyhow.workspace = true
async-trait.workspace = true
Expand All @@ -19,7 +20,8 @@ cairo-lang-casm = "2.3.1"
cairo-lang-starknet = "2.3.1"
cairo-vm.workspace = true
convert_case.workspace = true
ethers = "2.0.11"
derive_more.workspace = true
ethers = { version = "2.0.11", optional = true }
flate2.workspace = true
futures.workspace = true
lazy_static = "1.4.0"
Expand All @@ -42,5 +44,5 @@ hex = "0.4.3"
tempfile = "3.8.1"

[features]
messaging = [ ]
messaging = [ "ethers" ]
starknet-messaging = [ ]
84 changes: 26 additions & 58 deletions crates/katana/core/src/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::sync::Arc;

use katana_executor::ExecutorFactory;
use katana_primitives::block::{
Block, FinalityStatus, GasPrices, Header, PartialHeader, SealedBlockWithStatus,
};
use katana_primitives::chain::ChainId;
use katana_primitives::env::{BlockEnv, CfgEnv, FeeTokenAddressses};
use katana_primitives::env::BlockEnv;
use katana_primitives::receipt::Receipt;
use katana_primitives::state::StateUpdatesWithDeclaredClasses;
use katana_primitives::transaction::TxWithHash;
Expand All @@ -13,7 +14,6 @@ use katana_primitives::FieldElement;
use katana_provider::providers::fork::ForkedProvider;
use katana_provider::providers::in_memory::InMemoryProvider;
use katana_provider::traits::block::{BlockHashProvider, BlockWriter};
use katana_provider::traits::state::{StateFactoryProvider, StateProvider};
use parking_lot::RwLock;
use starknet::core::types::{BlockId, BlockStatus, MaybePendingBlockWithTxHashes};
use starknet::core::utils::parse_cairo_short_string;
Expand All @@ -27,12 +27,11 @@ pub mod storage;

use self::config::StarknetConfig;
use self::storage::Blockchain;
use crate::constants::MAX_RECURSION_DEPTH;
use crate::env::{get_default_vm_resource_fee_cost, BlockContextGenerator};
use crate::env::BlockContextGenerator;
use crate::service::block_producer::{BlockProductionError, MinedBlockOutcome};
use crate::utils::get_current_timestamp;

pub struct Backend {
pub struct Backend<EF: ExecutorFactory> {
/// The config used to generate the backend.
pub config: StarknetConfig,
/// stores all block related data in memory
Expand All @@ -41,15 +40,15 @@ pub struct Backend {
pub chain_id: ChainId,
/// The block context generator.
pub block_context_generator: RwLock<BlockContextGenerator>,

pub executor_factory: Arc<EF>,
}

impl Backend {
pub async fn new(mut config: StarknetConfig) -> Self {
impl<EF: ExecutorFactory> Backend<EF> {
pub async fn new(executor_factory: Arc<EF>, mut config: StarknetConfig) -> Self {
let block_context_generator = config.block_context_generator();

let (blockchain, chain_id): (Blockchain, ChainId) = if let Some(forked_url) =
&config.fork_rpc_url
{
let blockchain: Blockchain = if let Some(forked_url) = &config.fork_rpc_url {
let provider = Arc::new(JsonRpcClient::new(HttpTransport::new(forked_url.clone())));
let forked_chain_id = provider.chain_id().await.unwrap();

Expand Down Expand Up @@ -98,43 +97,25 @@ impl Backend {
)
.expect("able to create forked blockchain");

(blockchain, forked_chain_id.into())
config.env.chain_id = forked_chain_id.into();
blockchain
} else if let Some(db_path) = &config.db_dir {
(
Blockchain::new_with_db(db_path, &config.genesis)
.expect("able to create blockchain from db"),
config.env.chain_id,
)
Blockchain::new_with_db(db_path, &config.genesis)
.expect("able to create blockchain from db")
} else {
let blockchain = Blockchain::new_with_genesis(InMemoryProvider::new(), &config.genesis)
.expect("able to create blockchain from genesis block");

(blockchain, config.env.chain_id)
Blockchain::new_with_genesis(InMemoryProvider::new(), &config.genesis)
.expect("able to create blockchain from genesis block")
};

Self {
chain_id,
chain_id: config.env.chain_id,
blockchain,
config,
executor_factory,
block_context_generator: RwLock::new(block_context_generator),
}
}

/// Mines a new block based on the provided execution outcome.
/// This method should only be called by the
/// [IntervalBlockProducer](crate::service::block_producer::IntervalBlockProducer) when the node
/// is running in `interval` mining mode.
pub fn mine_pending_block(
&self,
block_env: &BlockEnv,
tx_receipt_pairs: Vec<(TxWithHash, Receipt)>,
state_updates: StateUpdatesWithDeclaredClasses,
) -> Result<(MinedBlockOutcome, Box<dyn StateProvider>), BlockProductionError> {
let outcome = self.do_mine_block(block_env, tx_receipt_pairs, state_updates)?;
let new_state = StateFactoryProvider::latest(&self.blockchain.provider())?;
Ok((outcome, new_state))
}

pub fn do_mine_block(
&self,
block_env: &BlockEnv,
Expand All @@ -144,9 +125,11 @@ impl Backend {
let (txs, receipts): (Vec<TxWithHash>, Vec<Receipt>) = tx_receipt_pairs.into_iter().unzip();

let prev_hash = BlockHashProvider::latest_hash(self.blockchain.provider())?;
let block_number = block_env.number;
let tx_count = txs.len();

let partial_header = PartialHeader {
number: block_env.number,
number: block_number,
parent_hash: prev_hash,
version: CURRENT_STARKNET_VERSION,
timestamp: block_env.timestamp,
Expand All @@ -157,10 +140,7 @@ impl Backend {
},
};

let tx_count = txs.len();
let block_number = block_env.number;

let header = Header::new(partial_header, block_number, FieldElement::ZERO);
let header = Header::new(partial_header, FieldElement::ZERO);
let block = Block { header, body: txs }.seal();
let block = SealedBlockWithStatus { block, status: FinalityStatus::AcceptedOnL2 };

Expand Down Expand Up @@ -193,21 +173,6 @@ impl Backend {
block_env.timestamp = timestamp;
}

/// Retrieves the chain configuration environment values.
pub(crate) fn chain_cfg_env(&self) -> CfgEnv {
CfgEnv {
chain_id: self.chain_id,
vm_resource_fee_cost: get_default_vm_resource_fee_cost(),
invoke_tx_max_n_steps: self.config.env.invoke_max_steps,
validate_max_n_steps: self.config.env.validate_max_steps,
max_recursion_depth: MAX_RECURSION_DEPTH,
fee_token_addresses: FeeTokenAddressses {
eth: self.config.genesis.fee_token.address,
strk: Default::default(),
},
}
}

pub fn mine_empty_block(
&self,
block_env: &BlockEnv,
Expand All @@ -219,6 +184,9 @@ impl Backend {
#[cfg(test)]
mod tests {

use std::sync::Arc;

use katana_executor::implementation::noop::NoopExecutorFactory;
use katana_primitives::genesis::Genesis;
use katana_provider::traits::block::{BlockNumberProvider, BlockProvider};
use katana_provider::traits::env::BlockEnvProvider;
Expand All @@ -235,8 +203,8 @@ mod tests {
}
}

async fn create_test_backend() -> Backend {
Backend::new(create_test_starknet_config()).await
async fn create_test_backend() -> Backend<NoopExecutorFactory> {
Backend::new(Arc::new(NoopExecutorFactory::default()), create_test_starknet_config()).await
}

#[tokio::test]
Expand Down
Loading

0 comments on commit d5841e1

Please sign in to comment.