rpc: wait for filter ack before returning subscriptions#20536
rpc: wait for filter ack before returning subscriptions#20536JayeTurn wants to merge 2 commits intoerigontech:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses a race in log/receipt subscription setup by ensuring client-side filter updates only complete after the server has applied them, preventing missed notifications (and removing a workaround wait in TestEthSubscribeReceipts).
Changes:
- Add per-stream “filter applied” acknowledgements for logs and receipts filter updates on the privateapi bidi streams.
- Make
rpc/rpchelperwait for these applied acknowledgements before returning from filter update calls. - Update/extend tests to validate the applied-ack behavior and remove the
Eventuallywait in the JSON-RPC receipts subscription test.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| rpc/rpchelper/filters.go | Adds applied-ack waiting, pending-update handling, and sentinel-ack detection for logs/receipts. |
| rpc/rpchelper/filters_test.go | Adds a new unit test asserting filter updates block until applied-ack is observed. |
| rpc/jsonrpc/eth_subscribe_test.go | Removes the Eventually workaround wait now that subscriptions should be race-free. |
| node/privateapi/logsfilter.go | Sends a sentinel “logs filter applied” reply after each received filter update. |
| node/privateapi/logsfilter_test.go | Verifies server sends one applied-ack per filter update. |
| node/privateapi/receiptsfilter.go | Sends a sentinel “receipts filter applied” reply after each received filter update. |
| node/privateapi/receiptsfilter_test.go | Verifies server sends one applied-ack per filter update. |
| cmd/rpcdaemon/rpcservices/eth_backend.go | Adds SubscribeLogsOnReady and makes onReady hooks async to avoid blocking subscription receive loops. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| drainFilterAppliedAck(ackCh) | ||
| if err := send(); err != nil { | ||
| return err | ||
| } | ||
|
|
There was a problem hiding this comment.
waitForFilterUpdateApplied can misattribute a late ack from a previous update to a subsequent update after a timeout (e.g., update #1 times out, update #2 sends, then ack #1 arrives and unblocks update #2 even if it isn't applied yet). To avoid incorrect readiness, treat an ack timeout as a broken stream (clear the requestor / force a resubscribe) or add a per-update identifier to the ack so it can be matched to the correct request.
Summary
Eventuallywait fromTestEthSubscribeReceiptsRoot cause
SubscribeLogsandSubscribeReceiptsreturned after enqueueing the server-side filter update, not after the server had actually applied it. If blocks were inserted in that window, the first receipts or logs could be published before the corresponding server filter became active, which silently dropped notifications and madeTestEthSubscribeReceiptsflaky.Fix
node/privateapi/logsfilter.goandnode/privateapi/receiptsfilter.goafter each filter update is appliedrpc/rpchelper/filters.gowait for that acknowledgment before completing the local filter updateApiBackendsignature unchanged by using aRemoteBackend-specific ready hook for the logs startup pathTest plan
go test node/privateapi/logsfilter.go node/privateapi/logsfilter_test.gogo test node/privateapi/logsfilter.go node/privateapi/receiptsfilter.go node/privateapi/receiptsfilter_test.goGOPROXY=https://goproxy.cn,direct GOSUMDB=sum.golang.google.cn go test ./rpc/rpchelper -run '^TestFilters_FilterUpdateWaitsForAppliedAck$'GOPROXY=https://goproxy.cn,direct GOSUMDB=sum.golang.google.cn go test ./cmd/rpcdaemon/rpcservices -run '^$'GOPROXY=https://goproxy.cn,direct GOSUMDB=sum.golang.google.cn go test ./rpc/jsonrpc -run '^TestEthSubscribeReceipts$'