Skip to content

Phase B3 (part 2): C++<->TS interop — a C++ node joins a TS-driven DHT#78

Merged
ptesavol merged 1 commit into
mainfrom
claude/ts-interop
Jul 11, 2026
Merged

Phase B3 (part 2): C++<->TS interop — a C++ node joins a TS-driven DHT#78
ptesavol merged 1 commit into
mainfrom
claude/ts-interop

Conversation

@ptesavol

Copy link
Copy Markdown
Collaborator

Summary

Completes the milestone B exit criterion against the real TypeScript implementation: a C++ DhtNode joins a layer-0 DHT whose entry point is @streamr/dht@103.8.0-rc.3 (exactly the TS pin) installed from npm and run in a child node process, over real websockets on 127.0.0.1. Mutual visibility is asserted from both sides.

How the harness works

  • test/ts-interop/entryPoint.js — node driver that starts a TS DhtNode entry point (constructed exactly like the TS Layer0.test.ts entry point at the pin), joins its own DHT, then speaks a line protocol on stdout: DESCRIPTOR <hex> (the protobuf-binary PeerDescriptor — exact wire fidelity, no field mapping) followed by NEIGHBORS <id,...> every 500 ms. region is passed explicitly because TS start() otherwise does a GeoIP/CDN lookup over the real network.

  • test/ts-interop/package.json + lockfile — per the granular-packages direction: the harness depends only on the published npm package at the pin; the TS monorepo checkout is never built. npm ci runs on demand from the test itself when node_modules is absent.

  • test/ts-interop/TsInteropTest.cpp (new streamr-dht-test-ts-interop target) — spawns the driver, reads the descriptor, starts a serverless C++ node with the TS node as entry point, and joins. The serverless start also exercises the B1 connectivity request/response protocol against the TS websocket server for real. Asserts:

    • C++ -> TS: the TS entry point is the C++ node's closest contact and has a live connection,
    • TS -> C++: the TS node reports the C++ node id among its DHT neighbors.

    Node runtime discovery: $STREAMR_TS_INTEROP_NODE, then PATH node if >= 20 (required by the pinned package's dependencies), then the newest ~/.nvm install. Only a missing runtime skips the test; every other failure (npm ci, driver crash, join failure) is a hard failure.

  • CI: actions/setup-node (node 22) added to the validate workflow so all three legs run the interop test.

  • lint: npm-vendored third-party C++ under node_modules excluded from the sweep; TsInteropTest.cpp joins the documented std-type-unification exclusion list (the compiler builds and runs it; clang-format still checks it).

Test results (local, arm64 mac)

Suite Result
ts-interop 6/6 consecutive runs, ~1.7 s each
unit 181/181
integration 43/43 (including SingleLayer1Dht this run)
end-to-end 7/7
lint.sh rc=0

With this, milestone B is complete: C++ nodes interoperate over websocket + WebRTC with each other (part 1, #77) and over websocket with the pinned TS implementation (this PR). Known follow-up (pre-existing, documented in #77): the occasional Layer1ScaleTest.SingleLayer1Dht neighbor-count flake.

🤖 Generated with Claude Code

…dht from npm

Completes the milestone B exit criterion against the real TypeScript
implementation: a C++ DhtNode joins a layer-0 DHT whose entry point is
@streamr/dht 103.8.0-rc.3 (the TS pin) installed from npm and run in a
child node process, over real websockets on 127.0.0.1.

- test/ts-interop/entryPoint.js: node driver that starts a TS DhtNode
  entry point (mirroring the TS Layer0.test.ts construction), prints its
  PeerDescriptor as protobuf-binary hex (exact wire fidelity — the C++
  side parses it with the PeerDescriptor protobuf), then reports its DHT
  neighbor set every 500 ms. region is passed explicitly because without
  it TS start() does a GeoIP/CDN lookup over the real network.
- test/ts-interop/package.json + package-lock.json: the harness depends
  on the granular published npm package at the pin — the TS monorepo
  checkout is never built.
- test/ts-interop/TsInteropTest.cpp: spawns the driver, joins the DHT
  from a serverless C++ node (which also exercises the B1 connectivity
  request/response protocol against the TS server), and asserts mutual
  visibility: the TS entry point is the C++ node's closest contact with
  a live connection, and the TS node lists the C++ node id among its
  neighbors. npm ci runs on demand when node_modules is absent. Only a
  missing node runtime (>= 20, required by the pinned package's
  dependencies) skips the test; all other failures are hard failures.
- validate.yml: actions/setup-node (node 22) before the test step so all
  three CI legs run the interop test.
- lint.sh: exclude npm-vendored third-party C++ sources under
  node_modules from the sweep; TsInteropTest.cpp joins the documented
  std-type-unification exclusion list (compiler builds and runs it,
  clang-format still checks it).

Local: interop 6/6 runs, unit 181/181, integration 43/43, e2e 7/7,
lint rc=0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added ci Pull requests that update Continuous Integration build dht labels Jul 11, 2026
@ptesavol ptesavol merged commit 55fa6d9 into main Jul 11, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Pull requests that update Continuous Integration build dht

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant