Skip to content

Add Connect libp2p endpoint transport#31

Merged
robinbraemer merged 26 commits into
connectfrom
codex/connect-libp2p-native-endpoint
Jun 22, 2026
Merged

Add Connect libp2p endpoint transport#31
robinbraemer merged 26 commits into
connectfrom
codex/connect-libp2p-native-endpoint

Conversation

@robinbraemer

@robinbraemer robinbraemer commented Jun 15, 2026

Copy link
Copy Markdown
Member

Summary

  • add the connector-side libp2p endpoint transport for Paper, Velocity, and Bungee platforms
  • persist endpoint peer identity in libp2p-identity.key and expose CONNECT_LIBP2P_* configuration
  • sign server-challenged relay circuit addresses so Connect edges can publish Machine-specific relay dial addresses while endpoints reserve through public bootstrap addresses
  • keep the existing WatchService/WebSocket tunnel path as server-side fallback for older connectors
  • remove misleading native naming from the new endpoint code path
  • refresh against origin/connect and preserve the WatchService WebSocket liveness fix from PR fix(connect): avoid watch websocket read timeouts #33

Current branch state

  • connect-java head: 291803869939
  • Paired Moxy PR Stop using regex to replace username GeyserMC/Floodgate#265 merged into main as 9b1e0f58862901e6caf7d908db93f59401c0819f
  • Refreshed against current origin/connect on 2026-06-22; conflict in CommonModuleTest resolved by keeping both libp2p token coverage and WatchService WebSocket liveness coverage.

Local verification on 2026-06-22

  • ./gradlew :core:test --tests com.minekube.connect.module.CommonModuleTest
  • ./gradlew :core:test :spigot:build --quiet

CI status

  • GitHub PR build passed for head 291803869939.

Staging evidence

  • Moxy PR Stop using regex to replace username GeyserMC/Floodgate#265 was validated and merged with Gate v0.66.36.
  • Local Paper runs this PR plugin in tmux session connect-libp2p-paper-staging with endpoint codexstage22a.
  • Paper logged Connect libp2p endpoint registered: d8si51qcinjc21qhkqvg, endpoint name codexstage22a, and public address codexstage22a.play.minekube.net.
  • Moxy logged libp2p endpoint registration committed and renewed for codexstage22a, endpoint peer 12D3KooWHWp6xF9M6wCjx7Mm3hMN5pvNCnCHi5S5ew67YyZ13AxW.
  • Clean-release Java hold validation passed on staging: session d8so4dbi940s206cfb70, selectedTransport=direct, selected address /ip4/172.16.61.34/tcp/64300, warmPath=warm, connectionStatus=success, no keepalive out-of-order/timeout/internal-server-error through 2026-06-22T18:45:52Z.
  • Java chat validation passed after setting the local Paper staging backend to enforce-secure-profile=false: session d8t366bi940s21vr1hu0, selectedTransport=direct, selected address /ip4/172.16.61.34/tcp/64414, warmPath=warm; Paper accepted [Not Secure] <RoboFlax2> hi and [Not Secure] <RoboFlax2> test with no new missing-profile-public-key warning.
  • Bedrock hold validation passed for the observed 2026-06-23 window through the same endpoint: Paper logged a tunneled RoboFlax2 login from 127.0.0.1:0 with floodgate:* and erosion:msg plugin channels, then ongoing gameplay at 09:25:56 and 09:26:21 Europe/Berlin, with no monitored timeout/disconnect/keepalive kick.

Notes

  • For this offline/proxied Paper staging backend, server.properties must keep enforce-secure-profile=false; otherwise Paper rejects chat state with Chat disabled due to missing profile public key.

Update: backend-close diagnostics on 2026-06-23

  • Added local diagnostic logs to LocalChannelInboundHandler and TunnelHandler in the staging worktree to distinguish local backend close from tunnel-stream close; preserved the byte-copy fixes already under validation.
  • Built with ./gradlew :spigot:shadowJar -x test and installed connect-spigot.jar on the local Paper staging server; SHA-256 8affd0471ee9b7318fc31c41737174483dad1725158a31178cc2cd6a89ed32e6.
  • Paper staging now runs under tmux socket connectdebug, session connect-libp2p-paper-staging2, with Java 25 and explicit CONNECT_LIBP2P_EDGE_ADDR / CONNECT_LIBP2P_RELAY_ADDRS pointing at edge peer 12D3KooWCqs14yyxXW5rosC5CJ9tmNsRvQ97KKUx5HzGKK1pyVsN.
  • Diagnostic finding: a Java session d8t86sji940s21r2entg closed because the tunnel stream closed first, then the local backend channel closed.
  • Bedrock retest then passed the observed >5 minute window: session d8t8713i940s21r2enu0, selectedTransport=direct, selected address /ip4/172.16.61.34/tcp/64766, warmPath=warm, connectionStatus=success, duration 594.886026ms; Paper logged the main local backend channel active for RoboFlax2 and no matching close through 2026-06-23T13:06:22Z.
  • Remaining risk is not connect-java packet copying in this successful run; it is Fly anycast reaching different edge peers for peer-specific libp2p addresses.

