Skip to content

Commit 81be2d3

Browse files
kariyclaude
andcommitted
refactor(cli): move sidecar bootstrapping from node to CLI
Move the sidecar bootstrap code (contract deployment for paymaster and VRF) from the node module to the CLI layer. The node now only contains VRF account derivation logic needed for CartridgeApi configuration. The CLI is now responsible for: - Deploying forwarder contracts for paymaster - Deploying VRF account and consumer contracts - Starting and managing sidecar processes This further decouples the node from sidecar management, making the node treat all paymaster/VRF services as purely external. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3ce85f4 commit 81be2d3

File tree

6 files changed

+806
-606
lines changed

6 files changed

+806
-606
lines changed

Cargo.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cli/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ version.workspace = true
88
[dependencies]
99
katana-chain-spec.workspace = true
1010
katana-core.workspace = true
11+
katana-executor.workspace = true
1112
katana-messaging.workspace = true
1213
katana-node.workspace = true
1314
katana-genesis.workspace = true
15+
katana-pool.workspace = true
16+
katana-pool-api.workspace = true
1417
katana-primitives.workspace = true
18+
katana-provider.workspace = true
1519
katana-rpc-server.workspace = true
20+
katana-rpc-types.workspace = true
1621
katana-slot-controller = { workspace = true, optional = true }
1722
katana-tee = { workspace = true, optional = true }
1823
katana-tracing.workspace = true
@@ -21,12 +26,16 @@ serde-utils.workspace = true
2126

2227
alloy-primitives.workspace = true
2328
anyhow.workspace = true
29+
ark-ff = { version = "0.4.2", optional = true }
2430
clap.workspace = true
2531
console.workspace = true
32+
futures.workspace = true
2633
reqwest = { workspace = true, optional = true }
2734
serde.workspace = true
2835
serde_json.workspace = true
2936
shellexpand = "3.1.0"
37+
stark-vrf = { workspace = true, optional = true }
38+
starknet = { workspace = true, optional = true }
3039
tokio.workspace = true
3140
toml.workspace = true
3241
tracing.workspace = true
@@ -41,11 +50,14 @@ starknet.workspace = true
4150
paymaster = [
4251
"dep:katana-slot-controller",
4352
"dep:reqwest",
53+
"dep:starknet",
4454
"katana-node/paymaster",
4555
"katana-rpc-server/paymaster",
4656
]
4757
vrf = [
4858
"paymaster",
59+
"dep:ark-ff",
60+
"dep:stark-vrf",
4961
"katana-node/vrf",
5062
"katana-rpc-server/vrf",
5163
]

