Skip to content

Commit 531747c

Browse files
committed
Add early check for RPC block relevancy (#2289)
## Issue Addressed NA ## Proposed Changes When observing `jemallocator` heap profiles and Grafana, it became clear that Lighthouse is spending significant RAM/CPU on processing blocks from the RPC. On investigation, it seems that we are loading the parent of the block *before* we check to see if the block is already known. This is a big waste of resources. This PR adds an additional `check_block_relevancy` call as the first thing we do when we try to process a `SignedBeaconBlock` via the RPC (or other similar methods). Ultimately, `check_block_relevancy` will be called again later in the block processing flow. It's a very light function and I don't think trying to optimize it out is worth the risk of a bad block slipping through. Also adds a `New RPC block received` info log when we process a new RPC block. This seems like interesting and infrequent info. ## Additional Info NA
1 parent bf4e02e commit 531747c

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

beacon_node/beacon_chain/src/block_verification.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -690,15 +690,14 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
690690
/// Returns an error if the block is invalid, or if the block was unable to be verified.
691691
pub fn new(
692692
block: SignedBeaconBlock<T::EthSpec>,
693+
block_root: Hash256,
693694
chain: &BeaconChain<T>,
694695
) -> Result<Self, BlockError<T::EthSpec>> {
695696
let (mut parent, block) = load_parent(block, chain)?;
696697

697698
// Reject any block that exceeds our limit on skipped slots.
698699
check_block_skip_slots(chain, parent.beacon_block.slot(), &block.message)?;
699700

700-
let block_root = get_block_root(&block);
701-
702701
let state = cheap_state_advance_to_obtain_committees(
703702
&mut parent.pre_state,
704703
parent.beacon_state_root,
@@ -726,10 +725,11 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
726725
/// As for `new` above but producing `BlockSlashInfo`.
727726
pub fn check_slashable(
728727
block: SignedBeaconBlock<T::EthSpec>,
728+
block_root: Hash256,
729729
chain: &BeaconChain<T>,
730730
) -> Result<Self, BlockSlashInfo<BlockError<T::EthSpec>>> {
731731
let header = block.signed_block_header();
732-
Self::new(block, chain).map_err(|e| BlockSlashInfo::from_early_error(header, e))
732+
Self::new(block, block_root, chain).map_err(|e| BlockSlashInfo::from_early_error(header, e))
733733
}
734734

735735
/// Finishes signature verification on the provided `GossipVerifedBlock`. Does not re-verify
@@ -814,7 +814,11 @@ impl<T: BeaconChainTypes> IntoFullyVerifiedBlock<T> for SignedBeaconBlock<T::Eth
814814
self,
815815
chain: &BeaconChain<T>,
816816
) -> Result<FullyVerifiedBlock<T>, BlockSlashInfo<BlockError<T::EthSpec>>> {
817-
SignatureVerifiedBlock::check_slashable(self, chain)?
817+
// Perform an early check to prevent wasting time on irrelevant blocks.
818+
let block_root = check_block_relevancy(&self, None, chain)
819+
.map_err(|e| BlockSlashInfo::SignatureNotChecked(self.signed_block_header(), e))?;
820+
821+
SignatureVerifiedBlock::check_slashable(self, block_root, chain)?
818822
.into_fully_verified_block_slashable(chain)
819823
}
820824

beacon_node/network/src/beacon_processor/worker/sync_methods.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::sync::manager::SyncMessage;
66
use crate::sync::{BatchProcessResult, ChainId};
77
use beacon_chain::{BeaconChainTypes, BlockError, ChainSegmentResult};
88
use eth2_libp2p::PeerId;
9-
use slog::{crit, debug, error, trace, warn};
9+
use slog::{crit, debug, error, info, trace, warn};
1010
use types::{Epoch, Hash256, SignedBeaconBlock};
1111

1212
/// Id associated to a block processing request, either a batch or a single block.
@@ -28,10 +28,20 @@ impl<T: BeaconChainTypes> Worker<T> {
2828
block: SignedBeaconBlock<T::EthSpec>,
2929
result_tx: BlockResultSender<T::EthSpec>,
3030
) {
31+
let slot = block.slot();
3132
let block_result = self.chain.process_block(block);
3233

3334
metrics::inc_counter(&metrics::BEACON_PROCESSOR_RPC_BLOCK_IMPORTED_TOTAL);
3435

36+
if let Ok(root) = &block_result {
37+
info!(
38+
self.log,
39+
"New RPC block received";
40+
"slot" => slot,
41+
"hash" => %root
42+
);
43+
}
44+
3545
if result_tx.send(block_result).is_err() {
3646
crit!(self.log, "Failed return sync block result");
3747
}

0 commit comments

Comments
 (0)