mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-10 04:01:51 +00:00
Add broadcast validation routes to Beacon Node HTTP API (#4316)
## Issue Addressed - #4293 - #4264 ## Proposed Changes *Changes largely follow those suggested in the main issue*. - Add new routes to HTTP API - `post_beacon_blocks_v2` - `post_blinded_beacon_blocks_v2` - Add new routes to `BeaconNodeHttpClient` - `post_beacon_blocks_v2` - `post_blinded_beacon_blocks_v2` - Define new Eth2 common types - `BroadcastValidation`, enum representing the level of validation to apply to blocks prior to broadcast - `BroadcastValidationQuery`, the corresponding HTTP query string type for the above type - ~~Define `_checked` variants of both `publish_block` and `publish_blinded_block` that enforce a validation level at a type level~~ - Add interactive tests to the `bn_http_api_tests` test target covering each validation level (to their own test module, `broadcast_validation_tests`) - `beacon/blocks` - `broadcast_validation=gossip` - Invalid (400) - Full Pass (200) - Partial Pass (202) - `broadcast_validation=consensus` - Invalid (400) - Only gossip (400) - Only consensus pass (i.e., equivocates) (200) - Full pass (200) - `broadcast_validation=consensus_and_equivocation` - Invalid (400) - Invalid due to early equivocation (400) - Only gossip (400) - Only consensus (400) - Pass (200) - `beacon/blinded_blocks` - `broadcast_validation=gossip` - Invalid (400) - Full Pass (200) - Partial Pass (202) - `broadcast_validation=consensus` - Invalid (400) - Only gossip (400) - ~~Only consensus pass (i.e., equivocates) (200)~~ - Full pass (200) - `broadcast_validation=consensus_and_equivocation` - Invalid (400) - Invalid due to early equivocation (400) - Only gossip (400) - Only consensus (400) - Pass (200) - Add a new trait, `IntoGossipVerifiedBlock`, which allows type-level guarantees to be made as to gossip validity - Modify the structure of the `ObservedBlockProducers` cache from a `(slot, validator_index)` mapping to a `((slot, validator_index), block_root)` mapping - Modify `ObservedBlockProducers::proposer_has_been_observed` to return a `SeenBlock` rather than a boolean on success - Punish gossip peer (low) for submitting equivocating blocks - Rename `BlockError::SlashablePublish` to `BlockError::SlashableProposal` ## Additional Info This PR contains changes that directly modify how blocks are verified within the client. For more context, consult [comments in-thread](https://github.com/sigp/lighthouse/pull/4316#discussion_r1234724202). Co-authored-by: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
@@ -785,6 +785,20 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
|
||||
verified_block
|
||||
}
|
||||
Err(e @ BlockError::Slashable) => {
|
||||
warn!(
|
||||
self.log,
|
||||
"Received equivocating block from peer";
|
||||
"error" => ?e
|
||||
);
|
||||
/* punish peer for submitting an equivocation, but not too harshly as honest peers may conceivably forward equivocating blocks to us from time to time */
|
||||
self.gossip_penalize_peer(
|
||||
peer_id,
|
||||
PeerAction::MidToleranceError,
|
||||
"gossip_block_mid",
|
||||
);
|
||||
return None;
|
||||
}
|
||||
Err(BlockError::ParentUnknown(block)) => {
|
||||
debug!(
|
||||
self.log,
|
||||
@@ -806,7 +820,6 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
Err(e @ BlockError::FutureSlot { .. })
|
||||
| Err(e @ BlockError::WouldRevertFinalizedSlot { .. })
|
||||
| Err(e @ BlockError::BlockIsAlreadyKnown)
|
||||
| Err(e @ BlockError::RepeatProposal { .. })
|
||||
| Err(e @ BlockError::NotFinalizedDescendant { .. }) => {
|
||||
debug!(self.log, "Could not verify block for gossip. Ignoring the block";
|
||||
"error" => %e);
|
||||
@@ -948,7 +961,12 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
|
||||
let result = self
|
||||
.chain
|
||||
.process_block(block_root, verified_block, NotifyExecutionLayer::Yes)
|
||||
.process_block(
|
||||
block_root,
|
||||
verified_block,
|
||||
NotifyExecutionLayer::Yes,
|
||||
|| Ok(()),
|
||||
)
|
||||
.await;
|
||||
|
||||
match &result {
|
||||
|
||||
@@ -98,33 +98,21 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
});
|
||||
|
||||
// Checks if a block from this proposer is already known.
|
||||
let proposal_already_known = || {
|
||||
let block_equivocates = || {
|
||||
match self
|
||||
.chain
|
||||
.observed_block_producers
|
||||
.read()
|
||||
.proposer_has_been_observed(block.message())
|
||||
.proposer_has_been_observed(block.message(), block.canonical_root())
|
||||
{
|
||||
Ok(is_observed) => is_observed,
|
||||
// Both of these blocks will be rejected, so reject them now rather
|
||||
Ok(seen_status) => seen_status.is_slashable(),
|
||||
//Both of these blocks will be rejected, so reject them now rather
|
||||
// than re-queuing them.
|
||||
Err(ObserveError::FinalizedBlock { .. })
|
||||
| Err(ObserveError::ValidatorIndexTooHigh { .. }) => false,
|
||||
}
|
||||
};
|
||||
|
||||
// Returns `true` if the block is already known to fork choice. Notably,
|
||||
// this will return `false` for blocks that we've already imported but
|
||||
// ancestors of the finalized checkpoint. That should not be an issue
|
||||
// for our use here since finalized blocks will always be late and won't
|
||||
// be requeued anyway.
|
||||
let block_is_already_known = || {
|
||||
self.chain
|
||||
.canonical_head
|
||||
.fork_choice_read_lock()
|
||||
.contains_block(&block_root)
|
||||
};
|
||||
|
||||
// If we've already seen a block from this proposer *and* the block
|
||||
// arrived before the attestation deadline, requeue it to ensure it is
|
||||
// imported late enough that it won't receive a proposer boost.
|
||||
@@ -132,7 +120,7 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
// Don't requeue blocks if they're already known to fork choice, just
|
||||
// push them through to block processing so they can be handled through
|
||||
// the normal channels.
|
||||
if !block_is_late && proposal_already_known() && !block_is_already_known() {
|
||||
if !block_is_late && block_equivocates() {
|
||||
debug!(
|
||||
self.log,
|
||||
"Delaying processing of duplicate RPC block";
|
||||
@@ -165,7 +153,7 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
let parent_root = block.message().parent_root();
|
||||
let result = self
|
||||
.chain
|
||||
.process_block(block_root, block, NotifyExecutionLayer::Yes)
|
||||
.process_block(block_root, block, NotifyExecutionLayer::Yes, || Ok(()))
|
||||
.await;
|
||||
|
||||
metrics::inc_counter(&metrics::BEACON_PROCESSOR_RPC_BLOCK_IMPORTED_TOTAL);
|
||||
|
||||
Reference in New Issue
Block a user