Skip to content

fix: conform kad-dht interop node to the cross-implementation contract - #265

Merged
adust09 merged 1 commit into
mainfrom
fix/kad-dht-interop-value-convention
Aug 17, 2026
Merged

fix: conform kad-dht interop node to the cross-implementation contract#265
adust09 merged 1 commit into
mainfrom
fix/kad-dht-interop-value-convention

Conversation

@adust09

@adust09 adust09 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

The kad-dht interop node added in #264 was only ever exercised against itself.
Running it against the actual libp2p/unified-testing matrix (py, dotnet, nim)
turned up two defects. Both are in interop/kad-dht-node/Main.hs; the library
is untouched.

1. Value payload did not follow the suite's convention

The provider stored <TEST_KEY>-value and the querier compared for exact
equality. Every other implementation stores hello from <impl> client and
matches on the hello from substring:

impl stores matches
py hello from py client b"hello from" in value
dotnet hello from dotnet client strVal.Contains("hello from")
haskell (before) <TEST_KEY>-value exact equality

py's node carries the comment "Accept any 'hello from' message for
cross-language interop"
, so the substring match is the intended contract.

The DHT itself was working the whole time — a py querier found the haskell
provider and retrieved its record, then rejected the payload:

provider (haskell) | putValue succeeded
querier  (py)      | Test 2 -> Success! Found 1 provider(s)!
querier  (py)      | Test Failed: Expected value containing 'hello from',
                   |              but got b'702199ac-value'

Now stores hello from haskell client and matches on the shared marker.

2. Identify handlers were never registered

No role called registerIdentifyHandlers. dotnet-libp2p awaits
/ipfs/id/1.0.0 on every outbound connection before its dial resolves —
Libp2pPeerFactory.ConnectedTo calls session.DialAsync<IdentifyProtocol>(),
and Peer.DialAsyncCore blocks on session.Connected until that returns — so
a node that does not serve it is undialable from dotnet:

provider (dotnet) | Ctx(1): Session created by dialer for /ip4/.../p2p/12D3KooWFW11...
provider (dotnet) | Unhandled exception. System.TimeoutException: The operation has timed out.
                  |    at Nethermind.Libp2p.Core.LocalPeer.DialAsyncDeduped(...)

This was directional: haskell dialing dotnet worked, dotnet dialing haskell
failed 100% of the time (7/7 cases). Registered in all three roles, since DHT
peers dial each other in every role, not just the bootstrap.

Results

Full local run of the 37 unified-testing matrix tests that involve haskell
(bootstrap x provider x querier over py, dotnet, nim, haskell):

passed
#264 as merged 8 / 37
+ value convention 30 / 37
+ Identify handlers 37 / 37

For reference, the same harness scores 24/27 on the pre-existing py/dotnet/nim
matrix (three dotnet-querier tests fail independently of this change).

Two defects kept the kad-dht interop node from interoperating with the
other implementations in libp2p/unified-testing. Measured against the py,
dotnet and nim nodes, the 37 matrix tests involving haskell went from
8/37 to 37/37 passing.

Value payload: the provider stored "<TEST_KEY>-value" and the querier
compared for exact equality. Every other implementation stores
"hello from <impl> client" and matches on the "hello from" substring, so
haskell records were rejected by py/dotnet/nim queriers and records from
those implementations were rejected by the haskell querier. Store the
conventional payload and match on the shared marker.

Identify: no role registered the Identify handlers. dotnet-libp2p awaits
/ipfs/id/1.0.0 on every outbound connection before its dial resolves
(Libp2pPeerFactory.ConnectedTo calls session.DialAsync<IdentifyProtocol>,
and Peer.DialAsyncCore blocks on session.Connected until it returns), so
a node that does not serve it is undialable from dotnet. Register the
handlers in all three roles.
@adust09
adust09 merged commit 25cf16e into main Aug 17, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant