Skip to content

Commit 93c0301

Browse files
Merge branch 'unstable' into attestation-rewards-electra
2 parents 501280c + 7e4b27c commit 93c0301

File tree

52 files changed

+1828
-1287
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1828
-1287
lines changed

Cargo.lock

Lines changed: 543 additions & 293 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ install-audit:
250250
cargo install --force cargo-audit
251251

252252
audit-CI:
253-
cargo audit --ignore RUSTSEC-2024-0421
253+
cargo audit
254254

255255
# Runs `cargo vendor` to make sure dependencies can be vendored for packaging, reproducibility and archival purpose.
256256
vendor:

account_manager/src/lib.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@ mod common;
22
pub mod validator;
33
pub mod wallet;
44

5-
use clap::Arg;
6-
use clap::ArgAction;
75
use clap::ArgMatches;
86
use clap::Command;
9-
use clap_utils::FLAG_HEADER;
107
use environment::Environment;
118
use types::EthSpec;
129

@@ -21,15 +18,6 @@ pub fn cli_app() -> Command {
2118
.visible_aliases(["a", "am", "account"])
2219
.about("Utilities for generating and managing Ethereum 2.0 accounts.")
2320
.display_order(0)
24-
.arg(
25-
Arg::new("help")
26-
.long("help")
27-
.short('h')
28-
.help("Prints help information")
29-
.action(ArgAction::HelpLong)
30-
.display_order(0)
31-
.help_heading(FLAG_HEADER),
32-
)
3321
.subcommand(wallet::cli_app())
3422
.subcommand(validator::cli_app())
3523
}

account_manager/src/validator/mod.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ pub mod slashing_protection;
88

