mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-11 18:04:18 +00:00
API for LightClientBootstrap, LightClientFinalityUpdate, LightClientOptimisticUpdate and light client events (#3954)
* rebase and add comment * conditional test * test * optimistic chould be working now * finality should be working now * try again * try again * clippy fix * add lc bootstrap beacon api * add lc optimistic/finality update to events * fmt * That error isn't occuring on my computer but I think this should fix it * Add missing test file * Update light client types to comply with Altair light client spec. * Fix test compilation * Support deserializing light client structures for the Bellatrix fork * Move `get_light_client_bootstrap` logic to `BeaconChain`. `LightClientBootstrap` API to return `ForkVersionedResponse`. * Misc fixes. - log cleanup - move http_api config mutation to `config::get_config` for consistency - fix light client API responses * Add light client bootstrap API test and fix existing ones. * Fix test for `light-client-server` http api config. * Appease clippy * Efficiency improvement when retrieving beacon state. --------- Co-authored-by: Jimmy Chen <jchen.tc@gmail.com>
This commit is contained in:
@@ -6446,6 +6446,39 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub fn data_availability_boundary(&self) -> Option<Epoch> {
|
||||
self.data_availability_checker.data_availability_boundary()
|
||||
}
|
||||
|
||||
/// Gets the `LightClientBootstrap` object for a requested block root.
|
||||
///
|
||||
/// Returns `None` when the state or block is not found in the database.
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn get_light_client_bootstrap(
|
||||
&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 {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(mut state) = self.get_state(&state_root, Some(slot))? else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let fork_name = state
|
||||
.fork_name(&self.spec)
|
||||
.map_err(Error::InconsistentFork)?;
|
||||
|
||||
match fork_name {
|
||||
ForkName::Altair | ForkName::Merge => {
|
||||
LightClientBootstrap::from_beacon_state(&mut state)
|
||||
.map(|bootstrap| Some((bootstrap, fork_name)))
|
||||
.map_err(Error::LightClientError)
|
||||
}
|
||||
ForkName::Base | ForkName::Capella | ForkName::Deneb => Err(Error::UnsupportedFork),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> Drop for BeaconChain<T> {
|
||||
|
||||
@@ -221,6 +221,8 @@ pub enum BeaconChainError {
|
||||
ProposerHeadForkChoiceError(fork_choice::Error<proto_array::Error>),
|
||||
UnableToPublish,
|
||||
AvailabilityCheckError(AvailabilityCheckError),
|
||||
LightClientError(LightClientError),
|
||||
UnsupportedFork,
|
||||
}
|
||||
|
||||
easy_from_to!(SlotProcessingError, BeaconChainError);
|
||||
|
||||
@@ -17,6 +17,8 @@ pub struct ServerSentEventHandler<T: EthSpec> {
|
||||
contribution_tx: Sender<EventKind<T>>,
|
||||
payload_attributes_tx: Sender<EventKind<T>>,
|
||||
late_head: Sender<EventKind<T>>,
|
||||
light_client_finality_update_tx: Sender<EventKind<T>>,
|
||||
light_client_optimistic_update_tx: Sender<EventKind<T>>,
|
||||
block_reward_tx: Sender<EventKind<T>>,
|
||||
log: Logger,
|
||||
}
|
||||
@@ -40,6 +42,8 @@ impl<T: EthSpec> ServerSentEventHandler<T> {
|
||||
let (contribution_tx, _) = broadcast::channel(capacity);
|
||||
let (payload_attributes_tx, _) = broadcast::channel(capacity);
|
||||
let (late_head, _) = broadcast::channel(capacity);
|
||||
let (light_client_finality_update_tx, _) = broadcast::channel(capacity);
|
||||
let (light_client_optimistic_update_tx, _) = broadcast::channel(capacity);
|
||||
let (block_reward_tx, _) = broadcast::channel(capacity);
|
||||
|
||||
Self {
|
||||
@@ -53,6 +57,8 @@ impl<T: EthSpec> ServerSentEventHandler<T> {
|
||||
contribution_tx,
|
||||
payload_attributes_tx,
|
||||
late_head,
|
||||
light_client_finality_update_tx,
|
||||
light_client_optimistic_update_tx,
|
||||
block_reward_tx,
|
||||
log,
|
||||
}
|
||||
@@ -108,6 +114,14 @@ impl<T: EthSpec> ServerSentEventHandler<T> {
|
||||
.late_head
|
||||
.send(kind)
|
||||
.map(|count| log_count("late head", count)),
|
||||
EventKind::LightClientFinalityUpdate(_) => self
|
||||
.light_client_finality_update_tx
|
||||
.send(kind)
|
||||
.map(|count| log_count("light client finality update", count)),
|
||||
EventKind::LightClientOptimisticUpdate(_) => self
|
||||
.light_client_optimistic_update_tx
|
||||
.send(kind)
|
||||
.map(|count| log_count("light client optimistic update", count)),
|
||||
EventKind::BlockReward(_) => self
|
||||
.block_reward_tx
|
||||
.send(kind)
|
||||
@@ -158,6 +172,14 @@ impl<T: EthSpec> ServerSentEventHandler<T> {
|
||||
self.late_head.subscribe()
|
||||
}
|
||||
|
||||
pub fn subscribe_light_client_finality_update(&self) -> Receiver<EventKind<T>> {
|
||||
self.light_client_finality_update_tx.subscribe()
|
||||
}
|
||||
|
||||
pub fn subscribe_light_client_optimistic_update(&self) -> Receiver<EventKind<T>> {
|
||||
self.light_client_optimistic_update_tx.subscribe()
|
||||
}
|
||||
|
||||
pub fn subscribe_block_reward(&self) -> Receiver<EventKind<T>> {
|
||||
self.block_reward_tx.subscribe()
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ impl<T: BeaconChainTypes> VerifiedLightClientFinalityUpdate<T> {
|
||||
chain: &BeaconChain<T>,
|
||||
seen_timestamp: Duration,
|
||||
) -> Result<Self, Error> {
|
||||
let gossiped_finality_slot = light_client_finality_update.finalized_header.slot;
|
||||
let gossiped_finality_slot = light_client_finality_update.finalized_header.beacon.slot;
|
||||
let one_third_slot_duration = Duration::new(chain.spec.seconds_per_slot / 3, 0);
|
||||
let signature_slot = light_client_finality_update.signature_slot;
|
||||
let start_time = chain.slot_clock.start_of(signature_slot);
|
||||
@@ -88,7 +88,7 @@ impl<T: BeaconChainTypes> VerifiedLightClientFinalityUpdate<T> {
|
||||
.get_blinded_block(&finalized_block_root)?
|
||||
.ok_or(Error::FailedConstructingUpdate)?;
|
||||
let latest_seen_finality_update_slot = match latest_seen_finality_update.as_ref() {
|
||||
Some(update) => update.finalized_header.slot,
|
||||
Some(update) => update.finalized_header.beacon.slot,
|
||||
None => Slot::new(0),
|
||||
};
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ impl<T: BeaconChainTypes> VerifiedLightClientOptimisticUpdate<T> {
|
||||
chain: &BeaconChain<T>,
|
||||
seen_timestamp: Duration,
|
||||
) -> Result<Self, Error> {
|
||||
let gossiped_optimistic_slot = light_client_optimistic_update.attested_header.slot;
|
||||
let gossiped_optimistic_slot = light_client_optimistic_update.attested_header.beacon.slot;
|
||||
let one_third_slot_duration = Duration::new(chain.spec.seconds_per_slot / 3, 0);
|
||||
let signature_slot = light_client_optimistic_update.signature_slot;
|
||||
let start_time = chain.slot_clock.start_of(signature_slot);
|
||||
@@ -88,7 +88,7 @@ impl<T: BeaconChainTypes> VerifiedLightClientOptimisticUpdate<T> {
|
||||
.get_state(&attested_block.state_root(), Some(attested_block.slot()))?
|
||||
.ok_or(Error::FailedConstructingUpdate)?;
|
||||
let latest_seen_optimistic_update_slot = match latest_seen_optimistic_update.as_ref() {
|
||||
Some(update) => update.attested_header.slot,
|
||||
Some(update) => update.attested_header.beacon.slot,
|
||||
None => Slot::new(0),
|
||||
};
|
||||
|
||||
@@ -114,6 +114,7 @@ impl<T: BeaconChainTypes> VerifiedLightClientOptimisticUpdate<T> {
|
||||
// otherwise queue
|
||||
let canonical_root = light_client_optimistic_update
|
||||
.attested_header
|
||||
.beacon
|
||||
.canonical_root();
|
||||
|
||||
if canonical_root != head_block.message().parent_root() {
|
||||
|
||||
Reference in New Issue
Block a user