Skip to content

Commit

Permalink
Couple blocks and blobs in gossip (#3670)
Browse files Browse the repository at this point in the history
* Revert "Add more gossip verification conditions"

This reverts commit 1430b56.

* Revert "Add todos"

This reverts commit 91efb9d.

* Revert "Reprocess blob sidecar messages"

This reverts commit 21bf3d3.

* Add the coupled topic

* Decode SignedBeaconBlockAndBlobsSidecar correctly

* Process Block and Blobs in beacon processor

* Remove extra blob publishing logic from vc

* Remove blob signing in vc

* Ugly hack to compile
  • Loading branch information
pawanjay176 authored Nov 1, 2022
1 parent 9f155ee commit 29f2ec4
Show file tree
Hide file tree
Showing 25 changed files with 294 additions and 990 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1778,11 +1778,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
})
}

/// Accepts some `SignedBlobsSidecar` from the network and attempts to verify it,
/// Accepts some `BlobsSidecar` received over from the network and attempts to verify it,
/// returning `Ok(_)` if it is valid to be (re)broadcast on the gossip network.
pub fn verify_blobs_sidecar_for_gossip<'a>(
&self,
blobs_sidecar: &'a SignedBlobsSidecar<T::EthSpec>,
blobs_sidecar: &'a BlobsSidecar<T::EthSpec>,
) -> Result<VerifiedBlobsSidecar<'a, T>, BlobError> {
metrics::inc_counter(&metrics::BLOBS_SIDECAR_PROCESSING_REQUESTS);
let _timer = metrics::start_timer(&metrics::BLOBS_SIDECAR_GOSSIP_VERIFICATION_TIMES);
Expand Down
97 changes: 14 additions & 83 deletions beacon_node/beacon_chain/src/blob_verification.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
use derivative::Derivative;
use slot_clock::SlotClock;

use crate::beacon_chain::{
BeaconChain, BeaconChainTypes, MAXIMUM_GOSSIP_CLOCK_DISPARITY,
VALIDATOR_PUBKEY_CACHE_LOCK_TIMEOUT,
};
use crate::beacon_chain::{BeaconChain, BeaconChainTypes, MAXIMUM_GOSSIP_CLOCK_DISPARITY};
use crate::BeaconChainError;
use bls::PublicKey;
use types::{consts::eip4844::BLS_MODULUS, BeaconStateError, Hash256, SignedBlobsSidecar, Slot};
use types::{consts::eip4844::BLS_MODULUS, BeaconStateError, BlobsSidecar, Hash256, Slot};

pub enum BlobError {
/// The blob sidecar is from a slot that is later than the current slot (with respect to the
Expand Down Expand Up @@ -61,21 +58,6 @@ pub enum BlobError {
/// be equal to the given sidecar.
RepeatSidecar { proposer: u64, slot: Slot },

/// The `blobs_sidecar.message.beacon_block_root` block is unknown.
///
/// ## Peer scoring
///
/// The attestation points to a block we have not yet imported. It's unclear if the attestation
/// is valid or not.
UnknownHeadBlock { beacon_block_root: Hash256 },

/// The proposal_index corresponding to blob.beacon_block_root is not known.
///
/// ## Peer scoring
///
/// The block is invalid and the peer is faulty.
UnknownValidator(u64),

/// There was an error whilst processing the sync contribution. It is not known if it is valid or invalid.
///
/// ## Peer scoring
Expand All @@ -97,109 +79,58 @@ impl From<BeaconStateError> for BlobError {
}
}

/// A wrapper around a `SignedBlobsSidecar` that indicates it has been approved for re-gossiping on
/// the p2p network.
/// A wrapper around a `BlobsSidecar` that indicates it has been verified w.r.t the corresponding
/// `SignedBeaconBlock`.
#[derive(Derivative)]
#[derivative(Debug(bound = "T: BeaconChainTypes"))]
pub struct VerifiedBlobsSidecar<'a, T: BeaconChainTypes> {
pub blob_sidecar: &'a SignedBlobsSidecar<T::EthSpec>,
pub blob_sidecar: &'a BlobsSidecar<T::EthSpec>,
}

