Skip to content

fix(net): sync p2p fixes from libp2p release-v2.3.0 - #7034

Merged
kuny0707 merged 14 commits into
tronprotocol:release_v4.8.3from
317787106:feature/p2p_v230_migration_v1
Oct 15, 2026
Merged

kuny0707 merged 14 commits into
tronprotocol:release_v4.8.3from
317787106:feature/p2p_v230_migration_v1

Conversation

@317787106

@317787106 317787106 commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Synchronize the in-tree p2p module with the merged fixes in libp2p release-v2.3.0, and update java-tron's integration logic to follow the new channel identity, HELLO, and active-node behavior. Peers must complete P2P HELLO validation before application traffic is accepted or a peer slot is registered; pending inbound sockets are bounded and expire after 10 seconds. The update also bounds queued UDP pong timeout tasks and keeps distinct TCP channels registered when their remote socket addresses collide.

Baseline Revision
Initial java-tron base release_v4.8.3 at a901f85a4abaec4cc65a7a2e1cff7d499d57134f
Initial libp2p import in #6992 v2.2.9 at c564f263d310d7a964035d3b597634aba6bda86d
Upstream synchronization target release-v2.3.0 at f13c67cdca73cec36eb5dd83bb5ef51f9ba7f9bc

The migration includes these upstream changes and their regression tests:

Upstream PR Commit Change
libp2p #147 b223c3f Log the actual UDP packet sender and retain deterministic IP/connection-pool test coverage.
libp2p #151 f8fd2ad Propagate initial TCP/UDP bind failures, clean up startup resources, and make the standalone CLI exit with failure status.
libp2p #157 826dc1f Discard unknown Protobuf fields while parsing P2P messages, including compressed envelopes.
libp2p #149 38db102 Validate advertised ports before discovery admission, address construction, and connection-pool selection.
libp2p #146 5516b62 Limit pending inbound connections to 32 globally and 2 per IP, with an absolute 10-second HELLO deadline.
libp2p #123 a6c64db Select Okio 1.17.6 for the Aliyun SDK HTTP dependency chain to address CVE-2023-3635; regenerate dependency verification metadata.
libp2p #145 1e26de4 Reject application messages before HELLO; check network ID and self/duplicate peers before completing the handshake and registering the connection.
libp2p #150 eb1d59f Close established peers sending STATUS, notify disconnect once, and prevent an old channel from removing its replacement at the same socket address.
libp2p #155 f78ce0e Avoid duplicate active-node dials while a connection is pending; clear the retry cache on failure and defer dynamic active-node retries to the next tick.
libp2p #154 e6ca2f1 Track pool and registry membership by channel instance, so same-address channels are counted and disconnected independently.
libp2p #148 f13c67c Limit queued UDP pong timeout tasks to 20,000; cancel completed probes' tasks and handle scheduler rejection without closing the UDP channel.

The Protobuf source-directory alignment from libp2p #152 (bdb10d9) was already included in #6992, so it requires no additional change here.

