-
Notifications
You must be signed in to change notification settings - Fork 8
feat: improve log messages #66
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
d3b108c
5fd3464
45da221
8d4923f
2f852ff
b4f49fe
2b609bc
4a42fea
e8da495
2dabc22
19f6064
e8b3f10
23695d6
1809149
b87a06a
a6fee9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ use ethlambda_state_transition::is_proposer; | |
| use ethlambda_storage::Store; | ||
| use ethlambda_types::primitives::H256; | ||
| use ethlambda_types::{ | ||
| ShortRoot, | ||
| attestation::{Attestation, AttestationData, SignedAttestation}, | ||
| block::{BlockSignatures, BlockWithAttestation, SignedBlockWithAttestation}, | ||
| primitives::TreeHash, | ||
|
|
@@ -277,6 +278,7 @@ impl BlockChainServer { | |
| let slot = signed_block.message.block.slot; | ||
| let block_root = signed_block.message.block.tree_hash_root(); | ||
| let parent_root = signed_block.message.block.parent_root; | ||
| let proposer = signed_block.message.block.proposer_index; | ||
|
|
||
| // Check if parent block exists before attempting to process | ||
| if !self.store.contains_block(&parent_root) { | ||
|
|
@@ -296,13 +298,26 @@ impl BlockChainServer { | |
| // Parent exists, proceed with processing | ||
| match self.process_block(signed_block) { | ||
| Ok(_) => { | ||
| info!(%slot, "Block processed successfully"); | ||
| info!( | ||
| %slot, | ||
| proposer, | ||
| block_root = %ShortRoot(&block_root.0), | ||
| parent_root = %ShortRoot(&parent_root.0), | ||
|
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
Overall, the PR needs further verification and explanations about how errors are handled and secured before it can be merged. |
||
| "Block imported successfully" | ||
| ); | ||
|
|
||
| // Check if any pending blocks can now be processed | ||
| self.process_pending_children(block_root); | ||
| } | ||
| Err(err) => { | ||
| warn!(%slot, %err, "Failed to process block"); | ||
| warn!( | ||
| %slot, | ||
| proposer, | ||
| block_root = %ShortRoot(&block_root.0), | ||
| parent_root = %ShortRoot(&parent_root.0), | ||
| %err, | ||
| "Failed to process block" | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
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
Overall, the additions concerning logging enhance observability, but attention to the broader consensus and performance impacts is essential. Consider also scrutinizing upstream and downstream code interactions not visible in this change. |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ use ethlambda_state_transition::{ | |
| }; | ||
| use ethlambda_storage::{ForkCheckpoints, SignatureKey, Store}; | ||
| use ethlambda_types::{ | ||
| ShortRoot, | ||
| attestation::{AggregatedAttestation, Attestation, AttestationData, SignedAttestation}, | ||
| block::{ | ||
| AggregatedAttestations, AggregatedSignatureProof, AggregationBits, Block, BlockBody, | ||
|
|
@@ -43,6 +44,22 @@ fn update_head(store: &mut Store) { | |
| info!(%old_head, %new_head, "Fork choice reorg detected"); | ||
| } | ||
| store.update_checkpoints(ForkCheckpoints::head_only(new_head)); | ||
|
|
||
| if old_head != new_head { | ||
| let old_slot = store.get_block(&old_head).map(|b| b.slot).unwrap_or(0); | ||
| let new_slot = store.get_block(&new_head).map(|b| b.slot).unwrap_or(0); | ||
|
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 Review for ethlambda PR
ConclusionThere are concerns around ensuring consistent import order, strict correctness in state management and processing logic, and a strong emphasis on security practices. It's recommended to address these considerations before proceeding with the merge. |
||
| let justified_slot = store.latest_justified().slot; | ||
| let finalized_slot = store.latest_finalized().slot; | ||
| info!( | ||
| head_slot = new_slot, | ||
| head_root = %ShortRoot(&new_head.0), | ||
| previous_head_slot = old_slot, | ||
| previous_head_root = %ShortRoot(&old_head.0), | ||
| justified_slot, | ||
| finalized_slot, | ||
| "Fork choice head updated" | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /// Update the safe target for attestation. | ||
|
|
@@ -196,7 +213,7 @@ pub fn on_gossip_attestation( | |
| return Err(StoreError::SignatureVerificationFailed); | ||
| } | ||
| } | ||
| on_attestation(store, attestation, false)?; | ||
| on_attestation(store, attestation.clone(), false)?; | ||
|
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
Overall, the code shows improvements by adopting more idiomatic practices but requires attention on error handling to ensure robustness in critical systems like blockchain clients. |
||
|
|
||
| if cfg!(not(feature = "skip-signature-verification")) { | ||
| // Store signature for later lookup during block building | ||
|
|
@@ -206,6 +223,20 @@ pub fn on_gossip_attestation( | |
| store.insert_gossip_signature(signature_key, signature); | ||
| } | ||
| metrics::inc_attestations_valid("gossip"); | ||
|
|
||
| let slot = attestation.data.slot; | ||
| let target_slot = attestation.data.target.slot; | ||
| let source_slot = attestation.data.source.slot; | ||
| info!( | ||
| slot, | ||
| validator = validator_id, | ||
| target_slot, | ||
| target_root = %ShortRoot(&attestation.data.target.root.0), | ||
| source_slot, | ||
| source_root = %ShortRoot(&attestation.data.source.root.0), | ||
| "Attestation processed" | ||
| ); | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
|
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.
Overall, the proposed changes should consider minimizing unnecessary object cloning, closely managing slot errors, and improving debug logging for error cases. |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ ethlambda-types.workspace = true | |
| ethlambda-metrics.workspace = true | ||
|
|
||
| thiserror.workspace = true | ||
| tracing.workspace = true | ||
|
|
||
| [dev-dependencies] | ||
| serde.workspace = true | ||
|
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. General OverviewThe addition of a new dependency, Specific Concerns1. Code Correctness & Potential BugsThere is no direct code to review in the provided snippet, but adding 2. Security VulnerabilitiesWhile 3. Performance ImplicationsImplementing tracing can introduce performance overhead, especially if used excessively in high-traffic code paths. Consider using conditional compilation flags to disable verbose logging in production builds. 4. Rust Best Practices & Idiomatic PatternsAdding 5. Memory Safety & Proper Error Handling
6. Code Readability & MaintainabilityEnsure that logging improves, rather than complicates, code readability. Use structured logging to maintain consistent, parseable logs that contribute to maintainability. Consensus-layer ConsiderationsThis addition doesn't directly affect consensus logic but can support diagnosing issues in fork choice, attestation processing, and state transitions by reproducing internal states or changes. Actionable Suggestions
In conclusion, while the addition of |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,12 @@ | ||
| use std::collections::HashMap; | ||
|
|
||
| use ethlambda_types::{ | ||
| ShortRoot, | ||
| block::{AggregatedAttestations, Block, BlockHeader}, | ||
| primitives::{H256, TreeHash}, | ||
| state::{Checkpoint, JustificationValidators, State}, | ||
| }; | ||
| use tracing::info; | ||
|
|
||
| mod justified_slots_ops; | ||
| pub mod metrics; | ||
|
|
@@ -296,6 +298,16 @@ fn process_attestations( | |
| target.slot, | ||
| ); | ||
|
|
||
| let justified_slot = target.slot; | ||
| let threshold = (2 * validator_count).div_ceil(3); | ||
| info!( | ||
| justified_slot, | ||
| justified_root = %ShortRoot(&target.root.0), | ||
| vote_count, | ||
| threshold, | ||
| "Checkpoint justified" | ||
| ); | ||
|
|
||
| justifications.remove(&target.root); | ||
|
|
||
| // Consider whether finalization can advance. | ||
|
|
@@ -307,6 +319,17 @@ fn process_attestations( | |
| state.latest_finalized = source; | ||
| metrics::inc_finalizations("success"); | ||
|
|
||
| let finalized_slot = source.slot; | ||
| let previous_finalized = old_finalized_slot; | ||
| let justified_slot = state.latest_justified.slot; | ||
| info!( | ||
| finalized_slot, | ||
| finalized_root = %ShortRoot(&source.root.0), | ||
| previous_finalized, | ||
| justified_slot, | ||
| "Checkpoint finalized" | ||
| ); | ||
|
|
||
| // Shift window to drop finalized slots from the front | ||
| let delta = (state.latest_finalized.slot - old_finalized_slot) as usize; | ||
| justified_slots_ops::shift_window(&mut state.justified_slots, delta); | ||
|
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
Additional Notes
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,3 +4,15 @@ pub mod genesis; | |
| pub mod primitives; | ||
| pub mod signature; | ||
| pub mod state; | ||
|
|
||
| /// Display helper for truncated root hashes (8 hex chars) | ||
| pub struct ShortRoot<'a>(pub &'a [u8; 32]); | ||
|
|
||
| impl std::fmt::Display for ShortRoot<'_> { | ||
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| for byte in &self.0[..4] { | ||
| write!(f, "{:02x}", byte)?; | ||
| } | ||
| Ok(()) | ||
| } | ||
| } | ||
|
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. General Feedback:The proposed code appears to introduce a utility for displaying a shortened version of Ethereum root hashes. While the implementation is straightforward, there are a few areas that could benefit from improvement to adhere to Rust best practices and ensure future maintainability. 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:
Conclusion:While the implementation is acceptable, addressing the identified concerns will enhance the overall robustness and maintainability of the code. Specifically, adding error handling for unexpected input sizes will prevent potential issues when used within the broader codebase. Assuming inputs are always valid can lead to future bugs when the codebase evolves. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,10 @@ | ||
| use ethlambda_types::{attestation::SignedAttestation, block::SignedBlockWithAttestation}; | ||
| use ethlambda_types::{ | ||
| ShortRoot, attestation::SignedAttestation, block::SignedBlockWithAttestation, | ||
| }; | ||
| use libp2p::gossipsub::Event; | ||
| use ssz::{Decode, Encode}; | ||
| use tracing::{error, info, trace}; | ||
| use tree_hash::TreeHash; | ||
|
|
||
| use super::{ | ||
| encoding::{compress_message, decompress_message}, | ||
|
|
@@ -32,7 +35,18 @@ pub async fn handle_gossipsub_message(server: &mut P2PServer, event: Event) { | |
| return; | ||
| }; | ||
| let slot = signed_block.message.block.slot; | ||
| info!(%slot, "Received new block from gossipsub, sending for processing"); | ||
| let block_root = signed_block.message.block.tree_hash_root(); | ||
| let proposer = signed_block.message.block.proposer_index; | ||
| let parent_root = signed_block.message.block.parent_root; | ||
| let attestation_count = signed_block.message.block.body.attestations.len(); | ||
| info!( | ||
| %slot, | ||
| proposer, | ||
| block_root = %ShortRoot(&block_root.0), | ||
| parent_root = %ShortRoot(&parent_root.0), | ||
| attestation_count, | ||
| "Received block from gossip" | ||
| ); | ||
| server.blockchain.notify_new_block(signed_block).await; | ||
| } | ||
| Some(ATTESTATION_TOPIC_KIND) => { | ||
|
|
@@ -49,7 +63,16 @@ pub async fn handle_gossipsub_message(server: &mut P2PServer, event: Event) { | |
| }; | ||
| let slot = signed_attestation.message.slot; | ||
| let validator = signed_attestation.validator_id; | ||
| info!(%slot, %validator, "Received new attestation from gossipsub, sending for processing"); | ||
| info!( | ||
| %slot, | ||
| validator, | ||
| head_root = %ShortRoot(&signed_attestation.message.head.root.0), | ||
| target_slot = signed_attestation.message.target.slot, | ||
| target_root = %ShortRoot(&signed_attestation.message.target.root.0), | ||
| source_slot = signed_attestation.message.source.slot, | ||
| source_root = %ShortRoot(&signed_attestation.message.source.root.0), | ||
| "Received attestation from gossip" | ||
| ); | ||
| server | ||
| .blockchain | ||
| .notify_new_attestation(signed_attestation) | ||
|
|
@@ -77,7 +100,15 @@ pub async fn publish_attestation(server: &mut P2PServer, attestation: SignedAtte | |
| .behaviour_mut() | ||
| .gossipsub | ||
| .publish(server.attestation_topic.clone(), compressed) | ||
| .inspect(|_| trace!(%slot, %validator, "Published attestation to gossipsub")) | ||
| .inspect(|_| info!( | ||
| %slot, | ||
| validator, | ||
| target_slot = attestation.message.target.slot, | ||
| target_root = %ShortRoot(&attestation.message.target.root.0), | ||
| source_slot = attestation.message.source.slot, | ||
| source_root = %ShortRoot(&attestation.message.source.root.0), | ||
| "Published attestation to gossipsub" | ||
| )) | ||
| .inspect_err(|err| { | ||
| tracing::warn!(%slot, %validator, %err, "Failed to publish attestation to gossipsub") | ||
| }); | ||
|
|
@@ -86,6 +117,9 @@ pub async fn publish_attestation(server: &mut P2PServer, attestation: SignedAtte | |
| pub async fn publish_block(server: &mut P2PServer, signed_block: SignedBlockWithAttestation) { | ||
| let slot = signed_block.message.block.slot; | ||
| let proposer = signed_block.message.block.proposer_index; | ||
| let block_root = signed_block.message.block.tree_hash_root(); | ||
| let parent_root = signed_block.message.block.parent_root; | ||
| let attestation_count = signed_block.message.block.body.attestations.len(); | ||
|
|
||
| // Encode to SSZ | ||
| let ssz_bytes = signed_block.as_ssz_bytes(); | ||
|
|
@@ -99,7 +133,16 @@ pub async fn publish_block(server: &mut P2PServer, signed_block: SignedBlockWith | |
| .behaviour_mut() | ||
| .gossipsub | ||
| .publish(server.block_topic.clone(), compressed) | ||
| .inspect(|_| info!(%slot, %proposer, "Published block to gossipsub")) | ||
| .inspect(|_| { | ||
| info!( | ||
| %slot, | ||
| proposer, | ||
| block_root = %ShortRoot(&block_root.0), | ||
| parent_root = %ShortRoot(&parent_root.0), | ||
| attestation_count, | ||
| "Published block to gossipsub" | ||
| ) | ||
| }) | ||
| .inspect_err( | ||
| |err| tracing::warn!(%slot, %proposer, %err, "Failed to publish block to gossipsub"), | ||
| ); | ||
|
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: Overall, while the changes mostly affect logging and do not directly modify core consensus functions, thoroughly testing these additions in an integration or simulation environment is recommended to ensure they do not inadvertently introduce race conditions or reveal any sensitive operational data. |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -246,10 +246,20 @@ async fn handle_swarm_event(server: &mut P2PServer, event: SwarmEvent<BehaviourE | |
| let direction = connection_direction(&endpoint); | ||
| if num_established.get() == 1 { | ||
| server.connected_peers.insert(peer_id); | ||
| let peer_count = server.connected_peers.len(); | ||
| metrics::notify_peer_connected(&Some(peer_id), direction, "success"); | ||
| // Send status request on first connection to this peer | ||
| let our_status = build_status(&server.store); | ||
| info!(%peer_id, %direction, finalized_slot=%our_status.finalized.slot, head_slot=%our_status.head.slot, "Added connection to new peer, sending status request"); | ||
| let our_finalized_slot = our_status.finalized.slot; | ||
| let our_head_slot = our_status.head.slot; | ||
| info!( | ||
| %peer_id, | ||
| %direction, | ||
| peer_count, | ||
| our_finalized_slot, | ||
| our_head_slot, | ||
| "Peer connected" | ||
| ); | ||
| server | ||
| .swarm | ||
| .behaviour_mut() | ||
|
|
@@ -290,9 +300,18 @@ async fn handle_swarm_event(server: &mut P2PServer, event: SwarmEvent<BehaviourE | |
| }; | ||
| if num_established == 0 { | ||
| server.connected_peers.remove(&peer_id); | ||
| let peer_count = server.connected_peers.len(); | ||
| metrics::notify_peer_disconnected(&Some(peer_id), direction, reason); | ||
| info!( | ||
| %peer_id, | ||
| %direction, | ||
| %reason, | ||
| peer_count, | ||
| "Peer disconnected" | ||
| ); | ||
|
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. General
Performance Implications
Rust Best Practices and Idiomatic Patterns
Memory Safety and Proper Error Handling
Code Readability and Maintainability
Consensus-Layer Considerations
In conclusion, the logging improvements are beneficial, though ensure holistic correctness and security throughout the codebase. Further context-specific analysis would solidify the assurance levels of these changes. |
||
| } else { | ||
| info!(%peer_id, %direction, %reason, "Peer connection closed but other connections remain"); | ||
| } | ||
| info!(%peer_id, %direction, %reason, "Peer disconnected"); | ||
| } | ||
| SwarmEvent::OutgoingConnectionError { peer_id, error, .. } => { | ||
| let result = if error.to_string().to_lowercase().contains("timed out") { | ||
|
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. Review CommentsCode Correctness and Potential Bugs
Security Vulnerabilities
Performance Implications
Rust Best Practices and Idiomatic Patterns
Memory Safety and Proper Error Handling
Code Readability and Maintainability
Consistency and Fault Tolerance
In summary, the main concern revolves around log message correctness and the unnecessary use of |
||
|
|
||
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.
Here is the review for the code snippet provided:
ShortRoot. Line imports should look like:ResultandOptiontypes should be leveraged.unsafeblocks unless absolutely necessary. Also, use borrowing appropriately to avoid unnecessary copies.spawned_concurrency::tasks, evaluate the potential for performance bottlenecks, especially in a consensus-critical system.To proceed, I suggest reordering the imports back to an alphabetically sorted list and ensure comprehensive test coverage for all consensus-critical operations discussed above. Additional context or code would allow for a deeper review.