crates/cli/src/args.rs

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,11 @@ impl SequencerNodeArgs {
212212
// Launch the node
213213
let handle = node.launch().await.context("failed to launch forked node")?;
214214

215-
// Start sidecars if needed (sidecar processes are managed by CLI)
215+
// Bootstrap and start sidecars if needed
216216
#[cfg(feature = "paymaster")]
217-
let mut sidecars = start_sidecars_if_needed(
217+
let mut sidecars = bootstrap_and_start_sidecars(
218218
self,
219-
handle.sidecar_bootstrap(),
219+
handle.node(),
220220
handle.rpc().addr(),
221221
paymaster_sidecar.as_ref(),
222222
#[cfg(feature = "vrf")]
@@ -249,11 +249,11 @@ impl SequencerNodeArgs {
249249
// Launch the node
250250
let handle = node.launch().await.context("failed to launch node")?;
251251

252-
// Start sidecars if needed (sidecar processes are managed by CLI)
252+
// Bootstrap and start sidecars if needed
253253
#[cfg(feature = "paymaster")]
254-
let mut sidecars = start_sidecars_if_needed(
254+
let mut sidecars = bootstrap_and_start_sidecars(
255255
self,
256-
handle.sidecar_bootstrap(),
256+
handle.node(),
257257
handle.rpc().addr(),
258258
paymaster_sidecar.as_ref(),
259259
#[cfg(feature = "vrf")]
@@ -775,51 +775,89 @@ impl SequencerNodeArgs {
775775
}
776776
}
777777

778-
/// Start sidecar processes if needed based on the configuration.
778+
/// Bootstrap contracts and start sidecar processes if needed.
779779
///
780-
/// This function is called after the node is launched to start any sidecar processes
781-
/// that are configured in sidecar mode (not external mode).
780+
/// This function is called after the node is launched to:
781+
/// 1. Bootstrap necessary contracts (forwarder, VRF accounts)
782+
/// 2. Start sidecar processes in sidecar mode
782783
#[cfg(feature = "paymaster")]
783-
async fn start_sidecars_if_needed(
784+
async fn bootstrap_and_start_sidecars<P>(
784785
args: &SequencerNodeArgs,
785-
bootstrap: &katana_node::sidecar::BootstrapResult,
786+
node: &katana_node::Node<P>,
786787
rpc_addr: &std::net::SocketAddr,
787788
paymaster_sidecar: Option<&PaymasterSidecarInfo>,
788789
#[cfg(feature = "vrf")] vrf_sidecar: Option<&VrfSidecarInfo>,
789-
) -> Result<Option<crate::sidecar::SidecarProcesses>> {
790+
) -> Result<Option<crate::sidecar::SidecarProcesses>>
791+
where
792+
P: katana_provider::ProviderFactory + Clone,
793+
<P as katana_provider::ProviderFactory>::Provider:
794+
katana_core::backend::storage::ProviderRO,
795+
<P as katana_provider::ProviderFactory>::ProviderMut:
796+
katana_core::backend::storage::ProviderRW,
797+
{
790798
#[cfg(feature = "vrf")]
791-
use crate::sidecar::VrfSidecarConfig;
792-
use crate::sidecar::{start_sidecars, PaymasterSidecarConfig, SidecarStartConfig};
799+
use crate::sidecar::{VrfBootstrapConfig, VrfKeySource, VrfSidecarConfig};
800+
use crate::sidecar::{
801+
bootstrap_sidecars, start_sidecars, BootstrapConfig, PaymasterSidecarConfig,
802+
SidecarStartConfig,
803+
};
804+
805+
// If no sidecars need to be started, return None
806+
#[cfg(feature = "vrf")]
807+
let has_sidecars = paymaster_sidecar.is_some() || vrf_sidecar.is_some();
808+
#[cfg(not(feature = "vrf"))]
809+
let has_sidecars = paymaster_sidecar.is_some();
810+
811+
if !has_sidecars {
812+
return Ok(None);
813+
}
793814

794-
// Build paymaster sidecar config if needed
815+
// Build bootstrap config
816+
let bootstrap_config = BootstrapConfig {
817+
paymaster_prefunded_index: paymaster_sidecar.map(|_| args.paymaster.prefunded_index),
818+
#[cfg(feature = "vrf")]
819+
vrf: vrf_sidecar.map(|_| {
820+
let key_source = match args.vrf.key_source {
821+
crate::options::VrfKeySource::Prefunded => VrfKeySource::Prefunded,
822+
crate::options::VrfKeySource::Sequencer => VrfKeySource::Sequencer,
823+
};
824+
VrfBootstrapConfig {
825+
key_source,
826+
prefunded_index: args.vrf.prefunded_index,
827+
sequencer_address: node.config().chain.genesis().sequencer_address,
828+
}
829+
}),
830+
fee_enabled: node.config().dev.fee,
831+
};
832+
833+
// Bootstrap contracts
834+
let bootstrap = bootstrap_sidecars(
835+
&bootstrap_config,
836+
node.backend(),
837+
node.block_producer(),
838+
node.pool(),
839+
)
840+
.await?;
841+
842+
// Build sidecar start config
795843
let paymaster_config = paymaster_sidecar.map(|info| PaymasterSidecarConfig {
796844
options: &args.paymaster,
797845
port: info.port,
798846
api_key: info.api_key.clone(),
799847
});
800848

801-
// Build VRF sidecar config if needed
802849
#[cfg(feature = "vrf")]
803850
let vrf_config =
804851
vrf_sidecar.map(|info| VrfSidecarConfig { options: &args.vrf, port: info.port });
805852

806-
// If no sidecars need to be started, return None
807-
#[cfg(feature = "vrf")]
808-
let has_sidecars = paymaster_config.is_some() || vrf_config.is_some();
809-
#[cfg(not(feature = "vrf"))]
810-
let has_sidecars = paymaster_config.is_some();
811-
812-
if !has_sidecars {
813-
return Ok(None);
814-
}
815-
816-
let config = SidecarStartConfig {
853+
let start_config = SidecarStartConfig {
817854
paymaster: paymaster_config,
818855
#[cfg(feature = "vrf")]
819856
vrf: vrf_config,
820857
};
821858

822-
let processes = start_sidecars(&config, bootstrap, rpc_addr).await?;
859+
// Start sidecar processes
860+
let processes = start_sidecars(&start_config, &bootstrap, rpc_addr).await?;
823861
Ok(Some(processes))
824862
}
825863

0 commit comments

Comments
 (0)