mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-19 21:04:41 +00:00
Use blinded blocks for light client proofs (#6201)
* Use blinded blocks for light client proofs
This commit is contained in:
@@ -6766,12 +6766,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
&self,
|
||||
block_root: &Hash256,
|
||||
) -> Result<Option<(LightClientBootstrap<T::EthSpec>, ForkName)>, Error> {
|
||||
let handle = self
|
||||
.task_executor
|
||||
.handle()
|
||||
.ok_or(BeaconChainError::RuntimeShutdown)?;
|
||||
|
||||
let Some(block) = handle.block_on(async { self.get_block(block_root).await })? else {
|
||||
let Some(block) = self.get_blinded_block(block_root)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
|
||||
@@ -84,13 +84,12 @@ impl<T: BeaconChainTypes> LightClientServerCache<T> {
|
||||
let signature_slot = block_slot;
|
||||
let attested_block_root = block_parent_root;
|
||||
|
||||
let attested_block =
|
||||
store
|
||||
.get_full_block(attested_block_root)?
|
||||
.ok_or(BeaconChainError::DBInconsistent(format!(
|
||||
"Block not available {:?}",
|
||||
attested_block_root
|
||||
)))?;
|
||||
let attested_block = store.get_blinded_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(),
|
||||
@@ -130,7 +129,7 @@ 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_full_block(&cached_parts.finalized_block_root)?
|
||||
store.get_blinded_block(&cached_parts.finalized_block_root)?
|
||||
{
|
||||
*self.latest_finality_update.write() = Some(LightClientFinalityUpdate::new(
|
||||
&attested_block,
|
||||
|
||||
@@ -129,6 +129,11 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBody<E, Payload> {
|
||||
pub fn execution_payload(&self) -> Result<Payload::Ref<'_>, Error> {
|
||||
self.to_ref().execution_payload()
|
||||
}
|
||||
|
||||
/// Returns the name of the fork pertaining to `self`.
|
||||
pub fn fork_name(&self) -> ForkName {
|
||||
self.to_ref().fork_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E, Payload> {
|
||||
@@ -239,6 +244,28 @@ impl<'a, E: EthSpec, Payload: AbstractExecPayload<E>> BeaconBlockBodyRef<'a, E,
|
||||
Ok(proof.into())
|
||||
}
|
||||
|
||||
pub fn block_body_merkle_proof(&self, 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 leaves = self.body_merkle_leaves();
|
||||
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)
|
||||
}
|
||||
|
||||
/// Return `true` if this block body has a non-zero number of blobs.
|
||||
pub fn has_blobs(self) -> bool {
|
||||
self.blob_kzg_commitments()
|
||||
@@ -832,73 +859,6 @@ impl<E: EthSpec> From<BeaconBlockBody<E, FullPayload<E>>>
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> BeaconBlockBody<E> {
|
||||
/// Returns the name of the fork pertaining to `self`.
|
||||
pub fn fork_name(&self) -> ForkName {
|
||||
self.to_ref().fork_name()
|
||||
}
|
||||
|
||||
pub fn block_body_merkle_proof(&self, 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 attestations_root = if self.fork_name() > ForkName::Electra {
|
||||
self.attestations_electra()?.tree_hash_root()
|
||||
} else {
|
||||
self.attestations_base()?.tree_hash_root()
|
||||
};
|
||||
|
||||
let attester_slashings_root = if self.fork_name() > ForkName::Electra {
|
||||
self.attester_slashings_electra()?.tree_hash_root()
|
||||
} else {
|
||||
self.attester_slashings_base()?.tree_hash_root()
|
||||
};
|
||||
|
||||
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(),
|
||||
attester_slashings_root,
|
||||
attestations_root,
|
||||
self.deposits().tree_hash_root(),
|
||||
self.voluntary_exits().tree_hash_root(),
|
||||
];
|
||||
|
||||
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();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
light_client_update::*, test_utils::TestRandom, BeaconState, ChainSpec, EthSpec, FixedVector,
|
||||
ForkName, ForkVersionDeserialize, Hash256, LightClientHeader, LightClientHeaderAltair,
|
||||
LightClientHeaderCapella, LightClientHeaderDeneb, LightClientHeaderElectra, SignedBeaconBlock,
|
||||
Slot, SyncCommittee,
|
||||
LightClientHeaderCapella, LightClientHeaderDeneb, LightClientHeaderElectra,
|
||||
SignedBlindedBeaconBlock, Slot, SyncCommittee,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -114,7 +114,7 @@ impl<E: EthSpec> LightClientBootstrap<E> {
|
||||
|
||||
pub fn from_beacon_state(
|
||||
beacon_state: &mut BeaconState<E>,
|
||||
block: &SignedBeaconBlock<E>,
|
||||
block: &SignedBlindedBeaconBlock<E>,
|
||||
chain_spec: &ChainSpec,
|
||||
) -> Result<Self, Error> {
|
||||
let mut header = beacon_state.latest_block_header().clone();
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::ChainSpec;
|
||||
use crate::{
|
||||
light_client_update::*, test_utils::TestRandom, ForkName, ForkVersionDeserialize,
|
||||
LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb,
|
||||
LightClientHeaderElectra, SignedBeaconBlock,
|
||||
LightClientHeaderElectra, SignedBlindedBeaconBlock,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -73,8 +73,8 @@ pub struct LightClientFinalityUpdate<E: EthSpec> {
|
||||
|
||||
impl<E: EthSpec> LightClientFinalityUpdate<E> {
|
||||
pub fn new(
|
||||
attested_block: &SignedBeaconBlock<E>,
|
||||
finalized_block: &SignedBeaconBlock<E>,
|
||||
attested_block: &SignedBlindedBeaconBlock<E>,
|
||||
finalized_block: &SignedBlindedBeaconBlock<E>,
|
||||
finality_branch: FixedVector<Hash256, FinalizedRootProofLen>,
|
||||
sync_aggregate: SyncAggregate<E>,
|
||||
signature_slot: Slot,
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::ForkVersionDeserialize;
|
||||
use crate::{light_client_update::*, BeaconBlockBody};
|
||||
use crate::{
|
||||
test_utils::TestRandom, EthSpec, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
|
||||
ExecutionPayloadHeaderElectra, FixedVector, Hash256, SignedBeaconBlock,
|
||||
ExecutionPayloadHeaderElectra, FixedVector, Hash256, SignedBlindedBeaconBlock,
|
||||
};
|
||||
use crate::{BeaconBlockHeader, ExecutionPayloadHeader};
|
||||
use derivative::Derivative;
|
||||
@@ -72,7 +72,7 @@ pub struct LightClientHeader<E: EthSpec> {
|
||||
|
||||
impl<E: EthSpec> LightClientHeader<E> {
|
||||
pub fn block_to_light_client_header(
|
||||
block: &SignedBeaconBlock<E>,
|
||||
block: &SignedBlindedBeaconBlock<E>,
|
||||
chain_spec: &ChainSpec,
|
||||
) -> Result<Self, Error> {
|
||||
let header = match block
|
||||
@@ -139,7 +139,9 @@ impl<E: EthSpec> LightClientHeader<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> LightClientHeaderAltair<E> {
|
||||
pub fn block_to_light_client_header(block: &SignedBeaconBlock<E>) -> Result<Self, Error> {
|
||||
pub fn block_to_light_client_header(
|
||||
block: &SignedBlindedBeaconBlock<E>,
|
||||
) -> Result<Self, Error> {
|
||||
Ok(LightClientHeaderAltair {
|
||||
beacon: block.message().block_header(),
|
||||
_phantom_data: PhantomData,
|
||||
@@ -148,7 +150,9 @@ impl<E: EthSpec> LightClientHeaderAltair<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> LightClientHeaderCapella<E> {
|
||||
pub fn block_to_light_client_header(block: &SignedBeaconBlock<E>) -> Result<Self, Error> {
|
||||
pub fn block_to_light_client_header(
|
||||
block: &SignedBlindedBeaconBlock<E>,
|
||||
) -> Result<Self, Error> {
|
||||
let payload = block
|
||||
.message()
|
||||
.execution_payload()?
|
||||
@@ -163,8 +167,9 @@ impl<E: EthSpec> LightClientHeaderCapella<E> {
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
let execution_branch =
|
||||
beacon_block_body.block_body_merkle_proof(EXECUTION_PAYLOAD_INDEX)?;
|
||||
let execution_branch = beacon_block_body
|
||||
.to_ref()
|
||||
.block_body_merkle_proof(EXECUTION_PAYLOAD_INDEX)?;
|
||||
|
||||
return Ok(LightClientHeaderCapella {
|
||||
beacon: block.message().block_header(),
|
||||
@@ -176,13 +181,15 @@ impl<E: EthSpec> LightClientHeaderCapella<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> LightClientHeaderDeneb<E> {
|
||||
pub fn block_to_light_client_header(block: &SignedBeaconBlock<E>) -> Result<Self, Error> {
|
||||
let payload = block
|
||||
pub fn block_to_light_client_header(
|
||||
block: &SignedBlindedBeaconBlock<E>,
|
||||
) -> Result<Self, Error> {
|
||||
let header = block
|
||||
.message()
|
||||
.execution_payload()?
|
||||
.execution_payload_deneb()?;
|
||||
.execution_payload_deneb()?
|
||||
.clone();
|
||||
|
||||
let header = ExecutionPayloadHeaderDeneb::from(payload);
|
||||
let beacon_block_body = BeaconBlockBody::from(
|
||||
block
|
||||
.message()
|
||||
@@ -191,8 +198,9 @@ impl<E: EthSpec> LightClientHeaderDeneb<E> {
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
let execution_branch =
|
||||
beacon_block_body.block_body_merkle_proof(EXECUTION_PAYLOAD_INDEX)?;
|
||||
let execution_branch = beacon_block_body
|
||||
.to_ref()
|
||||
.block_body_merkle_proof(EXECUTION_PAYLOAD_INDEX)?;
|
||||
|
||||
Ok(LightClientHeaderDeneb {
|
||||
beacon: block.message().block_header(),
|
||||
@@ -204,7 +212,9 @@ impl<E: EthSpec> LightClientHeaderDeneb<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> LightClientHeaderElectra<E> {
|
||||
pub fn block_to_light_client_header(block: &SignedBeaconBlock<E>) -> Result<Self, Error> {
|
||||
pub fn block_to_light_client_header(
|
||||
block: &SignedBlindedBeaconBlock<E>,
|
||||
) -> Result<Self, Error> {
|
||||
let payload = block
|
||||
.message()
|
||||
.execution_payload()?
|
||||
@@ -219,8 +229,9 @@ impl<E: EthSpec> LightClientHeaderElectra<E> {
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
let execution_branch =
|
||||
beacon_block_body.block_body_merkle_proof(EXECUTION_PAYLOAD_INDEX)?;
|
||||
let execution_branch = beacon_block_body
|
||||
.to_ref()
|
||||
.block_body_merkle_proof(EXECUTION_PAYLOAD_INDEX)?;
|
||||
|
||||
Ok(LightClientHeaderElectra {
|
||||
beacon: block.message().block_header(),
|
||||
|
||||
@@ -2,7 +2,7 @@ use super::{EthSpec, ForkName, ForkVersionDeserialize, LightClientHeader, Slot,
|
||||
use crate::test_utils::TestRandom;
|
||||
use crate::{
|
||||
light_client_update::*, ChainSpec, LightClientHeaderAltair, LightClientHeaderCapella,
|
||||
LightClientHeaderDeneb, LightClientHeaderElectra, SignedBeaconBlock,
|
||||
LightClientHeaderDeneb, LightClientHeaderElectra, SignedBlindedBeaconBlock,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
@@ -63,7 +63,7 @@ pub struct LightClientOptimisticUpdate<E: EthSpec> {
|
||||
|
||||
impl<E: EthSpec> LightClientOptimisticUpdate<E> {
|
||||
pub fn new(
|
||||
attested_block: &SignedBeaconBlock<E>,
|
||||
attested_block: &SignedBlindedBeaconBlock<E>,
|
||||
sync_aggregate: SyncAggregate<E>,
|
||||
signature_slot: Slot,
|
||||
chain_spec: &ChainSpec,
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::light_client_header::LightClientHeaderElectra;
|
||||
use crate::{
|
||||
beacon_state, test_utils::TestRandom, BeaconBlock, BeaconBlockHeader, BeaconState, ChainSpec,
|
||||
ForkName, ForkVersionDeserialize, LightClientHeaderAltair, LightClientHeaderCapella,
|
||||
LightClientHeaderDeneb, SignedBeaconBlock,
|
||||
LightClientHeaderDeneb, SignedBlindedBeaconBlock,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use safe_arith::ArithError;
|
||||
@@ -156,8 +156,8 @@ impl<E: EthSpec> LightClientUpdate<E> {
|
||||
beacon_state: BeaconState<E>,
|
||||
block: BeaconBlock<E>,
|
||||
attested_state: &mut BeaconState<E>,
|
||||
attested_block: &SignedBeaconBlock<E>,
|
||||
finalized_block: &SignedBeaconBlock<E>,
|
||||
attested_block: &SignedBlindedBeaconBlock<E>,
|
||||
finalized_block: &SignedBlindedBeaconBlock<E>,
|
||||
chain_spec: &ChainSpec,
|
||||
) -> Result<Self, Error> {
|
||||
let sync_aggregate = block.body().sync_aggregate()?;
|
||||
|
||||
Reference in New Issue
Block a user