mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-11 18:04:18 +00:00
* Add plumbing for peerdas supernodes (#5050, #5409, #5570, #5966) - add cli option `--subscribe-to-all-data-columns` - add custody subnet count to ENR, only if PeerDAS is scheduled - subscribe to data column topics, only if PeerDAS is scheduled Co-authored-by: Jacob Kaufmann <jacobkaufmann18@gmail.com> * Merge branch 'unstable' into das-supernode * Update CLI docs. * Merge branch 'unstable' into das-supernode * Fix fork epoch comparison with `FAR_FUTURE_EPOCH`. * Merge branch 'unstable' into das-supernode * Hide `--subscribe-all-data-column-subnets` flag and update help. * Fix docs only * Merge branch 'unstable' into das-supernode
This commit is contained in:
@@ -42,7 +42,7 @@ pub struct Config {
|
||||
pub network_dir: PathBuf,
|
||||
|
||||
/// IP addresses to listen on.
|
||||
listen_addresses: ListenAddress,
|
||||
pub(crate) listen_addresses: ListenAddress,
|
||||
|
||||
/// The address to broadcast to peers about which address we are listening on. None indicates
|
||||
/// that no discovery address has been set in the CLI args.
|
||||
@@ -100,6 +100,9 @@ pub struct Config {
|
||||
/// Attempt to construct external port mappings with UPnP.
|
||||
pub upnp_enabled: bool,
|
||||
|
||||
/// Subscribe to all data column subnets for the duration of the runtime.
|
||||
pub subscribe_all_data_column_subnets: bool,
|
||||
|
||||
/// Subscribe to all subnets for the duration of the runtime.
|
||||
pub subscribe_all_subnets: bool,
|
||||
|
||||
@@ -338,6 +341,7 @@ impl Default for Config {
|
||||
upnp_enabled: true,
|
||||
network_load: 4,
|
||||
private: false,
|
||||
subscribe_all_data_column_subnets: false,
|
||||
subscribe_all_subnets: false,
|
||||
import_all_attestations: false,
|
||||
shutdown_after_sync: false,
|
||||
|
||||
@@ -14,7 +14,7 @@ use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use types::{EnrForkId, EthSpec};
|
||||
use types::{ChainSpec, EnrForkId, EthSpec};
|
||||
|
||||
use super::enr_ext::{EnrExt, QUIC6_ENR_KEY, QUIC_ENR_KEY};
|
||||
|
||||
@@ -24,6 +24,8 @@ pub const ETH2_ENR_KEY: &str = "eth2";
|
||||
pub const ATTESTATION_BITFIELD_ENR_KEY: &str = "attnets";
|
||||
/// The ENR field specifying the sync committee subnet bitfield.
|
||||
pub const SYNC_COMMITTEE_BITFIELD_ENR_KEY: &str = "syncnets";
|
||||
/// The ENR field specifying the peerdas custody subnet count.
|
||||
pub const PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY: &str = "csc";
|
||||
|
||||
/// Extension trait for ENR's within Eth2.
|
||||
pub trait Eth2Enr {
|
||||
@@ -35,6 +37,9 @@ pub trait Eth2Enr {
|
||||
&self,
|
||||
) -> Result<EnrSyncCommitteeBitfield<E>, &'static str>;
|
||||
|
||||
/// The peerdas custody subnet count associated with the ENR.
|
||||
fn custody_subnet_count<E: EthSpec>(&self, spec: &ChainSpec) -> u64;
|
||||
|
||||
fn eth2(&self) -> Result<EnrForkId, &'static str>;
|
||||
}
|
||||
|
||||
@@ -59,6 +64,16 @@ impl Eth2Enr for Enr {
|
||||
.map_err(|_| "Could not decode the ENR syncnets bitfield")
|
||||
}
|
||||
|
||||
/// if the custody value is non-existent in the ENR, then we assume the minimum custody value
|
||||
/// defined in the spec.
|
||||
fn custody_subnet_count<E: EthSpec>(&self, spec: &ChainSpec) -> u64 {
|
||||
self.get_decodable::<u64>(PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY)
|
||||
.and_then(|r| r.ok())
|
||||
// If value supplied in ENR is invalid, fallback to `custody_requirement`
|
||||
.filter(|csc| csc <= &spec.data_column_sidecar_subnet_count)
|
||||
.unwrap_or(spec.custody_requirement)
|
||||
}
|
||||
|
||||
fn eth2(&self) -> Result<EnrForkId, &'static str> {
|
||||
let eth2_bytes = self.get(ETH2_ENR_KEY).ok_or("ENR has no eth2 field")?;
|
||||
|
||||
@@ -126,12 +141,13 @@ pub fn build_or_load_enr<E: EthSpec>(
|
||||
config: &NetworkConfig,
|
||||
enr_fork_id: &EnrForkId,
|
||||
log: &slog::Logger,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Enr, String> {
|
||||
// Build the local ENR.
|
||||
// Note: Discovery should update the ENR record's IP to the external IP as seen by the
|
||||
// majority of our peers, if the CLI doesn't expressly forbid it.
|
||||
let enr_key = CombinedKey::from_libp2p(local_key)?;
|
||||
let mut local_enr = build_enr::<E>(&enr_key, config, enr_fork_id)?;
|
||||
let mut local_enr = build_enr::<E>(&enr_key, config, enr_fork_id, spec)?;
|
||||
|
||||
use_or_load_enr(&enr_key, &mut local_enr, config, log)?;
|
||||
Ok(local_enr)
|
||||
@@ -142,6 +158,7 @@ pub fn build_enr<E: EthSpec>(
|
||||
enr_key: &CombinedKey,
|
||||
config: &NetworkConfig,
|
||||
enr_fork_id: &EnrForkId,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Enr, String> {
|
||||
let mut builder = discv5::enr::Enr::builder();
|
||||
let (maybe_ipv4_address, maybe_ipv6_address) = &config.enr_address;
|
||||
@@ -221,6 +238,16 @@ pub fn build_enr<E: EthSpec>(
|
||||
|
||||
builder.add_value(SYNC_COMMITTEE_BITFIELD_ENR_KEY, &bitfield.as_ssz_bytes());
|
||||
|
||||
// only set `csc` if PeerDAS fork epoch has been scheduled
|
||||
if spec.is_peer_das_scheduled() {
|
||||
let custody_subnet_count = if config.subscribe_all_data_column_subnets {
|
||||
spec.data_column_sidecar_subnet_count
|
||||
} else {
|
||||
spec.custody_requirement
|
||||
};
|
||||
builder.add_value(PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY, &custody_subnet_count);
|
||||
}
|
||||
|
||||
builder
|
||||
.build(enr_key)
|
||||
.map_err(|e| format!("Could not build Local ENR: {:?}", e))
|
||||
@@ -244,10 +271,12 @@ fn compare_enr(local_enr: &Enr, disk_enr: &Enr) -> bool {
|
||||
// take preference over disk udp port if one is not specified
|
||||
&& (local_enr.udp4().is_none() || local_enr.udp4() == disk_enr.udp4())
|
||||
&& (local_enr.udp6().is_none() || local_enr.udp6() == disk_enr.udp6())
|
||||
// we need the ATTESTATION_BITFIELD_ENR_KEY and SYNC_COMMITTEE_BITFIELD_ENR_KEY key to match,
|
||||
// otherwise we use a new ENR. This will likely only be true for non-validating nodes
|
||||
// we need the ATTESTATION_BITFIELD_ENR_KEY and SYNC_COMMITTEE_BITFIELD_ENR_KEY and
|
||||
// PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY key to match, otherwise we use a new ENR. This will
|
||||
// likely only be true for non-validating nodes.
|
||||
&& local_enr.get(ATTESTATION_BITFIELD_ENR_KEY) == disk_enr.get(ATTESTATION_BITFIELD_ENR_KEY)
|
||||
&& local_enr.get(SYNC_COMMITTEE_BITFIELD_ENR_KEY) == disk_enr.get(SYNC_COMMITTEE_BITFIELD_ENR_KEY)
|
||||
&& local_enr.get(PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY) == disk_enr.get(PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY)
|
||||
}
|
||||
|
||||
/// Loads enr from the given directory
|
||||
@@ -280,3 +309,77 @@ pub fn save_enr_to_disk(dir: &Path, enr: &Enr, log: &slog::Logger) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::config::Config as NetworkConfig;
|
||||
use types::{Epoch, MainnetEthSpec};
|
||||
|
||||
type E = MainnetEthSpec;
|
||||
|
||||
fn make_eip7594_spec() -> ChainSpec {
|
||||
let mut spec = E::default_spec();
|
||||
spec.eip7594_fork_epoch = Some(Epoch::new(10));
|
||||
spec
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custody_subnet_count_default() {
|
||||
let config = NetworkConfig {
|
||||
subscribe_all_data_column_subnets: false,
|
||||
..NetworkConfig::default()
|
||||
};
|
||||
let spec = make_eip7594_spec();
|
||||
|
||||
let enr = build_enr_with_config(config, &spec).0;
|
||||
|
||||
assert_eq!(
|
||||
enr.custody_subnet_count::<E>(&spec),
|
||||
spec.custody_requirement,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custody_subnet_count_all() {
|
||||
let config = NetworkConfig {
|
||||
subscribe_all_data_column_subnets: true,
|
||||
..NetworkConfig::default()
|
||||
};
|
||||
let spec = make_eip7594_spec();
|
||||
let enr = build_enr_with_config(config, &spec).0;
|
||||
|
||||
assert_eq!(
|
||||
enr.custody_subnet_count::<E>(&spec),
|
||||
spec.data_column_sidecar_subnet_count,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custody_subnet_count_fallback_default() {
|
||||
let config = NetworkConfig::default();
|
||||
let spec = make_eip7594_spec();
|
||||
let (mut enr, enr_key) = build_enr_with_config(config, &spec);
|
||||
let invalid_subnet_count = 99u64;
|
||||
|
||||
enr.insert(
|
||||
PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY,
|
||||
&invalid_subnet_count,
|
||||
&enr_key,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
enr.custody_subnet_count::<E>(&spec),
|
||||
spec.custody_requirement,
|
||||
);
|
||||
}
|
||||
|
||||
fn build_enr_with_config(config: NetworkConfig, spec: &ChainSpec) -> (Enr, CombinedKey) {
|
||||
let keypair = libp2p::identity::secp256k1::Keypair::generate();
|
||||
let enr_key = CombinedKey::from_secp256k1(&keypair);
|
||||
let enr_fork_id = EnrForkId::default();
|
||||
let enr = build_enr::<E>(&enr_key, &config, &enr_fork_id, spec).unwrap();
|
||||
(enr, enr_key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1220,7 +1220,7 @@ mod tests {
|
||||
let mut config = NetworkConfig::default();
|
||||
config.set_listening_addr(crate::ListenAddress::unused_v4_ports());
|
||||
let enr_key: CombinedKey = CombinedKey::from_secp256k1(&keypair);
|
||||
let enr: Enr = build_enr::<E>(&enr_key, &config, &EnrForkId::default()).unwrap();
|
||||
let enr: Enr = build_enr::<E>(&enr_key, &config, &EnrForkId::default(), &spec).unwrap();
|
||||
let log = build_log(slog::Level::Debug, false);
|
||||
let globals = NetworkGlobals::new(
|
||||
enr,
|
||||
|
||||
@@ -162,6 +162,7 @@ impl<E: EthSpec> Network<E> {
|
||||
&config,
|
||||
&ctx.enr_fork_id,
|
||||
&log,
|
||||
ctx.chain_spec,
|
||||
)?;
|
||||
// Construct the metadata
|
||||
let meta_data = utils::load_or_build_metadata(&config.network_dir, &log);
|
||||
|
||||
Reference in New Issue
Block a user