99
use crate::{VALIDATOR_DIR_FLAG, VALIDATOR_DIR_FLAG_ALIAS};
1010
use clap::{Arg, ArgAction, ArgMatches, Command};
11-
use clap_utils::FLAG_HEADER;
1211
use directory::{parse_path_or_default_with_flag, DEFAULT_VALIDATOR_DIR};
1312
use environment::Environment;
1413
use std::path::PathBuf;
@@ -20,16 +19,6 @@ pub fn cli_app() -> Command {
2019
Command::new(CMD)
2120
.display_order(0)
2221
.about("Provides commands for managing Eth2 validators.")
23-
.arg(
24-
Arg::new("help")
25-
.long("help")
26-
.short('h')
27-
.help("Prints help information")
28-
.action(ArgAction::HelpLong)
29-
.display_order(0)
30-
.help_heading(FLAG_HEADER)
31-
.global(true),
32-
)
3322
.arg(
3423
Arg::new(VALIDATOR_DIR_FLAG)
3524
.long(VALIDATOR_DIR_FLAG)

account_manager/src/wallet/mod.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ pub mod recover;
44

55
use crate::WALLETS_DIR_FLAG;
66
use clap::{Arg, ArgAction, ArgMatches, Command};
7-
use clap_utils::FLAG_HEADER;
87
use directory::{parse_path_or_default_with_flag, DEFAULT_WALLET_DIR};
98
use std::fs::create_dir_all;
109
use std::path::PathBuf;
@@ -15,16 +14,6 @@ pub fn cli_app() -> Command {
1514
Command::new(CMD)
1615
.about("Manage wallets, from which validator keys can be derived.")
1716
.display_order(0)
18-
.arg(
19-
Arg::new("help")
20-
.long("help")
21-
.short('h')
22-
.help("Prints help information")
23-
.action(ArgAction::HelpLong)
24-
.display_order(0)
25-
.help_heading(FLAG_HEADER)
26-
.global(true)
27-
)
2817
.arg(
2918
Arg::new(WALLETS_DIR_FLAG)
3019
.long(WALLETS_DIR_FLAG)

beacon_node/beacon_chain/src/builder.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::fork_choice_signal::ForkChoiceSignalTx;
99
use crate::fork_revert::{reset_fork_choice_to_finalization, revert_to_fork_boundary};
1010
use crate::graffiti_calculator::{GraffitiCalculator, GraffitiOrigin};
1111
use crate::head_tracker::HeadTracker;
12+
use crate::kzg_utils::blobs_to_data_column_sidecars;
1213
use crate::light_client_server_cache::LightClientServerCache;
1314
use crate::migrate::{BackgroundMigrator, MigratorConfig};
1415
use crate::observed_data_sidecars::ObservedDataSidecars;
@@ -562,9 +563,30 @@ where
562563
.put_block(&weak_subj_block_root, weak_subj_block.clone())
563564
.map_err(|e| format!("Failed to store weak subjectivity block: {e:?}"))?;
564565
if let Some(blobs) = weak_subj_blobs {
565-
store
566-
.put_blobs(&weak_subj_block_root, blobs)
567-
.map_err(|e| format!("Failed to store weak subjectivity blobs: {e:?}"))?;
566+
if self
567+
.spec
568+
.is_peer_das_enabled_for_epoch(weak_subj_block.epoch())
569+
{
570+
// After PeerDAS recompute columns from blobs to not force the checkpointz server
571+
// into exposing another route.
572+
let blobs = blobs
573+
.iter()
574+
.map(|blob_sidecar| &blob_sidecar.blob)
575+
.collect::<Vec<_>>();
576+
let data_columns =
577+
blobs_to_data_column_sidecars(&blobs, &weak_subj_block, &self.kzg, &self.spec)
578+
.map_err(|e| {
579+
format!("Failed to compute weak subjectivity data_columns: {e:?}")
580+
})?;
581+
// TODO(das): only persist the columns under custody
582+
store
583+
.put_data_columns(&weak_subj_block_root, data_columns)
584+
.map_err(|e| format!("Failed to store weak subjectivity data_column: {e:?}"))?;
585+
} else {
586+
store
587+
.put_blobs(&weak_subj_block_root, blobs)
588+
.map_err(|e| format!("Failed to store weak subjectivity blobs: {e:?}"))?;
589+
}
568590
}
569591

570592
// Stage the database's metadata fields for atomic storage when `build` is called.

beacon_node/beacon_chain/src/data_availability_checker.rs

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ mod overflow_lru_cache;
2727
mod state_lru_cache;
2828

2929
use crate::data_column_verification::{
30-
verify_kzg_for_data_column, verify_kzg_for_data_column_list, CustodyDataColumn,
31-
GossipVerifiedDataColumn, KzgVerifiedCustodyDataColumn, KzgVerifiedDataColumn,
30+
verify_kzg_for_data_column_list_with_scoring, CustodyDataColumn, GossipVerifiedDataColumn,
31+
KzgVerifiedCustodyDataColumn, KzgVerifiedDataColumn,
3232
};
3333
use crate::metrics::{
3434
KZG_DATA_COLUMN_RECONSTRUCTION_ATTEMPTS, KZG_DATA_COLUMN_RECONSTRUCTION_FAILURES,
@@ -230,19 +230,14 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
230230
block_root: Hash256,
231231
custody_columns: DataColumnSidecarList<T::EthSpec>,
232232
) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> {
233-
// TODO(das): report which column is invalid for proper peer scoring
234-
// TODO(das): batch KZG verification here, but fallback into checking each column
235-
// individually to report which column(s) are invalid.
236-
let verified_custody_columns = custody_columns
233+
// Attributes fault to the specific peer that sent an invalid column
234+
let kzg_verified_columns = KzgVerifiedDataColumn::from_batch(custody_columns, &self.kzg)
235+
.map_err(AvailabilityCheckError::InvalidColumn)?;
236+
237+
let verified_custody_columns = kzg_verified_columns
237238
.into_iter()
238-
.map(|column| {
239-
let index = column.index;
240-
Ok(KzgVerifiedCustodyDataColumn::from_asserted_custody(
241-
KzgVerifiedDataColumn::new(column, &self.kzg)
242-
.map_err(|e| AvailabilityCheckError::InvalidColumn(index, e))?,
243-
))
244-
})
245-
.collect::<Result<Vec<_>, AvailabilityCheckError>>()?;
239+
.map(KzgVerifiedCustodyDataColumn::from_asserted_custody)
240+
.collect::<Vec<_>>();
246241

247242
self.availability_cache.put_kzg_verified_data_columns(
248243
block_root,
@@ -365,7 +360,8 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
365360
.iter()
366361
.map(|custody_column| custody_column.as_data_column()),
367362
&self.kzg,
368-
)?;
363+
)
364+
.map_err(AvailabilityCheckError::InvalidColumn)?;
369365
Ok(MaybeAvailableBlock::Available(AvailableBlock {
370366
block_root,
371367
block,
@@ -432,8 +428,9 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
432428

433429
// verify kzg for all data columns at once
434430
if !all_data_columns.is_empty() {
435-
// TODO: Need to also attribute which specific block is faulty
436-
verify_kzg_for_data_column_list_with_scoring(all_data_columns.iter(), &self.kzg)?;
431+
// Attributes fault to the specific peer that sent an invalid column
432+
verify_kzg_for_data_column_list_with_scoring(all_data_columns.iter(), &self.kzg)
433+
.map_err(AvailabilityCheckError::InvalidColumn)?;
437434
}
438435

439436
for block in blocks {
@@ -716,32 +713,6 @@ async fn availability_cache_maintenance_service<T: BeaconChainTypes>(
716713
}
717714
}
718715

719-
fn verify_kzg_for_data_column_list_with_scoring<'a, E: EthSpec, I>(
720-
data_column_iter: I,
721-
kzg: &'a Kzg,
722-
) -> Result<(), AvailabilityCheckError>
723-
where
724-
I: Iterator<Item = &'a Arc<DataColumnSidecar<E>>> + Clone,
725-
{
726-
let Err(batch_err) = verify_kzg_for_data_column_list(data_column_iter.clone(), kzg) else {
727-
return Ok(());
728-
};
729-
730-
let data_columns = data_column_iter.collect::<Vec<_>>();
731-
// Find which column is invalid. If len is 1 or 0 continue to default case below.
732-
// If len > 1 at least one column MUST fail.
733-
if data_columns.len() > 1 {
734-
for data_column in data_columns {
735-
if let Err(e) = verify_kzg_for_data_column(data_column.clone(), kzg) {
736-
return Err(AvailabilityCheckError::InvalidColumn(data_column.index, e));
737-
}
738-
}
739-
}
740-
741-
// len 0 should never happen
742-
Err(AvailabilityCheckError::InvalidColumn(0, batch_err))
743-
}
744-
745716
/// A fully available block that is ready to be imported into fork choice.
746717
#[derive(Clone, Debug, PartialEq)]
747718
pub struct AvailableBlock<E: EthSpec> {

beacon_node/beacon_chain/src/data_availability_checker/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use types::{BeaconStateError, ColumnIndex, Hash256};
44
#[derive(Debug)]
55
pub enum Error {
66
InvalidBlobs(KzgError),
7-
InvalidColumn(ColumnIndex, KzgError),
7+
InvalidColumn(Vec<(ColumnIndex, KzgError)>),
88
ReconstructColumnsError(KzgError),
99
KzgCommitmentMismatch {
1010
blob_commitment: KzgCommitment,

beacon_node/beacon_chain/src/data_column_verification.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,18 @@ impl<E: EthSpec> KzgVerifiedDataColumn<E> {
239239
pub fn new(data_column: Arc<DataColumnSidecar<E>>, kzg: &Kzg) -> Result<Self, KzgError> {
240240
verify_kzg_for_data_column(data_column, kzg)
241241
}
242+
243+
pub fn from_batch(
244+
data_columns: Vec<Arc<DataColumnSidecar<E>>>,
245+
kzg: &Kzg,
246+
) -> Result<Vec<Self>, Vec<(ColumnIndex, KzgError)>> {
247+
verify_kzg_for_data_column_list_with_scoring(data_columns.iter(), kzg)?;
248+
Ok(data_columns
249+
.into_iter()
250+
.map(|column| Self { data: column })
251+
.collect())
252+
}
253+
242254
pub fn to_data_column(self) -> Arc<DataColumnSidecar<E>> {
243255
self.data
244256
}
@@ -378,6 +390,38 @@ where
378390
Ok(())
379391
}
380392

393+
/// Complete kzg verification for a list of `DataColumnSidecar`s.
394+
///
395+
/// If there's at least one invalid column, it re-verifies all columns individually to identify the
396+
/// first column that is invalid. This is necessary to attribute fault to the specific peer that
397+
/// sent bad data. The re-verification cost should not be significant. If a peer sends invalid data it
398+
/// will be quickly banned.
399+
pub fn verify_kzg_for_data_column_list_with_scoring<'a, E: EthSpec, I>(
400+
data_column_iter: I,
401+
kzg: &'a Kzg,
402+
) -> Result<(), Vec<(ColumnIndex, KzgError)>>
403+
where
404+
I: Iterator<Item = &'a Arc<DataColumnSidecar<E>>> + Clone,
405+
{
406+
if verify_kzg_for_data_column_list(data_column_iter.clone(), kzg).is_ok() {
407+
return Ok(());
408+
};
409+
410+
// Find all columns that are invalid and identify by index. If we hit this condition there
411+
// should be at least one invalid column
412+
let errors = data_column_iter
413+
.filter_map(|data_column| {
414+
if let Err(e) = verify_kzg_for_data_column(data_column.clone(), kzg) {
415+
Some((data_column.index, e))
416+
} else {
417+
None
418+
}
419+
})
420+
.collect::<Vec<_>>();
421+
422+
Err(errors)
423+
}
424+
381425
pub fn validate_data_column_sidecar_for_gossip<T: BeaconChainTypes, O: ObservationStrategy>(
382426
data_column: Arc<DataColumnSidecar<T::EthSpec>>,
383427
subnet: u64,

beacon_node/builder_client/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ authors = ["Sean Anderson <[email protected]>"]
66

77
[dependencies]
88
eth2 = { workspace = true }
9+
ethereum_ssz = { workspace = true }
910
lighthouse_version = { workspace = true }
1011
reqwest = { workspace = true }
1112
sensitive_url = { workspace = true }
1213
serde = { workspace = true }
14+
serde_json = { workspace = true }

0 commit comments

Comments
 (0)