diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 33205e97c..d3f5e9d7d 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -1379,8 +1379,10 @@ impl BeaconChain { let previous_slot = self.head().beacon_block.slot; let new_slot = beacon_block.slot; + let is_reorg = self.head().beacon_block_root != beacon_block.parent_root; + // If we switched to a new chain (instead of building atop the present chain). - if self.head().beacon_block_root != beacon_block.parent_root { + if is_reorg { metrics::inc_counter(&metrics::FORK_CHOICE_REORG_COUNT); warn!( self.log, @@ -1415,12 +1417,34 @@ impl BeaconChain { new_epoch: new_finalized_epoch, }) } else { - self.update_canonical_head(CheckPoint { + let previous_head_beacon_block_root = self.canonical_head.read().beacon_block_root; + let current_head_beacon_block_root = beacon_block_root; + + let mut new_head = CheckPoint { beacon_block, beacon_block_root, beacon_state, beacon_state_root, - })?; + }; + + new_head.beacon_state.build_all_caches(&self.spec)?; + + let timer = metrics::start_timer(&metrics::UPDATE_HEAD_TIMES); + + // Update the checkpoint that stores the head of the chain at the time it received the + // block. + *self.canonical_head.write() = new_head; + + metrics::stop_timer(timer); + + // Save `self` to `self.store`. + self.persist()?; + + let _ = self.event_handler.register(EventKind::BeaconHeadChanged { + reorg: is_reorg, + previous_head_beacon_block_root, + current_head_beacon_block_root, + }); if new_finalized_epoch != old_finalized_epoch { self.after_finalization(old_finalized_epoch, finalized_root)?; @@ -1442,28 +1466,6 @@ impl BeaconChain { result } - /// Update the canonical head to `new_head`. - fn update_canonical_head(&self, mut new_head: CheckPoint) -> Result<(), Error> { - let timer = metrics::start_timer(&metrics::UPDATE_HEAD_TIMES); - - new_head.beacon_state.build_all_caches(&self.spec)?; - - trace!(self.log, "Taking write lock on head"); - - // Update the checkpoint that stores the head of the chain at the time it received the - // block. - *self.canonical_head.write() = new_head; - - trace!(self.log, "Dropping write lock on head"); - - // Save `self` to `self.store`. - self.persist()?; - - metrics::stop_timer(timer); - - Ok(()) - } - /// Called after `self` has had a new block finalized. /// /// Performs pruning and finality-based optimizations. @@ -1495,6 +1497,11 @@ impl BeaconChain { self.op_pool.prune_all(&finalized_state, &self.spec); + let _ = self.event_handler.register(EventKind::BeaconFinalization { + epoch: new_finalized_epoch, + root: finalized_block_root, + }); + Ok(()) } } diff --git a/beacon_node/beacon_chain/src/events.rs b/beacon_node/beacon_chain/src/events.rs index d690eabf1..c93a13c8a 100644 --- a/beacon_node/beacon_chain/src/events.rs +++ b/beacon_node/beacon_chain/src/events.rs @@ -1,6 +1,6 @@ use serde_derive::{Deserialize, Serialize}; use std::marker::PhantomData; -use types::{Attestation, BeaconBlock, EthSpec, Hash256}; +use types::{Attestation, BeaconBlock, Epoch, EthSpec, Hash256}; pub trait EventHandler: Sized + Send + Sync { fn register(&self, kind: EventKind) -> Result<(), String>; @@ -33,6 +33,10 @@ pub enum EventKind { current_head_beacon_block_root: Hash256, previous_head_beacon_block_root: Hash256, }, + BeaconFinalization { + epoch: Epoch, + root: Hash256, + }, BeaconBlockImported { block_root: Hash256, block: Box>,