Skip to content

Avoid attempting to serve blobs after Fulu fork #7756

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

Open
wants to merge 18 commits into
base: unstable
Choose a base branch
from

Conversation

chong-he
Copy link
Member

@chong-he chong-he requested a review from jxs as a code owner July 18, 2025 01:33
@chong-he chong-he added the work-in-progress PR is a work-in-progress label Jul 18, 2025
@chong-he chong-he changed the title Das blobs by range Do not response to blobs request after Fulu fork Jul 18, 2025
@chong-he chong-he changed the title Do not response to blobs request after Fulu fork Avoid attempting to serve Blobs after Fulu fork Jul 18, 2025
@chong-he chong-he changed the title Avoid attempting to serve Blobs after Fulu fork Avoid attempting to serve blobs after Fulu fork Jul 18, 2025
@chong-he chong-he added ready-for-review The code is ready for review fulu Required for the upcoming Fulu hard fork and removed work-in-progress PR is a work-in-progress labels Jul 22, 2025
@chong-he chong-he requested a review from jimmygchen July 22, 2025 01:15
Comment on lines 298 to 299
if let Some(fulu_slot) = fulu_start_slot {
if blob.slot() >= fulu_slot {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified slightly using fulu_start_slot.is_some_and(|fulu_slot| blob.slot() >= fulu_slot).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fulu_slot is used in the logging below. So after changing, the compiler is saying fulu_sot not found.

Should I remove fulu_slot from the logging?

Comment on lines 330 to 331
if let Some(fulu_slot) = fulu_start_slot {
if blob_sidecar.slot() >= fulu_slot {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above

// First attempt to get the blobs from the RPC cache.
if let Ok(Some(blob)) = self.chain.data_availability_checker.get_blob(id) {
// Check if the blob requested is from a Fulu slot, if so, skip the current blob id and proceed to the next
Copy link
Member

@jimmygchen jimmygchen Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if the block is after fulu slot, this condition will never satisfy, as the result will always be Ok(None) as we never store blobs from Fulu. I don't think we need to handle it here as it should be unreachable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revised in bf20880

@@ -306,6 +326,20 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
Ok(blobs_sidecar_list) => {
'inner: for blob_sidecar in blobs_sidecar_list.iter() {
if blob_sidecar.index == *index {
// Same logic as above to check for Fulu slot
if let Some(fulu_slot) = fulu_start_slot {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will also be unreachable.

The purpose to avoid serving post-fulu slots in the byRange method is to save us work from doing block roots lookup - it doesn't seem as relevant here, as we've already hit the database and incurred the cost.

The spec also says the following, so we can't really penalise these peers during this deprecation period

Clients SHOULD NOT penalize peers for requesting blob sidecars from FULU_FORK_EPOCH.

I think we could probably check all the caches to see if we have the block before hitting the database?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revised in bf20880, trying to avoid touching the database

@@ -884,6 +918,36 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
);

let request_start_slot = Slot::from(req.start_slot);
// This variable may only change when the request_start_slot + req.count spans across the Fulu fork slot
let mut effective_count = req.count;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could make the if / else block return the count, and that would allow you to remove the mut

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to revise this in 32c3ab0, not sure if it is good?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep that's better!

Copy link
Member

@jimmygchen jimmygchen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @chong-he I've added some comments.
I think it might be worth adding something similar to data columns methods, to avoid block roots retrieval if the slots are before Fulu

pub fn handle_data_columns_by_range_request_inner(
&self,
peer_id: PeerId,
inbound_request_id: InboundRequestId,
req: DataColumnsByRangeRequest,
) -> Result<(), (RpcErrorResponse, &'static str)> {
debug!(
%peer_id,
count = req.count,
start_slot = req.start_slot,
"Received DataColumnsByRange Request"
);
// Should not send more than max request data columns
if req.max_requested::<T::EthSpec>() > self.chain.spec.max_request_data_column_sidecars {
return Err((
RpcErrorResponse::InvalidRequest,
"Request exceeded `MAX_REQUEST_BLOBS_SIDECARS`",
));
}
let request_start_slot = Slot::from(req.start_slot);

@jimmygchen jimmygchen added waiting-on-author The reviewer has suggested changes and awaits thier implementation. and removed ready-for-review The code is ready for review labels Jul 28, 2025
@chong-he chong-he added the ready-for-review The code is ready for review label Aug 6, 2025
Copy link

mergify bot commented Aug 7, 2025

Some required checks have failed. Could you please take a look @chong-he? 🙏

@mergify mergify bot added waiting-on-author The reviewer has suggested changes and awaits thier implementation. and removed ready-for-review The code is ready for review labels Aug 7, 2025
@chong-he chong-he added ready-for-review The code is ready for review and removed waiting-on-author The reviewer has suggested changes and awaits thier implementation. labels Aug 7, 2025
@jimmygchen jimmygchen added the v8.0.0 Q4 2025 Fusaka Mainnet Release label Aug 12, 2025
let request_start_epoch = request_start_slot.epoch(T::EthSpec::slots_per_epoch());
// Should not send more than max request blob sidecars
if req.max_blobs_requested(request_start_epoch, &self.chain.spec)
> self.chain.spec.max_request_blob_sidecars_electra
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use the spec.max_request_blob_sidecars(fork_name) function here?
keeping those fields private means we don't leak the logic elsewhere -if we ever need to use a different config value for a different fork, we only need to update the above function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, revised in 0cbd9fd
I didn't notice this function is available, when I use the Electra one I was feeling unsure about it

}

#[tokio::test]
async fn test_blobs_by_range_spans_fulu_fork() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this test would fail before your PR?
but i think it's useful that it covers blobs by range works before Fulu

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this test wouldn't fail even without this PR change, which is why I think the test is not robust enough.

I have already started from mid-epoch slot, and the blob request spans across fork boundary. I wonder if I am missing something in the test?


#[tokio::test]
async fn test_blobs_by_root_post_fulu_should_return_empty() {
// Only test for Fulu fork
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it would be worth adding a test to confirm it still work right before fulu fork?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a test in 0cbd9fd

@@ -268,21 +268,64 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
inbound_request_id: InboundRequestId,
request: BlobsByRootRequest,
) -> Result<(), (RpcErrorResponse, &'static str)> {
let Some(requested_root) = request.blob_ids.as_slice().first().map(|id| id.block_root)
let Some(_requested_root) = request.blob_ids.as_slice().first().map(|id| id.block_root)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block is now redundant and can be removed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. The reason I am keeping this is, if we remove this, then it wouldn't have the check that if the request is empty before proceeding. wdyt?

Anyway I removed it in 0cbd9fd

let mut blob_list_results = HashMap::new();
let mut retrieve_blob_slot = HashMap::new();
Copy link
Member

@jimmygchen jimmygchen Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine being a bit more verbose here to help readability - what about using the map naming convention values_by_key, e.g. slots_by_block_root?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the variable as suggested

retrieve_blob_slot.insert(*root, slot);
Some(slot)
} else {
// Blobs not found in cache, return None to avoid hitting the database
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the case where block is not found in cache, and we just need to hit the database right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revise the comment to be clearer, thanks!

"BlobsByRoot request is at or after Fulu slot, returning empty response"
);
break 'inner;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove this block - if we have the blob then it means fulu is not activated and there's no need to check for fulu slot

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 0cbd9fd

debug!(
%peer_id,
%request_start_slot,
%fulu_start_slot,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we can remove all the fulu start slot logging to reduce the logging noise - this doesn't give us much during debugging as there's many easy way to find out, e.g. /config/spec, network config etc

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All fulu-related logging removed in 0cbd9fd

%block_root,
?blobs_indices,
returned = send_blob_count,
"BlobsByRoot outgoing response processed"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This log isn't accurate because send_blob_count is the total number of returned responses.

Maybe we could just log one entry, and the list of unique roots requested?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only log once after the revision 0cbd9fd

@jimmygchen jimmygchen added waiting-on-author The reviewer has suggested changes and awaits thier implementation. and removed ready-for-review The code is ready for review labels Aug 19, 2025
@chong-he
Copy link
Member Author

Thanks for the detailed review @jimmygchen. I have address all comments as above.

@chong-he chong-he added ready-for-review The code is ready for review and removed waiting-on-author The reviewer has suggested changes and awaits thier implementation. labels Aug 20, 2025
@jimmygchen jimmygchen added v8.0.0-rc.0 Q3 2025 release for Fusaka on Holesky v8.0.0 Q4 2025 Fusaka Mainnet Release and removed v8.0.0 Q4 2025 Fusaka Mainnet Release v8.0.0-rc.0 Q3 2025 release for Fusaka on Holesky labels Aug 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fulu Required for the upcoming Fulu hard fork ready-for-review The code is ready for review v8.0.0 Q4 2025 Fusaka Mainnet Release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants