fix: single in-flight identify per peer with event-driven fallback - #8955
Conversation
Replace retry-based identify approach with minimal fix: - Track one in-flight identify per peer using connection.id as epoch key - Add peer:identify event listener as safety net for identify-push - Dedup overlapping identify calls from repeated STATUS messages - Guard against stale results on reconnect (connection id mismatch) - Clean up in-flight tracking on disconnect Root cause: libp2p v3 enforces per-protocol stream limits (identify maxOutbound=1). Overlapping identify attempts cause TooManyOutboundProtocolStreamsError + cascading EOF failures, inflating Unknown peer percentage to ~22% (vs ~4% on v2). This fix ensures exactly one identify attempt per peer/connection, eliminating the overlapping-call pattern without retry spray.
Summary of ChangesHello @lodekeeper, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a critical issue in libp2p v3 where repeated Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request effectively addresses the issue of excessive identify errors by preventing overlapping calls for the same peer. The use of an identifyInProgress map with the connection ID as a key is a solid approach. The logic to handle race conditions during reconnects is well-thought-out, particularly the checks against the identifyKey before and after the async identify call. The event-driven fallback using the peer:identify event is also a great addition for robustness.
I've found one potential race condition in the onPeerIdentify event handler that could undermine the fix under specific circumstances. My review includes a comment with a detailed explanation and a suggested fix.
The new tests are comprehensive and cover the new logic well, including deduplication, reconnect races, and the event-driven fallback.
Overall, this is a great fix. Addressing the suggested change will make it even more robust.
10ea50e
into
ChainSafe:cayman/libp2p3-again
Squash merged ChainSafe#8958 and reverted ChainSafe#8955. Deployed to `feat1`
Motivation
PR #8890 (libp2p v3) suffers from ~22% Unknown peer rate (vs ~4% on v2/unstable). Root cause: libp2p v3 enforces per-protocol stream limits (
identify: maxOutboundStreams=1). When repeated STATUS messages trigger overlappingidentify()calls for the same peer, v3 throwsTooManyOutboundProtocolStreamsErrorwhich cascades into massive EOF failures (~5000 identify errors/2h on feat1 vs ~287 on unstable).Description
Minimal fix — no retries, no backoff, no spray:
identifyInProgressmap keyed byPeerIdStr → connection.id. Before callingidentify(), checks if there's already one in-flight for the same connection. If so, skips.peer:identifyevents from libp2p (fired on successful identify or identify-push). UpdatesagentVersion/agentClienteven if our explicitidentify()failed earlier.connection.idas epoch token. Afterawait identify(), verifies the in-flight key still matches before writing results — a reconnect during the await clears the old entry, so stale results are discarded.Changes
packages/beacon-node/src/network/peers/peerManager.ts: AddedidentifyInProgressmap,onPeerIdentifyevent handler, dedup guard inonStatus, stale-result guard inidentifyPeer(), cleanup in disconnect handlerpackages/beacon-node/test/e2e/network/peers/peerManager.test.ts: 4 new tests (dedup, reconnect race, event-driven fallback, existing flow preserved)Evidence
Loki log comparison (2h window):
AI Disclosure
This PR was authored with AI assistance (Claude Opus 4.6 via OpenClaw). All code was reviewed and tested by the AI agent.