-
Notifications
You must be signed in to change notification settings - Fork 8
feat: store block signatures and respond to BlocksByRoot requests #67
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -94,21 +94,41 @@ async fn handle_status_response(status: Status, peer: PeerId) { | |
| } | ||
|
|
||
| async fn handle_blocks_by_root_request( | ||
| _server: &mut P2PServer, | ||
| server: &mut P2PServer, | ||
| request: BlocksByRootRequest, | ||
| _channel: request_response::ResponseChannel<Response>, | ||
| channel: request_response::ResponseChannel<Response>, | ||
| peer: PeerId, | ||
| ) { | ||
| let num_roots = request.len(); | ||
| info!(%peer, num_roots, "Received BlocksByRoot request"); | ||
|
|
||
| // TODO: Implement signed block storage and send response chunks | ||
| // For now, we don't send any response (drop the channel) | ||
| // In a full implementation, we would: | ||
| // 1. Look up each requested block root | ||
| // 2. Send a response chunk for each found block | ||
| // 3. Each chunk contains: result byte + encoded SignedBlockWithAttestation | ||
| warn!(%peer, num_roots, "BlocksByRoot request received but block storage not implemented"); | ||
| // TODO: Support multiple blocks per request (currently only handles first root) | ||
| // The protocol supports up to 1024 roots, but our response type only holds one block. | ||
| let Some(root) = request.first() else { | ||
| debug!(%peer, "BlocksByRoot request with no roots"); | ||
| return; | ||
| }; | ||
|
|
||
| match server.store.get_signed_block(root) { | ||
| Some(signed_block) => { | ||
| let slot = signed_block.message.block.slot; | ||
| info!(%peer, %root, %slot, "Responding to BlocksByRoot request"); | ||
|
|
||
| if let Err(err) = server.swarm.behaviour_mut().req_resp.send_response( | ||
| channel, | ||
| Response::new( | ||
| ResponseResult::Success, | ||
| ResponsePayload::BlocksByRoot(signed_block), | ||
| ), | ||
| ) { | ||
| warn!(%peer, %root, ?err, "Failed to send BlocksByRoot response"); | ||
| } | ||
| } | ||
| None => { | ||
| debug!(%peer, %root, "Block not found for BlocksByRoot request"); | ||
| // Drop channel without response - peer will timeout | ||
| } | ||
| } | ||
| } | ||
|
|
||
| async fn handle_blocks_by_root_response( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code Correctness and Potential Bugs:
Line 32: warn!(%peer, %root, "Block not found for BlocksByRoot request");Suggestion: Send an explicit error response indicating the block is not found.
Security Considerations:
Performance Implications:
Rust Best Practices and Idiomatic Patterns:
Memory Safety and Proper Error Handling:
Code Readability and Maintainability:
Consensus-layer Considerations:
Overall, this PR has groundwork in place but requires additional handling and clear informative responses for better protocol adherence and robustness. |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,8 @@ | |
| pub enum Table { | ||
| /// Block storage: H256 -> Block | ||
| Blocks, | ||
| /// Block signatures storage: H256 -> BlockSignaturesWithAttestation | ||
| BlockSignatures, | ||
| /// State storage: H256 -> State | ||
| States, | ||
| /// Known attestations: u64 -> AttestationData | ||
|
|
@@ -18,8 +20,9 @@ pub enum Table { | |
| } | ||
|
|
||
| /// All table variants. | ||
| pub const ALL_TABLES: [Table; 7] = [ | ||
| pub const ALL_TABLES: [Table; 8] = [ | ||
| Table::Blocks, | ||
| Table::BlockSignatures, | ||
| Table::States, | ||
| Table::LatestKnownAttestations, | ||
| Table::LatestNewAttestations, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code Correctness and Potential Bugs
Security Vulnerabilities
Performance Implications
Rust Best Practices and Idiomatic Patterns
Memory Safety and Error Handling
Code Readability and Maintainability
Consensus-Layer Considerations
In conclusion, while this change appears structurally sound, additional review of related parts of the code base outside of this snippet is necessary to address potential security, performance, and consensus issues regarding the introduction of the |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,7 @@ use std::sync::Arc; | |
| fn cf_name(table: Table) -> &'static str { | ||
| match table { | ||
| Table::Blocks => "blocks", | ||
| Table::BlockSignatures => "block_signatures", | ||
| Table::States => "states", | ||
| Table::LatestKnownAttestations => "latest_known_attestations", | ||
| Table::LatestNewAttestations => "latest_new_attestations", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code Correctness and Potential Bugs
Security Vulnerabilities
Performance Implications
Rust Best Practices and Idiomatic Patterns
Memory Safety and Proper Error Handling
Code Readability and Maintainability
Consensus-layer Considerations
Based on the information provided, the code change looks appropriately applied; however, comprehensive testing and verification are required in the context of its impact throughout the codebase. |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,10 @@ use crate::api::{StorageBackend, Table}; | |
|
|
||
| use ethlambda_types::{ | ||
| attestation::AttestationData, | ||
| block::{AggregatedSignatureProof, Block, BlockBody}, | ||
| block::{ | ||
| AggregatedSignatureProof, Block, BlockBody, BlockSignaturesWithAttestation, | ||
| SignedBlockWithAttestation, | ||
| }, | ||
| primitives::{Decode, Encode, H256, TreeHash}, | ||
| signature::ValidatorSignature, | ||
| state::{ChainConfig, Checkpoint, State}, | ||
|
|
@@ -305,6 +308,46 @@ impl Store { | |
| batch.commit().expect("commit"); | ||
| } | ||
|
|
||
| // ============ Signed Blocks ============ | ||
|
|
||
| /// Insert a signed block, storing the block and signatures separately. | ||
| pub fn insert_signed_block(&mut self, root: H256, signed_block: &SignedBlockWithAttestation) { | ||
| let block = &signed_block.message.block; | ||
| let signatures = BlockSignaturesWithAttestation::from_signed_block(signed_block); | ||
|
|
||
| let mut batch = self.backend.begin_write().expect("write batch"); | ||
| batch | ||
| .put_batch( | ||
| Table::Blocks, | ||
| vec![(root.as_ssz_bytes(), block.as_ssz_bytes())], | ||
| ) | ||
| .expect("put block"); | ||
| batch | ||
| .put_batch( | ||
| Table::BlockSignatures, | ||
| vec![(root.as_ssz_bytes(), signatures.as_ssz_bytes())], | ||
| ) | ||
| .expect("put block signatures"); | ||
| batch.commit().expect("commit"); | ||
| } | ||
|
|
||
| /// Get a signed block by combining block and signatures. | ||
| /// | ||
| /// Returns None if either the block or signatures are not found. | ||
| pub fn get_signed_block(&self, root: &H256) -> Option<SignedBlockWithAttestation> { | ||
| let view = self.backend.begin_read().expect("read view"); | ||
| let key = root.as_ssz_bytes(); | ||
|
|
||
| let block_bytes = view.get(Table::Blocks, &key).expect("get")?; | ||
| let sig_bytes = view.get(Table::BlockSignatures, &key).expect("get")?; | ||
|
|
||
| let block = Block::from_ssz_bytes(&block_bytes).expect("valid block"); | ||
| let signatures = | ||
| BlockSignaturesWithAttestation::from_ssz_bytes(&sig_bytes).expect("valid signatures"); | ||
|
|
||
| Some(signatures.to_signed_block(block)) | ||
| } | ||
|
|
||
| // ============ States ============ | ||
|
|
||
| /// Iterate over all (root, state) pairs. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code Correctness and Potential Bugs
Security Vulnerabilities
Performance Implications
Rust Best Practices and Idiomatic Patterns
Memory Safety and Proper Error Handling
Code Readability and Maintainability
Consensus-layer Considerations
ConclusionThe code needs improvements primarily in terms of error handling and assumption management. Ensuring graceful handling of errors will significantly increase robustness and security. |
||
|
|
||
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.
Code Correctness and Potential Bugs
store.insert_block(block_root, block.clone());tostore.insert_signed_block(block_root, &signed_block);needs to be validated to ensure that all downstream logic that expects an unsigned block can properly handle a signed one. Ensure thatstore.insert_signed_blockis functionally equivalent or that the system is designed for this change.Security Vulnerabilities
Rust Best Practices and Idiomatic Patterns
blockto a borrowed&signed_blockis generally a good practice to reduce unnecessary allocations, assuming lifetime issues are managed correctly.Memory Safety and Proper Error Handling
insert_signed_block: Ensure thatinsert_signed_blockreturns aResultand errors are handled, rather than ignored, to prevent unnoticed failures in block storage.Code Readability and Maintainability
Store block and statetoStore signed block and stateis minor but helpful for context. Ensure that comments are updated to reflect the logical changes accurately and across the entire codebase where impacted.Performance Implications
signed_blockshould be more efficient than cloning it, assuming no mutation occurs that would require a clone later, which indicates good practice barring any unforeseen side effects.Consensus-layer Considerations
signed_blockcorrectly.Overall, ensure thorough testing around this code to guarantee that expectations around
signed_blockare met without introducing hidden bugs or security issues.