The upstream behavior changes also require these java-tron integration changes:

  • Channel and peer identity (libp2p #154): PeerManager matches and removes peers by channel instance, including timeout cleanup. PeerConnection uses instance identity for request tracking, so two connections with the same remote socket address remain independent in peer management, block sync, and message propagation.
  • Application HELLO identity (libp2p #145): HandshakeService requires the application HELLO node ID to match the ID already validated by the P2P handshake. A mismatch disconnects the peer instead of replacing its channel identity.
  • Dynamic active-node configuration (libp2p #155): DynamicArgs removes obsolete active nodes and adds new ones incrementally, keeping retained nodes visible to libp2p's connection loop throughout an update. Dynamic configuration owns the active-node list when enabled.

Why are these changes required?

#6992 internalized libp2p 2.2.9 without taking these later behavior changes. The module therefore retained handshake bypasses, unbounded pending inbound sockets and pong timeout tasks, incorrect peer cleanup after STATUS or same-address collisions, startup failures that could be logged without reaching the caller, and repeated dials to pending active nodes. Applying the upstream fixes also requires java-tron's peer tracking, application HELLO validation, and dynamic active-node updates to follow the new P2P behavior.

This PR has been tested by:

Local validation on macOS ARM64 / JDK 17:

Check Result
./gradlew clean build -x test PASS, including FullNode and standalone P2P packaging
./gradlew :p2p:test PASS: 463 tests, 0 failures/errors, 4 skipped
./gradlew :framework:test --tests org.tron.core.net.peer.PeerManagerTest PASS: 7 tests, including same-address removal and timeout cleanup
:p2p:checkstyleMain :p2p:checkstyleTest PASS
:framework:checkstyleMain :framework:checkstyleTest :plugins:checkstyleMain PASS; the CI Checkstyle command
bash .github/scripts/check_math_usage.sh PASS
Framework dependencyInsight and packaged FullNode.jar Okio resolves to and is packaged as 1.17.6
java -jar p2p/build/libs/p2p-standalone.jar --help PASS

The repository-wide test suite was not run to completion for this update; CI will validate it. Regression coverage includes real TCP connection limits and STATUS cleanup, concurrent admission and disconnect handling, HELLO deadline enforcement under partial-frame/keepalive traffic, malformed and boundary ports, unknown Protobuf fields, startup failure/cleanup in separate JVMs, active-node retry behavior, same-address channel lifecycles and request tracking, application HELLO identity mismatches, incremental dynamic active-node updates, and UDP pong timeout queue saturation.

Follow up

This is the first migration (v1). Compare later upstream changes against f13c67cdca73cec36eb5dd83bb5ef51f9ba7f9bc to avoid reapplying this batch in v2 or subsequent PRs.

Extra details

  • P2P admission behavior changes: networkId must match; the legacy version-only fallback and application-message handshake shortcut are removed. Pending inbound limits also apply to trusted peers. Initial listener bind failures now fail startup.
  • ChannelManager.getChannels() remains available as a deprecated, detached address-indexed snapshot. Internal callers use the complete channel list or count so address collisions do not hide connections.
  • Protobuf schemas, message field numbers, and consensus/state-transition rules are unchanged.
  • Preserve the local module layout, logging names, explicit locales, deterministic math adaptations, standalone packaging, and CLI trust-IP parsing fix from chore(p2p): internalize libp2p v2.2.9 as a local p2p module #6992. Keep the local loopback IP tests and additional connection-pool coverage when upstream tests overlap.
  • Okio is the only dependency version changed. Its patch is a separate commit, with verification metadata limited to the new Okio artifacts; other dependencies retain java-tron's versions.
  • Keep the migration inventory and next comparison baseline in this PR description; the module README retains only its short source-provenance note.

Port libp2p tronprotocol#123 (a6c64db) by selecting Okio 1.17.6 for the Aliyun
SDK HTTP dependency chain, addressing CVE-2023-3635. Regenerate Gradle
verification metadata and retain only the new Okio artifact checksums.
Port the merged upstream fixes from v2.2.9 (c564f263) through
release-v2.3.0 (eb1d59fa), based on release_v4.8.3 at a901f85.

Require HELLO before application traffic, validate peer admission and
advertised ports, bound pending inbound handshakes, propagate startup
bind failures, discard unknown protobuf fields, and clean up STATUS
connections safely.

Port regression tests while preserving java-tron's existing integration
and deterministic tests. Record upstream PRs and the next synchronization
baseline in p2p/README.md. Do not include unmerged upstream PRs.

Validation on macOS ARM64 / JDK 17:
- clean build -x test
- full test suite: 4,145 tests, 0 failures/errors, 30 skipped
- p2p tests: 438 tests, 0 failures/errors, 4 skipped
- module and CI Checkstyle gates; check_math_usage.sh
- FullNode runtime and packaged Okio resolve to 1.17.6
- standalone p2p --help smoke check
@github-actions
github-actions Bot requested a review from xxo1shine October 13, 2026 15:31
@317787106 317787106 changed the title feat(net): import libp2p v2.3.0 fix(net): sync p2p fixes from libp2p release-v2.3.0 Oct 13, 2026
@SeriousCoding789 SeriousCoding789 added this to the GreatVoyage-v4.8.3 milestone Oct 14, 2026
@SeriousCoding789
SeriousCoding789 self-requested a review October 14, 2026 02:17
@317787106
317787106 requested a review from 3for October 14, 2026 06:28

@SeriousCoding789 SeriousCoding789 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior changes listed under "Extra details" look worth carrying into the release notes, since operators would otherwise only notice them after upgrading:

  • networkId must now match. With the version-only fallback removed, nodes on this release will no longer complete outbound handshakes with nodes still running v4.7.0 or v4.7.1 (libp2p 0.1.1 / 0.1.4, whose HELLO carries no networkId). Inbound connections from those versions were already rejected, so the practical impact seems small.
  • The pending inbound limits (32 globally, 2 per IP, 10-second HELLO deadline) also apply to trusted peers.
  • An initial listener bind failure now fails node startup, surfacing as TronError(TRON_NET_SERVICE_INIT), instead of only being logged.

@SeriousCoding789 SeriousCoding789 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

  • I checked the port against upstream: for all 28 production files, the added and removed lines match upstream c564f263 (v2.2.9) → eb1d59fa (release-v2.3.0) line by line. The only difference is the logger field name (log upstream, logger here), which the description already notes as a local adaptation.

  • On documentation, p2p/README.md is the only file that records the libp2p version, and this PR already updates it. The other references (AGENTS.md, docs/modular-introduction-*.md) mention libp2p without a version, and upstream changed no docs in this range, so no other doc updates seem needed.

Sync the active-node retry cache fix from libp2p tronprotocol#155. Cache before dialing so fast failures can clear the entry, and defer retries for runtime-added active nodes until the next connection tick. Add regression coverage and adapt the port-validation test to simulate failed attempts.
Port the merged libp2p tronprotocol#148 discovery timeout queue limit and regression tests. Keep java-tron deterministic math and logging conventions.
Port merged libp2p tronprotocol#154 to the in-tree p2p module. Preserve distinct channels through registry, pool, keepalive, and status accounting, with lifecycle regression coverage. Match channels by instance in java-tron PeerManager so its callbacks retain the correct peer when addresses collide. Advance the upstream synchronization marker to f13c67c, which includes tronprotocol#154 and tronprotocol#148.
Comment thread p2p/src/main/java/org/tron/p2p/discover/Node.java
Comment thread framework/src/main/java/org/tron/core/net/peer/PeerManager.java
@3for

3for commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

[SHOULD] Enforce node ID consistency across both HELLO layers

Location: HandshakeService.java (line 43).

The current implementation still calls:

TronNetService.getP2pService()
    .updateNodeId(peer.getChannel(), msg.getFrom().getHexId());

Following the migration requirements in libp2p #145, please replace updateNodeId() with a consistency check between the node IDs in the two HELLO layers.

If the connection is already disconnected, return immediately. If the IDs differ, reject the connection with UNEXPECTED_IDENTITY without modifying the established channel identity.

Please preserve the subsequent application-level HELLO validation and add regression tests covering matching IDs, mismatched IDs, and already-disconnected connections. The mismatch test should also verify that the original node ID and other connections remain unchanged.

Comment thread framework/src/main/java/org/tron/core/net/peer/PeerManager.java
@3for

3for commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

[SHOULD] Enforce application-level HELLO before dispatching business messages.

Location: P2pEventHandlerImpl.java (line 178)

The underlying libp2p layer now ensures that the libp2p HELLO completes first, but the framework dispatcher does not verify that the java-tron application-level HELLO has succeeded.

This allows the following sequence:

libp2p HELLO completes
→ Application HELLO not yet sent
→ SYNC_BLOCK_CHAIN
→ Sync window initialized
→ FETCH_INV_DATA
→ Historical blocks read and sent

Completing the libp2p HELLO does not replace application-level HELLO admission.

Please enforce the application handshake state at the framework message entry point, rejecting sync, inventory, block-fetch, and other business messages until the application HELLO succeeds. Make sure this check also covers dispatch paths that return early.

At minimum, add regression tests verifying that sync and block-fetch handlers are not invoked when only the libp2p HELLO has completed, and that normal processing resumes after the application HELLO succeeds.

If this is deferred to a separate PR under the upstream migration plan, please link the follow-up in this PR.

@3for

3for commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

[SHOULD] Avoid the transient gap when updating the active-node list.

DynamicArgs.java (line 76) still updates the active-node list using clear() followed by addAll().

If a failure callback for a node that remains active occurs between these operations, triggerConnect() may fail to invalidate its dial cache, potentially delaying reconnection for the remaining 120-second TTL.

Please update the list incrementally by removing obsolete entries and adding new ones, so retained nodes never temporarily disappear.

This matches the final, narrowed downstream recommendation from libp2p #155. There is no need to expand the scope into a broader atomic configuration publication refactor.

@3for

3for commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

[NIT] Add the missing framework-level startup failure integration tests.

TronNetService.java (line 91) now handles and propagates bind failures from the underlying libp2p layer. I found no evidence of an inevitable NPE or suppressed startup failure.

However, the java-tron integration coverage requested in libp2p #151 is still missing. Please add tests verifying that a port-binding failure preserves the original error cause, partially initialized services can be shut down safely, and no background threads remain after startup failure.

This is a test coverage gap, not a confirmed runtime defect.

@317787106

317787106 commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator Author

[SHOULD] Enforce node ID consistency across both HELLO layers

Location: HandshakeService.java (line 43).

The current implementation still calls:

TronNetService.getP2pService()
    .updateNodeId(peer.getChannel(), msg.getFrom().getHexId());

Following the migration requirements in libp2p #145, please replace updateNodeId() with a consistency check between the node IDs in the two HELLO layers.

If the connection is already disconnected, return immediately. If the IDs differ, reject the connection with UNEXPECTED_IDENTITY without modifying the established channel identity.

Please preserve the subsequent application-level HELLO validation and add regression tests covering matching IDs, mismatched IDs, and already-disconnected connections. The mismatch test should also verify that the original node ID and other connections remain unchanged.

@3for Thanks for catching this. Addressed in 3b2b15b. HandshakeService now returns immediately for disconnected peers and compares the application HELLO node ID with the ID established by the libp2p HELLO. A mismatch is rejected with UNEXPECTED_IDENTITY without changing the channel identity; the remaining application-level HELLO checks are preserved.

Added tests for matching and mismatched IDs, preservation of the original ID and another connection, and already-disconnected peers. All 8 HandShakeServiceTest tests and framework Checkstyle passed.

@317787106

317787106 commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator Author

[SHOULD] Enforce application-level HELLO before dispatching business messages.

Location: P2pEventHandlerImpl.java (line 178)

The underlying libp2p layer now ensures that the libp2p HELLO completes first, but the framework dispatcher does not verify that the java-tron application-level HELLO has succeeded.

This allows the following sequence:

libp2p HELLO completes
→ Application HELLO not yet sent
→ SYNC_BLOCK_CHAIN
→ Sync window initialized
→ FETCH_INV_DATA
→ Historical blocks read and sent

Completing the libp2p HELLO does not replace application-level HELLO admission.

Please enforce the application handshake state at the framework message entry point, rejecting sync, inventory, block-fetch, and other business messages until the application HELLO succeeds. Make sure this check also covers dispatch paths that return early.

At minimum, add regression tests verifying that sync and block-fetch handlers are not invoked when only the libp2p HELLO has completed, and that normal processing resumes after the application HELLO succeeds.

If this is deferred to a separate PR under the upstream migration plan, please link the follow-up in this PR.

@3for Thanks for flagging this. I agree that completing the libp2p HELLO does not guarantee that the java-tron application HELLO has succeeded.

A fix is proposed in #6993. It checks the application HELLO state before both regular and PBFT dispatch, rejects other messages until validation succeeds, and includes regression tests. That PR is still open, so the fix is not part of this PR yet.

I suggest tracking this in #6993. I do not consider it a blocker for the libp2p 2.3.0 migration.

@317787106

317787106 commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator Author

[SHOULD] Avoid the transient gap when updating the active-node list.

DynamicArgs.java (line 76) still updates the active-node list using clear() followed by addAll().

If a failure callback for a node that remains active occurs between these operations, triggerConnect() may fail to invalidate its dial cache, potentially delaying reconnection for the remaining 120-second TTL.

Please update the list incrementally by removing obsolete entries and adding new ones, so retained nodes never temporarily disappear.

This matches the final, narrowed downstream recommendation from libp2p #155. There is no need to expand the scope into a broader atomic configuration publication refactor.

@3for Thanks for catching this. Fixed in d6673f5: DynamicArgs now removes obsolete active nodes and adds new ones without temporarily removing nodes retained across a reload. This keeps those nodes visible to triggerConnect() when a failure callback runs. I added a regression test for retained-node visibility; the targeted test and framework Checkstyle checks pass.

@317787106

317787106 commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator Author

[NIT] Add the missing framework-level startup failure integration tests.

TronNetService.java (line 91) now handles and propagates bind failures from the underlying libp2p layer. I found no evidence of an inevitable NPE or suppressed startup failure.

However, the java-tron integration coverage requested in libp2p #151 is still missing. Please add tests verifying that a port-binding failure preserves the original error cause, partially initialized services can be shut down safely, and no background threads remain after startup failure.

This is a test coverage gap, not a confirmed runtime defect.

@3for Thanks for highlighting this coverage gap. A full startup failure test would need to launch java-tron in a separate JVM and verify shutdown, so it fits better in a dedicated CI integration test than in this PR’s regular unit test suite. We can add that coverage in a follow-up. The existing p2p tests cover the library-level bind failure and cleanup paths; no java-tron runtime defect has been confirmed

@github-actions
github-actions Bot requested a review from xxo1shine October 15, 2026 07:01
Comment on lines +157 to +158
PeerConnection first = Mockito.spy(new PeerConnection());
PeerConnection second = Mockito.spy(new PeerConnection());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NIT] Use real peer instances in Adv/Sync regression tests.

Locations:

  • AdvServiceTest.java (line 157)
  • SyncServiceTest.java (line 238)

The production fix looks correct, and the real-object tests in PeerConnectionTest already provide regression coverage.

One non-blocking gap remains in the new Adv/Sync tests: both peers are Mockito spies, whose equals() and hashCode() use identity semantics independently of the production implementation. As a result, these fixtures do not reproduce the original address-based collision.

Please use real PeerConnection instances backed by distinct, same-address Channel instances, and capture outgoing messages through a test subclass or mocked transport.

The service tests should fail if the old address-based equality is restored, and independently verify message delivery and request ownership for each connection.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this. Fixed in bb12756. The Adv/Sync regression tests now use distinct real Channel instances with the same socket address and PeerConnection test subclasses that record outgoing messages, instead of Mockito spies. They verify message delivery and request ownership for each peer. The tests also assert that the channels compare equal while the peers remain distinct, so restoring address-based PeerConnection equality would fail them. Both targeted tests and :framework:checkstyleTest pass locally.

@3for 3for left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM now.

@kuny0707
kuny0707 merged commit 56b1ce1 into tronprotocol:release_v4.8.3 Oct 15, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants