use crate::{
AttributesBuilderConfig, DerivationContext, EngineContext, L1WatcherRpcContext, NetworkContext,
NodeActor, NodeMode, RpcContext, SequencerContext, SequencerInboundData,
actors::{
DerivationInboundChannels, EngineInboundData, L1WatcherRpcInboundChannels,
NetworkInboundData, PipelineBuilder,
},
service::spawn_and_wait,
};
use async_trait::async_trait;
use kona_derive::{AttributesBuilder, Pipeline, SignalReceiver};
use std::fmt::Display;
use tokio_util::sync::CancellationToken;
#[async_trait]
pub trait RollupNodeService {
type DataAvailabilityWatcher: NodeActor<
Error: Display,
OutboundData = L1WatcherRpcContext,
InboundData = L1WatcherRpcInboundChannels,
>;
type DerivationPipeline: Pipeline + SignalReceiver + Send + Sync + 'static;
type DerivationActor: NodeActor<
Error: Display,
Builder: PipelineBuilder<Pipeline = Self::DerivationPipeline>,
OutboundData = DerivationContext,
InboundData = DerivationInboundChannels,
>;
type EngineActor: NodeActor<Error: Display, OutboundData = EngineContext, InboundData = EngineInboundData>;
type NetworkActor: NodeActor<Error: Display, OutboundData = NetworkContext, InboundData = NetworkInboundData>;
type AttributesBuilder: AttributesBuilder + Send + Sync + 'static;
type SequencerActor: NodeActor<
Error: Display,
OutboundData = SequencerContext,
Builder: AttributesBuilderConfig<AB = Self::AttributesBuilder>,
InboundData = SequencerInboundData,
>;
type RpcActor: NodeActor<Error: Display, OutboundData = RpcContext, InboundData = ()>;
fn mode(&self) -> NodeMode;
fn da_watcher_builder(&self) -> <Self::DataAvailabilityWatcher as NodeActor>::Builder;
fn derivation_builder(&self) -> <Self::DerivationActor as NodeActor>::Builder;
fn network_builder(&self) -> <Self::NetworkActor as NodeActor>::Builder;
fn engine_builder(&self) -> <Self::EngineActor as NodeActor>::Builder;
fn rpc_builder(&self) -> Option<<Self::RpcActor as NodeActor>::Builder>;
fn sequencer_builder(&self) -> <Self::SequencerActor as NodeActor>::Builder;
async fn start(&self) -> Result<(), String> {
let cancellation = CancellationToken::new();
let (L1WatcherRpcInboundChannels { inbound_queries: da_watcher_rpc }, da_watcher) =
Self::DataAvailabilityWatcher::build(self.da_watcher_builder());
let (
DerivationInboundChannels {
derivation_signal_tx,
l1_head_updates_tx,
engine_l2_safe_head_tx,
el_sync_complete_tx,
},
derivation,
) = Self::DerivationActor::build(self.derivation_builder());
let (
EngineInboundData {
build_request_tx,
attributes_tx,
unsafe_block_tx,
reset_request_tx,
inbound_queries_tx: engine_rpc,
finalized_l1_block_tx,
},
engine,
) = Self::EngineActor::build(self.engine_builder());
let (
NetworkInboundData {
signer,
p2p_rpc: network_rpc,
gossip_payload_tx,
admin_rpc: net_admin_rpc,
},
network,
) = Self::NetworkActor::build(self.network_builder());
let (_, rpc) = self.rpc_builder().map(Self::RpcActor::build).unzip();
let (sequencer_inbound_data, sequencer) = self
.mode()
.is_sequencer()
.then_some(Self::SequencerActor::build(self.sequencer_builder()))
.unzip();
spawn_and_wait!(
cancellation,
actors = [
rpc.map(|r| (
r,
RpcContext {
cancellation: cancellation.clone(),
p2p_network: network_rpc,
network_admin: net_admin_rpc,
sequencer_admin: sequencer_inbound_data.as_ref().map(|s| s.admin_query_tx.clone()),
l1_watcher_queries: da_watcher_rpc,
engine_query: engine_rpc,
}
)),
sequencer.map(|s| (
s,
SequencerContext {
l1_head_rx: l1_head_updates_tx.subscribe(),
reset_request_tx: reset_request_tx.clone(),
build_request_tx: build_request_tx.expect(
"`build_request_tx` not set while in sequencer mode. This should never happen.",
),
gossip_payload_tx,
cancellation: cancellation.clone(),
})
),
Some((
network,
NetworkContext { blocks: unsafe_block_tx, cancellation: cancellation.clone() }
)),
Some((
da_watcher,
L1WatcherRpcContext {
latest_head: l1_head_updates_tx,
latest_finalized: finalized_l1_block_tx,
block_signer_sender: signer,
cancellation: cancellation.clone(),
})
),
Some((
derivation,
DerivationContext {
reset_request_tx: reset_request_tx.clone(),
derived_attributes_tx: attributes_tx,
cancellation: cancellation.clone(),
})),
Some((engine,
EngineContext {
engine_l2_safe_head_tx,
engine_unsafe_head_tx: sequencer_inbound_data
.map(|s| s.unsafe_head_tx),
sync_complete_tx: el_sync_complete_tx,
derivation_signal_tx,
cancellation: cancellation.clone(),
})
),
]
);
Ok(())
}
}