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

Add Capella & Deneb light client support #4946

Merged
merged 86 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
388a7cd
rebase and add comment
GeemoCandama Feb 7, 2023
b47b4f2
conditional test
GeemoCandama Feb 8, 2023
df78885
test
GeemoCandama Feb 8, 2023
e124c99
optimistic chould be working now
GeemoCandama Feb 8, 2023
cfdeca0
finality should be working now
GeemoCandama Feb 8, 2023
e15b98f
try again
GeemoCandama Feb 8, 2023
6db8a41
try again
GeemoCandama Feb 8, 2023
1537947
clippy fix
GeemoCandama Feb 8, 2023
5dbde26
add lc bootstrap beacon api
GeemoCandama Feb 9, 2023
4611a9c
add lc optimistic/finality update to events
GeemoCandama Feb 9, 2023
d3da99f
fmt
GeemoCandama Feb 9, 2023
a2f6a8a
That error isn't occuring on my computer but I think this should fix it
GeemoCandama Feb 11, 2023
00179e4
Merge branch 'unstable' into light_client_beacon_api_1
jimmygchen Nov 16, 2023
d74e3b4
Add missing test file
jimmygchen Nov 16, 2023
ad3cc69
Update light client types to comply with Altair light client spec.
jimmygchen Nov 16, 2023
f062e77
Fix test compilation
jimmygchen Nov 16, 2023
7307756
Merge branch 'unstable' into light_client_beacon_api_1
jimmygchen Nov 16, 2023
bfd3fb7
Support deserializing light client structures for the Bellatrix fork
jimmygchen Nov 17, 2023
d90df3f
Move `get_light_client_bootstrap` logic to `BeaconChain`. `LightClien…
jimmygchen Nov 17, 2023
80ff555
Misc fixes.
jimmygchen Nov 17, 2023
75bd2ac
Add light client bootstrap API test and fix existing ones.
jimmygchen Nov 17, 2023
bd75152
Merge branch 'unstable' into light_client_beacon_api_1
jimmygchen Nov 17, 2023
e0d0ece
Fix test for `light-client-server` http api config.
jimmygchen Nov 17, 2023
161ece6
Appease clippy
jimmygchen Nov 17, 2023
885958e
Add Altair light client SSZ tests
jimmygchen Nov 21, 2023
fc30e04
Merge branch 'unstable' of https://github.com/sigp/lighthouse into li…
eserilev Nov 21, 2023
fe8e2e4
updates to light client header
eserilev Nov 21, 2023
ec1400f
light client header from signed beacon block
eserilev Nov 22, 2023
435da02
using options
eserilev Nov 24, 2023
73a581a
implement helper functions
eserilev Nov 25, 2023
5ff6f43
placeholder conversion from vec hash256 to exec branch
eserilev Nov 25, 2023
7aacc65
add deneb
eserilev Nov 25, 2023
3593f52
using fixed vector
eserilev Nov 25, 2023
65a5770
remove unwraps
eserilev Nov 26, 2023
fd1a691
by epoch
eserilev Nov 28, 2023
443d219
compute merkle proof
eserilev Nov 28, 2023
a9fa092
merkle proof
eserilev Nov 28, 2023
effeec1
update comments
eserilev Nov 28, 2023
f92a296
resolve merge conflicts
eserilev Nov 28, 2023
03c163f
linting
eserilev Nov 28, 2023
67df375
Merge branch 'unstable' into light-client-ssz-tests
jimmygchen Nov 28, 2023
16740c2
superstruct attempt
eserilev Dec 1, 2023
302a1cb
superstruct changes
eserilev Dec 3, 2023
79eeefd
lint
eserilev Dec 3, 2023
17adb6a
altair
eserilev Dec 3, 2023
5ab7681
update
eserilev Dec 3, 2023
74b0b6f
update
eserilev Dec 3, 2023
1879bfd
changes to light_client_optimistic_ and finality
eserilev Dec 3, 2023
9f0a2bc
merge unstable
eserilev Dec 12, 2023
1d10abe
refactor
eserilev Dec 12, 2023
22dc62f
resolved merge conflicts
eserilev Jan 31, 2024
8ba6ebe
Merge branch 'unstable' of https://github.com/sigp/lighthouse into ca…
eserilev Jan 31, 2024
b75d23b
block_to_light_client_header fork aware
eserilev Feb 1, 2024
5f75f25
fmt
eserilev Feb 1, 2024
96f89a2
comment fix
eserilev Feb 1, 2024
7a253bf
comment fix
eserilev Feb 1, 2024
5808f7c
include merge fork, update deserialize_by_fork, refactor
eserilev Feb 3, 2024
6663614
fmt
eserilev Feb 3, 2024
f442b5a
pass by ref to prevent clone
eserilev Feb 3, 2024
932f440
rename merkle proof fn
eserilev Feb 3, 2024
5556891
add FIXME
eserilev Feb 5, 2024
06da24a
LightClientHeader TestRandom
eserilev Feb 6, 2024
453b4d2
fix comments
eserilev Feb 6, 2024
d97d496
fork version deserialize
eserilev Feb 29, 2024
e6f6876
merge unstable
eserilev Feb 29, 2024
b23c913
move fn arguments, fork name calc
eserilev Mar 2, 2024
dde9274
use task executor
eserilev Mar 3, 2024
38cdd77
remove unneeded fns
eserilev Mar 5, 2024
c064c45
remove dead code
eserilev Mar 6, 2024
b964f3f
add manual ssz decoding/encoding and add ssz_tests_by_fork macro
eserilev Mar 7, 2024
9c9fbca
merge deneb types with tests
eserilev Mar 7, 2024
3a3616c
merge ssz tests, revert code deletion, cleanup
eserilev Mar 7, 2024
6ddfe7e
move chainspec
eserilev Mar 7, 2024
258f51b
update ssz tests
eserilev Mar 8, 2024
cb41899
fmt
eserilev Mar 8, 2024
57d90fe
light client ssz tests
eserilev Mar 11, 2024
534e808
change to superstruct
eserilev Mar 11, 2024
dd43c12
changes from feedback
eserilev Mar 12, 2024
aba1475
linting
eserilev Mar 12, 2024
6fb0270
Merge branch 'unstable' of https://github.com/sigp/lighthouse into ca…
eserilev Mar 12, 2024
b3f7b81
test fix
eserilev Mar 12, 2024
8a7b2bc
cleanup
eserilev Mar 12, 2024
d314d12
Remove unused `derive`.
jimmygchen Mar 13, 2024
9b31545
Merge branch 'unstable' of https://github.com/sigp/lighthouse into ca…
eserilev Mar 23, 2024
a7dd9ee
beta compiler fix
eserilev Mar 23, 2024
d9a0b48
merge
eserilev Mar 23, 2024
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
16 changes: 9 additions & 7 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
) -> Result<(), Error> {
self.light_client_server_cache.recompute_and_cache_updates(
&self.log,
&self.spec,
self.store.clone(),
&parent_root,
slot,
Expand Down Expand Up @@ -6631,13 +6632,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
&self,
block_root: &Hash256,
) -> Result<Option<(LightClientBootstrap<T::EthSpec>, ForkName)>, Error> {
let Some((state_root, slot)) = self
.get_blinded_block(block_root)?
.map(|block| (block.state_root(), block.slot()))
else {
let runtime = tokio::runtime::Runtime::new().map_err(|_| Error::RuntimeShutdown)?;
jimmygchen marked this conversation as resolved.
Show resolved Hide resolved

let Some(block) = runtime.block_on(async { self.get_block(block_root).await })? else {
jimmygchen marked this conversation as resolved.
Show resolved Hide resolved
return Ok(None);
};

let (state_root, slot) = (block.state_root(), block.slot());

let Some(mut state) = self.get_state(&state_root, Some(slot))? else {
return Ok(None);
};
Expand All @@ -6647,12 +6649,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.map_err(Error::InconsistentFork)?;

match fork_name {
ForkName::Altair | ForkName::Merge => {
LightClientBootstrap::from_beacon_state(&mut state)
ForkName::Altair | ForkName::Merge | ForkName::Capella | ForkName::Deneb => {
LightClientBootstrap::from_beacon_state(&self.spec, &mut state, &block)
eserilev marked this conversation as resolved.
Show resolved Hide resolved
.map(|bootstrap| Some((bootstrap, fork_name)))
.map_err(Error::LightClientError)
}
ForkName::Base | ForkName::Capella | ForkName::Deneb => Err(Error::UnsupportedFork),
ForkName::Base => Err(Error::UnsupportedFork),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions beacon_node/beacon_chain/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ easy_from_to!(StateAdvanceError, BeaconChainError);
easy_from_to!(BlockReplayError, BeaconChainError);
easy_from_to!(InconsistentFork, BeaconChainError);
easy_from_to!(AvailabilityCheckError, BeaconChainError);
easy_from_to!(LightClientError, BeaconChainError);

#[derive(Debug)]
pub enum BlockProductionError {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl<T: BeaconChainTypes> VerifiedLightClientOptimisticUpdate<T> {
// otherwise queue
let canonical_root = rcv_optimistic_update
.attested_header
.beacon
.beacon()
.canonical_root();

if canonical_root != head_block.message().parent_root() {
Expand All @@ -84,7 +84,7 @@ impl<T: BeaconChainTypes> VerifiedLightClientOptimisticUpdate<T> {
return Err(Error::InvalidLightClientOptimisticUpdate);
}

let parent_root = rcv_optimistic_update.attested_header.beacon.parent_root;
let parent_root = rcv_optimistic_update.attested_header.beacon().parent_root;
Ok(Self {
light_client_optimistic_update: rcv_optimistic_update,
parent_root,
Expand Down
64 changes: 40 additions & 24 deletions beacon_node/beacon_chain/src/light_client_server_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ use parking_lot::{Mutex, RwLock};
use slog::{debug, Logger};
use ssz_types::FixedVector;
use std::num::NonZeroUsize;
use types::light_client_header::{
LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
};
use types::light_client_update::{FinalizedRootProofLen, FINALIZED_ROOT_INDEX};
use types::non_zero_usize::new_non_zero_usize;
use types::{
BeaconBlockRef, BeaconState, ChainSpec, EthSpec, ForkName, Hash256, LightClientFinalityUpdate,
LightClientHeader, LightClientOptimisticUpdate, Slot, SyncAggregate,
light_client_update::Error as LightClientError, BeaconBlockRef, BeaconState, ChainSpec,
EthSpec, ForkName, Hash256, LightClientFinalityUpdate, LightClientHeader,
LightClientOptimisticUpdate, SignedBeaconBlock, Slot, SyncAggregate,
};

/// A prev block cache miss requires to re-generate the state of the post-parent block. Items in the
Expand Down Expand Up @@ -72,6 +76,7 @@ impl<T: BeaconChainTypes> LightClientServerCache<T> {
pub fn recompute_and_cache_updates(
&self,
log: &Logger,
eserilev marked this conversation as resolved.
Show resolved Hide resolved
chain_spec: &ChainSpec,
store: BeaconStore<T>,
block_parent_root: &Hash256,
block_slot: Slot,
Expand All @@ -83,12 +88,13 @@ impl<T: BeaconChainTypes> LightClientServerCache<T> {
let signature_slot = block_slot;
let attested_block_root = block_parent_root;

let attested_block = store.get_blinded_block(attested_block_root)?.ok_or(
BeaconChainError::DBInconsistent(format!(
"Block not available {:?}",
attested_block_root
)),
)?;
let attested_block =
store
.get_full_block(attested_block_root)?
.ok_or(BeaconChainError::DBInconsistent(format!(
"Block not available {:?}",
attested_block_root
)))?;

let cached_parts = self.get_or_compute_prev_block_cache(
store.clone(),
Expand All @@ -99,6 +105,9 @@ impl<T: BeaconChainTypes> LightClientServerCache<T> {

let attested_slot = attested_block.slot();

let fork_name =
chain_spec.fork_name_at_epoch(attested_slot.epoch(T::EthSpec::slots_per_epoch()));
jimmygchen marked this conversation as resolved.
Show resolved Hide resolved

// Spec: Full nodes SHOULD provide the LightClientOptimisticUpdate with the highest
// attested_header.beacon.slot (if multiple, highest signature_slot) as selected by fork choice
let is_latest_optimistic = match &self.latest_optimistic_update.read().clone() {
Expand All @@ -110,7 +119,7 @@ impl<T: BeaconChainTypes> LightClientServerCache<T> {
if is_latest_optimistic {
// can create an optimistic update, that is more recent
*self.latest_optimistic_update.write() = Some(LightClientOptimisticUpdate {
attested_header: block_to_light_client_header(attested_block.message()),
attested_header: block_to_light_client_header(fork_name, &attested_block)?,
sync_aggregate: sync_aggregate.clone(),
signature_slot,
});
Expand All @@ -127,13 +136,13 @@ impl<T: BeaconChainTypes> LightClientServerCache<T> {
if is_latest_finality & !cached_parts.finalized_block_root.is_zero() {
// Immediately after checkpoint sync the finalized block may not be available yet.
if let Some(finalized_block) =
store.get_blinded_block(&cached_parts.finalized_block_root)?
store.get_full_block(&cached_parts.finalized_block_root)?
{
*self.latest_finality_update.write() = Some(LightClientFinalityUpdate {
// TODO: may want to cache this result from latest_optimistic_update if producing a
// light_client header becomes expensive
attested_header: block_to_light_client_header(attested_block.message()),
finalized_header: block_to_light_client_header(finalized_block.message()),
attested_header: block_to_light_client_header(fork_name, &attested_block)?,
finalized_header: block_to_light_client_header(fork_name, &finalized_block)?,
finality_branch: cached_parts.finality_branch.clone(),
sync_aggregate: sync_aggregate.clone(),
signature_slot,
Expand Down Expand Up @@ -214,7 +223,7 @@ impl LightClientCachedData {
}
}

// Implements spec priorization rules:
// Implements spec prioritization rules:
// > Full nodes SHOULD provide the LightClientFinalityUpdate with the highest attested_header.beacon.slot (if multiple, highest signature_slot)
//
// ref: https://github.com/ethereum/consensus-specs/blob/113c58f9bf9c08867f6f5f633c4d98e0364d612a/specs/altair/light-client/full-node.md#create_light_client_finality_update
Expand All @@ -223,14 +232,14 @@ fn is_latest_finality_update<T: EthSpec>(
attested_slot: Slot,
signature_slot: Slot,
) -> bool {
if attested_slot > prev.attested_header.beacon.slot {
if attested_slot > prev.attested_header.beacon().slot {
true
} else {
attested_slot == prev.attested_header.beacon.slot && signature_slot > prev.signature_slot
attested_slot == prev.attested_header.beacon().slot && signature_slot > prev.signature_slot
}
}

// Implements spec priorization rules:
// Implements spec prioritization rules:
// > Full nodes SHOULD provide the LightClientOptimisticUpdate with the highest attested_header.beacon.slot (if multiple, highest signature_slot)
//
// ref: https://github.com/ethereum/consensus-specs/blob/113c58f9bf9c08867f6f5f633c4d98e0364d612a/specs/altair/light-client/full-node.md#create_light_client_optimistic_update
Expand All @@ -239,18 +248,25 @@ fn is_latest_optimistic_update<T: EthSpec>(
attested_slot: Slot,
signature_slot: Slot,
) -> bool {
if attested_slot > prev.attested_header.beacon.slot {
if attested_slot > prev.attested_header.beacon().slot {
true
} else {
attested_slot == prev.attested_header.beacon.slot && signature_slot > prev.signature_slot
attested_slot == prev.attested_header.beacon().slot && signature_slot > prev.signature_slot
}
}

fn block_to_light_client_header<T: EthSpec>(
block: BeaconBlockRef<T, types::BlindedPayload<T>>,
) -> LightClientHeader {
// TODO: make fork aware
LightClientHeader {
beacon: block.block_header(),
}
fork_name: ForkName,
block: &SignedBeaconBlock<T>,
) -> Result<LightClientHeader<T>, BeaconChainError> {
let light_client_header = match fork_name {
ForkName::Base => return Err(LightClientError::AltairForkNotActive.into()),
ForkName::Merge | ForkName::Altair => {
LightClientHeaderAltair::block_to_light_client_header(block)?.into()
}
ForkName::Capella => LightClientHeaderCapella::block_to_light_client_header(block)?.into(),
ForkName::Deneb => LightClientHeaderDeneb::block_to_light_client_header(block)?.into(),
};

Ok(light_client_header)
}
2 changes: 1 addition & 1 deletion beacon_node/http_api/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1715,7 +1715,7 @@ impl ApiTester {
};

let expected = block.slot();
assert_eq!(result.header.beacon.slot, expected);
assert_eq!(result.header.beacon().slot, expected);

self
}
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ fn handle_rpc_response<T: EthSpec>(
MetaDataV1::from_ssz_bytes(decoded_buffer)?,
)))),
SupportedProtocol::LightClientBootstrapV1 => Ok(Some(RPCResponse::LightClientBootstrap(
LightClientBootstrap::from_ssz_bytes(decoded_buffer)?,
Arc::new(LightClientBootstrap::from_ssz_bytes(decoded_buffer)?),
))),
// MetaData V2 responses have no context bytes, so behave similarly to V1 responses
SupportedProtocol::MetaDataV2 => Ok(Some(RPCResponse::MetaData(MetaData::V2(
Expand Down
4 changes: 2 additions & 2 deletions beacon_node/lighthouse_network/src/rpc/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ pub enum RPCResponse<T: EthSpec> {
BlobsByRange(Arc<BlobSidecar<T>>),

/// A response to a get LIGHT_CLIENT_BOOTSTRAP request.
LightClientBootstrap(LightClientBootstrap<T>),
LightClientBootstrap(Arc<LightClientBootstrap<T>>),

/// A response to a get BLOBS_BY_ROOT request.
BlobsByRoot(Arc<BlobSidecar<T>>),
Expand Down Expand Up @@ -569,7 +569,7 @@ impl<T: EthSpec> std::fmt::Display for RPCResponse<T> {
write!(
f,
"LightClientBootstrap Slot: {}",
bootstrap.header.beacon.slot
bootstrap.header.beacon().slot
eserilev marked this conversation as resolved.
Show resolved Hide resolved
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/lighthouse_network/src/service/api_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pub enum Response<TSpec: EthSpec> {
/// A response to a get BLOBS_BY_ROOT request.
BlobsByRoot(Option<Arc<BlobSidecar<TSpec>>>),
/// A response to a LightClientUpdate request.
LightClientBootstrap(LightClientBootstrap<TSpec>),
LightClientBootstrap(Arc<LightClientBootstrap<TSpec>>),
}

impl<TSpec: EthSpec> std::convert::From<Response<TSpec>> for RPCCodedResponse<TSpec> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
match self.chain.get_light_client_bootstrap(&block_root) {
Ok(Some((bootstrap, _))) => self.send_response(
peer_id,
Response::LightClientBootstrap(bootstrap),
Response::LightClientBootstrap(Arc::new(bootstrap)),
request_id,
),
Ok(None) => self.send_error_response(
Expand Down
63 changes: 62 additions & 1 deletion consensus/types/src/beacon_block_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ pub type KzgCommitments<T> =
pub type KzgCommitmentOpts<T> =
FixedVector<Option<KzgCommitment>, <T as EthSpec>::MaxBlobsPerBlock>;

/// The number of leaves (including padding) on the `BeaconBlockBody` Merkle tree.
///
/// ## Note
///
/// This constant is set with the assumption that there are `> 8` and `<= 16` fields on the
/// `BeaconBlockBody`. **Tree hashing will fail if this value is set incorrectly.**
pub const NUM_BEACON_BLOCK_BODY_HASH_TREE_ROOT_LEAVES: usize = 16;
/// Index of the `blob_kzg_commitments` leaf in the `BeaconBlockBody` tree post-deneb.
pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;

Expand Down Expand Up @@ -47,11 +54,12 @@ pub const BLOB_KZG_COMMITMENTS_INDEX: usize = 11;
cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant")
)]
#[derive(Debug, Clone, Serialize, Deserialize, Derivative, arbitrary::Arbitrary)]
#[derive(Debug, Clone, Serialize, Deserialize, Derivative, TreeHash, arbitrary::Arbitrary)]
jimmygchen marked this conversation as resolved.
Show resolved Hide resolved
#[derivative(PartialEq, Hash(bound = "T: EthSpec"))]
#[serde(untagged)]
#[serde(bound = "T: EthSpec, Payload: AbstractExecPayload<T>")]
#[arbitrary(bound = "T: EthSpec, Payload: AbstractExecPayload<T>")]
#[tree_hash(enum_behaviour = "transparent")]
pub struct BeaconBlockBody<T: EthSpec, Payload: AbstractExecPayload<T> = FullPayload<T>> {
pub randao_reveal: Signature,
pub eth1_data: Eth1Data,
Expand Down Expand Up @@ -586,6 +594,59 @@ impl<E: EthSpec> From<BeaconBlockBody<E, FullPayload<E>>>
}
}

impl<T: EthSpec> BeaconBlockBody<T> {
pub fn block_body_merkle_proof(
&mut self,
eserilev marked this conversation as resolved.
Show resolved Hide resolved
generalized_index: usize,
) -> Result<Vec<Hash256>, Error> {
let field_index = match generalized_index {
light_client_update::EXECUTION_PAYLOAD_INDEX => {
// Execution payload is a top-level field, subtract off the generalized indices
// for the internal nodes. Result should be 9, the field offset of the execution
// payload in the `BeaconBlockBody`:
// https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/beacon-chain.md#beaconblockbody
generalized_index
.checked_sub(NUM_BEACON_BLOCK_BODY_HASH_TREE_ROOT_LEAVES)
.ok_or(Error::IndexNotSupported(generalized_index))?
}
_ => return Err(Error::IndexNotSupported(generalized_index)),
};

let mut leaves = vec![
self.randao_reveal().tree_hash_root(),
self.eth1_data().tree_hash_root(),
self.graffiti().tree_hash_root(),
self.proposer_slashings().tree_hash_root(),
self.attester_slashings().tree_hash_root(),
self.attestations().tree_hash_root(),
self.deposits().tree_hash_root(),
self.voluntary_exits().tree_hash_root(),
];
jimmygchen marked this conversation as resolved.
Show resolved Hide resolved

if let Ok(sync_aggregate) = self.sync_aggregate() {
leaves.push(sync_aggregate.tree_hash_root())
}

if let Ok(execution_payload) = self.execution_payload() {
leaves.push(execution_payload.tree_hash_root())
}

if let Ok(bls_to_execution_changes) = self.bls_to_execution_changes() {
leaves.push(bls_to_execution_changes.tree_hash_root())
}

if let Ok(blob_kzg_commitments) = self.blob_kzg_commitments() {
leaves.push(blob_kzg_commitments.tree_hash_root())
}

let depth = light_client_update::EXECUTION_PAYLOAD_PROOF_LEN;
let tree = merkle_proof::MerkleTree::create(&leaves, depth);
let (_, proof) = tree.generate_proof(field_index, depth)?;

Ok(proof)
}
}

/// Util method helpful for logging.
pub fn format_kzg_commitments(commitments: &[KzgCommitment]) -> String {
let commitment_strings: Vec<String> = commitments.iter().map(|x| x.to_string()).collect();
Expand Down
1 change: 1 addition & 0 deletions consensus/types/src/beacon_block_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use tree_hash_derive::TreeHash;
#[derive(
arbitrary::Arbitrary,
Debug,
Default,
jimmygchen marked this conversation as resolved.
Show resolved Hide resolved
PartialEq,
Eq,
Hash,
Expand Down
Loading