-
Notifications
You must be signed in to change notification settings - Fork 808
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
Simplify into_responses_with_blobs logic #6927
base: unstable
Are you sure you want to change the base?
Conversation
e7d0352
to
dd29c33
Compare
looks like there's a failing test here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
The one issue I see with this is we aren't enforcing the order of the blobs based on the index of the sidecars.
We will throw the error as KzgCommitmentMismatch
when trying to build the rpc block. Not sure if this would be an issue.
Edit: Actually the spec requires the sender to send it in the right order, so we were being quite permissive before
The following blob sidecars, where they exist, MUST be sent in consecutive (slot, index) order
Edit 2: I think it is fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
We can enforce that if we want, but why would we do so if we don't need to? If we had some optimization we can expect that behaviour but I don't see any damage to us from peers sending blobs or blocks out of order |
Ok(responses) | ||
// Now collect all blobs that match to the block by block root. BlobsByRange request checks | ||
// the inclusion proof so we know that the commitment is the expected. | ||
// RpcBlock::new ensures that the count of blobs is consistent with the block |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't actually perform the check if the blob list is empty or None
.
Seems like it's worth checking in both cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed with 16c95f0
.map(|block| { | ||
let block_root = get_block_root(&block); | ||
let max_blobs_per_block = spec.max_blobs_per_block(block.epoch()) as usize; | ||
let blobs = blobs_by_block.remove(&block_root).unwrap_or_default(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing code ensures the blobs are in order, and i think our code does assume they are - I think we should make sure they're in order here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh sorry just read Pawan's comment above.
but I don't see any damage to us from peers sending blobs or blocks out of order
Can you confirm this? IIRC we have some assumptions on the blob order in the code somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's one here but it's not affected by this change, although i feel like we should remove the assumption here
lighthouse/beacon_node/beacon_chain/src/kzg_utils.rs
Lines 166 to 176 in 5f053b0
// NOTE: assumes blob sidecars are ordered by index | |
let blob_cells_and_proofs_vec = blobs | |
.into_par_iter() | |
.map(|blob| { | |
let blob = blob | |
.as_ref() | |
.try_into() | |
.expect("blob should have a guaranteed size due to FixedVector"); | |
kzg.compute_cells_and_proofs(blob) | |
}) | |
.collect::<Result<Vec<_>, KzgError>>()?; |
Also the comment here mentions the assumption too:
lighthouse/beacon_node/beacon_chain/src/block_verification_types.rs
Lines 89 to 91 in 2792705
/// This variant is used with parent lookups and by-range responses. It should have all blobs | |
/// ordered, all block roots matching, and the correct number of blobs for this block. | |
BlockAndBlobs(Arc<SignedBeaconBlock<E>>, BlobSidecarList<E>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b983fa9 enforces ordered responses on all by_range requests
} | ||
} | ||
if block.num_expected_blobs() != blobs.as_ref().map(|blobs| blobs.len()).unwrap_or(0) { | ||
return Err(AvailabilityCheckError::MissingBlobs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now we always check that the blob count is consistent with the block regardless of empty list or None.
for (blob, &block_commitment) in blobs.iter().zip(block_commitments.iter()) { | ||
let blob_commitment = blob.kzg_commitment; | ||
if blob_commitment != block_commitment { | ||
return Err(AvailabilityCheckError::KzgCommitmentMismatch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to check the commitment equivalence anymore because:
- We check the inclusion proof of each blob
- We match blobs and blocks by block root
Therefore it's impossible for the commitment to not be equivalent
Ok(responses) | ||
// Now collect all blobs that match to the block by block root. BlobsByRange request checks | ||
// the inclusion proof so we know that the commitment is the expected. | ||
// RpcBlock::new ensures that the count of blobs is consistent with the block |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed with 16c95f0
return Err(LookupVerifyError::DuplicatedData(blob.slot(), blob.index)); | ||
} else if blob.index != prev.index + 1 { | ||
return Err(LookupVerifyError::NotSorted("non-sequential indices")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could group these two conditions into the "non-sequential" one. But I feel it's good to know if a sender is faulty due to duplicate data or non-sequential
Issue Addressed
Proposed Changes
The job of
into_responses_with_blobs
is to match block and blobs with the same block root. We can just use a HashMap and remove 41 lines of code.