Skip to content

Commit 733b1df

Browse files
authored
Update csc format in ENR and spec tests for devnet-1 (#5966)
* Update `csc` format in ENR. * Add spec tests for `recover_cells_and_kzg_proofs`. * Add tests for ENR. * Fix failing tests. * Add protection against invalid csc value in ENR. * Fix lint
1 parent 6ff9480 commit 733b1df

File tree

10 files changed

+211
-19
lines changed

10 files changed

+211
-19
lines changed

beacon_node/lighthouse_network/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub struct Config {
4242
pub network_dir: PathBuf,
4343

4444
/// IP addresses to listen on.
45-
listen_addresses: ListenAddress,
45+
pub(crate) listen_addresses: ListenAddress,
4646

4747
/// The address to broadcast to peers about which address we are listening on. None indicates
4848
/// that no discovery address has been set in the CLI args.

beacon_node/lighthouse_network/src/discovery/enr.rs

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub const ATTESTATION_BITFIELD_ENR_KEY: &str = "attnets";
2525
/// The ENR field specifying the sync committee subnet bitfield.
2626
pub const SYNC_COMMITTEE_BITFIELD_ENR_KEY: &str = "syncnets";
2727
/// The ENR field specifying the peerdas custody subnet count.
28-
pub const PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY: &str = "custody_subnet_count";
28+
pub const PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY: &str = "csc";
2929

3030
/// Extension trait for ENR's within Eth2.
3131
pub trait Eth2Enr {
@@ -68,7 +68,9 @@ impl Eth2Enr for Enr {
6868
/// defined in the spec.
6969
fn custody_subnet_count<E: EthSpec>(&self, spec: &ChainSpec) -> u64 {
7070
self.get(PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY)
71-
.and_then(|custody_bytes| u64::from_ssz_bytes(custody_bytes).ok())
71+
.and_then(|custody_bytes| custody_bytes.try_into().map(u64::from_be_bytes).ok())
72+
// If value supplied in ENR is invalid, fallback to `custody_requirement`
73+
.filter(|csc| csc <= &spec.data_column_sidecar_subnet_count)
7274
.unwrap_or(spec.custody_requirement)
7375
}
7476

@@ -243,10 +245,8 @@ pub fn build_enr<E: EthSpec>(
243245
spec.custody_requirement
244246
};
245247

246-
builder.add_value(
247-
PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY,
248-
&custody_subnet_count.as_ssz_bytes(),
249-
);
248+
let csc_bytes = custody_subnet_count.to_be_bytes();
249+
builder.add_value(PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY, &csc_bytes.as_slice());
250250

251251
builder
252252
.build(enr_key)
@@ -309,3 +309,70 @@ pub fn save_enr_to_disk(dir: &Path, enr: &Enr, log: &slog::Logger) {
309309
}
310310
}
311311
}
312+
313+
#[cfg(test)]
314+
mod test {
315+
use super::*;
316+
use crate::config::Config as NetworkConfig;
317+
use types::MainnetEthSpec;
318+
319+
type E = MainnetEthSpec;
320+
321+
#[test]
322+
fn custody_subnet_count_default() {
323+
let config = NetworkConfig {
324+
subscribe_all_data_column_subnets: false,
325+
..NetworkConfig::default()
326+
};
327+
let spec = E::default_spec();
328+
let enr = build_enr_with_config(config, &spec).0;
329+
330+
assert_eq!(
331+
enr.custody_subnet_count::<E>(&spec),
332+
spec.custody_requirement,
333+
);
334+
}
335+
336+
#[test]
337+
fn custody_subnet_count_all() {
338+
let config = NetworkConfig {
339+
subscribe_all_data_column_subnets: true,
340+
..NetworkConfig::default()
341+
};
342+
let spec = E::default_spec();
343+
let enr = build_enr_with_config(config, &spec).0;
344+
345+
assert_eq!(
346+
enr.custody_subnet_count::<E>(&spec),
347+
spec.data_column_sidecar_subnet_count,
348+
);
349+
}
350+
351+
#[test]
352+
fn custody_subnet_count_fallback_default() {
353+
let config = NetworkConfig::default();
354+
let spec = E::default_spec();
355+
let (mut enr, enr_key) = build_enr_with_config(config, &spec);
356+
let invalid_subnet_count = 999u64;
357+
358+
enr.insert(
359+
PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY,
360+
&invalid_subnet_count.to_be_bytes().as_slice(),
361+
&enr_key,
362+
)
363+
.unwrap();
364+
365+
assert_eq!(
366+
enr.custody_subnet_count::<E>(&spec),
367+
spec.custody_requirement,
368+
);
369+
}
370+
371+
fn build_enr_with_config(config: NetworkConfig, spec: &ChainSpec) -> (Enr, CombinedKey) {
372+
let keypair = libp2p::identity::secp256k1::Keypair::generate();
373+
let enr_key = CombinedKey::from_secp256k1(&keypair);
374+
let enr_fork_id = EnrForkId::default();
375+
let enr = build_enr::<E>(&enr_key, &config, &enr_fork_id, spec).unwrap();
376+
(enr, enr_key)
377+
}
378+
}

beacon_node/lighthouse_network/src/peer_manager/peerdb.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use peer_info::{ConnectionDirection, PeerConnectionStatus, PeerInfo};
55
use rand::seq::SliceRandom;
66
use score::{PeerAction, ReportSource, Score, ScoreState};
77
use slog::{crit, debug, error, trace, warn};
8-
use ssz::Encode;
98
use std::net::IpAddr;
109
use std::time::Instant;
1110
use std::{cmp::Ordering, fmt::Display};
@@ -687,7 +686,10 @@ impl<E: EthSpec> PeerDB<E> {
687686
if supernode {
688687
enr.insert(
689688
PEERDAS_CUSTODY_SUBNET_COUNT_ENR_KEY,
690-
&spec.data_column_sidecar_subnet_count.as_ssz_bytes(),
689+
&spec
690+
.data_column_sidecar_subnet_count
691+
.to_be_bytes()
692+
.as_slice(),
691693
&enr_key,
692694
)
693695
.expect("u64 can be encoded");

consensus/types/src/data_column_subnet_id.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,15 @@ impl From<u64> for DataColumnSubnetId {
107107
}
108108
}
109109

110-
impl Into<u64> for DataColumnSubnetId {
111-
fn into(self) -> u64 {
112-
self.0
110+
impl From<DataColumnSubnetId> for u64 {
111+
fn from(val: DataColumnSubnetId) -> Self {
112+
val.0
113113
}
114114
}
115115

116-
impl Into<u64> for &DataColumnSubnetId {
117-
fn into(self) -> u64 {
118-
self.0
116+
impl From<&DataColumnSubnetId> for u64 {
117+
fn from(val: &DataColumnSubnetId) -> Self {
118+
val.0
119119
}
120120
}
121121

testing/ef_tests/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
TESTS_TAG := v1.5.0-alpha.2
1+
TESTS_TAG := v1.5.0-alpha.3
22
TESTS = general minimal mainnet
33
TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS))
44

testing/ef_tests/check_all_files_accessed.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@
3535
"tests/.*/.*/ssz_static/LightClientStore",
3636
# LightClientSnapshot
3737
"tests/.*/.*/ssz_static/LightClientSnapshot",
38+
# Unused container for das
39+
"tests/.*/.*/ssz_static/MatrixEntry",
3840
# Unused kzg methods
39-
"tests/.*/.*/kzg/compute_cells",
40-
"tests/.*/.*/kzg/recover_all_cells",
4141
"tests/.*/.*/kzg/verify_cell_kzg_proof",
4242
# One of the EF researchers likes to pack the tarballs on a Mac
43-
".*\.DS_Store.*",
43+
".*/.DS_Store.*",
4444
# More Mac weirdness.
4545
"tests/mainnet/bellatrix/operations/deposit/pyspec_tests/deposit_with_previous_fork_version__valid_ineffective/._meta.yaml",
4646
"tests/mainnet/eip7594/networking/get_custody_columns/pyspec_tests/get_custody_columns__short_node_id/._meta.yaml",

testing/ef_tests/src/cases.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mod kzg_blob_to_kzg_commitment;
2323
mod kzg_compute_blob_kzg_proof;
2424
mod kzg_compute_cells_and_kzg_proofs;
2525
mod kzg_compute_kzg_proof;
26+
mod kzg_recover_cells_and_kzg_proofs;
2627
mod kzg_verify_blob_kzg_proof;
2728
mod kzg_verify_blob_kzg_proof_batch;
2829
mod kzg_verify_cell_kzg_proof_batch;
@@ -56,6 +57,7 @@ pub use kzg_blob_to_kzg_commitment::*;
5657
pub use kzg_compute_blob_kzg_proof::*;
5758
pub use kzg_compute_cells_and_kzg_proofs::*;
5859
pub use kzg_compute_kzg_proof::*;
60+
pub use kzg_recover_cells_and_kzg_proofs::*;
5961
pub use kzg_verify_blob_kzg_proof::*;
6062
pub use kzg_verify_blob_kzg_proof_batch::*;
6163
pub use kzg_verify_cell_kzg_proof_batch::*;
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
use super::*;
2+
use crate::case_result::compare_result;
3+
use kzg::{CellsAndKzgProofs, KzgProof};
4+
use serde::Deserialize;
5+
use std::convert::Infallible;
6+
use std::marker::PhantomData;
7+
8+
#[derive(Debug, Clone, Deserialize)]
9+
#[serde(deny_unknown_fields)]
10+
pub struct KZGRecoverCellsAndKzgProofsInput {
11+
pub cell_indices: Vec<u64>,
12+
pub cells: Vec<String>,
13+
pub proofs: Vec<String>,
14+
}
15+
16+
#[derive(Debug, Clone, Deserialize)]
17+
#[serde(bound = "E: EthSpec", deny_unknown_fields)]
18+
pub struct KZGRecoverCellsAndKZGProofs<E: EthSpec> {
19+
pub input: KZGRecoverCellsAndKzgProofsInput,
20+
pub output: Option<(Vec<String>, Vec<String>)>,
21+
#[serde(skip)]
22+
_phantom: PhantomData<E>,
23+
}
24+
25+
impl<E: EthSpec> LoadCase for KZGRecoverCellsAndKZGProofs<E> {
26+
fn load_from_dir(path: &Path, _fork_name: ForkName) -> Result<Self, Error> {
27+
decode::yaml_decode_file(path.join("data.yaml").as_path())
28+
}
29+
}
30+
31+
impl<E: EthSpec> Case for KZGRecoverCellsAndKZGProofs<E> {
32+
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
33+
fork_name == ForkName::Deneb
34+
}
35+
36+
fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> {
37+
let parse_input = |input: &KZGRecoverCellsAndKzgProofsInput| {
38+
// Proofs are not used for `recover_cells_and_compute_kzg_proofs`, they are only checked
39+
// to satisfy the spec tests.
40+
if input.proofs.len() != input.cell_indices.len() {
41+
return Err(Error::SkippedKnownFailure);
42+
}
43+
44+
let proofs = input
45+
.proofs
46+
.iter()
47+
.map(|s| parse_proof(s))
48+
.collect::<Result<Vec<_>, Error>>()?;
49+
50+
let cells = input
51+
.cells
52+
.iter()
53+
.map(|s| parse_cell(s))
54+
.collect::<Result<Vec<_>, Error>>()?;
55+
56+
Ok((proofs, cells, input.cell_indices.clone()))
57+
};
58+
59+
let result =
60+
parse_input(&self.input).and_then(|(input_proofs, input_cells, cell_indices)| {
61+
let (cells, proofs) = KZG
62+
.recover_cells_and_compute_kzg_proofs(
63+
cell_indices.as_slice(),
64+
input_cells.as_slice(),
65+
)
66+
.map_err(|e| {
67+
Error::InternalError(format!(
68+
"Failed to recover cells and kzg proofs: {e:?}"
69+
))
70+
})?;
71+
72+
// Check recovered proofs matches inputs proofs. This is done only to satisfy the
73+
// spec tests, as the ckzg library recomputes all proofs and does not require
74+
// proofs to recover.
75+
for (input_proof, cell_id) in input_proofs.iter().zip(cell_indices) {
76+
if let Err(e) = compare_result::<KzgProof, Infallible>(
77+
&Ok(*input_proof),
78+
&proofs.get(cell_id as usize).cloned(),
79+
) {
80+
return Err(e);
81+
}
82+
}
83+
84+
Ok((cells, proofs))
85+
});
86+
87+
let expected = self
88+
.output
89+
.as_ref()
90+
.and_then(|(cells, proofs)| parse_cells_and_proofs(cells, proofs).ok())
91+
.map(|(cells, proofs)| (cells.try_into().unwrap(), proofs.try_into().unwrap()));
92+
93+
compare_result::<CellsAndKzgProofs, _>(&result, &expected)
94+
}
95+
}

testing/ef_tests/src/handler.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,26 @@ impl<E: EthSpec> Handler for KZGVerifyCellKZGProofBatchHandler<E> {
886886
}
887887
}
888888

889+
#[derive(Derivative)]
890+
#[derivative(Default(bound = ""))]
891+
pub struct KZGRecoverCellsAndKZGProofHandler<E>(PhantomData<E>);
892+
893+
impl<E: EthSpec> Handler for KZGRecoverCellsAndKZGProofHandler<E> {
894+
type Case = cases::KZGRecoverCellsAndKZGProofs<E>;
895+
896+
fn config_name() -> &'static str {
897+
"general"
898+
}
899+
900+
fn runner_name() -> &'static str {
901+
"kzg"
902+
}
903+
904+
fn handler_name(&self) -> String {
905+
"recover_cells_and_kzg_proofs".into()
906+
}
907+
}
908+
889909
#[derive(Derivative)]
890910
#[derivative(Default(bound = ""))]
891911
pub struct MerkleProofValidityHandler<E>(PhantomData<E>);

testing/ef_tests/tests/tests.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,12 @@ fn kzg_verify_cell_proof_batch() {
755755
.run_for_feature(ForkName::Deneb, FeatureName::Eip7594);
756756
}
757757

758+
#[test]
759+
fn kzg_recover_cells_and_proofs() {
760+
KZGRecoverCellsAndKZGProofHandler::<MainnetEthSpec>::default()
761+
.run_for_feature(ForkName::Deneb, FeatureName::Eip7594);
762+
}
763+
758764
#[test]
759765
fn merkle_proof_validity() {
760766
MerkleProofValidityHandler::<MainnetEthSpec>::default().run();

0 commit comments

Comments
 (0)