2026-06-23 staging update

  • Local Paper staging is running this PR head 291803869939 plus diagnostic logging jar SHA-256 8affd0471ee9b7318fc31c41737174483dad1725158a31178cc2cd6a89.
  • Endpoint codexstage22a re-registered after the Moxy staging redeploy as endpoint ID d8si51qcinjc21qhkqvg, endpoint peer 12D3KooWHWp6xF9M6wCjx7Mm3hMN5pvNCnCHi5S5ew67YyZ13AxW, endpoint instance 99b7ab62-b29e-4fca-94a1-aced408c54a6.
  • Bedrock session d8t9baji940s201ckf9g was accepted at 2026-06-23T14:18:19Z with selectedTransport=direct, warmPath=warm, and Moxy reported connectionStatus=success at 2026-06-23T14:18:21Z.
  • Evidence doc updated in Moxy PR Stop using regex to replace username GeyserMC/Floodgate#265 worktree: docs/superpowers/plans/2026-06-18-connect-libp2p-pr265-readiness.md.

Correction to 2026-06-23 staging update: the later disconnect at 16:24:26 Europe/Berlin was caused by locally killing/restarting the deterministic fly proxy processes, which closed Bedrock session d8t9baji940s201ckf9g; it was not the prior fast disconnect.timeout path. Paper re-registered after proxies were restored.

Update: multi-relay endpoint records on 2026-06-23

  • Local staging fix makes connect-java include all successfully reserved relay circuit addrs in the signed endpoint record, not only the relay from the edge registration challenge.
  • Focused verification passed: ./gradlew :core:test --tests com.minekube.connect.tunnel.p2p.PeerRegistrationHandshakeTest, ./gradlew :core:test --tests 'com.minekube.connect.tunnel.p2p.*' --tests 'com.minekube.connect.network.netty.TunnelHandlerTest', and ./gradlew :spigot:shadowJar.
  • Installed local Paper plugin jar SHA-256 cd048c795ff640e7c433e96aa9b250da1a75db949b2d42c83ef9616d30c31031.
  • With Moxy staging validation patch deployed, endpoint instance 53010fda-d378-44d1-bb96-839a1d163776 renewed with relayAddrs=3; Bedrock session d8t9vn2fskps2294e7ug was accepted with selectedTransport=direct, warmPath=warm, and delivered successfully.

2026-06-23 Bedrock multi-relay staging retry

  • After staging redeploy, e827 regenerated its libp2p identity; local Paper was restarted with relay 14225 updated to 12D3KooWB1riwr5QRN4Uw6sm63jwid2R7tUfFDuJNckWaz5A7bFw.
  • Endpoint re-registered cleanly at 2026-06-23T15:18:42Z; Moxy committed codexstage22a endpoint instance b7b2da24-e2dd-424a-8f80-1bb4cbaabe82 with relayAddrs=3, exercising the connect-java change that signs all reserved relay circuit addrs.
  • Verified Robin Bedrock retry at 2026-06-23T15:19:24Z: session d8ta7v2fskps23njfh1g, selectedTransport=direct, warmPath=warm, connectionStatus=success, bedrock join attempt result=success, and Paper logged RoboFlax2 joined the game at 17:19:26 Europe/Berlin.
  • Remaining staging gap is operational, not endpoint-code: the no-volume bedrock Fly machine changes peer ID on redeploy, so staging needs persistent identity or dynamic relay discovery before production-like multi-machine Bedrock soak.

