fix(l1): explicitly filter discv4 and discv5 packets in multiplexer#6398
fix(l1): explicitly filter discv4 and discv5 packets in multiplexer#6398azteca1998 merged 3 commits intomainfrom
Conversation
🤖 Kimi Code ReviewThe changes look correct and improve the multiplexer's robustness by properly discriminating discovery protocols. A few observations: Code Correctness
Security Considerations
Suggestions
Overall: The PR correctly fixes the previous issue where non-discovery packets were incorrectly routed to the discv5 server. The fail-closed approach (drop unrecognized packets) is the correct security posture. Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Codex Code Review
Aside from those points, the discriminator itself is consistent with Verification was source inspection only; Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
Lines of code reportTotal lines added: Detailed view |
🤖 Claude Code ReviewNow I have all the context needed for a thorough review. Here is my assessment: Review: fix(p2p): explicitly filter discv4 and discv5 packets in multiplexerOverall: The fix is correct and addresses a real operational issue. The implementation is clean, the logic is sound. A few minor observations below.
|
🤖 Kimi Code ReviewFile: Issue 1: Potential panic due to insufficient length validation (Line 113-122) Suggestion: Add an explicit guard or static assertion: pub fn is_discv5_packet(dest_id: &H256, data: &[u8]) -> bool {
// Ensure MIN_PACKET_SIZE is sufficient for header decryption
const_assert!(MIN_PACKET_SIZE >= STATIC_HEADER_END);
if data.len() < STATIC_HEADER_END || data.len() > MAX_PACKET_SIZE {
return false;
}
// ... rest of function
}Issue 2: Performance/DoS vector (Line 112) Suggestion: Document the cryptographic cost in the function docstring: /// Returns true if the data looks like a valid discv5 packet destined for `dest_id`.
///
/// Note: This performs AES-128-CTR decryption and should be considered expensive.
/// Callers should ensure this is only invoked when necessary.
Issue 3: Magic numbers (Line 124-125) Suggestion: Use named constants: const PROTOCOL_ID_SIZE: usize = 6;
const VERSION_OFFSET: usize = PROTOCOL_ID_SIZE; // 6
static_header[..PROTOCOL_ID_SIZE] == PROTOCOL_ID
&& u16::from_be_bytes([static_header[VERSION_OFFSET], static_header[VERSION_OFFSET + 1]]) == PROTOCOL_VERSIONIssue 4: Non-constant-time comparison (Line 124) File: Acknowledgment: The logic change from Minor: Ensure Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
Greptile SummaryThis PR fixes noisy
Confidence Score: 5/5
|
| Filename | Overview |
|---|---|
| crates/networking/p2p/discv5/messages.rs | Adds is_discv5_packet() that positively identifies a discv5 packet by creating a fresh AES-128-CTR cipher from dest_id[..16] + masking-IV, decrypting a copy of the static header, and verifying protocol ID (b"discv5") and version (0x0001). Logic is correct: the function operates on a copy of the bytes so the original data slice is unmodified, allowing Packet::decode to re-decrypt from scratch using its own fresh cipher. Bounds are safe (MIN_PACKET_SIZE=63 > STATIC_HEADER_END=39). |
| crates/networking/p2p/discovery/multiplexer.rs | Updates route_packet to require positive identification for both protocols before routing, falling back to a trace!-level drop for unrecognized packets. The fix eliminates the noisy InvalidHeader debug spam caused by forwarding arbitrary UDP traffic to discv5. Import updated to include the new is_discv5_packet function. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[UDP Packet Received] --> B{is_discv4_packet?\nkeccak256 hash check}
B -- Yes --> C[route_to_discv4\nDiscv4Packet::decode]
B -- No --> D{is_discv5_packet?\nAES-CTR decrypt static header\ncheck protocol-id + version}
D -- Yes\nmatches our node ID --> E[route_to_discv5\nDiscv5Packet::decode]
D -- No\nwrong node / garbage / unknown --> F[trace! drop\nDropping unrecognized UDP packet]
C --> G{discv4_enabled?}
G -- No --> H[silent drop]
G -- Yes --> I[send to Discv4Server handler]
E --> J{discv5_enabled?}
J -- No --> K[silent drop]
J -- Yes --> L[send to Discv5Server handler]
Reviews (1): Last reviewed commit: "style(l1): fix cargo fmt in discv5 messa..." | Re-trigger Greptile
🤖 Codex Code ReviewOne minor performance concern:
Aside from that, I did not find a correctness, consensus, or security bug in this patch. The discriminator is using the local node ID as the discv5 masking key, which matches the expected receive-side header unmasking flow. I could not run Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🤖 Claude Code ReviewHere is my review: PR Review:
|
iovoid
left a comment
There was a problem hiding this comment.
Why not catch InvalidProtocol and the 'header too small' error instead of decrypting twice?
Previously, any packet that failed the discv4 hash check was blindly routed to discv5, causing a flood of InvalidHeader debug logs from unrelated or malformed UDP traffic. Now packets are positively identified for both protocols and anything unrecognized is silently dropped at trace level.
Remove is_discv5_packet() pre-check and instead catch InvalidProtocol, InvalidHeader, InvalidSize, and CipherError during normal packet decoding. Non-discv5 packets are silently dropped at trace level, avoiding both the double decryption and noisy debug logs.
bb3df4e to
a4ac7d9
Compare
Summary
route_to_discv5()in the discovery multiplexer to silently drop packets that fail decoding with identification errors (InvalidProtocol,InvalidHeader,InvalidSize,CipherError)trace!level instead of producing noisydebug!errorsdebug!levelMotivation
The previous logic routed every non-discv4 packet to discv5 unconditionally, and logged all decoding failures as debug errors. Any stray UDP traffic, malformed packets, or discv5 packets encrypted for a different node ID would cause a continuous stream of
Failed to decode discv5 packet error=InvalidHeaderdebug logs (as observed when running alongside Lighthouse).Changes
The fix explicitly handles common identification errors by:
InvalidProtocol,InvalidHeader,InvalidSize, andCipherErrorseparatelyThis reduces log noise from stray UDP traffic while preserving visibility into genuine discv5 protocol issues.
Test plan
InvalidHeaderspam is gone