Skip to content

Commit

Permalink
[Libp2p] Bootstrap from env variable instead (#1601)
Browse files Browse the repository at this point in the history
bootstrap from env variable
  • Loading branch information
rob-maron authored Jun 12, 2024
1 parent 0443c58 commit 1951d7a
Show file tree
Hide file tree
Showing 15 changed files with 82 additions and 112 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ jf-relation = { git = "https://github.com/EspressoSystems/jellyfish", tag = "0.4
"std",
] }
jf-utils = { git = "https://github.com/EspressoSystems/jellyfish", tag = "0.4.5" }
libp2p = { version = "0.53", default-features = false }
snafu = "0.8"
strum = { version = "0.26", features = ["derive"] }
surf-disco = "0.8"
Expand Down
1 change: 1 addition & 0 deletions builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ hotshot-state-prover = { path = "../hotshot-state-prover" }
hotshot-types = { workspace = true }
jf-merkle-tree = { workspace = true }
jf-signature = { workspace = true, features = ["bls"] }
libp2p = { workspace = true }
portpicker = { workspace = true }
rand = "0.8.5"
sequencer = { path = "../sequencer", features = ["testing"] }
Expand Down
14 changes: 14 additions & 0 deletions builder/src/bin/permissioned-builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use hotshot_types::light_client::StateSignKey;
use hotshot_types::signature_key::BLSPrivKey;
use hotshot_types::traits::metrics::NoMetrics;
use hotshot_types::traits::node_implementation::ConsensusTime;
use libp2p::Multiaddr;
use sequencer::persistence::no_storage::NoStorage;
use sequencer::{eth_signature_key::EthKeyPair, Genesis};
use sequencer::{L1Params, NetworkParams};
Expand Down Expand Up @@ -57,6 +58,18 @@ pub struct PermissionedBuilderOptions {
)]
pub libp2p_advertise_address: String,

/// A comma-separated list of Libp2p multiaddresses to use as bootstrap
/// nodes.
///
/// Overrides those loaded from the `HotShot` config.
#[clap(
long,
env = "ESPRESSO_SEQUENCER_LIBP2P_BOOTSTRAP_NODES",
value_delimiter = ',',
num_args = 1..
)]
pub libp2p_bootstrap_nodes: Option<Vec<Multiaddr>>,

