mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-29 10:54:24 +00:00
Return HTTP 404 for pruned blob requests (#6331)
* Return HTTP 404 for pruned blob requests
This commit is contained in:
@@ -274,10 +274,27 @@ impl BlockId {
|
|||||||
warp_utils::reject::custom_not_found(format!("beacon block with root {}", root))
|
warp_utils::reject::custom_not_found(format!("beacon block with root {}", root))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// Error if the block is pre-Deneb and lacks blobs.
|
||||||
|
let blob_kzg_commitments = block.message().body().blob_kzg_commitments().map_err(|_| {
|
||||||
|
warp_utils::reject::custom_bad_request(
|
||||||
|
"block is pre-Deneb and has no blobs".to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
// Return the `BlobSidecarList` identified by `self`.
|
// Return the `BlobSidecarList` identified by `self`.
|
||||||
let blob_sidecar_list = chain
|
let blob_sidecar_list = if !blob_kzg_commitments.is_empty() {
|
||||||
.get_blobs(&root)
|
chain
|
||||||
.map_err(warp_utils::reject::beacon_chain_error)?;
|
.store
|
||||||
|
.get_blobs(&root)
|
||||||
|
.map_err(|e| warp_utils::reject::beacon_chain_error(e.into()))?
|
||||||
|
.ok_or_else(|| {
|
||||||
|
warp_utils::reject::custom_not_found(format!(
|
||||||
|
"no blobs stored for block {root}"
|
||||||
|
))
|
||||||
|
})?
|
||||||
|
} else {
|
||||||
|
BlobSidecarList::default()
|
||||||
|
};
|
||||||
|
|
||||||
let blob_sidecar_list_filtered = match indices.indices {
|
let blob_sidecar_list_filtered = match indices.indices {
|
||||||
Some(vec) => {
|
Some(vec) => {
|
||||||
|
|||||||
@@ -1667,6 +1667,93 @@ impl ApiTester {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test fetching of blob sidecars that are not available in the database due to pruning.
|
||||||
|
///
|
||||||
|
/// If `zero_blobs` is false, test a block with >0 blobs, which should be unavailable.
|
||||||
|
/// If `zero_blobs` is true, then test a block with 0 blobs, which should still be available.
|
||||||
|
pub async fn test_get_blob_sidecars_pruned(self, zero_blobs: bool) -> Self {
|
||||||
|
// Prune all blobs prior to the database's split epoch.
|
||||||
|
let store = &self.chain.store;
|
||||||
|
let split_epoch = store.get_split_slot().epoch(E::slots_per_epoch());
|
||||||
|
let force_prune = true;
|
||||||
|
self.chain
|
||||||
|
.store
|
||||||
|
.try_prune_blobs(force_prune, split_epoch)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let oldest_blob_slot = store.get_blob_info().oldest_blob_slot.unwrap();
|
||||||
|
|
||||||
|
assert_ne!(
|
||||||
|
oldest_blob_slot, 0,
|
||||||
|
"blob pruning should have pruned some blobs"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find a block with either 0 blobs or 1+ depending on the value of `zero_blobs`.
|
||||||
|
let mut test_slot = None;
|
||||||
|
for slot in 0..oldest_blob_slot.as_u64() {
|
||||||
|
let block_id = BlockId(CoreBlockId::Slot(Slot::new(slot)));
|
||||||
|
let (block, _, _) = block_id.blinded_block(&self.chain).unwrap();
|
||||||
|
let num_blobs = block.num_expected_blobs();
|
||||||
|
|
||||||
|
if (zero_blobs && num_blobs == 0) || (!zero_blobs && num_blobs > 0) {
|
||||||
|
test_slot = Some(Slot::new(slot));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let test_slot = test_slot.expect(&format!(
|
||||||
|
"should be able to find a block matching zero_blobs={zero_blobs}"
|
||||||
|
));
|
||||||
|
|
||||||
|
match self
|
||||||
|
.client
|
||||||
|
.get_blobs::<E>(CoreBlockId::Slot(test_slot), None)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(result) => {
|
||||||
|
if zero_blobs {
|
||||||
|
assert_eq!(
|
||||||
|
&result.unwrap().data[..],
|
||||||
|
&[],
|
||||||
|
"empty blobs are always available"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
assert_eq!(result, None, "blobs should have been pruned");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => panic!("failed with non-404 status: {e:?}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn test_get_blob_sidecars_pre_deneb(self) -> Self {
|
||||||
|
let oldest_blob_slot = self.chain.store.get_blob_info().oldest_blob_slot.unwrap();
|
||||||
|
assert_ne!(
|
||||||
|
oldest_blob_slot, 0,
|
||||||
|
"oldest_blob_slot should be non-zero and post-Deneb"
|
||||||
|
);
|
||||||
|
let test_slot = oldest_blob_slot - 1;
|
||||||
|
assert!(
|
||||||
|
!self
|
||||||
|
.chain
|
||||||
|
.spec
|
||||||
|
.fork_name_at_slot::<E>(test_slot)
|
||||||
|
.deneb_enabled(),
|
||||||
|
"Deneb should not be enabled at {test_slot}"
|
||||||
|
);
|
||||||
|
|
||||||
|
match self
|
||||||
|
.client
|
||||||
|
.get_blobs::<E>(CoreBlockId::Slot(test_slot), None)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(result) => panic!("queries for pre-Deneb slots should fail. got: {result:?}"),
|
||||||
|
Err(e) => assert_eq!(e.status().unwrap(), 400),
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn test_beacon_blocks_attestations(self) -> Self {
|
pub async fn test_beacon_blocks_attestations(self) -> Self {
|
||||||
for block_id in self.interesting_block_ids() {
|
for block_id in self.interesting_block_ids() {
|
||||||
let result = self
|
let result = self
|
||||||
@@ -6846,6 +6933,36 @@ async fn get_blob_sidecars() {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
|
async fn get_blob_sidecars_pruned() {
|
||||||
|
let mut config = ApiTesterConfig::default();
|
||||||
|
config.spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||||
|
config.spec.bellatrix_fork_epoch = Some(Epoch::new(0));
|
||||||
|
config.spec.capella_fork_epoch = Some(Epoch::new(0));
|
||||||
|
config.spec.deneb_fork_epoch = Some(Epoch::new(0));
|
||||||
|
|
||||||
|
ApiTester::new_from_config(config)
|
||||||
|
.await
|
||||||
|
.test_get_blob_sidecars_pruned(false)
|
||||||
|
.await
|
||||||
|
.test_get_blob_sidecars_pruned(true)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
|
async fn get_blob_sidecars_pre_deneb() {
|
||||||
|
let mut config = ApiTesterConfig::default();
|
||||||
|
config.spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||||
|
config.spec.bellatrix_fork_epoch = Some(Epoch::new(0));
|
||||||
|
config.spec.capella_fork_epoch = Some(Epoch::new(0));
|
||||||
|
config.spec.deneb_fork_epoch = Some(Epoch::new(1));
|
||||||
|
|
||||||
|
ApiTester::new_from_config(config)
|
||||||
|
.await
|
||||||
|
.test_get_blob_sidecars_pre_deneb()
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn post_validator_liveness_epoch() {
|
async fn post_validator_liveness_epoch() {
|
||||||
ApiTester::new()
|
ApiTester::new()
|
||||||
|
|||||||
Reference in New Issue
Block a user