Update: persistent Bedrock relay identity on 2026-06-23

  • Staging now uses persistent Bedrock relay machine 1853d9df076d08 with Fly volume vol_rnzk2lxojyn193er; its relay peer ID 12D3KooWH8xrjYnNbBVumsTSUVKYd1e4mREcF1A6ZGKMCogHzKZa was unchanged after machine restart.
  • The connect-java multi-relay record path was exercised again: Paper re-registered codexstage22a with three deterministic relay peers, and Moxy committed endpoint instance 8f494346-5971-438f-b55f-4688505fd5b6 with relayAddrs=3.
  • Verified Robin Bedrock rejoin at 2026-06-23T15:46:14Z: session d8takhnsc8js21pncpbg, selectedTransport=direct, warmPath=warm, connectionStatus=success, and Paper logged RoboFlax2 joined the game at 17:46:15 Europe/Berlin.
  • Fresh Paper list at 17:57:55 Europe/Berlin showed RoboFlax2 still online, so the final observed Bedrock session stayed up at least 11m40s.
  • Remaining caveat is in Geyserlite/Bedrock runtime diagnostics, not this endpoint relay-record code: an earlier session closed after ~145s with a Geyserlite channelInactive raw-datagram dump.
  • Extended soak update: Paper list checks at 18:00:12, 18:03:02, 18:03:25, 18:04:25, 18:05:25, 18:06:25, and 18:07:25 Europe/Berlin all showed RoboFlax2 online; Paper scrollback showed no later RoboFlax2 left after the 17:46:15 join, proving the observed Bedrock session stayed up at least 21m10s. Bedrock machine 1853d9df076d08 stayed on instance 01KVTJ38S40XPDGZD88G75H5ZK with no Fly event after the manual 17:39:03 restart.
  • Final soak extension: a fresh Paper list at 18:10:39 Europe/Berlin still showed RoboFlax2 online, and Paper scrollback showed no later RoboFlax2 left after the 17:46:15 join; latest observed Bedrock hold is at least 24m24s.
  • Fresh Java public-listener check during the Bedrock hold: status ping to connect-proxy-staging.minekube.net:25565 returned packet id 0, version {protocol: 772, name: "26.1.2"}, players 1/512, description Paper, RTT 216.45ms.

@robinbraemer robinbraemer marked this pull request as ready for review June 15, 2026 13:09
@robinbraemer robinbraemer force-pushed the codex/connect-libp2p-native-endpoint branch from db9b158 to 218dbc6 Compare June 15, 2026 23:47
@robinbraemer robinbraemer force-pushed the codex/connect-libp2p-native-endpoint branch from 218dbc6 to 4905296 Compare June 15, 2026 23:50
@robinbraemer

Copy link
Copy Markdown
Member Author

Update: pushed d09e07b to reconnect native libp2p registration after Moxy restarts.\n\nVerification:\n- ./gradlew :core:test --tests '*PeerRegistrationClientTest' --tests '*NativeStatusReporterTest' --no-daemon\n- ./gradlew test shadowJar --no-daemon\n- copied rebuilt Spigot jar into local Paper and verified it re-registered automatically after staging Moxy restart/deploy without restarting Paper\n- staging Java status/login via connect-proxy-staging.fly.dev succeeded over native libp2p after reconnect

@robinbraemer

Copy link
Copy Markdown
Member Author

Update after relay hardening (c02d1c9):

  • Added JVM libp2p circuit relay client support for native endpoint hosts.
  • Added CONNECT_LIBP2P_NATIVE_RELAY_ADDRS; endpoint reserves each relay and advertises /p2p-circuit/p2p/<endpoint-peer-id> addresses.
  • Added an in-process relay test proving a Moxy-like host can open a stream to the endpoint through a relay circuit address.
  • Split stable peer id from per-process endpoint instance id for registration/status records.
  • Native session responder now rejects wrong-endpoint and expired offers before opening a local session.
  • Status reports now refresh every 5s with 15s TTL.
  • README documents the native libp2p env vars.

Fresh local verification:

git diff --check
./gradlew :core:test --no-daemon

Both passed locally on 2026-06-16. GitHub Actions build was still in progress when checked after push.

@robinbraemer

Copy link
Copy Markdown
Member Author

Staging validation after af618ca:

  • Built :spigot:shadowJar and installed the resulting plugin into the local Paper staging endpoint.
  • Restarted Paper with native libp2p relay config:
    • CONNECT_LIBP2P_NATIVE_MOXY_ADDR=/dns4/connect-proxy-staging.fly.dev/tcp/4001/p2p/12D3KooWNXa3WQenRYKVJCHxcadnp3JPcxRALCqk97qpMiqAG1tt
    • CONNECT_LIBP2P_NATIVE_RELAY_ADDRS=/dns4/connect-proxy-staging.fly.dev/tcp/4001/p2p/12D3KooWNXa3WQenRYKVJCHxcadnp3JPcxRALCqk97qpMiqAG1tt
  • Java status through Fly staging passed: mcstatus connect-proxy-staging.minekube.net status, 0/512, ~80ms.
  • Java login probe through Fly staging passed: node /tmp/connect-libp2p-staging-paper/mc-login-probe.cjs connect-proxy-staging.minekube.net 25565.
  • Moxy staging log shows native libp2p session accepted with endpoint instance UUID 2fddead1-e3ed-4d27-a800-7ff6a496f923 and player joined endpoint.
  • Bedrock status ping through Fly staging passed: connect-proxy-staging.minekube.net:19132 OK rtt=76ms name="Minekube" sub="Bedrock cross-play" protocol=26.30.