/// URL of the Light Client State Relay Server
#[clap(
long,
Expand Down Expand Up @@ -243,6 +256,7 @@ async fn main() -> anyhow::Result<()> {
cdn_endpoint: opt.cdn_endpoint,
libp2p_advertise_address,
libp2p_bind_address,
libp2p_bootstrap_nodes: opt.libp2p_bootstrap_nodes,
orchestrator_url: opt.orchestrator_url,
state_relay_server_url: opt.state_relay_server_url,
private_staking_key: private_staking_key.clone(),
Expand Down
27 changes: 19 additions & 8 deletions builder/src/permissioned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,7 @@ use hotshot_builder_core::{
use hotshot_state_prover;
use jf_merkle_tree::{namespaced_merkle_tree::NamespacedMerkleTreeScheme, MerkleTreeScheme};
use jf_signature::bls_over_bn254::VerKey;
use sequencer::state_signature::StakeTableCommitmentType;
use sequencer::{
catchup::mock::MockStateCatchup, eth_signature_key::EthKeyPair, network::libp2p::BootstrapNode,
ChainConfig,
};
use sequencer::{catchup::mock::MockStateCatchup, eth_signature_key::EthKeyPair, ChainConfig};
use sequencer::{
catchup::StatePeers,
context::{Consensus, SequencerContext},
Expand All @@ -82,6 +78,7 @@ use sequencer::{
state_signature::{static_stake_table_commitment, StateSigner},
Genesis, L1Params, NetworkParams, Node, NodeState, Payload, PrivKey, PubKey, SeqTypes,
};
use sequencer::{network::libp2p::split_off_peer_id, state_signature::StakeTableCommitmentType};
use std::{alloc::System, any, fmt::Debug, mem};
use std::{marker::PhantomData, net::IpAddr};
use std::{net::Ipv4Addr, thread::Builder};
Expand Down Expand Up @@ -178,9 +175,23 @@ pub async fn init_node<P: SequencerPersistence, Ver: StaticVersionType + 'static
.await?
.0;

// If the network is configured manually, override what we got from the orchestrator
if let Some(genesis_network_config) = genesis.network {
genesis_network_config.populate_config(&mut config)?;
// If the `Libp2p` bootstrap nodes were supplied via the command line, override those
// present in the config file.
if let Some(bootstrap_nodes) = network_params.libp2p_bootstrap_nodes {
if let Some(libp2p_config) = config.libp2p_config.as_mut() {
// If the libp2p configuration is present, we can override the bootstrap nodes.

// Split off the peer ID from the addresses
libp2p_config.bootstrap_nodes = bootstrap_nodes
.into_iter()
.map(split_off_peer_id)
.collect::<Result<Vec<_>, _>>()
.with_context(|| "Failed to parse peer ID from bootstrap node")?;
} else {
// If not, don't try launching with them. Eventually we may want to
// provide a default configuration here instead.
tracing::warn!("No libp2p configuration found, ignoring bootstrap nodes");
}
}

tracing::info!(
Expand Down
9 changes: 0 additions & 9 deletions data/genesis/cappuccino.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,3 @@ fee_recipient = '0x0000000000000000000000000000000000000000'

[header]
timestamp = "1970-01-01T00:00:00Z"

[network]
# bootstrap_nodes = [
# "/ip4/127.0.0.1/udp/7003/quic-v1/p2p/12D3KooWFLKhKr61FhtdcMNR2wV4XHnceJQRFo6KKwQvwvRCRvy6",
# "/ip4/127.0.0.1/udp/7001/quic-v1/p2p/12D3KooWR9caJf3eqwyB3rZQX7DFUYTjM1jvXZJJxYbwhkAnPf4w",
# "/ip4/127.0.0.1/udp/7002/quic-v1/p2p/12D3KooWGbEJ2VsfX8KdUZgVaLYFndAxmtdScC91EritK57FbE2N",
# "/ip4/127.0.0.1/udp/7000/quic-v1/p2p/12D3KooWDtGECieXrqKoVxfDhU7afYnS6toj1GqWXuEDfcaGPDxa",
# "/ip4/127.0.0.1/udp/1769/quic-v1/p2p/12D3KooWCzRqAGWkUib7EqHgaWsJsGvKnujXSLsm4xf8u36nJKhH"
# ]
9 changes: 0 additions & 9 deletions data/genesis/demo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,3 @@ fee_contract = '0xa15bb66138824a1c7167f5e85b957d04dd34e468'

[header]
timestamp = "1970-01-01T00:00:00Z"

[network]
# bootstrap_nodes = [
# "/ip4/127.0.0.1/udp/7003/quic-v1/p2p/12D3KooWFLKhKr61FhtdcMNR2wV4XHnceJQRFo6KKwQvwvRCRvy6",
# "/ip4/127.0.0.1/udp/7001/quic-v1/p2p/12D3KooWR9caJf3eqwyB3rZQX7DFUYTjM1jvXZJJxYbwhkAnPf4w",
# "/ip4/127.0.0.1/udp/7002/quic-v1/p2p/12D3KooWGbEJ2VsfX8KdUZgVaLYFndAxmtdScC91EritK57FbE2N",
# "/ip4/127.0.0.1/udp/7000/quic-v1/p2p/12D3KooWDtGECieXrqKoVxfDhU7afYnS6toj1GqWXuEDfcaGPDxa",
# "/ip4/127.0.0.1/udp/1769/quic-v1/p2p/12D3KooWCzRqAGWkUib7EqHgaWsJsGvKnujXSLsm4xf8u36nJKhH"
# ]
9 changes: 0 additions & 9 deletions data/genesis/staging.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,3 @@ fee_recipient = '0x0000000000000000000000000000000000000000'

[header]
timestamp = "1970-01-01T00:00:00Z"

[network]
# bootstrap_nodes = [
# "/ip4/127.0.0.1/udp/7003/quic-v1/p2p/12D3KooWFLKhKr61FhtdcMNR2wV4XHnceJQRFo6KKwQvwvRCRvy6",
# "/ip4/127.0.0.1/udp/7001/quic-v1/p2p/12D3KooWR9caJf3eqwyB3rZQX7DFUYTjM1jvXZJJxYbwhkAnPf4w",
# "/ip4/127.0.0.1/udp/7002/quic-v1/p2p/12D3KooWGbEJ2VsfX8KdUZgVaLYFndAxmtdScC91EritK57FbE2N",
# "/ip4/127.0.0.1/udp/7000/quic-v1/p2p/12D3KooWDtGECieXrqKoVxfDhU7afYnS6toj1GqWXuEDfcaGPDxa",
# "/ip4/127.0.0.1/udp/1769/quic-v1/p2p/12D3KooWCzRqAGWkUib7EqHgaWsJsGvKnujXSLsm4xf8u36nJKhH"
# ]
2 changes: 1 addition & 1 deletion sequencer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jf-rescue = { workspace = true }
jf-signature = { workspace = true, features = ["bls", "schnorr"] }
jf-utils = { workspace = true } # TODO temporary: used only for test_rng()
jf-vid = { workspace = true }
libp2p = { version = "0.53", default-features = false }
libp2p = { workspace = true }
num-traits = "0.2.18"
portpicker = { workspace = true }
rand = "0.8.5"
Expand Down
2 changes: 0 additions & 2 deletions sequencer/src/genesis.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::{
l1_client::L1BlockInfo,
network::GenesisNetworkConfig,
state::{FeeAccount, FeeAmount},
ChainConfig,
};
Expand Down Expand Up @@ -99,7 +98,6 @@ pub struct Genesis {
pub accounts: HashMap<FeeAccount, FeeAmount>,
pub l1_finalized: Option<L1Finalized>,
pub header: GenesisHeader,
pub network: Option<GenesisNetworkConfig>,
}

impl Genesis {
Expand Down
25 changes: 22 additions & 3 deletions sequencer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use genesis::{GenesisHeader, L1Finalized};

use l1_client::L1Client;

use libp2p::Multiaddr;
use network::libp2p::split_off_peer_id;
use state::FeeAccount;
use state_signature::static_stake_table_commitment;
use url::Url;
Expand Down Expand Up @@ -292,6 +294,9 @@ pub struct NetworkParams {
pub libp2p_advertise_address: SocketAddr,
/// The address to bind to for Libp2p
pub libp2p_bind_address: SocketAddr,
/// The (optional) bootstrap node addresses for Libp2p. If supplied, these will
/// override the bootstrap nodes specified in the config file.
pub libp2p_bootstrap_nodes: Option<Vec<Multiaddr>>,
}

pub struct L1Params {
Expand Down Expand Up @@ -380,9 +385,23 @@ pub async fn init_node<P: PersistenceOptions, Ver: StaticVersionType + 'static>(
}
};

// If the network is configured manually, override what we got from the orchestrator
if let Some(genesis_network_config) = genesis.network {
genesis_network_config.populate_config(&mut config)?;
// If the `Libp2p` bootstrap nodes were supplied via the command line, override those
// present in the config file.
if let Some(bootstrap_nodes) = network_params.libp2p_bootstrap_nodes {
if let Some(libp2p_config) = config.libp2p_config.as_mut() {
// If the libp2p configuration is present, we can override the bootstrap nodes.

// Split off the peer ID from the addresses
libp2p_config.bootstrap_nodes = bootstrap_nodes
.into_iter()
.map(split_off_peer_id)
.collect::<Result<Vec<_>, _>>()
.with_context(|| "Failed to parse peer ID from bootstrap node")?;
} else {
// If not, don't try launching with them. Eventually we may want to
// provide a default configuration here instead.
tracing::warn!("No libp2p configuration found, ignoring supplied bootstrap nodes");
}
}

let node_index = config.node_index;
Expand Down
2 changes: 1 addition & 1 deletion sequencer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ where
cdn_endpoint: opt.cdn_endpoint,
libp2p_advertise_address,
libp2p_bind_address,
libp2p_bootstrap_nodes: opt.libp2p_bootstrap_nodes,
orchestrator_url: opt.orchestrator_url,
state_relay_server_url: opt.state_relay_server_url,
private_staking_key,
Expand Down Expand Up @@ -194,7 +195,6 @@ mod test {
accounts: Default::default(),
l1_finalized: Default::default(),
header: Default::default(),
network: Default::default(),
};
genesis.to_file(&genesis_file).unwrap();

Expand Down
42 changes: 9 additions & 33 deletions sequencer/src/network/libp2p.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,14 @@
use anyhow::Result;
use libp2p::{multiaddr::Protocol, Multiaddr, PeerId};
use serde::{Deserialize, Serialize};

/// A bootstrap node. Contains the multiaddress and peer ID
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(try_from = "Multiaddr", into = "Multiaddr")]
pub struct BootstrapNode {
pub address: Multiaddr,
pub peer_id: PeerId,
}

impl From<BootstrapNode> for Multiaddr {
fn from(node: BootstrapNode) -> Self {
let mut address = node.address;

// The standard is to have the peer ID as the last part of the address
address.push(Protocol::P2p(node.peer_id));

address
}
}

impl TryFrom<Multiaddr> for BootstrapNode {
type Error = anyhow::Error;

fn try_from(address: Multiaddr) -> Result<Self> {
// Clone the address so we can pop the peer ID off the end
let mut address = address.clone();

// The standard is to have the peer ID as the last part of the address
let Some(Protocol::P2p(peer_id)) = address.pop() else {
return Err(anyhow::anyhow!("Failed to parse peer ID from address"));
};
/// Split off the peer ID from a multiaddress, returning the shortened address and the peer ID.
///
/// # Errors
/// - If the last protocol in the address is not a peer ID.
pub fn split_off_peer_id(mut address: Multiaddr) -> Result<(PeerId, Multiaddr)> {
let Some(Protocol::P2p(peer_id)) = address.pop() else {
return Err(anyhow::anyhow!("Failed to parse peer ID from address"));
};

Ok(BootstrapNode { address, peer_id })
}
Ok((peer_id, address))
}
37 changes: 0 additions & 37 deletions sequencer/src/network/mod.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,10 @@
use anyhow::Result;
use hotshot_types::message::Message;
use libp2p::BootstrapNode;
use persistence::NetworkConfig;

use super::*;

pub mod cdn;
pub mod libp2p;

/// The genesis network configuration. Overrides what is received from the orchestrator
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct GenesisNetworkConfig {
/// An optional list of bootstrap nodes (multiaddress and peer ID) to connect to
pub bootstrap_nodes: Option<Vec<BootstrapNode>>,
}

impl GenesisNetworkConfig {
/// Update the HotShot config with the genesis network config
pub fn populate_config(&self, config: &mut NetworkConfig) -> Result<()> {
// Attempt to populate the bootstrap nodes if present
if let Some(bootstrap_nodes) = &self.bootstrap_nodes {
// Make sure Libp2p is configured if we have supplied bootstrap nodes
let Some(ref mut libp2p_config) = config.libp2p_config else {
return Err(anyhow::anyhow!(
"Bootstrap nodes supplied but no libp2p configuration found"
));
};

// Replace the bootstrap nodes with the ones from the file
libp2p_config.bootstrap_nodes = bootstrap_nodes
.iter()
.cloned()
.map(|node| {
let BootstrapNode { address, peer_id } = node;
(peer_id, address)
})
.collect();
}

Ok(())
}
}

pub trait Type: 'static {
type DAChannel: ConnectedNetwork<Message<SeqTypes>, PubKey>;
type QuorumChannel: ConnectedNetwork<Message<SeqTypes>, PubKey>;
Expand Down
13 changes: 13 additions & 0 deletions sequencer/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use derivative::Derivative;
use derive_more::From;
use hotshot_types::light_client::StateSignKey;
use hotshot_types::signature_key::BLSPrivKey;
use libp2p::Multiaddr;
use snafu::Snafu;
use std::{
collections::{HashMap, HashSet},
Expand Down Expand Up @@ -78,6 +79,18 @@ pub struct Options {
)]
pub libp2p_advertise_address: String,

/// A comma-separated list of Libp2p multiaddresses to use as bootstrap
/// nodes.
///
/// Overrides those loaded from the `HotShot` config.
#[clap(
long,
env = "ESPRESSO_SEQUENCER_LIBP2P_BOOTSTRAP_NODES",
value_delimiter = ',',
num_args = 1..
)]
pub libp2p_bootstrap_nodes: Option<Vec<Multiaddr>>,

/// URL of the Light Client State Relay Server
#[clap(
long,
Expand Down

0 comments on commit 1951d7a

Please sign in to comment.