mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-16 03:12:41 +00:00
Final changes for fusaka-devnet-2 (#7655)
Closes #7467. This PR primarily addresses [the P2P changes](https://github.com/ethereum/EIPs/pull/9840) in [fusaka-devnet-2](https://fusaka-devnet-2.ethpandaops.io/). Specifically: * [the new `nfd` parameter added to the `ENR`](https://github.com/ethereum/EIPs/pull/9840) * [the modified `compute_fork_digest()` changes for every BPO fork](https://github.com/ethereum/EIPs/pull/9840) 90% of this PR was absolutely hacked together as fast as possible during the Berlinterop as fast as I could while running between Glamsterdam debates. Luckily, it seems to work. But I was unable to be as careful in avoiding bugs as I usually am. I've cleaned up the things *I remember* wanting to come back and have a closer look at. But still working on this. Progress: * [x] get it working on `fusaka-devnet-2` * [ ] [*optional* disconnect from peers with incorrect `nfd` at the fork boundary](https://github.com/ethereum/consensus-specs/pull/4407) - Can be addressed in a future PR if necessary * [x] first pass clean-up * [x] fix up all the broken tests * [x] final self-review * [x] more thorough review from people more familiar with affected code
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
pub use discv5::enr::CombinedKey;
|
||||
|
||||
use super::enr_ext::CombinedKeyExt;
|
||||
use super::enr_ext::{EnrExt, QUIC6_ENR_KEY, QUIC_ENR_KEY};
|
||||
use super::ENR_FILENAME;
|
||||
use crate::types::{Enr, EnrAttestationBitfield, EnrSyncCommitteeBitfield};
|
||||
use crate::NetworkConfig;
|
||||
@@ -18,10 +19,10 @@ use std::str::FromStr;
|
||||
use tracing::{debug, warn};
|
||||
use types::{ChainSpec, EnrForkId, EthSpec};
|
||||
|
||||
use super::enr_ext::{EnrExt, QUIC6_ENR_KEY, QUIC_ENR_KEY};
|
||||
|
||||
/// The ENR field specifying the fork id.
|
||||
pub const ETH2_ENR_KEY: &str = "eth2";
|
||||
/// The ENR field specifying the next fork digest.
|
||||
pub const NEXT_FORK_DIGEST_ENR_KEY: &str = "nfd";
|
||||
/// The ENR field specifying the attestation subnet bitfield.
|
||||
pub const ATTESTATION_BITFIELD_ENR_KEY: &str = "attnets";
|
||||
/// The ENR field specifying the sync committee subnet bitfield.
|
||||
@@ -42,6 +43,9 @@ pub trait Eth2Enr {
|
||||
/// The peerdas custody group count associated with the ENR.
|
||||
fn custody_group_count<E: EthSpec>(&self, spec: &ChainSpec) -> Result<u64, &'static str>;
|
||||
|
||||
/// The next fork digest associated with the ENR.
|
||||
fn next_fork_digest(&self) -> Result<[u8; 4], &'static str>;
|
||||
|
||||
fn eth2(&self) -> Result<EnrForkId, &'static str>;
|
||||
}
|
||||
|
||||
@@ -81,6 +85,12 @@ impl Eth2Enr for Enr {
|
||||
}
|
||||
}
|
||||
|
||||
fn next_fork_digest(&self) -> Result<[u8; 4], &'static str> {
|
||||
self.get_decodable::<[u8; 4]>(NEXT_FORK_DIGEST_ENR_KEY)
|
||||
.ok_or("ENR next fork digest non-existent")?
|
||||
.map_err(|_| "Could not decode the ENR next fork digest")
|
||||
}
|
||||
|
||||
fn eth2(&self) -> Result<EnrForkId, &'static str> {
|
||||
let eth2_bytes: Bytes = self
|
||||
.get_decodable(ETH2_ENR_KEY)
|
||||
@@ -149,13 +159,14 @@ pub fn build_or_load_enr<E: EthSpec>(
|
||||
local_key: Keypair,
|
||||
config: &NetworkConfig,
|
||||
enr_fork_id: &EnrForkId,
|
||||
next_fork_digest: [u8; 4],
|
||||
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, spec)?;
|
||||
let mut local_enr = build_enr::<E>(&enr_key, config, enr_fork_id, next_fork_digest, spec)?;
|
||||
|
||||
use_or_load_enr(&enr_key, &mut local_enr, config)?;
|
||||
Ok(local_enr)
|
||||
@@ -166,6 +177,7 @@ pub fn build_enr<E: EthSpec>(
|
||||
enr_key: &CombinedKey,
|
||||
config: &NetworkConfig,
|
||||
enr_fork_id: &EnrForkId,
|
||||
next_fork_digest: [u8; 4],
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Enr, String> {
|
||||
let mut builder = discv5::enr::Enr::builder();
|
||||
@@ -257,7 +269,7 @@ pub fn build_enr<E: EthSpec>(
|
||||
&bitfield.as_ssz_bytes().into(),
|
||||
);
|
||||
|
||||
// only set `cgc` if PeerDAS fork epoch has been scheduled
|
||||
// only set `cgc` and `nfd` if PeerDAS fork (Fulu) epoch has been scheduled
|
||||
if spec.is_peer_das_scheduled() {
|
||||
let custody_group_count =
|
||||
if let Some(false_cgc) = config.advertise_false_custody_group_count {
|
||||
@@ -268,6 +280,7 @@ pub fn build_enr<E: EthSpec>(
|
||||
spec.custody_requirement
|
||||
};
|
||||
builder.add_value(PEERDAS_CUSTODY_GROUP_COUNT_ENR_KEY, &custody_group_count);
|
||||
builder.add_value(NEXT_FORK_DIGEST_ENR_KEY, &next_fork_digest);
|
||||
}
|
||||
|
||||
builder
|
||||
@@ -340,6 +353,7 @@ mod test {
|
||||
use types::{Epoch, MainnetEthSpec};
|
||||
|
||||
type E = MainnetEthSpec;
|
||||
const TEST_NFD: [u8; 4] = [0x01, 0x02, 0x03, 0x04];
|
||||
|
||||
fn make_fulu_spec() -> ChainSpec {
|
||||
let mut spec = E::default_spec();
|
||||
@@ -351,10 +365,17 @@ mod test {
|
||||
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();
|
||||
let enr = build_enr::<E>(&enr_key, &config, &enr_fork_id, TEST_NFD, spec).unwrap();
|
||||
(enr, enr_key)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nfd_enr_encoding() {
|
||||
let spec = make_fulu_spec();
|
||||
let enr = build_enr_with_config(NetworkConfig::default(), &spec).0;
|
||||
assert_eq!(enr.next_fork_digest().unwrap(), TEST_NFD);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custody_group_count_default() {
|
||||
let config = NetworkConfig {
|
||||
|
||||
@@ -49,7 +49,7 @@ use tracing::{debug, error, info, trace, warn};
|
||||
use types::{ChainSpec, EnrForkId, EthSpec};
|
||||
|
||||
mod subnet_predicate;
|
||||
use crate::discovery::enr::PEERDAS_CUSTODY_GROUP_COUNT_ENR_KEY;
|
||||
use crate::discovery::enr::{NEXT_FORK_DIGEST_ENR_KEY, PEERDAS_CUSTODY_GROUP_COUNT_ENR_KEY};
|
||||
pub use subnet_predicate::subnet_predicate;
|
||||
use types::non_zero_usize::new_non_zero_usize;
|
||||
|
||||
@@ -570,6 +570,19 @@ impl<E: EthSpec> Discovery<E> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_enr_nfd(&mut self, nfd: [u8; 4]) -> Result<(), String> {
|
||||
self.discv5
|
||||
.enr_insert::<Bytes>(NEXT_FORK_DIGEST_ENR_KEY, &nfd.as_ssz_bytes().into())
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
info!(
|
||||
next_fork_digest = ?nfd,
|
||||
"Updating the ENR nfd"
|
||||
);
|
||||
enr::save_enr_to_disk(Path::new(&self.enr_dir), &self.local_enr());
|
||||
*self.network_globals.local_enr.write() = self.discv5.local_enr();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Updates the `eth2` field of our local ENR.
|
||||
pub fn update_eth2_enr(&mut self, enr_fork_id: EnrForkId) {
|
||||
// to avoid having a reference to the spec constant, for the logging we assume
|
||||
@@ -1217,7 +1230,15 @@ mod tests {
|
||||
config.set_listening_addr(crate::ListenAddress::unused_v4_ports());
|
||||
let config = Arc::new(config);
|
||||
let enr_key: CombinedKey = CombinedKey::from_secp256k1(&keypair);
|
||||
let enr: Enr = build_enr::<E>(&enr_key, &config, &EnrForkId::default(), &spec).unwrap();
|
||||
let next_fork_digest = [0; 4];
|
||||
let enr: Enr = build_enr::<E>(
|
||||
&enr_key,
|
||||
&config,
|
||||
&EnrForkId::default(),
|
||||
next_fork_digest,
|
||||
&spec,
|
||||
)
|
||||
.unwrap();
|
||||
let globals = NetworkGlobals::new(
|
||||
enr,
|
||||
MetaData::V2(MetaDataV2 {
|
||||
|
||||
Reference in New Issue
Block a user