-
Notifications
You must be signed in to change notification settings - Fork 1.1k
fix: use standard peer-record domain and payload type #6230
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
base: master
Are you sure you want to change the base?
Conversation
Add cross-implementation interoperability tests that verify Rust can decode and verify signed peer records created by Go and JavaScript libp2p implementations. Test fixtures: - JavaScript fixture generated using @libp2p/peer-record - Go fixture generated using go-libp2p/core/peer - Both use standard domain 'libp2p-peer-record' and payload type [3, 1] Current behavior: - Tests FAIL with UnexpectedPayloadType error - Rust expects '/libp2p/routing-state-record' [47, 108, ...] - JS/Go provide standard payload type [3, 1] This demonstrates the incompatibility bug that will be fixed in the next commit.
Changes PeerRecord to use the standard libp2p-peer-record constants instead of routing-state-record values, ensuring interoperability with Go and JavaScript implementations. Changes: - PAYLOAD_TYPE: '/libp2p/routing-state-record' -> [0x03, 0x01] - DOMAIN_SEP: 'libp2p-routing-state' -> 'libp2p-peer-record' The payload type [0x03, 0x01] is the multicodec identifier for libp2p-peer-record, as defined in the multicodec table: https://github.com/multiformats/multicodec/blob/master/table.csv This matches the implementations in: - Go: https://github.com/libp2p/go-libp2p/blob/master/core/peer/record.go#L21-L29 - JS: https://github.com/libp2p/js-libp2p/blob/main/packages/peer-record/src/peer-record/consts.ts#L1-L7 BREAKING CHANGE: Existing signed peer records created with Rust libp2p will not be verifiable with this change, as the domain and payload type have changed. However, this fixes interoperability with Go/JS libp2p. Fixes cross-implementation compatibility issue where Rust could not verify signed peer records from Go/JS implementations.
Documents the breaking fix that aligns PeerRecord constants with Go/JS implementations, changing domain to 'libp2p-peer-record' and payload type to [0x03, 0x01] for cross-implementation compatibility. Pull-Request: libp2p#6205.
Bumps libp2p-core from 0.43.1 to 0.44.0 due to breaking change in PeerRecord domain and payload type constants. This is a minor version bump (not patch) because the change breaks compatibility with existing Rust-created peer records. The breaking change: - PAYLOAD_TYPE: '/libp2p/routing-state-record' -> [0x03, 0x01] - DOMAIN_SEP: 'libp2p-routing-state' -> 'libp2p-peer-record' Existing signed peer records created with the old constants will not be verifiable after this change, but the new constants align with Go/JS implementations and fix cross-implementation interoperability. See also: - PR libp2p#6205: The fix implementation - Issue libp2p#6204: Original bug report"
|
The issue here is not only about the domain. Even if we allow the caller to provide a domain string, it’s still not enough — because the failure occurs earlier, due to an invalid payload type (BadPayload(UnexpectedPayloadType)). Right now, the Rust implementation signs a peer record using defaults that do not match the values used in Go, JS, and Python. Those implementations validate against a specific domain and payload type. For example: Go: Py: Because of this, leaving the current Rust function as-is will produce signatures that will not interoperate with other libp2p stacks. It will sign a PeerRecord — but one that other languages will reject. So at minimum, we should either: Remove the existing no-arg function and introduce a new function that requires both domain and payload type explicitly, |
…compatibility
Add optional `peer-record-interop` feature flag to enable standard libp2p
peer-record format for interoperability with Go and JavaScript implementations.
When enabled, uses:
- PAYLOAD_TYPE: [0x03, 0x01] (multicodec identifier)
- DOMAIN_SEP: "libp2p-peer-record"
When disabled (default), maintains backward compatibility with existing
Rust libp2p peer records using legacy constants:
- PAYLOAD_TYPE: "/libp2p/routing-state-record"
- DOMAIN_SEP: "libp2p-routing-state"
The legacy format is marked as deprecated to guide users toward the
standard format in future releases.
Changes:
- Add `peer-record-interop` feature flag to core/Cargo.toml
- Add conditional compilation for PAYLOAD_TYPE and DOMAIN_SEP constants
- Mark legacy constants as deprecated with migration guidance
- Update internal methods to handle both constant types (&[u8] vs &str)
- Gate interop tests to only run with feature enabled
- Update CHANGELOG and add inline documentation
Migration:
Users needing cross-implementation compatibility should add:
`libp2p-core = { version = "0.43.2", features = ["peer-record-interop"] }`
Add `new_interop()` and `from_signed_envelope_interop()` methods to `PeerRecord` for cross-implementation compatibility with Go and JavaScript libp2p implementations. The new methods use the standard libp2p-peer-record format: - Domain: "libp2p-peer-record" - Payload type: [0x03, 0x01] (multicodec identifier) Existing methods (`new()`, `from_signed_envelope()`) continue to use the legacy routing-state-record format for backward compatibility with existing Rust libp2p deployments.
|
After conversation with @jxs we maintain both old version code and provide 2 new '_interop' functions |
Description
Fixes #6204
PAYLOAD_TYPE: "/libp2p/routing-state-record" → [0x03, 0x01]
DOMAIN_SEP: "libp2p-routing-state" → "libp2p-peer-record"
The payload type [0x03, 0x01] is the multicodec identifier for libp2p-peer-record, as defined in:
Multicodec table
This matches the implementations in:
Go libp2p
JS libp2p
PR Recreation Notice
This PR is a recreation of [#6205], which was automatically closed after I mistakenly deleted my fork.
It restores the exact same code and commits as before. No additional changes were made.
Follow-up plan (based on discussion in the original PR)
During the previous review, the suggested direction was:
Introduce this change behind a new Cargo feature, which will be false by default.
Deprecate the current implementation, allowing users to switch gradually.
Give the ecosystem time to migrate, before potentially making the new behavior the default in the future.
Why I’m reopening now
This PR is being reopened and then I added the new optional
peer-record-interopfeature flag.Testing
Added cross-implementation interoperability tests:
core/tests/peer_record_interop.rs - Tests that verify Rust can decode and verify signed peer records from Go and JS
core/tests/fixtures/ - Test fixtures with signed peer records generated by Go and JS implementations
Before the fix, these tests failed with:
BadPayload(UnexpectedPayloadType { expected: [47, 108, ...], got: [3, 1] })
After the fix, all tests pass.
⚠️ BREAKING CHANGE: Existing signed peer records created with Rust libp2p will not be verifiable with this change, as the domain and payload type have changed. However, this is necessary to fix interoperability with Go/JS libp2p implementations.
Breaking Change
Notes & open questions
None - this is a straightforward alignment with the standard used by other libp2p implementations.
Change checklist
[x ] I have performed a self-review of my own code
I have made corresponding changes to the documentation
I have added tests that prove my fix is effective or that my feature works
[x ] A changelog entry has been made in the appropriate crates