Check data availability boundary in rpc request

This commit is contained in:
Emilia Hane 2023-01-17 09:53:37 +01:00
parent e046657b4f
commit 9445ac70d8
No known key found for this signature in database
GPG Key ID: E73394F9C09206FA
4 changed files with 99 additions and 25 deletions

View File

@ -2486,7 +2486,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
while let Some((_root, block)) = filtered_chain_segment.first() {
// Determine the epoch of the first block in the remaining segment.
let start_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch());
let start_epoch = block.epoch();
// The `last_index` indicates the position of the first block in an epoch greater
// than the current epoch: partitioning the blocks into a run of blocks in the same
@ -2494,9 +2494,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
// the same `BeaconState`.
let last_index = filtered_chain_segment
.iter()
.position(|(_root, block)| {
block.slot().epoch(T::EthSpec::slots_per_epoch()) > start_epoch
})
.position(|(_root, block)| block.epoch() > start_epoch)
.unwrap_or(filtered_chain_segment.len());
let mut blocks = filtered_chain_segment.split_off(last_index);
@ -3162,7 +3160,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
// Sync aggregate.
if let Ok(sync_aggregate) = block.body().sync_aggregate() {
// `SyncCommittee` for the sync_aggregate should correspond to the duty slot
let duty_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch());
let duty_epoch = block.epoch();
match self.sync_committee_at_epoch(duty_epoch) {
Ok(sync_committee) => {
@ -3429,7 +3427,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
parent_block_slot: Slot,
) {
// Do not write to eth1 finalization cache for blocks older than 5 epochs.
if block.slot().epoch(T::EthSpec::slots_per_epoch()) + 5 < current_epoch {
if block.epoch() + 5 < current_epoch {
return;
}
@ -5860,6 +5858,29 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.flatten()
}
/// The epoch since which we cater blob data upon a request 'ByRoot'.
/// `None` if the `Eip4844` fork is disabled.
pub fn data_availability_boundary_by_root_rpc_request(&self) -> Option<Epoch> {
self.spec
.eip4844_fork_epoch
.map(|fork_epoch| {
self.epoch().ok().map(|current_epoch| {
vec![
fork_epoch,
current_epoch.saturating_sub(*MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS),
self.canonical_head
.cached_head()
.finalized_checkpoint()
.epoch,
]
.into_iter()
.max()
})
})
.flatten()
.flatten()
}
/// Returns `true` if we are at or past the `Eip4844` fork. This will always return `false` if
/// the `Eip4844` fork is disabled.
pub fn is_data_availability_check_required(&self) -> Result<bool, Error> {

View File

@ -246,19 +246,39 @@ impl<T: BeaconChainTypes> Worker<T> {
"request_root" => ?root
);
}
Ok((Some(_), None)) => {
debug!(
self.log,
"Peer requested block and blob, but no blob found";
"peer" => %peer_id,
"request_root" => ?root
);
self.send_error_response(
peer_id,
RPCResponseErrorCode::ResourceUnavailable,
"No blob for requested block".into(),
request_id,
);
Ok((Some(block), None)) => {
let data_availability_boundary_by_root = self.chain.data_availability_boundary_by_root_rpc_request();
let block_epoch = block.epoch();
if Some(block_epoch) >= data_availability_boundary_by_root {
debug!(
self.log,
"Peer requested block and blob that should be available, but no blob found";
"peer" => %peer_id,
"request_root" => ?root,
"data_availability_boundary_by_root" => data_availability_boundary_by_root,
);
self.send_error_response(
peer_id,
RPCResponseErrorCode::ResourceUnavailable,
"No blob for requested block.".into(),
request_id,
);
} else {
debug!(
self.log,
"Peer requested block and blob older than the data availability boundary for ByRoot request, no blob found";
"peer" => %peer_id,
"request_root" => ?root,
"data_availability_boundary_by_root" => data_availability_boundary_by_root,
);
self.send_error_response(
peer_id,
RPCResponseErrorCode::ResourceUnavailable,
format!("No blob for requested block. Requested blob is older than the data availability boundary for a ByRoot request, currently at epoch {:?}", data_availability_boundary_by_root),
request_id,
);
}
send_response = false;
break;
}
@ -592,15 +612,33 @@ impl<T: BeaconChainTypes> Worker<T> {
"start_slot" => req.start_slot,
);
let start_slot = Slot::from(req.start_slot);
let start_epoch = start_slot.epoch(T::EthSpec::slots_per_epoch());
let data_availability_boundary = self.chain.data_availability_boundary();
if Some(start_epoch) < data_availability_boundary {
let oldest_blob_slot = self
.chain
.store
.get_blob_info()
.map(|blob_info| blob_info.oldest_blob_slot);
debug!(self.log, "Range request start slot is older than data availability boundary"; "requested_slot" => req.start_slot, "oldest_known_slot" => ?oldest_blob_slot, "data_availability_boundary" => data_availability_boundary);
return self.send_error_response(
peer_id,
RPCResponseErrorCode::ResourceUnavailable,
format!("Requested start slot in epoch {}. Data availability boundary is currently at epoch {:?}", start_epoch, data_availability_boundary),
request_id,
);
}
// Should not send more than max request blocks
if req.count > MAX_REQUEST_BLOBS_SIDECARS {
req.count = MAX_REQUEST_BLOBS_SIDECARS;
}
let forwards_block_root_iter = match self
.chain
.forwards_iter_block_roots(Slot::from(req.start_slot))
{
let forwards_block_root_iter = match self.chain.forwards_iter_block_roots(start_slot) {
Ok(iter) => iter,
Err(BeaconChainError::HistoricalBlockError(
HistoricalBlockError::BlockOutOfRange {

View File

@ -195,7 +195,7 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedBeaconBlock<E, Payload>
}
let domain = spec.get_domain(
self.slot().epoch(E::slots_per_epoch()),
self.epoch(),
Domain::BeaconProposer,
fork,
genesis_validators_root,
@ -227,6 +227,11 @@ impl<E: EthSpec, Payload: AbstractExecPayload<E>> SignedBeaconBlock<E, Payload>
self.message().slot()
}
/// Convenience accessor for the block's epoch.
pub fn epoch(&self) -> Epoch {
self.message().slot().epoch(E::slots_per_epoch())
}
/// Convenience accessor for the block's parent root.
pub fn parent_root(&self) -> Hash256 {
self.message().parent_root()

View File

@ -1,5 +1,7 @@
use crate::signed_beacon_block::BlobReconstructionError;
use crate::{BlobsSidecar, EthSpec, Hash256, SignedBeaconBlock, SignedBeaconBlockEip4844, Slot};
use crate::{
BlobsSidecar, Epoch, EthSpec, Hash256, SignedBeaconBlock, SignedBeaconBlockEip4844, Slot,
};
use derivative::Derivative;
use serde_derive::{Deserialize, Serialize};
use ssz::{Decode, DecodeError};
@ -74,6 +76,14 @@ impl<T: EthSpec> BlockWrapper<T> {
}
}
}
pub fn epoch(&self) -> Epoch {
match &self.0 {
BlockWrapperInner::Block(block) => block.epoch(),
BlockWrapperInner::BlockAndBlob(block_sidecar_pair) => {
block_sidecar_pair.beacon_block.epoch()
}
}
}
pub fn block(&self) -> &SignedBeaconBlock<T> {
match &self.0 {
BlockWrapperInner::Block(block) => &block,