feat(netlayer): extract @metamask/netlayer-libp2p + flip runtime injection (phase 4)#973
Draft
rekmarks wants to merge 8 commits into
Draft
feat(netlayer): extract @metamask/netlayer-libp2p + flip runtime injection (phase 4)#973rekmarks wants to merge 8 commits into
rekmarks wants to merge 8 commits into
Conversation
Move the libp2p netlayer implementation out of @MetaMask/ocap-kernel into a new @metamask/netlayer-libp2p package, with no runtime behavior change. The package exports the browser-default `libp2pNetlayerFactory` (`.`), a Node.js factory with direct QUIC/TCP transports (`./nodejs`), and the circuit-relay server (`./relay`). - Move connection-factory, lp-framing test, multiaddr/network utils, and the provider-only constants into the new package. - Extract the module-private read-error mapper into `error-mapper.ts`, and fold the libp2p `MuxerClosedError`/`Dial`/`Transport`/`NO_RESERVATION` name-sniffing out of `@metamask/kernel-errors` into the provider: the libp2p `dial` now maps raw errors onto neutral kernel-errors so the transport-neutral engine classifies reconnection identically. `isRetryableNetworkError` / `getNetworkErrorCode` are reduced to the neutral subset. - Move the relay server from `@metamask/kernel-utils/libp2p` to `@metamask/netlayer-libp2p/relay`; repoint kernel-cli and e2e consumers. - ocap-kernel keeps a temporary `initTransport` compatibility shim that delegates to the browser factory (never reaching the `./nodejs` subpath, so the extension bundle is unaffected); `directTransports` keeps flowing from `NodejsPlatformServices`. Remove all direct libp2p deps from ocap-kernel and kernel-utils. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Invert control so runtimes inject a `NetlayerRegistry` and callers select an
implementation with a `NetlayerSpecifier` (`{ netlayer, config: Json }`) instead
of the kernel hard-wiring libp2p.
- `PlatformServices.initializeRemoteComms` becomes an options bag
(`{ keySeed, specifier, hooks, incarnationId? }`); `NodejsPlatformServices`
and `PlatformServicesServer`/`Client` are constructed with a
`NetlayerRegistry`. `make-kernel` defaults to `{ libp2p:
nodejsLibp2pNetlayerFactory }` and accepts a `netlayers` override.
- `RemoteCommsOptions` shrinks to the kernel-owned fields plus the specifier;
`remote-comms.ts` injects the persisted hint pool as `config.knownRelays` and
keeps `mnemonic` out of the `Json` config. `DirectTransport` /
`ConnectionFactoryOptions` are removed.
- RPC superstructs (`rpc/platform-services/`, `rpc/kernel-control/`) carry the
specifier with `JsonStruct` config; kernel-cli daemon, extension/omnium
`offscreen.ts`, and `comms-query-string.ts` pass a specifier.
- Remove the `initTransport` re-export and ALL libp2p deps from ocap-kernel;
`packages/ocap-kernel/package.json` now has zero libp2p-family deps.
Deviations from phase-4.md: the endoify-node `@libp2p/webrtc` relocation
(§3.7) is deferred (kept in kernel-shims) — every kernel-node-runtime importer
transitively loads webrtc, so relocating risks silent pre-lockdown failures
across ~7 packages; it is not required for the zero-libp2p gate (ocap-kernel).
The browser `PlatformServicesServer` does not capture `getListenAddresses`
(the client returns `[]` for Node-only direct transport; capturing would be
dead code).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add Unreleased changelog entries (linking #973) for @metamask/netlayer-libp2p (new), ocap-kernel, kernel-errors, kernel-utils, kernel-node-runtime, kernel-browser-runtime, and kernel-cli. Mark Phase 4 done in master.md with a Landed-decisions block, and reconcile phase-5.md against the landed contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Node test helpers and evm-wallet-experiment runners construct
`NodejsPlatformServices` directly (not via `make-kernel`), so they must pass the
now-required `netlayers` registry. Without it, `initializeRemoteComms` threw
`Cannot read properties of undefined (reading 'libp2p')`, failing the
kernel-node-runtime remote-comms/relay e2e suites and the evm-wallet peer-wallet
integration tests.
- `kernel-node-runtime/test/helpers/kernel.ts` and `kernel-test` ctors pass
`{ libp2p: nodejsLibp2pNetlayerFactory }`.
- All `evm-wallet-experiment` runners/scripts/tests do the same; add
`@metamask/netlayer-libp2p` to that package.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pre-injection e2e and integration tests passed libp2p-specific options (relays, directListenAddresses, backoff timings) at the top level of initRemoteComms. After the netlayer-injection flip these fields belong in specifier.config, so they were silently dropped and connections failed. Introduce a libp2pComms test helper that maps the flat shape into the injected RemoteCommsOptions and route all e2e call sites through it (or an inline specifier). Also add explicit tsconfig path mappings for the netlayer-libp2p ./nodejs and ./relay subpaths so vitest resolves them to source rather than dist, keeping a single lockdown-time @libp2p/webrtc instance. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Coverage Report
File Coverage |
Per a user directive, the WebSocket netlayer (phase 5) is deferred and the effort skips straight to phase 6 (cleanup + docs). Mark phase 5 deferred in master.md and adjust the sequence/estimate so phase 6 follows phase 4. Add a prominent deferral banner to phase-5.md. Revise phase-6.md against landed phases 1-4 and the phase 5 deferral: reword every reference to the WebSocket netlayer (package, hub/handshake, kernel-test parameterization, changelog row, README) as future work. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
With phase 5 deferred, reword the endoify/@libp2p/webrtc relocation note in master.md from a "phase-5/6" to a phase-6/future follow-up, and add a dedicated "follow-ups carried from phase 4" section to phase-6.md capturing the four items that now land in phase 6's lap: the review-gated webrtc pre-lockdown relocation, the browser getListenAddresses gap, the libp2pComms test-helper retirement, and the load-bearing tsconfig subpath-mapping rule for netlayer-libp2p. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 4 of the pluggable-netlayer effort (issue #968), stacked on #972 (
rekm/netlayer-3). Two coherent commits: 4a extracts the libp2p implementation into a new package; 4b flips control so runtimes inject a netlayer registry.4a — Extract
@metamask/netlayer-libp2p.(browserlibp2pNetlayerFactory),./nodejs(QUIC/TCPnodejsLibp2pNetlayerFactory, moved fromkernel-node-runtime), and./relay(startRelay, moved fromkernel-utils/libp2p).connection-factory,lp-framing,utils/multiaddr,utils/network, provider-only constants, and extracted the read-error mapper intoerror-mapper.ts.MuxerClosedError/Dial/Transport/NO_RESERVATIONname-sniffing out of@metamask/kernel-errorsinto the provider:connection-factory.dialnow maps raw libp2p errors onto neutral kernel-errors so the transport-neutral engine classifies reconnection identically (behavior-preserving;PERMANENT_FAILURE_ERROR_CODESare Node-code-only).isRetryableNetworkError/getNetworkErrorCodereduced to the neutral subset.relaycommand + e2e consumers repointed; ocap-kernel and kernel-utils lost their direct libp2p deps.4b — Flip runtime injection
PlatformServices.initializeRemoteCommsis now an options bag ({ keySeed, specifier, hooks, incarnationId? });NodejsPlatformServicesandPlatformServicesServer/Clienttake aNetlayerRegistry.make-kerneldefaults to{ libp2p: nodejsLibp2pNetlayerFactory }and accepts anetlayersoverride.RemoteCommsOptionsshrinks to kernel-owned fields +specifier;remote-comms.tsinjects the persisted hint pool asconfig.knownRelaysand keepsmnemonicout of theJsonconfig. RPC superstructs useJsonStructfor config; kernel-cli daemon, extension/omniumoffscreen.ts, andcomms-query-string.tspass a specifier.packages/ocap-kernel/package.jsonnow has zerolibp2p/@libp2p/@chainsafe/@multiformatsdeps (plainmultiformatsstays — neutral base58btc).initTransportexport removed.For reviewer attention
@libp2p/webrtcendoify relocation (phase-4.md §3.7) is DEFERRED. kernel-shims keeps the pre-lockdownimport '@libp2p/webrtc'inendoify-node.js. Rationale: every@metamask/kernel-node-runtimeimporter transitively loads@libp2p/webrtcat module-eval (viamake-kernel→ the nodejs factory →connection-factory), so relocating the pre-lockdown import means repointing ~7 packages' entrypoints/setup files with a silent-lockdown-failure risk if any is missed. It is not required for the zero-libp2p gate (that gate is ocap-kernel only). Flagging for a human decision on whether to pursue it separately.@metamask/netlayer-websocket) is DEFERRED per a user directive: the effort skips from Phase 4 straight to Phase 6 (cleanup + docs). This PR's doc updates reflect that —master.mdmarks Phase 5 deferred and sequences Phase 6 after Phase 4,phase-5.mdcarries a prominent deferral banner, andphase-6.mdis reconciled against landed Phases 1–4 with every WebSocket-netlayer reference reworded as future work.PlatformServicesServerdoes not capturegetListenAddresses(the client returns[]for Node-only direct transport; capturing it would be dead code that fails the unused-private-member lint).Verification
yarn lint:fix,yarn build,yarn test:dev:quietall green (58 turbo tasks).offscreen.jsunchanged (~1,320 kB / 435 kB gzip) — libp2p was already transitively bundled.🤖 Generated with Claude Code