forc_node/ignition/
op.rs

1use super::cmd::IgnitionCmd;
2use crate::{
3    chain_config::{check_and_update_chain_config, ChainConfig},
4    consts::{
5        MAINNET_BOOTSTRAP_NODE, MAINNET_RELAYER_DA_DEPLOY_HEIGHT,
6        MAINNET_RELAYER_LISTENING_CONTRACT, MAINNET_RELAYER_LOG_PAGE_SIZE, MAINNET_SERVICE_NAME,
7        MAINNET_SYNC_HEADER_BATCH_SIZE,
8    },
9    run_opts::{DbType, RunOpts},
10    util::{ask_user_keypair, ask_user_string, HumanReadableCommand, KeyPair},
11};
12use anyhow::Context;
13use forc_tracing::println_green;
14use std::{
15    net::IpAddr,
16    path::PathBuf,
17    process::{Child, Command},
18};
19/// Configures the node with testnet configuration to connect the node to latest testnet.
20/// Returns `None` if this is a dry_run and no child process created for fuel-core.
21pub(crate) async fn run(cmd: IgnitionCmd, dry_run: bool) -> anyhow::Result<Option<Child>> {
22    check_and_update_chain_config(ChainConfig::Testnet).await?;
23    let keypair = if let (Some(peer_id), Some(secret)) = (
24        &cmd.connection_settings.peer_id,
25        &cmd.connection_settings.secret,
26    ) {
27        KeyPair {
28            peer_id: peer_id.to_string(),
29            secret: secret.to_string(),
30        }
31    } else {
32        ask_user_keypair()?
33    };
34
35    let relayer = cmd
36        .connection_settings
37        .relayer
38        .map_or_else(|| ask_user_string("Ethereum RPC (mainnet) Endpoint:"), Ok)?;
39
40    let opts = IgnitionOpts {
41        keypair,
42        relayer,
43        ip: cmd.connection_settings.ip,
44        port: cmd.connection_settings.port,
45        peering_port: cmd.connection_settings.peering_port,
46        db_path: cmd.db_path,
47    };
48    let run_opts = RunOpts::from(opts);
49    let params = run_opts.generate_params();
50    let mut fuel_core_command = Command::new("fuel-core");
51    fuel_core_command.arg("run");
52    fuel_core_command.args(params.as_slice());
53
54    println_green(&format!(
55        "{}",
56        HumanReadableCommand::from(&fuel_core_command)
57    ));
58
59    if dry_run {
60        return Ok(None);
61    }
62
63    // Spawn the process with proper error handling
64    let handle = fuel_core_command
65        .spawn()
66        .with_context(|| "Failed to spawn fuel-core process:".to_string())?;
67    Ok(Some(handle))
68}
69
70#[derive(Debug)]
71pub struct IgnitionOpts {
72    keypair: KeyPair,
73    relayer: String,
74    ip: IpAddr,
75    port: u16,
76    peering_port: u16,
77    db_path: PathBuf,
78}
79
80impl From<IgnitionOpts> for RunOpts {
81    fn from(value: IgnitionOpts) -> Self {
82        Self {
83            service_name: Some(MAINNET_SERVICE_NAME.to_string()),
84            db_type: DbType::RocksDb,
85            debug: false,
86            snapshot: ChainConfig::Testnet.into(),
87            keypair: Some(value.keypair.secret),
88            relayer: Some(value.relayer),
89            ip: Some(value.ip),
90            port: Some(value.port),
91            peering_port: Some(value.peering_port),
92            db_path: Some(value.db_path),
93            utxo_validation: true,
94            poa_instant: false,
95            enable_p2p: true,
96            sync_header_batch_size: Some(MAINNET_SYNC_HEADER_BATCH_SIZE),
97            enable_relayer: true,
98            relayer_listener: Some(MAINNET_RELAYER_LISTENING_CONTRACT.to_string()),
99            relayer_da_deploy_height: Some(MAINNET_RELAYER_DA_DEPLOY_HEIGHT),
100            relayer_log_page_size: Some(MAINNET_RELAYER_LOG_PAGE_SIZE),
101            sync_block_stream_buffer_size: Some(MAINNET_SYNC_HEADER_BATCH_SIZE),
102            bootstrap_nodes: Some(MAINNET_BOOTSTRAP_NODE.to_string()),
103        }
104    }
105}