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

feat(eth-lc): electra fork #3878

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
19 changes: 14 additions & 5 deletions lib/beacon-api-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ use std::{

use hex_literal::hex;
use typenum::{NonZero, Unsigned};
use unionlabs::primitives::FixedBytes;
use unionlabs::primitives::{FixedBytes, H256};

pub use crate::{
attestation::Attestation, attestation_data::AttestationData,
@@ -368,6 +368,10 @@ consts_traits![
mk_chain_spec!(Minimal is preset::MINIMAL);
mk_chain_spec!(Mainnet is preset::MAINNET);

pub type CurrentSyncCommitteeBranch = Vec<H256>;
pub type NextSyncCommitteeBranch = Vec<H256>;
pub type FinalityBranch = Vec<H256>;

/// Values that are constant across all configurations.
pub mod consts {
use hex_literal::hex;
@@ -394,13 +398,13 @@ pub mod consts {

// https://github.com/ethereum/consensus-specs/blob/dev/ssz/merkle-proofs.md
/// `get_generalized_index(BeaconState, "finalized_checkpoint", "root")`
pub const FINALIZED_ROOT_INDEX: u64 = 105;
pub const FINALIZED_ROOT_GINDEX: u64 = 105;
/// `get_generalized_index(BeaconState, "current_sync_committee")`
pub const CURRENT_SYNC_COMMITTEE_INDEX: u64 = 54;
pub const CURRENT_SYNC_COMMITTEE_GINDEX: u64 = 54;
/// `get_generalized_index(BeaconState, "next_sync_committee")`
pub const NEXT_SYNC_COMMITTEE_INDEX: u64 = 55;
pub const NEXT_SYNC_COMMITTEE_GINDEX: u64 = 55;
/// `get_generalized_index(BeaconBlockBody, "execution_payload")`
pub const EXECUTION_PAYLOAD_INDEX: u64 = 25;
pub const EXECUTION_PAYLOAD_GINDEX: u64 = 25;
Comment on lines +401 to +407
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename the old ones to deneb?


pub const fn default_epoch() -> u64 {
u64::MAX
@@ -412,6 +416,11 @@ pub mod consts {
epoch: default_epoch(),
}
}

// https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/light-client/sync-protocol.md#new-constants
pub const FINALIZED_ROOT_GINDEX_ELECTRA: u64 = 169;
pub const CURRENT_SYNC_COMMITTEE_GINDEX_ELECTRA: u64 = 86;
pub const NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA: u64 = 87;
}

pub mod preset {
6 changes: 2 additions & 4 deletions lib/beacon-api-types/src/light_client_bootstrap.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use unionlabs::primitives::H256;

use crate::{
consts::{floorlog2, CURRENT_SYNC_COMMITTEE_INDEX},
light_client_header::LightClientHeader,
sync_committee::SyncCommittee,
CurrentSyncCommitteeBranch,
};

#[derive(Debug, Clone, PartialEq)]
@@ -12,5 +10,5 @@ pub struct LightClientBootstrap {
pub header: LightClientHeader,
/// Current sync committee corresponding to `beacon_header.state_root`
pub current_sync_committee: SyncCommittee,
pub current_sync_committee_branch: [H256; floorlog2(CURRENT_SYNC_COMMITTEE_INDEX)],
pub current_sync_committee_branch: CurrentSyncCommitteeBranch,
}
10 changes: 2 additions & 8 deletions lib/beacon-api-types/src/light_client_finality_update.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
use unionlabs::primitives::H256;

use crate::{
consts::{floorlog2, FINALIZED_ROOT_INDEX},
light_client_header::LightClientHeader,
Slot, SyncAggregate,
};
use crate::{light_client_header::LightClientHeader, FinalityBranch, Slot, SyncAggregate};

#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@@ -13,7 +7,7 @@ pub struct LightClientFinalityUpdate {
pub attested_header: LightClientHeader,
/// Finalized header corresponding to `attested_header.state_root`
pub finalized_header: LightClientHeader,
pub finality_branch: [H256; floorlog2(FINALIZED_ROOT_INDEX)],
pub finality_branch: FinalityBranch,
/// Sync committee aggregate signature
pub sync_aggregate: SyncAggregate,
/// Slot at which the aggregate signature was created (untrusted)
6 changes: 3 additions & 3 deletions lib/beacon-api-types/src/light_client_header.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ use unionlabs::primitives::H256;

use crate::{
beacon_block_header::BeaconBlockHeader,
consts::{floorlog2, EXECUTION_PAYLOAD_INDEX},
consts::{floorlog2, EXECUTION_PAYLOAD_GINDEX},
execution_payload_header::ExecutionPayloadHeader,
};

@@ -12,7 +12,7 @@ use crate::{
pub struct LightClientHeader {
pub beacon: BeaconBlockHeader,
pub execution: ExecutionPayloadHeader,
pub execution_branch: [H256; floorlog2(EXECUTION_PAYLOAD_INDEX)],
pub execution_branch: [H256; floorlog2(EXECUTION_PAYLOAD_GINDEX)],
}

#[cfg(feature = "ssz")]
@@ -25,5 +25,5 @@ pub struct LightClientHeader {
pub struct LightClientHeaderSsz<C: crate::BYTES_PER_LOGS_BLOOM + crate::MAX_EXTRA_DATA_BYTES> {
pub beacon: BeaconBlockHeader,
pub execution: crate::ExecutionPayloadHeaderSsz<C>,
pub execution_branch: [H256; floorlog2(EXECUTION_PAYLOAD_INDEX)],
pub execution_branch: [H256; floorlog2(EXECUTION_PAYLOAD_GINDEX)],
}
8 changes: 1 addition & 7 deletions lib/beacon-api-types/src/light_client_update.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
use unionlabs::primitives::H256;

use crate::{
consts::{floorlog2, FINALIZED_ROOT_INDEX, NEXT_SYNC_COMMITTEE_INDEX},
LightClientHeader, Slot, SyncAggregate, SyncCommittee,
FinalityBranch, LightClientHeader, NextSyncCommitteeBranch, Slot, SyncAggregate, SyncCommittee,
};

pub type NextSyncCommitteeBranch = [H256; floorlog2(NEXT_SYNC_COMMITTEE_INDEX)];
pub type FinalityBranch = [H256; floorlog2(FINALIZED_ROOT_INDEX)];

#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct LightClientUpdate {
2 changes: 1 addition & 1 deletion lib/ethereum-light-client-types/src/light_client_update.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use beacon_api_types::{light_client_update::NextSyncCommitteeBranch, SyncCommittee};
use beacon_api_types::{NextSyncCommitteeBranch, SyncCommittee};

use crate::LightClientUpdateData;

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use beacon_api_types::{
light_client_update::{FinalityBranch, NextSyncCommitteeBranch},
LightClientHeader, Slot, SyncAggregate, SyncCommittee,
FinalityBranch, LightClientHeader, NextSyncCommitteeBranch, Slot, SyncAggregate, SyncCommittee
};

/// Common data required for all light client updates.
70 changes: 53 additions & 17 deletions lib/ethereum-sync-protocol/src/lib.rs
Original file line number Diff line number Diff line change
@@ -7,8 +7,9 @@ pub mod utils;

use beacon_api_types::{
consts::{
floorlog2, get_subtree_index, EXECUTION_PAYLOAD_INDEX, FINALIZED_ROOT_INDEX,
NEXT_SYNC_COMMITTEE_INDEX,
CURRENT_SYNC_COMMITTEE_GINDEX, CURRENT_SYNC_COMMITTEE_GINDEX_ELECTRA,
EXECUTION_PAYLOAD_GINDEX, FINALIZED_ROOT_GINDEX, FINALIZED_ROOT_GINDEX_ELECTRA,
NEXT_SYNC_COMMITTEE_GINDEX, NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA,
},
light_client_update::LightClientUpdate,
ChainSpec, DomainType, ExecutionPayloadHeaderSsz, ForkParameters, LightClientHeader, Slot,
@@ -42,6 +43,42 @@ pub trait BlsVerify {
) -> Result<(), Error>;
}

// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#finalized_root_gindex_at_slot
pub fn finalized_root_gindex_at_slot<C: ChainSpec>(
fork_parameters: &ForkParameters,
slot: Slot,
) -> u64 {
let epoch = compute_epoch_at_slot::<C>(slot);
if epoch >= fork_parameters.electra.epoch {
return FINALIZED_ROOT_GINDEX_ELECTRA;
}
FINALIZED_ROOT_GINDEX
}

// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#current_sync_committee_gindex_at_slot
pub fn current_sync_committee_gindex_at_slot<C: ChainSpec>(
fork_parameters: &ForkParameters,
slot: Slot,
) -> u64 {
let epoch = compute_epoch_at_slot::<C>(slot);
if epoch >= fork_parameters.electra.epoch {
return CURRENT_SYNC_COMMITTEE_GINDEX_ELECTRA;
}
CURRENT_SYNC_COMMITTEE_GINDEX
}

// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#next_sync_committee_gindex_at_slot
pub fn next_sync_committee_gindex_at_slot<C: ChainSpec>(
fork_parameters: &ForkParameters,
slot: Slot,
) -> u64 {
let epoch = compute_epoch_at_slot::<C>(slot);
if epoch >= fork_parameters.electra.epoch {
return NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA;
}
NEXT_SYNC_COMMITTEE_GINDEX
}

Comment on lines +46 to +81
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nit but make the links doc comments: /// <link>

/// Verifies if the light client `update` is valid.
///
/// * `update`: The light client update we want to verify.
@@ -169,8 +206,7 @@ pub fn validate_light_client_update<C: ChainSpec, V: BlsVerify>(
validate_merkle_branch(
&update.finalized_header.beacon.tree_hash_root(),
&update.finality_branch,
floorlog2(FINALIZED_ROOT_INDEX),
get_subtree_index(FINALIZED_ROOT_INDEX),
finalized_root_gindex_at_slot::<C>(fork_parameters, update_attested_slot),
&update.attested_header.beacon.state_root,
)?;

@@ -188,14 +224,17 @@ pub fn validate_light_client_update<C: ChainSpec, V: BlsVerify>(
},
)?;
}

// This validates the given next sync committee against the attested header's state root.
validate_merkle_branch(
&TryInto::<SyncCommitteeSsz<C>>::try_into(next_sync_committee.clone())
.unwrap()
.tree_hash_root(),
&update.next_sync_committee_branch.unwrap_or_default(),
floorlog2(NEXT_SYNC_COMMITTEE_INDEX),
get_subtree_index(NEXT_SYNC_COMMITTEE_INDEX),
&update
.next_sync_committee_branch
.clone()
.unwrap_or_default()[..],
next_sync_committee_gindex_at_slot::<C>(fork_parameters, update_attested_slot),
&update.attested_header.beacon.state_root,
)?;
}
@@ -245,19 +284,17 @@ pub fn get_lc_execution_root<C: ChainSpec>(
header: &LightClientHeader,
) -> H256 {
let epoch = compute_epoch_at_slot::<C>(header.beacon.slot);
// Now new field in electra
if epoch >= fork_parameters.electra.epoch {
return TryInto::<ExecutionPayloadHeaderSsz<C>>::try_into(header.execution.clone())
.unwrap()
.tree_hash_root();
}
if epoch >= fork_parameters.deneb.epoch {
return TryInto::<ExecutionPayloadHeaderSsz<C>>::try_into(header.execution.clone())
.unwrap()
.tree_hash_root();
}
Comment on lines +287 to 297
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these branches are the same?


// TODO: Figure out what to do here
// if epoch >= fork_parameters.capella.epoch {
// return CapellaExecutionPayloadHeader::from(header.execution.clone())
// .tree_hash_root()
// .into();
// }

H256::default()
}

@@ -285,8 +322,7 @@ pub fn is_valid_light_client_header<C: ChainSpec>(
validate_merkle_branch(
&get_lc_execution_root::<C>(fork_parameters, header),
&header.execution_branch,
floorlog2(EXECUTION_PAYLOAD_INDEX),
get_subtree_index(EXECUTION_PAYLOAD_INDEX),
EXECUTION_PAYLOAD_GINDEX,
&header.beacon.body_root,
)
}
27 changes: 15 additions & 12 deletions lib/ethereum-sync-protocol/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use beacon_api_types::{
consts::{floorlog2, get_subtree_index},
Domain, DomainType, ForkData, ForkParameters, SigningData, Slot, Version,
EPOCHS_PER_SYNC_COMMITTEE_PERIOD, SECONDS_PER_SLOT, SLOTS_PER_EPOCH,
};
@@ -17,7 +18,9 @@ use crate::{
///
/// [See in consensus-spec](https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/fork.md#modified-compute_fork_version)
pub fn compute_fork_version(fork_parameters: &ForkParameters, epoch: u64) -> Version {
if epoch >= fork_parameters.deneb.epoch {
if epoch >= fork_parameters.electra.epoch {
fork_parameters.electra.version
} else if epoch >= fork_parameters.deneb.epoch {
fork_parameters.deneb.version
} else if epoch >= fork_parameters.capella.epoch {
fork_parameters.capella.version
@@ -137,12 +140,12 @@ pub fn validate_signature_supermajority(sync_committee_bits: &[u8]) -> bool {
pub fn validate_merkle_branch<'a>(
leaf: &H256,
branch: impl IntoIterator<Item = &'a H256>,
depth: usize,
index: u64,
gindex: u64,
root: &H256,
) -> Result<(), Error> {
let depth = floorlog2(gindex);
let index = get_subtree_index(gindex);
let branch = branch.into_iter().cloned().collect::<Vec<_>>();

'block: {
let mut value = *leaf;

@@ -338,8 +341,8 @@ pub fn validate_merkle_branch<'a>(
// // validate_merkle_branch(
// // &valid_leaf,
// // &valid_branch,
// // floorlog2(EXECUTION_PAYLOAD_INDEX),
// // EXECUTION_PAYLOAD_INDEX,
// // floorlog2(EXECUTION_PAYLOAD_GINDEX),
// // EXECUTION_PAYLOAD_GINDEX,
// // &valid_root,
// // ),
// // Ok(())
@@ -349,8 +352,8 @@ pub fn validate_merkle_branch<'a>(
// // assert!(validate_merkle_branch(
// // &valid_leaf,
// // &valid_branch,
// // floorlog2(EXECUTION_PAYLOAD_INDEX),
// // EXECUTION_PAYLOAD_INDEX + 1,
// // floorlog2(EXECUTION_PAYLOAD_GINDEX),
// // EXECUTION_PAYLOAD_GINDEX + 1,
// // &valid_root,
// // )
// // .is_err());
@@ -365,8 +368,8 @@ pub fn validate_merkle_branch<'a>(
// // assert!(validate_merkle_branch(
// // &invalid_leaf,
// // &valid_branch,
// // floorlog2(EXECUTION_PAYLOAD_INDEX),
// // EXECUTION_PAYLOAD_INDEX,
// // floorlog2(EXECUTION_PAYLOAD_GINDEX),
// // EXECUTION_PAYLOAD_GINDEX,
// // &valid_root,
// // )
// // .is_err());
@@ -381,8 +384,8 @@ pub fn validate_merkle_branch<'a>(
// // assert!(validate_merkle_branch(
// // &valid_leaf,
// // &invalid_branch,
// // floorlog2(EXECUTION_PAYLOAD_INDEX),
// // EXECUTION_PAYLOAD_INDEX,
// // floorlog2(EXECUTION_PAYLOAD_GINDEX),
// // EXECUTION_PAYLOAD_GINDEX,
// // &valid_root,
// // )
// // .is_err());