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

[Libp2p] Bootstrap from env variable instead #1601

Merged
merged 1 commit into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading