2.5 KiB
2.5 KiB
erldistpy roadmap
Phases below are sized to land as discrete commits. Each phase ends with
make all green and a real-VM interop test where applicable.
Phase 0 — Repo bones ✅
- LICENSE, README, .gitignore, Makefile, pyproject.toml
- Package skeleton, ruff config matches unfeed
make bootstrap test lintworks on a fresh checkout
Phase 1 — ETF codec ✅
- Subset of External Term Format we need for gen_call to Elixir: small_int, int, big_int, atom_utf8 (legacy atom_ext on decode), binary, nil, list, tuple (small + large), pid (new_pid), ref (newer_reference)
- Booleans and
Noneride as atomstrue/false/nil - Golden vectors decoded from real
term_to_binary/1output - Round-trip tests for the encoder
- Generator script committed at
docs/etf_vectors.erl
Phase 2 — EPMD client ✅
EPMD (Erlang Port Mapper Daemon) maps node names to TCP ports.
- Synchronous TCP client
PORT_PLEASE2_REQ(122) →EpmdInfo(name, port, node_type, protocol, hi_ver, lo_ver, extra)- Returns
Nonecleanly on unregistered node, raisesEpmdErroron socket failures - Tests: recorded byte streams from real EPMD + live integration that
spawns its own
erl -snameand tears it down
Phase 3 — Distribution handshake
- TCP connect to the resolved port
send_name/recv_status/recv_challenge/send_challenge_reply/recv_challenge_ack- Cookie digest via
erlang:phash2-equivalent (md5-based per spec) - Version 6 ("v6") handshake, the modern one Elixir 1.15+ uses
- Tests: handshake against a live Erlang node started in conftest
Phase 4 — Distribution channel
- After handshake, the socket carries control + payload messages framed by a 4-byte length prefix
- Send
SEND_TT/REG_SENDfor outgoing messages - Receive replies, route by ref
- Tick loop for keepalive (60s default per OTP)
Phase 5 — gen_call convenience layer
Node.call(name_or_pid, request, timeout=5.0)→ reply term- Wraps the
$gen_callprotocol used by:gen_server - Idempotency-key handling lives in the caller; we just pass the term
Phase 6 — TLS dist
- Wrap the post-EPMD socket in TLS
- Match
inet_tls_distconfig on the Erlang side (cert + key + ca paths) - Same handshake, just runs inside the TLS tunnel
Phase 7 — unfeed integration
ErlangDistTransportimplementing unfeed'sWalletTransportProtocol- Maps
/v1/health,/v1/address, ... to gen_call requests unfeeddeploys with a config switch:wallet_transport = http | erldist- Cutover after a soak period on staging