Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
lion committed Nov 8, 2023
1 parent dfcb336 commit 1ee564f
Show file tree
Hide file tree
Showing 10 changed files with 562 additions and 173 deletions.
27 changes: 20 additions & 7 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::light_client_finality_update_verification::{
use crate::light_client_optimistic_update_verification::{
Error as LightClientOptimisticUpdateError, VerifiedLightClientOptimisticUpdate,
};
use crate::lightclient_proofs_cache::LightclientServerCache;
use crate::migrate::BackgroundMigrator;
use crate::naive_aggregation_pool::{
AggregatedAttestationMap, Error as NaiveAggregationError, NaiveAggregationPool,
Expand Down Expand Up @@ -106,6 +107,7 @@ use task_executor::{ShutdownReason, TaskExecutor};
use tokio_stream::Stream;
use tree_hash::TreeHash;
use types::beacon_state::CloneConfig;
use types::light_client_update::{FINALIZED_ROOT_INDEX, NEXT_SYNC_COMMITTEE_INDEX};
use types::*;

pub type ForkChoiceError = fork_choice::Error<crate::ForkChoiceStoreError>;
Expand Down Expand Up @@ -363,10 +365,6 @@ pub struct BeaconChain<T: BeaconChainTypes> {
/// Maintains a record of which validators we've seen BLS to execution changes for.
pub(crate) observed_bls_to_execution_changes:
Mutex<ObservedOperations<SignedBlsToExecutionChange, T::EthSpec>>,
/// The most recently validated light client finality update received on gossip.
pub latest_seen_finality_update: Mutex<Option<LightClientFinalityUpdate<T::EthSpec>>>,
/// The most recently validated light client optimistic update received on gossip.
pub latest_seen_optimistic_update: Mutex<Option<LightClientOptimisticUpdate<T::EthSpec>>>,
/// Provides information from the Ethereum 1 (PoW) chain.
pub eth1_chain: Option<Eth1Chain<T::Eth1Chain, T::EthSpec>>,
/// Interfaces with the execution client.
Expand Down Expand Up @@ -409,6 +407,8 @@ pub struct BeaconChain<T: BeaconChainTypes> {
pub block_times_cache: Arc<RwLock<BlockTimesCache>>,
/// A cache used to track pre-finalization block roots for quick rejection.
pub pre_finalization_block_cache: PreFinalizationBlockCache,
/// A cache used to produce lightclient server messages
pub lightclient_server_cache: LightclientServerCache<T>,
/// Sender given to tasks, so that if they encounter a state in which execution cannot
/// continue they can request that everything shuts down.
pub shutdown_sender: Sender<ShutdownReason>,
Expand Down Expand Up @@ -2834,7 +2834,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
parent_block: SignedBlindedBeaconBlock<T::EthSpec>,
parent_eth1_finalization_data: Eth1FinalizationData,
mut consensus_context: ConsensusContext<T::EthSpec>,
) -> Result<Hash256, BlockError<T::EthSpec>> {
) -> Result<(Hash256, LightclientBlockUpdates), BlockError<T::EthSpec>> {
// ----------------------------- BLOCK NOT YET ATTESTABLE ----------------------------------
// Everything in this initial section is on the hot path between processing the block and
// being able to attest to it. DO NOT add any extra processing in this initial section
Expand Down Expand Up @@ -2985,6 +2985,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {

let db_write_timer = metrics::start_timer(&metrics::BLOCK_PROCESSING_DB_WRITE);

ops.extend(
self.lightclient_server_cache
.import_block(block_root, &state)?,
);

// Store the block and its state, and execute the confirmation batch for the intermediate
// states, which will delete their temporary flags.
// If the write fails, revert fork choice to the version from disk, else we can
Expand Down Expand Up @@ -3106,7 +3111,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
current_slot,
);

Ok(block_root)
let lightclient_updates = self
.lightclient_server_cache
.produce_latest_updates_on_block(self.store, &block)
.unwrap_or_else(|e| {
error!(self.log, "error producing lightclient updates {:?}", e);
(None, None)
});

Ok((block_root, lightclient_updates))
}

/// Check block's consistentency with any configured weak subjectivity checkpoint.
Expand Down Expand Up @@ -5949,4 +5962,4 @@ impl<T: EthSpec> ChainSegmentResult<T> {
ChainSegmentResult::Successful { .. } => Ok(()),
}
}
}
}
3 changes: 2 additions & 1 deletion beacon_node/beacon_chain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod head_tracker;
pub mod historical_blocks;
pub mod light_client_finality_update_verification;
pub mod light_client_optimistic_update_verification;
mod lightclient_proofs_cache;
pub mod merge_readiness;
pub mod metrics;
pub mod migrate;
Expand Down Expand Up @@ -81,4 +82,4 @@ pub use state_processing::per_block_processing::errors::{
};
pub use store;
pub use timeout_rw_lock::TimeoutRwLock;
pub use types;
pub use types;
Original file line number Diff line number Diff line change
Expand Up @@ -65,42 +65,24 @@ impl<T: BeaconChainTypes> VerifiedLightClientFinalityUpdate<T> {
/// Returns `Ok(Self)` if the `light_client_finality_update` is valid to be (re)published on the gossip
/// network.
pub fn verify(
light_client_finality_update: LightClientFinalityUpdate<T::EthSpec>,
rcv_finality_update: LightClientFinalityUpdate<T::EthSpec>,
chain: &BeaconChain<T>,
seen_timestamp: Duration,
) -> Result<Self, Error> {
let gossiped_finality_slot = light_client_finality_update.finalized_header.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);
let mut latest_seen_finality_update = chain.latest_seen_finality_update.lock();

let head = chain.canonical_head.cached_head();
let head_block = &head.snapshot.beacon_block;
let attested_block_root = head_block.message().parent_root();
let attested_block = chain
.get_blinded_block(&attested_block_root)?
.ok_or(Error::FailedConstructingUpdate)?;
let mut attested_state = chain
.get_state(&attested_block.state_root(), Some(attested_block.slot()))?
.ok_or(Error::FailedConstructingUpdate)?;

let finalized_block_root = attested_state.finalized_checkpoint().root;
let finalized_block = chain
.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,
None => Slot::new(0),
};
let latest_finality_update = chain.lightclient_server_cache.get_latest_finality_update();