Local verification run:

  • ./gradlew :core:test --no-daemon
  • ./gradlew :spigot:shadowJar --no-daemon

@robinbraemer

Copy link
Copy Markdown
Member Author

Update after peer-auth review:

  • Native session responder now authorizes incoming session streams against the configured Moxy peer ids from CONNECT_LIBP2P_NATIVE_MOXY_ADDR.
  • Added config/test coverage for extracting the configured Moxy peer id.
  • Downgraded transient native reconnect/status-report failures to warning summaries instead of full ERROR stack traces.

Verification:

Staging used the freshly built Spigot plugin jar and re-registered against Moxy. Public Java login and Bedrock status probes passed through connect-proxy-staging.minekube.net; Moxy logged selectedTransport=relay for the Java login probe.

@robinbraemer

Copy link
Copy Markdown
Member Author

Updated native registration signing in 4771056c:

  • PeerRecordSigningPayload now writes deterministic protobuf bytes via CodedOutputStream#useDeterministicSerialization() instead of the temporary JSON payload.
  • Added a golden hex test vector generated from Moxy's deterministic Go protobuf marshal path.

Fresh local verification:

./gradlew :core:test --no-daemon
# BUILD SUCCESSFUL

./gradlew :spigot:shadowJar --no-daemon
# BUILD SUCCESSFUL

This is the matching endpoint-side change for Moxy PR GeyserMC#265 commit 4a75ee8; both sides need to land/deploy together because native registration signatures are intentionally changing to the spec format.

@robinbraemer

Copy link
Copy Markdown
Member Author

Latest staging evidence for 4771056c:

  • Rebuilt :spigot:shadowJar and deployed the resulting Connect.jar to the local staging Paper server used for the Moxy staging test.
  • The plugin registered native endpoint codexp2p3 successfully with peer 12D3KooWEzZpASrUwA3s8CM3UCDCCYjQzfh91ZyJnxRqaZ9xTi31.
  • Moxy staging, running 4a75ee8, accepted a native libp2p session from that plugin: session d8ohhgji940s21q3691g, endpoint instance 0aedb6a9-31ad-41fe-9f3a-624df2416476, selected transport relay.
  • Java login probe through connect-proxy-staging.minekube.net:25565 completed with login then clean end done.
  • Paper logs show CodexBot joined through Connect and disconnected cleanly.
  • Bedrock RakNet status against connect-proxy-staging.minekube.net:19132 returned OK with MOTD Minekube, sub-MOTD Bedrock cross-play, protocol 26.30.

GitHub Actions for this PR is green at 4771056c (build succeeded). The paired Moxy PR currently has red Actions caused by GitHub account billing/spending limits before any job step starts; local Moxy gates and staging validation passed.

@robinbraemer

Copy link
Copy Markdown
Member Author

Review/staging follow-up after the senior-pass review:

  • Pushed 7fc9a4f8 so native status reports half-close the write side with Stream.closeWrite() instead of resetting the full stream after a one-shot report.
  • The staging symptom before this was repeated Moxy native libp2p status stream failed logs with stream reset; after installing the new jar and filtering logs from 2026-06-16T10:57:00Z, only the expected native relay session/join lines remain.
  • Local verification passed on this head:
    • ./gradlew :core:test --tests 'com.minekube.connect.tunnel.p2p.NativeStatusReporterTest' --no-daemon
    • ./gradlew :core:test :spigot:shadowJar --no-daemon
  • Built and installed spigot/build/libs/connect-spigot.jar into the staging Paper server; SHA-256: 588e67efa6038d3f1a977e945641abc25f24217705866a0109c0041bfa647fda.
  • Runtime validation against staging passed:
    • Paper registered native libp2p for codexp2p3.
    • Java probe node /tmp/connect-libp2p-staging-paper/mc-login-probe.cjs connect-proxy-staging.fly.dev 25565 logged in successfully.
    • Moxy accepted the session via native libp2p relay with endpoint peer 12D3KooWEzZpASrUwA3s8CM3UCDCCYjQzfh91ZyJnxRqaZ9xTi31 and selectedTransport: "relay".

GitHub PR build is green on the latest commit.

@robinbraemer robinbraemer changed the title Add native libp2p endpoint registration Add native libp2p Connect endpoint mode Jun 16, 2026
@robinbraemer robinbraemer changed the title Add native libp2p Connect endpoint mode Add Connect libp2p endpoint transport Jun 19, 2026
@robinbraemer robinbraemer merged commit c2c4f65 into connect Jun 22, 2026
1 check passed
@robinbraemer robinbraemer deleted the codex/connect-libp2p-native-endpoint branch June 22, 2026 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant