diff --git a/Cargo.lock b/Cargo.lock index 2e71159eac..14e5553b0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8059,6 +8059,7 @@ dependencies = [ "katana-tasks", "lazy_static", "metrics", + "num-traits 0.2.19", "parking_lot 0.12.3", "reqwest 0.12.7", "serde", @@ -8139,7 +8140,6 @@ dependencies = [ "katana-rpc", "katana-rpc-api", "katana-tasks", - "num-traits 0.2.19", "serde_json", "starknet 0.12.0", "strum 0.25.0", diff --git a/bin/katana/src/cli/node.rs b/bin/katana/src/cli/node.rs index e1e945ece1..6c56d56d22 100644 --- a/bin/katana/src/cli/node.rs +++ b/bin/katana/src/cli/node.rs @@ -27,11 +27,13 @@ use katana_core::constants::{ use katana_core::service::messaging::MessagingConfig; use katana_node::config::db::DbConfig; use katana_node::config::dev::DevConfig; +use katana_node::config::fork::ForkingConfig; use katana_node::config::metrics::MetricsConfig; use katana_node::config::rpc::{ ApiKind, RpcConfig, DEFAULT_RPC_ADDR, DEFAULT_RPC_MAX_CONNECTIONS, DEFAULT_RPC_PORT, }; use katana_node::config::{Config, SequencingConfig}; +use katana_primitives::block::BlockHashOrNumber; use katana_primitives::chain::ChainId; use katana_primitives::chain_spec::{self, ChainSpec}; use katana_primitives::class::ClassHash; @@ -47,7 +49,7 @@ use tracing_log::LogTracer; use tracing_subscriber::{fmt, EnvFilter}; use url::Url; -use crate::utils::{parse_genesis, parse_seed}; +use crate::utils::{parse_block_hash_or_number, parse_genesis, parse_seed}; #[derive(Parser, Debug)] pub struct NodeArgs { @@ -73,10 +75,16 @@ pub struct NodeArgs { initialized Katana database.")] pub db_dir: Option, - #[arg(long)] - #[arg(value_name = "URL")] + #[arg(long = "fork.rpc-url", value_name = "URL", alias = "rpc-url")] #[arg(help = "The Starknet RPC provider to fork the network from.")] - pub rpc_url: Option, + pub fork_rpc_url: Option, + + #[arg(long = "fork.block", value_name = "BLOCK_ID", alias = "fork-block-number")] + #[arg(requires = "fork_rpc_url")] + #[arg(help = "Fork the network at a specific block id, can either be a hash (0x-prefixed) \ + or number.")] + #[arg(value_parser = parse_block_hash_or_number)] + pub fork_block: Option, #[arg(long)] pub dev: bool, @@ -91,12 +99,6 @@ pub struct NodeArgs { #[arg(long, value_name = "SOCKET", value_parser = parse_socket_address, help_heading = "Metrics")] pub metrics: Option, - #[arg(long)] - #[arg(requires = "rpc_url")] - #[arg(value_name = "BLOCK_NUMBER")] - #[arg(help = "Fork the network at a specific block.")] - pub fork_block_number: Option, - #[arg(long)] #[arg(value_name = "PATH")] #[arg(value_parser = katana_core::service::messaging::MessagingConfig::parse)] @@ -170,7 +172,7 @@ pub struct StarknetOptions { #[arg(long)] #[arg(value_parser = parse_genesis)] - #[arg(conflicts_with_all(["rpc_url", "seed", "total_accounts"]))] + #[arg(conflicts_with_all(["fork_rpc_url", "seed", "total_accounts"]))] pub genesis: Option, } @@ -255,10 +257,9 @@ impl NodeArgs { } fn init_logging(&self) -> Result<()> { - const DEFAULT_LOG_FILTER: &str = "tasks=debug,info,executor=trace,forking::backend=trace,\ - server=debug,katana_core=trace,blockifier=off,\ - jsonrpsee_server=off,hyper=off,messaging=debug,\ - node=error"; + const DEFAULT_LOG_FILTER: &str = "info,tasks=debug,executor=trace,forking::backend=trace,\ + server=debug,blockifier=off,jsonrpsee_server=off,\ + hyper=off,messaging=debug,node=error"; LogTracer::init()?; @@ -282,10 +283,11 @@ impl NodeArgs { let chain = self.chain_spec()?; let metrics = self.metrics_config(); let starknet = self.starknet_config()?; + let forking = self.forking_config()?; let sequencing = self.sequencer_config(); let messaging = self.messaging.clone(); - Ok(Config { metrics, db, dev, rpc, chain, starknet, sequencing, messaging }) + Ok(Config { metrics, db, dev, rpc, chain, starknet, sequencing, messaging, forking }) } fn sequencer_config(&self) -> SequencingConfig { @@ -347,8 +349,6 @@ impl NodeArgs { fn starknet_config(&self) -> Result { Ok(StarknetConfig { - fork_rpc_url: self.rpc_url.clone(), - fork_block_number: self.fork_block_number, env: Environment { invoke_max_steps: self.starknet.environment.invoke_max_steps, validate_max_steps: self.starknet.environment.validate_max_steps, @@ -356,6 +356,14 @@ impl NodeArgs { }) } + fn forking_config(&self) -> Result> { + if let Some(url) = self.fork_rpc_url.clone() { + Ok(Some(ForkingConfig { url, block: self.fork_block })) + } else { + Ok(None) + } + } + fn db_config(&self) -> DbConfig { DbConfig { dir: self.db_dir.clone() } } @@ -488,8 +496,7 @@ mod test { assert!(config.dev.fee); assert!(config.dev.account_validation); - assert_eq!(config.starknet.fork_rpc_url, None); - assert_eq!(config.starknet.fork_block_number, None); + assert!(config.forking.is_none()); assert_eq!(config.starknet.env.invoke_max_steps, DEFAULT_INVOKE_MAX_STEPS); assert_eq!(config.starknet.env.validate_max_steps, DEFAULT_VALIDATE_MAX_STEPS); assert_eq!(config.db.dir, None); diff --git a/bin/katana/src/utils.rs b/bin/katana/src/utils.rs index f05f5a7634..580924962e 100644 --- a/bin/katana/src/utils.rs +++ b/bin/katana/src/utils.rs @@ -1,5 +1,7 @@ use std::path::PathBuf; +use anyhow::{Context, Result}; +use katana_primitives::block::{BlockHash, BlockHashOrNumber, BlockNumber}; use katana_primitives::genesis::json::GenesisJson; use katana_primitives::genesis::Genesis; @@ -16,12 +18,22 @@ pub fn parse_seed(seed: &str) -> [u8; 32] { } /// Used as clap value parser for [Genesis]. -pub fn parse_genesis(value: &str) -> Result { +pub fn parse_genesis(value: &str) -> Result { let path = PathBuf::from(shellexpand::full(value)?.into_owned()); let genesis = Genesis::try_from(GenesisJson::load(path)?)?; Ok(genesis) } +/// If the value starts with `0x`, it is parsed as a [`BlockHash`], otherwise as a [`BlockNumber`]. +pub fn parse_block_hash_or_number(value: &str) -> Result { + if value.starts_with("0x") { + Ok(BlockHashOrNumber::Hash(BlockHash::from_hex(value)?)) + } else { + let num = value.parse::().context("could not parse block number")?; + Ok(BlockHashOrNumber::Num(num)) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/katana/core/Cargo.toml b/crates/katana/core/Cargo.toml index c8ae350146..ae9cd35dd3 100644 --- a/crates/katana/core/Cargo.toml +++ b/crates/katana/core/Cargo.toml @@ -21,6 +21,7 @@ dojo-metrics.workspace = true futures.workspace = true lazy_static.workspace = true metrics.workspace = true +num-traits.workspace = true parking_lot.workspace = true reqwest.workspace = true serde.workspace = true diff --git a/crates/katana/core/src/backend/config.rs b/crates/katana/core/src/backend/config.rs index 42b1139a84..b4c2922d89 100644 --- a/crates/katana/core/src/backend/config.rs +++ b/crates/katana/core/src/backend/config.rs @@ -1,14 +1,9 @@ -use katana_primitives::block::BlockNumber; -use url::Url; - use crate::constants::{DEFAULT_INVOKE_MAX_STEPS, DEFAULT_VALIDATE_MAX_STEPS}; use crate::env::BlockContextGenerator; #[derive(Debug, Clone, Default)] pub struct StarknetConfig { pub env: Environment, - pub fork_rpc_url: Option, - pub fork_block_number: Option, } impl StarknetConfig { diff --git a/crates/katana/core/src/backend/storage.rs b/crates/katana/core/src/backend/storage.rs index 779b823a66..ac7eb899fa 100644 --- a/crates/katana/core/src/backend/storage.rs +++ b/crates/katana/core/src/backend/storage.rs @@ -1,9 +1,15 @@ -use anyhow::{anyhow, Result}; +use std::sync::Arc; + +use anyhow::{anyhow, bail, Context, Result}; use katana_db::mdbx::DbEnv; -use katana_primitives::block::{BlockHash, FinalityStatus, SealedBlockWithStatus}; +use katana_primitives::block::{ + BlockHashOrNumber, BlockIdOrTag, FinalityStatus, SealedBlockWithStatus, +}; use katana_primitives::chain_spec::ChainSpec; use katana_primitives::state::StateUpdatesWithDeclaredClasses; +use katana_primitives::version::ProtocolVersion; use katana_provider::providers::db::DbProvider; +use katana_provider::providers::fork::ForkedProvider; use katana_provider::traits::block::{BlockProvider, BlockWriter}; use katana_provider::traits::contract::ContractClassWriter; use katana_provider::traits::env::BlockEnvProvider; @@ -14,6 +20,13 @@ use katana_provider::traits::transaction::{ TransactionsProviderExt, }; use katana_provider::BlockchainProvider; +use num_traits::ToPrimitive; +use starknet::core::types::{BlockStatus, MaybePendingBlockWithTxHashes}; +use starknet::core::utils::parse_cairo_short_string; +use starknet::providers::jsonrpc::HttpTransport; +use starknet::providers::{JsonRpcClient, Provider}; +use tracing::info; +use url::Url; pub trait Database: BlockProvider @@ -68,7 +81,7 @@ impl Blockchain { } /// Creates a new [Blockchain] with the given [Database] implementation and genesis state. - pub fn new_with_genesis(provider: impl Database, chain: &ChainSpec) -> Result { + pub fn new_with_chain(provider: impl Database, chain: &ChainSpec) -> Result { // check whether the genesis block has been initialized let genesis_hash = provider.block_hash_by_num(chain.genesis.number)?; @@ -90,33 +103,84 @@ impl Blockchain { let block = SealedBlockWithStatus { block, status: FinalityStatus::AcceptedOnL1 }; let state_updates = chain.state_updates(); - Self::new_with_block_and_state(provider, block, state_updates) + Self::new_with_genesis_block_and_state(provider, block, state_updates) } } } /// Creates a new [Blockchain] from a database at `path` and `genesis` state. pub fn new_with_db(db: DbEnv, chain: &ChainSpec) -> Result { - Self::new_with_genesis(DbProvider::new(db), chain) + Self::new_with_chain(DbProvider::new(db), chain) } /// Builds a new blockchain with a forked block. - pub fn new_from_forked( - provider: impl Database, - genesis_hash: BlockHash, - chain: &ChainSpec, - block_status: FinalityStatus, + pub async fn new_from_forked( + fork_url: Url, + fork_block: Option, + chain: &mut ChainSpec, ) -> Result { - let block = chain.block().seal_with_hash_and_status(genesis_hash, block_status); + let provider = JsonRpcClient::new(HttpTransport::new(fork_url)); + let chain_id = provider.chain_id().await.context("failed to fetch forked network id")?; + + // if the id is not in ASCII encoding, we display the chain id as is in hex. + let parsed_id = match parse_cairo_short_string(&chain_id) { + Ok(id) => id, + Err(_) => format!("{chain_id:#x}"), + }; + + // If the fork block number is not specified, we use the latest accepted block on the forked + // network. + let block_id = if let Some(id) = fork_block { + id + } else { + let num = provider.block_number().await?; + BlockHashOrNumber::Num(num) + }; + + info!(chain = %parsed_id, block = %block_id, "Forking chain."); + + let block = provider + .get_block_with_tx_hashes(BlockIdOrTag::from(block_id)) + .await + .context("failed to fetch forked block")?; + + let MaybePendingBlockWithTxHashes::Block(block) = block else { + bail!("forking a pending block is not allowed") + }; + + chain.id = chain_id.into(); + chain.version = ProtocolVersion::parse(&block.starknet_version)?; + + // adjust the genesis to match the forked block + chain.genesis.timestamp = block.timestamp; + chain.genesis.number = block.block_number; + chain.genesis.state_root = block.new_root; + chain.genesis.parent_hash = block.parent_hash; + chain.genesis.sequencer_address = block.sequencer_address.into(); + chain.genesis.gas_prices.eth = + block.l1_gas_price.price_in_wei.to_u128().expect("should fit in u128"); + chain.genesis.gas_prices.strk = + block.l1_gas_price.price_in_fri.to_u128().expect("should fit in u128"); + + let status = match block.status { + BlockStatus::AcceptedOnL1 => FinalityStatus::AcceptedOnL1, + BlockStatus::AcceptedOnL2 => FinalityStatus::AcceptedOnL2, + // we already checked for pending block earlier. so this should never happen. + _ => bail!("qed; block status shouldn't be pending"), + }; + + let database = ForkedProvider::new(Arc::new(provider), block_id)?; + let block = chain.block().seal_with_hash_and_status(block.block_hash, status); let state_updates = chain.state_updates(); - Self::new_with_block_and_state(provider, block, state_updates) + + Self::new_with_genesis_block_and_state(database, block, state_updates) } pub fn provider(&self) -> &BlockchainProvider> { &self.inner } - fn new_with_block_and_state( + fn new_with_genesis_block_and_state( provider: impl Database, block: SealedBlockWithStatus, states: StateUpdatesWithDeclaredClasses, @@ -142,7 +206,6 @@ mod tests { 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, }; - use katana_primitives::genesis::Genesis; use katana_primitives::receipt::{InvokeTxReceipt, Receipt}; use katana_primitives::state::StateUpdatesWithDeclaredClasses; use katana_primitives::trace::TxExecInfo; @@ -150,8 +213,7 @@ mod tests { use katana_primitives::{chain_spec, Felt}; use katana_provider::providers::in_memory::InMemoryProvider; use katana_provider::traits::block::{ - BlockHashProvider, BlockNumberProvider, BlockProvider, BlockStatusProvider, BlockWriter, - HeaderProvider, + BlockHashProvider, BlockNumberProvider, BlockProvider, BlockWriter, }; use katana_provider::traits::state::StateFactoryProvider; use katana_provider::traits::transaction::{TransactionProvider, TransactionTraceProvider}; @@ -164,7 +226,7 @@ mod tests { fn blockchain_from_genesis_states() { let provider = InMemoryProvider::new(); - let blockchain = Blockchain::new_with_genesis(provider, &chain_spec::DEV) + let blockchain = Blockchain::new_with_chain(provider, &chain_spec::DEV) .expect("failed to create blockchain from genesis block"); let state = blockchain.provider().latest().expect("failed to get latest state"); @@ -178,50 +240,6 @@ mod tests { assert_eq!(fee_token_class_hash, DEFAULT_LEGACY_ERC20_CLASS_HASH); } - #[test] - fn blockchain_from_fork() { - let provider = InMemoryProvider::new(); - - let genesis = Genesis { - number: 23, - parent_hash: Felt::ZERO, - state_root: felt!("1334"), - timestamp: 6868, - gas_prices: GasPrices { eth: 9090, strk: 8080 }, - ..Default::default() - }; - - let mut chain = chain_spec::DEV.clone(); - chain.genesis = genesis; - - let genesis_hash = felt!("1111"); - - let blockchain = Blockchain::new_from_forked( - provider, - genesis_hash, - &chain, - FinalityStatus::AcceptedOnL1, - ) - .expect("failed to create fork blockchain"); - - let latest_number = blockchain.provider().latest_number().unwrap(); - let latest_hash = blockchain.provider().latest_hash().unwrap(); - let header = blockchain.provider().header(latest_number.into()).unwrap().unwrap(); - let block_status = - blockchain.provider().block_status(latest_number.into()).unwrap().unwrap(); - - assert_eq!(latest_number, chain.genesis.number); - assert_eq!(latest_hash, genesis_hash); - - assert_eq!(header.gas_prices.eth, 9090); - assert_eq!(header.gas_prices.strk, 8080); - assert_eq!(header.timestamp, 6868); - assert_eq!(header.number, latest_number); - assert_eq!(header.state_root, chain.genesis.state_root); - assert_eq!(header.parent_hash, chain.genesis.parent_hash); - assert_eq!(block_status, FinalityStatus::AcceptedOnL1); - } - #[test] fn blockchain_from_db() { let db_path = tempfile::TempDir::new().expect("Failed to create temp dir.").into_path(); diff --git a/crates/katana/node/Cargo.toml b/crates/katana/node/Cargo.toml index 57cf4268e3..1c460a128d 100644 --- a/crates/katana/node/Cargo.toml +++ b/crates/katana/node/Cargo.toml @@ -22,7 +22,6 @@ dojo-metrics.workspace = true futures.workspace = true hyper.workspace = true jsonrpsee.workspace = true -num-traits.workspace = true serde_json.workspace = true starknet.workspace = true tower = { workspace = true, features = [ "full" ] } diff --git a/crates/katana/node/src/config/fork.rs b/crates/katana/node/src/config/fork.rs new file mode 100644 index 0000000000..da9c91617b --- /dev/null +++ b/crates/katana/node/src/config/fork.rs @@ -0,0 +1,11 @@ +use katana_primitives::block::BlockHashOrNumber; +use starknet::providers::Url; + +/// Node forking configurations. +#[derive(Debug, Clone)] +pub struct ForkingConfig { + /// The JSON-RPC URL of the network to fork from. + pub url: Url, + /// The block number to fork from. If `None`, the latest block will be used. + pub block: Option, +} diff --git a/crates/katana/node/src/config/mod.rs b/crates/katana/node/src/config/mod.rs index f9adaaf97c..1c9fa68041 100644 --- a/crates/katana/node/src/config/mod.rs +++ b/crates/katana/node/src/config/mod.rs @@ -1,10 +1,12 @@ pub mod db; pub mod dev; +pub mod fork; pub mod metrics; pub mod rpc; use db::DbConfig; use dev::DevConfig; +use fork::ForkingConfig; use katana_core::backend::config::StarknetConfig; use katana_core::service::messaging::MessagingConfig; use katana_primitives::chain_spec::ChainSpec; @@ -22,6 +24,9 @@ pub struct Config { /// Database options. pub db: DbConfig, + /// Forking options. + pub forking: Option, + /// Rpc options. pub rpc: RpcConfig, diff --git a/crates/katana/node/src/lib.rs b/crates/katana/node/src/lib.rs index bbff280bad..53f103b9c7 100644 --- a/crates/katana/node/src/lib.rs +++ b/crates/katana/node/src/lib.rs @@ -31,10 +31,7 @@ use katana_pipeline::{stage, Pipeline}; use katana_pool::ordering::FiFo; use katana_pool::validation::stateful::TxValidator; use katana_pool::TxPool; -use katana_primitives::block::FinalityStatus; use katana_primitives::env::{CfgEnv, FeeTokenAddressses}; -use katana_primitives::version::ProtocolVersion; -use katana_provider::providers::fork::ForkedProvider; use katana_provider::providers::in_memory::InMemoryProvider; use katana_rpc::dev::DevApi; use katana_rpc::metrics::RpcServerMetrics; @@ -46,13 +43,8 @@ use katana_rpc_api::saya::SayaApiServer; use katana_rpc_api::starknet::{StarknetApiServer, StarknetTraceApiServer, StarknetWriteApiServer}; use katana_rpc_api::torii::ToriiApiServer; use katana_tasks::TaskManager; -use num_traits::ToPrimitive; -use starknet::core::types::{BlockId, BlockStatus, MaybePendingBlockWithTxHashes}; -use starknet::core::utils::parse_cairo_short_string; -use starknet::providers::jsonrpc::HttpTransport; -use starknet::providers::{JsonRpcClient, Provider}; use tower_http::cors::{AllowOrigin, CorsLayer}; -use tracing::{info, trace}; +use tracing::info; use crate::exit::NodeStoppedFuture; @@ -189,61 +181,14 @@ pub async fn build(mut config: Config) -> Result { // --- build backend - let (blockchain, db) = if let Some(forked_url) = &config.starknet.fork_rpc_url { - let provider = Arc::new(JsonRpcClient::new(HttpTransport::new(forked_url.clone()))); - let forked_chain_id = provider.chain_id().await.unwrap(); - - let forked_block_num = if let Some(num) = config.starknet.fork_block_number { - num - } else { - provider.block_number().await.expect("failed to fetch block number from forked network") - }; - - let block = - provider.get_block_with_tx_hashes(BlockId::Number(forked_block_num)).await.unwrap(); - let MaybePendingBlockWithTxHashes::Block(block) = block else { - panic!("block to be forked is a pending block") - }; - - config.chain.version = ProtocolVersion::parse(&block.starknet_version)?; - - // adjust the genesis to match the forked block - config.chain.genesis.number = block.block_number; - config.chain.genesis.state_root = block.new_root; - config.chain.genesis.parent_hash = block.parent_hash; - config.chain.genesis.timestamp = block.timestamp; - config.chain.genesis.sequencer_address = block.sequencer_address.into(); - config.chain.genesis.gas_prices.eth = - block.l1_gas_price.price_in_wei.to_u128().expect("should fit in u128"); - config.chain.genesis.gas_prices.strk = - block.l1_gas_price.price_in_fri.to_u128().expect("should fit in u128"); - - trace!( - chain = %parse_cairo_short_string(&forked_chain_id).unwrap(), - block_number = %block.block_number, - forked_url = %forked_url, - "Forking chain.", - ); - - let blockchain = Blockchain::new_from_forked( - ForkedProvider::new(provider, forked_block_num.into()).unwrap(), - block.block_hash, - &config.chain, - match block.status { - BlockStatus::AcceptedOnL1 => FinalityStatus::AcceptedOnL1, - BlockStatus::AcceptedOnL2 => FinalityStatus::AcceptedOnL2, - _ => panic!("unable to fork for non-accepted block"), - }, - )?; - - config.chain.id = forked_chain_id.into(); - - (blockchain, None) + let (blockchain, db) = if let Some(cfg) = config.forking { + let bc = Blockchain::new_from_forked(cfg.url.clone(), cfg.block, &mut config.chain).await?; + (bc, None) } else if let Some(db_path) = &config.db.dir { let db = katana_db::init_db(db_path)?; (Blockchain::new_with_db(db.clone(), &config.chain)?, Some(db)) } else { - (Blockchain::new_with_genesis(InMemoryProvider::new(), &config.chain)?, None) + (Blockchain::new_with_chain(InMemoryProvider::new(), &config.chain)?, None) }; let block_context_generator = BlockContextGenerator::default().into(); diff --git a/crates/katana/primitives/src/block.rs b/crates/katana/primitives/src/block.rs index 21579bd2bd..6a68d1d27e 100644 --- a/crates/katana/primitives/src/block.rs +++ b/crates/katana/primitives/src/block.rs @@ -15,6 +15,15 @@ pub enum BlockHashOrNumber { Num(BlockNumber), } +impl std::fmt::Display for BlockHashOrNumber { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BlockHashOrNumber::Num(num) => write!(f, "{num}"), + BlockHashOrNumber::Hash(hash) => write!(f, "{hash:#x}"), + } + } +} + /// Block number type. pub type BlockNumber = u64; /// Block hash type. @@ -187,6 +196,15 @@ impl From for BlockHashOrNumber { } } +impl From for BlockIdOrTag { + fn from(value: BlockHashOrNumber) -> Self { + match value { + BlockHashOrNumber::Hash(hash) => BlockIdOrTag::Hash(hash), + BlockHashOrNumber::Num(number) => BlockIdOrTag::Number(number), + } + } +} + /// A block that can executed. This is a block whose transactions includes /// all the necessary information to be executed. #[derive(Debug, Clone)] diff --git a/crates/katana/storage/provider/src/providers/fork/backend.rs b/crates/katana/storage/provider/src/providers/fork/backend.rs index 8b41259fd1..265aa502a3 100644 --- a/crates/katana/storage/provider/src/providers/fork/backend.rs +++ b/crates/katana/storage/provider/src/providers/fork/backend.rs @@ -22,7 +22,7 @@ use katana_primitives::Felt; use parking_lot::Mutex; use starknet::core::types::{BlockId, ContractClass as RpcContractClass, StarknetError}; use starknet::providers::{Provider, ProviderError as StarknetProviderError}; -use tracing::{error, info, trace}; +use tracing::{error, trace}; use crate::error::ProviderError; use crate::providers::in_memory::cache::CacheStateDb; @@ -152,7 +152,7 @@ where }) .map_err(BackendError::BackendThreadInit)?; - info!(target: LOG_TARGET, "Forking backend started."); + trace!(target: LOG_TARGET, "Forking backend started."); Ok(handle) }