Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add enable-relayer flag to fuel-core CLI #1279

Merged
merged 18 commits into from
Aug 15, 2023
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Description of the upcoming release here.
- [#1293](https://github.com/FuelLabs/fuel-core/issues/1293): Parallelized the `estimate_predicates` endpoint to utilize all available threads.

#### Breaking
- [#1279](https://github.com/FuelLabs/fuel-core/pull/1279): Added a new CLI flag to enable the Relayer service `--enable-relayer`, and disabled the Relayer service by default. When supplying the `--enable-relayer` flag, the `--relayer` argument becomes mandatory, and omitting it is an error. Similarly, providing a `--relayer` argument without the `--enable-relayer` flag is an error. Lastly, providing the `--keypair` or `--network` arguments will also produce an error if the `--enable-p2p` flag is not set.
- [#1262](https://github.com/FuelLabs/fuel-core/pull/1262): The `ConsensusParameters` aggregates all configuration data related to the consensus. It contains many fields that are segregated by the usage. The API of some functions was affected to use lesser types instead the whole `ConsensusParameters`. It is a huge breaking change requiring repetitively monotonically updating all places that use the `ConsensusParameters`. But during updating, consider that maybe you can use lesser types. Usage of them may simplify signatures of methods and make them more user-friendly and transparent.
- [#1290](https://github.com/FuelLabs/fuel-core/pull/1290): Standardize CLI args to use `-` instead of `_`

Expand Down
12 changes: 8 additions & 4 deletions bin/fuel-core/src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ pub struct Command {
#[arg(long = "coinbase-recipient", env)]
pub coinbase_recipient: Option<String>,

#[cfg_attr(feature = "relayer", clap(flatten))]
#[cfg(feature = "relayer")]
#[clap(flatten)]
pub relayer_args: relayer::RelayerArgs,

#[cfg_attr(feature = "p2p", clap(flatten))]
Expand Down Expand Up @@ -236,6 +236,9 @@ impl Command {

let chain_conf: ChainConfig = chain_config.as_str().parse()?;

#[cfg(feature = "relayer")]
let relayer_cfg = relayer_args.into_config();

#[cfg(feature = "p2p")]
let p2p_cfg = p2p_args.into_config(metrics)?;

Expand Down Expand Up @@ -314,7 +317,7 @@ impl Command {
block_executor: Default::default(),
block_importer: Default::default(),
#[cfg(feature = "relayer")]
relayer: relayer_args.into(),
relayer: relayer_cfg,
#[cfg(feature = "p2p")]
p2p: p2p_cfg,
#[cfg(feature = "p2p")]
Expand Down Expand Up @@ -342,8 +345,9 @@ pub async fn exec(command: Command) -> anyhow::Result<()> {
.unwrap_or_else(|| "default_network".to_string())
}
#[cfg(not(feature = "p2p"))]
"default_network".to_string()
};
"default_network"
}
.to_string();
// log fuel-core version
info!("Fuel Core version v{}", env!("CARGO_PKG_VERSION"));
trace!("Initializing in TRACE mode.");
Expand Down
169 changes: 86 additions & 83 deletions bin/fuel-core/src/cli/run/p2p.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use anyhow::anyhow;
use clap::Args;
use clap::{
builder::ArgPredicate::IsPresent,
Args,
};
use fuel_core::{
p2p::{
config::{
Expand Down Expand Up @@ -34,17 +37,19 @@ const MAX_RESPONSE_SIZE_STR: &str = const_format::formatcp!("{MAX_RESPONSE_SIZE}
pub struct P2PArgs {
/// Enable P2P. By default, P2P is disabled, even when the binary is compiled with the "p2p"
/// feature flag. Providing `--enable-p2p` will enable the P2P service.
#[clap(long, short, action)]
#[clap(long = "enable-p2p", action)]
pub enable_p2p: bool,

/// Peering secret key. Supports either a hex encoded secret key inline or a path to bip32 mnemonic encoded secret file.
#[clap(long = "keypair", env, value_parser = KeypairArg::try_from_string)]
#[arg(required_if_eq("enable_p2p", "true"))]
#[arg(requires_if(IsPresent, "enable_p2p"))]
pub keypair: Option<KeypairArg>,

/// The name of the p2p Network
#[clap(long = "network", env)]
#[arg(required_if_eq("enable_p2p", "true"))]
#[arg(requires_if(IsPresent, "enable_p2p"))]
pub network: Option<String>,

/// p2p network's IP Address
Expand Down Expand Up @@ -217,88 +222,86 @@ impl P2PArgs {
self,
metrics: bool,
) -> anyhow::Result<Option<Config<NotInitialized>>> {
if self.enable_p2p {
let local_keypair = {
match self.keypair.expect("mandatory value") {
KeypairArg::Path(path) => {
let phrase = std::fs::read_to_string(path)?;
let secret_key =
fuel_crypto::SecretKey::new_from_mnemonic_phrase_with_path(
&phrase,
"m/44'/60'/0'/0/0",
)?;

convert_to_libp2p_keypair(&mut secret_key.to_vec())?
}
KeypairArg::InlineSecret(secret_key) => {
convert_to_libp2p_keypair(&mut secret_key.to_vec())?
}
}
};

let gossipsub_config = default_gossipsub_builder()
.mesh_n(self.ideal_mesh_size)
.mesh_n_low(self.min_mesh_size)
.mesh_n_high(self.max_mesh_size)
.history_length(self.history_length)
.history_gossip(self.history_gossip)
.heartbeat_interval(Duration::from_secs(self.gossip_heartbeat_interval))
.max_transmit_size(self.max_transmit_size)
.build()
.expect("valid gossipsub configuration");

let random_walk = if self.random_walk == 0 {
None
} else {
Some(Duration::from_secs(self.random_walk))
};

let heartbeat_config = {
let send_duration = Duration::from_secs(self.heartbeat_send_duration);
let idle_duration = Duration::from_secs(self.heartbeat_idle_duration);
HeartbeatConfig::new(
send_duration,
idle_duration,
self.heartbeat_max_failures,
)
};

let config = Config {
keypair: local_keypair,
network_name: self.network.expect("mandatory value"),
checksum: Default::default(),
address: self
.address
.unwrap_or_else(|| IpAddr::V4(Ipv4Addr::from([0, 0, 0, 0]))),
public_address: self.public_address,
tcp_port: self.peering_port,
max_block_size: self.max_block_size,
bootstrap_nodes: self.bootstrap_nodes,
reserved_nodes: self.reserved_nodes,
reserved_nodes_only_mode: self.reserved_nodes_only_mode,
enable_mdns: self.enable_mdns,
max_peers_connected: self.max_peers_connected,
max_connections_per_peer: self.max_connections_per_peer,
allow_private_addresses: self.allow_private_addresses,
random_walk,
connection_idle_timeout: Some(Duration::from_secs(
self.connection_idle_timeout,
)),
gossipsub_config,
heartbeat_config,
set_request_timeout: Duration::from_secs(self.request_timeout),
set_connection_keep_alive: Duration::from_secs(
self.connection_keep_alive,
),
info_interval: Some(Duration::from_secs(self.info_interval)),
identify_interval: Some(Duration::from_secs(self.identify_interval)),
metrics,
state: NotInitialized,
};
Ok(Some(config))
} else {
if !self.enable_p2p {
tracing::info!("P2P service disabled");
Ok(None)
return Ok(None)
}

let local_keypair = {
match self.keypair.expect("mandatory value") {
KeypairArg::Path(path) => {
let phrase = std::fs::read_to_string(path)?;
let secret_key =
fuel_crypto::SecretKey::new_from_mnemonic_phrase_with_path(
&phrase,
"m/44'/60'/0'/0/0",
)?;

convert_to_libp2p_keypair(&mut secret_key.to_vec())?
}
KeypairArg::InlineSecret(secret_key) => {
convert_to_libp2p_keypair(&mut secret_key.to_vec())?
}
}
};

let gossipsub_config = default_gossipsub_builder()
.mesh_n(self.ideal_mesh_size)
.mesh_n_low(self.min_mesh_size)
.mesh_n_high(self.max_mesh_size)
.history_length(self.history_length)
.history_gossip(self.history_gossip)
.heartbeat_interval(Duration::from_secs(self.gossip_heartbeat_interval))
.max_transmit_size(self.max_transmit_size)
.build()
.expect("valid gossipsub configuration");

let random_walk = if self.random_walk == 0 {
None
} else {
Some(Duration::from_secs(self.random_walk))
};

let heartbeat_config = {
let send_duration = Duration::from_secs(self.heartbeat_send_duration);
let idle_duration = Duration::from_secs(self.heartbeat_idle_duration);
HeartbeatConfig::new(
send_duration,
idle_duration,
self.heartbeat_max_failures,
)
};

let config = Config {
keypair: local_keypair,
network_name: self.network.expect("mandatory value"),
checksum: Default::default(),
address: self
.address
.unwrap_or_else(|| IpAddr::V4(Ipv4Addr::from([0, 0, 0, 0]))),
public_address: self.public_address,
tcp_port: self.peering_port,
max_block_size: self.max_block_size,
bootstrap_nodes: self.bootstrap_nodes,
reserved_nodes: self.reserved_nodes,
reserved_nodes_only_mode: self.reserved_nodes_only_mode,
enable_mdns: self.enable_mdns,
max_peers_connected: self.max_peers_connected,
max_connections_per_peer: self.max_connections_per_peer,
allow_private_addresses: self.allow_private_addresses,
random_walk,
connection_idle_timeout: Some(Duration::from_secs(
self.connection_idle_timeout,
)),
gossipsub_config,
heartbeat_config,
set_request_timeout: Duration::from_secs(self.request_timeout),
set_connection_keep_alive: Duration::from_secs(self.connection_keep_alive),
info_interval: Some(Duration::from_secs(self.info_interval)),
identify_interval: Some(Duration::from_secs(self.identify_interval)),
metrics,
state: NotInitialized,
};
Ok(Some(config))
}
}
43 changes: 30 additions & 13 deletions bin/fuel-core/src/cli/run/relayer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use clap::Args;
use clap::{
builder::ArgPredicate::IsPresent,
Args,
};
use core::time::Duration;
use fuel_core::{
relayer::{
Expand All @@ -11,9 +14,17 @@ use std::str::FromStr;

#[derive(Debug, Clone, Args)]
pub struct RelayerArgs {
/// Enable the Relayer. By default, the Relayer is disabled, even when the binary is compiled
/// with the "relayer" feature flag. Providing `--enable-relayer` will enable the relayer
/// service.
#[clap(long = "enable-relayer", action)]
pub enable_relayer: bool,

/// Uri address to ethereum client. It can be in format of `http://localhost:8545/` or `ws://localhost:8545/`.
/// If not set relayer will not start.
#[arg(long = "relayer", env)]
#[arg(required_if_eq("enable_relayer", "true"))]
#[arg(requires_if(IsPresent, "enable_relayer"))]
pub eth_client: Option<url::Url>,

/// Ethereum contract address. Create EthAddress into fuel_types
Expand Down Expand Up @@ -50,18 +61,24 @@ pub fn parse_h160(input: &str) -> Result<H160, <H160 as FromStr>::Err> {
H160::from_str(input)
}

impl From<RelayerArgs> for Config {
fn from(args: RelayerArgs) -> Self {
Config {
da_deploy_height: DaBlockHeight(args.da_deploy_height),
da_finalization: DaBlockHeight(args.da_finalization),
eth_client: args.eth_client,
eth_v2_listening_contracts: args.eth_v2_listening_contracts,
log_page_size: args.log_page_size,
sync_minimum_duration: Duration::from_secs(args.sync_minimum_duration_secs),
syncing_call_frequency: Duration::from_secs(args.syncing_call_frequency_secs),
syncing_log_frequency: Duration::from_secs(args.syncing_log_frequency_secs),
metrics: false,
impl RelayerArgs {
pub fn into_config(self) -> Option<Config> {
if !self.enable_relayer {
tracing::info!("Relayer service disabled");
return None
}

let config = Config {
da_deploy_height: DaBlockHeight(self.da_deploy_height),
da_finalization: DaBlockHeight(self.da_finalization),
eth_client: self.eth_client,
eth_v2_listening_contracts: self.eth_v2_listening_contracts,
log_page_size: self.log_page_size,
sync_minimum_duration: Duration::from_secs(self.sync_minimum_duration_secs),
syncing_call_frequency: Duration::from_secs(self.syncing_call_frequency_secs),
syncing_log_frequency: Duration::from_secs(self.syncing_log_frequency_secs),
metrics: false,
};
Some(config)
}
}
7 changes: 5 additions & 2 deletions crates/fuel-core/src/service/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ use fuel_core_p2p::config::{
NotInitialized,
};

#[cfg(feature = "relayer")]
use fuel_core_relayer::Config as RelayerConfig;

pub use fuel_core_poa::Trigger;

#[derive(Clone, Debug)]
Expand All @@ -46,7 +49,7 @@ pub struct Config {
pub block_executor: fuel_core_executor::Config,
pub block_importer: fuel_core_importer::Config,
#[cfg(feature = "relayer")]
pub relayer: fuel_core_relayer::Config,
pub relayer: Option<RelayerConfig>,
#[cfg(feature = "p2p")]
pub p2p: Option<P2PConfig<NotInitialized>>,
#[cfg(feature = "p2p")]
Expand Down Expand Up @@ -92,7 +95,7 @@ impl Config {
block_executor: Default::default(),
block_importer: Default::default(),
#[cfg(feature = "relayer")]
relayer: Default::default(),
relayer: None,
#[cfg(feature = "p2p")]
p2p: Some(P2PConfig::<NotInitialized>::default("test_network")),
#[cfg(feature = "p2p")]
Expand Down
14 changes: 11 additions & 3 deletions crates/fuel-core/src/service/sub_services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ use fuel_core_poa::Trigger;
use std::sync::Arc;
use tokio::sync::Mutex;

#[cfg(feature = "relayer")]
use crate::relayer::Config as RelayerConfig;
#[cfg(feature = "relayer")]
use fuel_core_types::blockchain::primitives::DaBlockHeight;

pub type PoAService =
fuel_core_poa::Service<TxPoolAdapter, BlockProducerAdapter, BlockImporterAdapter>;
#[cfg(feature = "relayer")]
Expand All @@ -46,10 +51,10 @@ pub fn init_sub_services(
"The blockchain is not initialized with any block"
))?;
#[cfg(feature = "relayer")]
let relayer_service = if config.relayer.eth_client.is_some() {
let relayer_service = if let Some(config) = &config.relayer {
Some(fuel_core_relayer::new_service(
database.clone(),
config.relayer.clone(),
config.clone(),
)?)
} else {
None
Expand All @@ -60,7 +65,10 @@ pub fn init_sub_services(
#[cfg(feature = "relayer")]
relayer_synced: relayer_service.as_ref().map(|r| r.shared.clone()),
#[cfg(feature = "relayer")]
da_deploy_height: config.relayer.da_deploy_height,
da_deploy_height: config.relayer.as_ref().map_or(
DaBlockHeight(RelayerConfig::DEFAULT_DA_DEPLOY_HEIGHT),
|config| config.da_deploy_height,
),
};

let executor = ExecutorAdapter {
Expand Down
Loading