// verify that no other finality_update with a lower or equal
// finalized_header.slot was already forwarded on the network
if gossiped_finality_slot <= latest_seen_finality_update_slot {
if rcv_finality_update.finalized_header.slot <= latest_finality_update.finalized_header.slot
{
return Err(Error::FinalityUpdateAlreadySeen);
}

// verify that enough time has passed for the block to have been propagated
let start_time = chain
.slot_clock
.start_of(rcv_finality_update.signature_slot);
let one_third_slot_duration = Duration::new(chain.spec.seconds_per_slot / 3, 0);
match start_time {
Some(time) => {
if seen_timestamp + MAXIMUM_GOSSIP_CLOCK_DISPARITY < time + one_third_slot_duration
Expand All @@ -111,25 +93,14 @@ impl<T: BeaconChainTypes> VerifiedLightClientFinalityUpdate<T> {
None => return Err(Error::SigSlotStartIsNone),
}

let head_state = &head.snapshot.beacon_state;
let finality_update = LightClientFinalityUpdate::new(
&chain.spec,
head_state,
head_block,
&mut attested_state,
&finalized_block,
)?;

// verify that the gossiped finality update is the same as the locally constructed one.
if finality_update != light_client_finality_update {
if latest_finality_update != &rcv_finality_update {
return Err(Error::InvalidLightClientFinalityUpdate);
}

*latest_seen_finality_update = Some(light_client_finality_update.clone());

Ok(Self {
light_client_finality_update,
light_client_finality_update: rcv_finality_update,
seen_timestamp,
})
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,38 +69,15 @@ impl<T: BeaconChainTypes> VerifiedLightClientOptimisticUpdate<T> {
/// Returns `Ok(Self)` if the `light_client_optimistic_update` is valid to be (re)published on the gossip
/// network.
pub fn verify(
light_client_optimistic_update: LightClientOptimisticUpdate<T::EthSpec>,
rcv_optimistic_update: LightClientOptimisticUpdate<T::EthSpec>,
chain: &BeaconChain<T>,
seen_timestamp: Duration,
) -> Result<Self, Error> {
let gossiped_optimistic_slot = light_client_optimistic_update.attested_header.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);
let mut latest_seen_optimistic_update = chain.latest_seen_optimistic_update.lock();

let head = chain.canonical_head.cached_head();
let head_block = &head.snapshot.beacon_block;
let attested_block_root = head_block.message().parent_root();
let attested_block = chain
.get_blinded_block(&attested_block_root)?
.ok_or(Error::FailedConstructingUpdate)?;

let attested_state = chain
.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,
None => Slot::new(0),
};

// verify that no other optimistic_update with a lower or equal
// optimistic_header.slot was already forwarded on the network
if gossiped_optimistic_slot <= latest_seen_optimistic_update_slot {
return Err(Error::OptimisticUpdateAlreadySeen);
}

// verify that enough time has passed for the block to have been propagated
let start_time = chain
.slot_clock
.start_of(rcv_optimistic_update.signature_slot);
let one_third_slot_duration = Duration::new(chain.spec.seconds_per_slot / 3, 0);
match start_time {
Some(time) => {
if seen_timestamp + MAXIMUM_GOSSIP_CLOCK_DISPARITY < time + one_third_slot_duration
Expand All @@ -111,30 +88,20 @@ impl<T: BeaconChainTypes> VerifiedLightClientOptimisticUpdate<T> {
None => return Err(Error::SigSlotStartIsNone),
}

// check if we can process the optimistic update immediately
// otherwise queue
let canonical_root = light_client_optimistic_update
.attested_header
.canonical_root();

if canonical_root != head_block.message().parent_root() {
return Err(Error::UnknownBlockParentRoot(canonical_root));
}

let optimistic_update =
LightClientOptimisticUpdate::new(&chain.spec, head_block, &attested_state)?;
let latest_optimistic_update = chain
.lightclient_server_cache
.get_latest_optimistic_update();

// verify that the gossiped optimistic update is the same as the locally constructed one.
if optimistic_update != light_client_optimistic_update {
if latest_optimistic_update != &rcv_optimistic_update {
return Err(Error::InvalidLightClientOptimisticUpdate);
}

*latest_seen_optimistic_update = Some(light_client_optimistic_update.clone());

Ok(Self {
light_client_optimistic_update,
parent_root: canonical_root,
light_client_optimistic_update: rcv_optimistic_update,
// TODO: why is the parent_root necessary here?
parent_root: rcv_optimistic_update.attested_header.parent_root,
seen_timestamp,
})
}
}
}
Loading

0 comments on commit 1ee564f

Please sign in to comment.