feat(network): add local-tx-monitor server agent, align codec with the wire protocol#792
Open
Javieracost wants to merge 3 commits into
Open
feat(network): add local-tx-monitor server agent, align codec with the wire protocol#792Javieracost wants to merge 3 commits into
Javieracost wants to merge 3 commits into
Conversation
Rust 1.97 stable introduces lints that fail the workspace clippy job: - for_kv_map in pallas-validate phase1 (alonzo, babbage, conway, shelley_ma): iterate map keys directly instead of destructuring unused values - useless_borrows_in_formatting in pallas-math tests and pallas-hardano haskell_display: drop redundant references in format arguments Mechanical fixes only, no behavior change. Verified clean under both 1.93 and 1.97 clippy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The local-tx-monitor codec diverged from the authoritative ouroboros-network codec in three ways that made interop with real peers (cardano-node, ogmios) impossible: - MsgAwaitAcquire was guessed as label 4, which does not exist in the spec. The wire shares label 1 with MsgAcquire and peers disambiguate by protocol state (Idle = acquire, Acquired = await re-acquire). The AwaitAcquire variant now encodes as 1; a stateless decode always yields Acquire and agents map it back based on their state. - TxId was modeled as a text string. The wire format is the hard-fork-combinator GenTxId: an era-wrapped [era, hash-bytes] pair. Clients such as ogmios treat the era wrapper as significant and probe every plausible era for the same hash. - MsgGetMeasures (11) / MsgReplyGetMeasures (12), part of the protocol since node-to-client v20, were not modeled at all, so receiving them killed the decode. The client agent is repaired along the way: release() was rejected by its own outbound-state assertion, Release/AwaitAcquire/Done were missing from the assert tables, and await_acquire(), query_measures() and done() are added. The error type is renamed Error -> ClientError, matching the chainsync ClientError/ServerError convention, to make room for the server agent. BREAKING: TxId changes shape and the client error type is renamed. No working code can regress on the wire format: the previous encoding was never accepted by real peers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the server side of the local-tx-monitor miniprotocol, mirroring the localstate server pattern: recv_while_idle / recv_while_acquired drive the session and typed send_* replies cover NextTx, HasTx, GetSizes and GetMeasures. Wire label 1 received in the Acquired state surfaces as ClientQueryRequest::AwaitAcquire. NodeServer now subscribes PROTOCOL_N2C_TX_MONITOR and exposes the agent via txmonitor(). Without the subscription, the multiplexer kills the whole session as soon as a client opens protocol 9 - which ogmios does on every connection, making pallas-based N2C servers (e.g. dolos) unusable behind it. The server accepts GetMeasures regardless of the negotiated handshake version (the spec gates it at v20+); pallas miniprotocol agents are version-agnostic by design, so the server errs on the lenient side. Includes a full client/server pair test over a unix socket exercising acquire, iteration, has-tx, sizes, measures, blocking re-acquire, release and termination. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughChangesThe tx-monitor protocol now supports typed transaction IDs, mempool measures, CBOR request/response messages, client queries, server-side state handling, NodeServer wiring, and an integration test. Separate cleanup changes remove unnecessary formatting references and iterate directly over minted policy keys. Tx-monitor protocol support
Formatting and iteration cleanups
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant NodeClient
participant NodeServer
participant TxMonitorServer
NodeClient->>NodeServer: Connect and open tx-monitor protocol
NodeServer->>TxMonitorServer: Route protocol channel
NodeClient->>TxMonitorServer: Request acquire and mempool queries
TxMonitorServer->>NodeClient: Return transactions, sizes, and measures
NodeClient->>TxMonitorServer: Release and done
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
What
Server-side support for the local-tx-monitor miniprotocol (N2C protocol 9), plus the codec fixes required for it to interoperate with real peers. Three commits, each self-contained:
chore: fix clippy lints for Rust 1.97— unblocks the workspace clippy job on current stable; no functional changes. Happy to split this into its own PR if you'd rather merge it independently.fix(network): align txmonitor codec with the on-the-wire protocol— the existing local-tx-monitor codec diverged from the authoritative ouroboros-network codec in three ways that made interop with cardano-node and ogmios impossible:MsgAwaitAcquirewas guessed as wire label 4, which doesn't exist in the spec. The wire shares label 1 withMsgAcquire; peers disambiguate by protocol state (Idle = acquire, Acquired = await re-acquire). It now encodes as 1, and a stateless decode always yieldsAcquire, which agents map back based on their state.txmonitor::TxId(the type used only by local-tx-monitor messages — not the chain-level transaction id types elsewhere in pallas) was modeled as a text string. The wire format is the hard-fork-combinatorGenTxId: an era-wrapped[era, hash-bytes]pair. Clients such as ogmios treat the era wrapper as significant and probe the same hash under every plausible era.MsgGetMeasures(11) /MsgReplyGetMeasures(12), part of the protocol since node-to-client v20, weren't modeled, so receiving them killed the decode.The client agent is repaired along the way:
release()was rejected by its own outbound-state assertion,Release/AwaitAcquire/Donewere missing from the assert tables, andawait_acquire(),query_measures()anddone()are added. The error type is renamedError→ClientError(matching the chainsyncClientError/ServerErrorconvention) to make room for the server agent.feat(network): add txmonitor server agent and wire it into NodeServer— mirrors the localstate server pattern:recv_while_idle/recv_while_acquireddrive the session and typedsend_*replies cover NextTx, HasTx, GetSizes and GetMeasures. Wire label 1 received in the Acquired state surfaces asClientQueryRequest::AwaitAcquire.NodeServernow subscribesPROTOCOL_N2C_TX_MONITORand exposes the agent viatxmonitor().Why
Any pallas-based N2C server is currently unusable behind ogmios: ogmios opens local-tx-monitor eagerly on every session, and since accepting the N2C handshake claims support for the full protocol set, the unsubscribed protocol makes the multiplexer kill the whole connection. The immediate beneficiary is dolos, whose ouroboros N2C endpoint gains a local-tx-monitor session handler built on this agent — see the companion PR txpipe/dolos#1120.
Breaking changes
txmonitor::TxIdchanges shape (text string → era-wrappedGenTxId). No working code can regress on the wire format: the previous encoding was never accepted by real peers.localtxmonitorclient error type renamedError→ClientError.Testing
One deliberate leniency: the server accepts
GetMeasuresregardless of the negotiated handshake version (the spec gates it at v20+). Pallas miniprotocol agents are version-agnostic by design, so the server errs on the lenient side.Summary by CodeRabbit
New Features
Tests