impl<'a, T: BeaconChainTypes> VerifiedBlobsSidecar<'a, T> {
pub fn verify(
blob_sidecar: &'a SignedBlobsSidecar<T::EthSpec>,
blob_sidecar: &'a BlobsSidecar<T::EthSpec>,
chain: &BeaconChain<T>,
) -> Result<Self, BlobError> {
let block_slot = blob_sidecar.message.beacon_block_slot;
let block_root = blob_sidecar.message.beacon_block_root;
let blob_slot = blob_sidecar.beacon_block_slot;
// Do not gossip or process blobs from future or past slots.
let latest_permissible_slot = chain
.slot_clock
.now_with_future_tolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY)
.ok_or(BeaconChainError::UnableToReadSlot)?;
if block_slot > latest_permissible_slot {
if blob_slot > latest_permissible_slot {
return Err(BlobError::FutureSlot {
message_slot: latest_permissible_slot,
latest_permissible_slot: block_slot,
latest_permissible_slot: blob_slot,
});
}

// TODO: return `UnknownHeadBlock` if blob_root doesn't exist in fork choice
// and wherever it could be found.

let earliest_permissible_slot = chain
.slot_clock
.now_with_past_tolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY)
.ok_or(BeaconChainError::UnableToReadSlot)?;
if block_slot > earliest_permissible_slot {
if blob_slot > earliest_permissible_slot {
return Err(BlobError::PastSlot {
message_slot: earliest_permissible_slot,
earliest_permissible_slot: block_slot,
earliest_permissible_slot: blob_slot,
});
}

// Verify that blobs are properly formatted
//TODO: add the check while constructing a Blob type from bytes instead of after
for (i, blob) in blob_sidecar.message.blobs.iter().enumerate() {
for (i, blob) in blob_sidecar.blobs.iter().enumerate() {
if blob.iter().any(|b| *b >= *BLS_MODULUS) {
return Err(BlobError::BlobOutOfRange { blob_index: i });
}
}

// Verify that the KZG proof is a valid G1 point
// TODO(pawan): KZG commitment can also be point at infinity, use a different check
// (bls.KeyValidate)
if PublicKey::deserialize(&blob_sidecar.message.kzg_aggregate_proof.0).is_err() {
if PublicKey::deserialize(&blob_sidecar.kzg_aggregate_proof.0).is_err() {
return Err(BlobError::InvalidKZGCommitment);
}

let proposer_shuffling_root = chain
.canonical_head
.cached_head()
.snapshot
.beacon_state
.proposer_shuffling_decision_root(block_root)?;

let (proposer_index, fork) = match chain
.beacon_proposer_cache
.lock()
.get_slot::<T::EthSpec>(proposer_shuffling_root, block_slot)
{
Some(proposer) => (proposer.index, proposer.fork),
None => {
let state = &chain.canonical_head.cached_head().snapshot.beacon_state;
(
state.get_beacon_proposer_index(block_slot, &chain.spec)?,
state.fork(),
)
}
};
let signature_is_valid = {
let pubkey_cache = chain
.validator_pubkey_cache
.try_read_for(VALIDATOR_PUBKEY_CACHE_LOCK_TIMEOUT)
.ok_or(BeaconChainError::ValidatorPubkeyCacheLockTimeout)
.map_err(BlobError::BeaconChainError)?;

let pubkey = pubkey_cache
.get(proposer_index as usize)
.ok_or_else(|| BlobError::UnknownValidator(proposer_index as u64))?;

blob_sidecar.verify_signature(
None,
pubkey,
&fork,
chain.genesis_validators_root,
&chain.spec,
)
};

if !signature_is_valid {
return Err(BlobError::ProposalSignatureInvalid);
}
// TODO: Check that we have not already received a sidecar with a valid signature for this slot.

// TODO(pawan): Check that we have not already received a sidecar with a valid signature for this slot.
// TODO(pawan): check if block hash is already known
Ok(Self { blob_sidecar })
}
}
28 changes: 4 additions & 24 deletions beacon_node/http_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ mod block_rewards;
mod database;
mod metrics;
mod proposer_duties;
mod publish_blobs;
mod publish_blocks;
mod state_id;
mod sync_committees;
Expand Down Expand Up @@ -49,7 +48,7 @@ use types::{
Attestation, AttestationData, AttesterSlashing, BeaconStateError, BlindedPayload,
CommitteeCache, ConfigAndPreset, Epoch, EthSpec, ForkName, FullPayload,
ProposerPreparationData, ProposerSlashing, RelativeEpoch, SignedAggregateAndProof,
SignedBeaconBlock, SignedBlindedBeaconBlock, SignedBlobsSidecar, SignedContributionAndProof,
SignedBeaconBlock, SignedBlindedBeaconBlock, SignedContributionAndProof,
SignedValidatorRegistrationData, SignedVoluntaryExit, Slot, SyncCommitteeMessage,
SyncContributionData,
};
Expand Down Expand Up @@ -1047,27 +1046,9 @@ pub fn serve<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| async move {
publish_blocks::publish_block(None, block, chain, &network_tx, log)
.await
.map(|()| warp::reply())
},
);

// POST beacon/blobs
let post_beacon_blobs = eth_v1
.and(warp::path("beacon"))
.and(warp::path("blobs"))
.and(warp::path::end())
.and(warp::body::json())
.and(chain_filter.clone())
.and(network_tx_filter.clone())
.and(log_filter.clone())
.and_then(
|blobs: Arc<SignedBlobsSidecar<T::EthSpec>>,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| async move {
publish_blobs::publish_blobs(blobs, chain, &network_tx, log)
// need to have cached the blob sidecar somewhere in the beacon chain
// to publish
publish_blocks::publish_block(None, block, None, chain, &network_tx, log)
.await
.map(|()| warp::reply())
},
Expand Down Expand Up @@ -3183,7 +3164,6 @@ pub fn serve<T: BeaconChainTypes>(
post_beacon_blocks
.boxed()
.or(post_beacon_blinded_blocks.boxed())
.or(post_beacon_blobs.boxed())
.or(post_beacon_pool_attestations.boxed())
.or(post_beacon_pool_attester_slashings.boxed())
.or(post_beacon_pool_proposer_slashings.boxed())
Expand Down
124 changes: 0 additions & 124 deletions beacon_node/http_api/src/publish_blobs.rs

This file was deleted.

Loading

0 comments on commit 29f2ec4

Please sign in to comment.