0.1.7: declare DFLAG_MANDATORY_25_DIGEST + decode dist-header replies

Against real-world OTP 26 peers the v6 handshake "succeeded" but the
first REG_SEND silently dropped on the peer side — peer accepted the
connection then closed the link with no bytes when we tried to call a
registered process. Hit during MPS↔portal wallet RPC smoke test.

Root cause: OTP 25+ requires DFLAG_MANDATORY_25_DIGEST to be present
in our advertised flag set. The digest is the hash of the OTP-25
mandatory flag set; without it the peer's dist driver loses confidence
in the negotiation and drops messages from us without surfacing an
error.

Adds DFLAG_MANDATORY_25_DIGEST to DEFAULT_FLAGS. Also extends
_decode_message to accept both legacy pass-through (0x70 ...) and
dist-header framing (0x83 0x44 0x00 ...) on receive — modern OTP may
send dist-headed messages even when we didn't negotiate
DFLAG_DIST_HDR_ATOM_CACHE. Fragments (0x83 0x45 / 0x83 0x46) still
TODO; we surface a clear ChannelError instead of silent corruption.

Send side still uses pass-through framing — we don't yet implement
the atom-cache encode/decode that DFLAG_DIST_HDR_ATOM_CACHE would
require. Peer routes our pass-through sends without issue.

122/122 tests pass including live integration against a local Erlang
node and the TLS dist suite.
This commit is contained in:
russell@unturf.com 2026-06-17 08:51:09 -04:00
parent 16b33c6a37
commit d86ef8530f
No known key found for this signature in database
4 changed files with 89 additions and 16 deletions

View file

@ -57,7 +57,7 @@ def test_encode_message_with_payload():
def test_decode_rejects_wrong_first_byte():
with pytest.raises(ChannelError, match="pass-through byte"):
with pytest.raises(ChannelError, match="pass-through .0x70. or dist header"):
_decode_message(b"\x00" + encode((1,)))