Skip to content

Commit

Permalink
refactor(katana-rpc): remove some components dependency from starknet…
Browse files Browse the repository at this point in the history
… rpc handler (dojoengine#2759)

the idea is to make the StarknetApi struct not depend on components that are not shared in a full and sequencer node configuration.
  • Loading branch information
kariy authored and augustin-v committed Dec 4, 2024
1 parent 75866dd commit e7c98c5
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 50 deletions.
17 changes: 4 additions & 13 deletions crates/katana/node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use katana_executor::implementation::blockifier::BlockifierFactory;
use katana_executor::{ExecutionFlags, ExecutorFactory};
use katana_pipeline::stage::Sequencing;
use katana_pool::ordering::FiFo;
use katana_pool::validation::stateful::TxValidator;
use katana_pool::TxPool;
use katana_primitives::block::GasPrices;
use katana_primitives::env::{CfgEnv, FeeTokenAddressses};
Expand Down Expand Up @@ -120,7 +119,6 @@ impl Node {
let pool = self.pool.clone();
let backend = self.backend.clone();
let block_producer = self.block_producer.clone();
let validator = self.block_producer.validator().clone();

// --- build and run sequencing task

Expand All @@ -139,7 +137,7 @@ impl Node {
.name("Sequencing")
.spawn(sequencing.into_future());

let node_components = (pool, backend, block_producer, validator, self.forked_client.take());
let node_components = (pool, backend, block_producer, self.forked_client.take());
let rpc = spawn(node_components, self.config.rpc.clone()).await?;

// --- build and start the gas oracle worker task
Expand Down Expand Up @@ -266,16 +264,10 @@ pub async fn build(mut config: Config) -> Result<Node> {

// Moved from `katana_rpc` crate
pub async fn spawn<EF: ExecutorFactory>(
node_components: (
TxPool,
Arc<Backend<EF>>,
BlockProducer<EF>,
TxValidator,
Option<ForkedClient>,
),
node_components: (TxPool, Arc<Backend<EF>>, BlockProducer<EF>, Option<ForkedClient>),
config: RpcConfig,
) -> Result<RpcServer> {
let (pool, backend, block_producer, validator, forked_client) = node_components;
let (pool, backend, block_producer, forked_client) = node_components;

let mut methods = RpcModule::new(());
methods.register_method("health", |_, _| Ok(serde_json::json!({ "health": true })))?;
Expand All @@ -288,12 +280,11 @@ pub async fn spawn<EF: ExecutorFactory>(
backend.clone(),
pool.clone(),
block_producer.clone(),
validator,
client,
cfg,
)
} else {
StarknetApi::new(backend.clone(), pool.clone(), block_producer.clone(), validator, cfg)
StarknetApi::new(backend.clone(), pool.clone(), Some(block_producer.clone()), cfg)
};

methods.merge(StarknetApiServer::into_rpc(server.clone()))?;
Expand Down
7 changes: 7 additions & 0 deletions crates/katana/rpc/rpc/src/starknet/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[derive(Debug, Clone)]
pub struct StarknetApiConfig {
/// The max chunk size that can be served from the `getEvents` method.
///
/// If `None`, the maximum chunk size is bounded by [`u64::MAX`].
pub max_event_page_size: Option<u64>,
}
86 changes: 49 additions & 37 deletions crates/katana/rpc/rpc/src/starknet/mod.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
//! Server implementation for the Starknet JSON-RPC API.
pub mod forking;
mod read;
mod trace;
mod write;

use std::sync::Arc;

use forking::ForkedClient;
use katana_core::backend::Backend;
use katana_core::service::block_producer::{BlockProducer, BlockProducerMode, PendingExecutor};
use katana_executor::{ExecutionResult, ExecutorFactory};
use katana_pool::validation::stateful::TxValidator;
use katana_pool::{TransactionPool, TxPool};
use katana_primitives::block::{
BlockHash, BlockHashOrNumber, BlockIdOrTag, BlockNumber, BlockTag, FinalityStatus,
Expand Down Expand Up @@ -51,75 +44,85 @@ use starknet::core::types::{
use crate::utils;
use crate::utils::events::{Cursor, EventBlockId};

pub type StarknetApiResult<T> = Result<T, StarknetApiError>;
mod config;
pub mod forking;
mod read;
mod trace;
mod write;

#[allow(missing_debug_implementations)]
pub struct StarknetApi<EF: ExecutorFactory> {
inner: Arc<Inner<EF>>,
}
pub use config::StarknetApiConfig;
use forking::ForkedClient;

#[derive(Debug, Clone)]
pub struct StarknetApiConfig {
pub max_event_page_size: Option<u64>,
}
type StarknetApiResult<T> = Result<T, StarknetApiError>;

impl<EF: ExecutorFactory> Clone for StarknetApi<EF> {
fn clone(&self) -> Self {
Self { inner: Arc::clone(&self.inner) }
}
/// Handler for the Starknet JSON-RPC server.
///
/// This struct implements all the JSON-RPC traits required to serve the Starknet API (ie,
/// [read](katana_rpc_api::starknet::StarknetApi),
/// [write](katana_rpc_api::starknet::StarknetWriteApi), and
/// [trace](katana_rpc_api::starknet::StarknetTraceApi) APIs.
#[allow(missing_debug_implementations)]
pub struct StarknetApi<EF>
where
EF: ExecutorFactory,
{
inner: Arc<StarknetApiInner<EF>>,
}

struct Inner<EF: ExecutorFactory> {
validator: TxValidator,
struct StarknetApiInner<EF>
where
EF: ExecutorFactory,
{
pool: TxPool,
backend: Arc<Backend<EF>>,
block_producer: BlockProducer<EF>,
blocking_task_pool: BlockingTaskPool,
forked_client: Option<ForkedClient>,
blocking_task_pool: BlockingTaskPool,
block_producer: Option<BlockProducer<EF>>,
config: StarknetApiConfig,
}

impl<EF: ExecutorFactory> StarknetApi<EF> {
impl<EF> StarknetApi<EF>
where
EF: ExecutorFactory,
{
pub fn new(
backend: Arc<Backend<EF>>,
pool: TxPool,
block_producer: BlockProducer<EF>,
validator: TxValidator,
block_producer: Option<BlockProducer<EF>>,
config: StarknetApiConfig,
) -> Self {
Self::new_inner(backend, pool, block_producer, validator, None, config)
Self::new_inner(backend, pool, block_producer, None, config)
}

pub fn new_forked(
backend: Arc<Backend<EF>>,
pool: TxPool,
block_producer: BlockProducer<EF>,
validator: TxValidator,
forked_client: ForkedClient,
config: StarknetApiConfig,
) -> Self {
Self::new_inner(backend, pool, block_producer, validator, Some(forked_client), config)
Self::new_inner(backend, pool, Some(block_producer), Some(forked_client), config)
}

fn new_inner(
backend: Arc<Backend<EF>>,
pool: TxPool,
block_producer: BlockProducer<EF>,
validator: TxValidator,
block_producer: Option<BlockProducer<EF>>,
forked_client: Option<ForkedClient>,
config: StarknetApiConfig,
) -> Self {
let blocking_task_pool =
BlockingTaskPool::new().expect("failed to create blocking task pool");
let inner = Inner {

let inner = StarknetApiInner {
pool,
backend,
block_producer,
blocking_task_pool,
validator,
forked_client,
config,
};

Self { inner: Arc::new(inner) }
}

Expand Down Expand Up @@ -184,10 +187,10 @@ impl<EF: ExecutorFactory> StarknetApi<EF> {

/// Returns the pending state if the sequencer is running in _interval_ mode. Otherwise `None`.
fn pending_executor(&self) -> Option<PendingExecutor> {
match &*self.inner.block_producer.producer.read() {
self.inner.block_producer.as_ref().and_then(|bp| match &*bp.producer.read() {
BlockProducerMode::Instant(_) => None,
BlockProducerMode::Interval(producer) => Some(producer.executor()),
}
})
}

fn state(&self, block_id: &BlockIdOrTag) -> StarknetApiResult<Box<dyn StateProvider>> {
Expand Down Expand Up @@ -357,7 +360,7 @@ impl<EF: ExecutorFactory> StarknetApi<EF> {
// TODO: this is a temporary solution, we should have a better way to handle this.
// perhaps a pending/pool state provider that implements all the state provider traits.
let result = if let BlockIdOrTag::Tag(BlockTag::Pending) = block_id {
this.inner.validator.pool_nonce(contract_address)?
this.inner.pool.validator().pool_nonce(contract_address)?
} else {
let state = this.state(&block_id)?;
state.nonce(contract_address)?
Expand Down Expand Up @@ -1122,3 +1125,12 @@ impl<EF: ExecutorFactory> StarknetApi<EF> {
Ok(id)
}
}

impl<EF> Clone for StarknetApi<EF>
where
EF: ExecutorFactory,
{
fn clone(&self) -> Self {
Self { inner: Arc::clone(&self.inner) }
}
}

0 comments on commit e7c98c5

Please sign in to comment.