Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Couple blocks and blobs in gossip #3670

Merged
merged 9 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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