feat(rpc): add ?topics= filtering to the events stream#518
Conversation
🤖 Kimi Code ReviewThe PR introduces topic-filtered SSE subscriptions with a bitmask-based filter ( Critical: Potential overflow in
self.0 & (1 << topic as u16) != 0If the Suggestion: Add a compile-time assertion or document the invariant: impl TopicSet {
// ...
pub fn contains(self, topic: Topic) -> bool {
let discriminant = topic as u16;
debug_assert!(discriminant < 16, "Topic discriminant overflow");
self.0 & (1 << discriminant) != 0
}
}Alternatively, use Minor: Whitespace handling in topic parsing
list.split(',').map(Topic::from_str).collect()This does not handle whitespace around commas. A request to Suggestion: Trim whitespace: list.split(',').map(str::trim).map(Topic::from_str).collect()Minor: Unbounded string in error variant
Code quality observations
Documentation The divergence from the Beacon API (optional vs mandatory Summary Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Codex Code ReviewNo findings. The PR is narrowly scoped to SSE event delivery and topic parsing in crates/blockchain/src/events.rs and crates/net/rpc/src/events.rs. I did not see correctness, security, or performance regressions in the touched paths. The filtering remains outside consensus execution, so fork choice, attestation validation, justification/finalization, state transition, XMSS, and SSZ logic are unaffected by this change. Verification gap: I could not run the Rust tests in this environment because Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
Greptile SummaryThis PR adds topic filtering to the chain-event SSE endpoint. The main changes are:
Confidence Score: 5/5The latest changes look safe to merge.
|
| Filename | Overview |
|---|---|
| crates/blockchain/src/events.rs | Adds topic parsing, topic bitsets, and filtered event subscriptions while preserving lag errors. |
| crates/net/rpc/src/events.rs | Adds query parsing, validation, filtered SSE streaming, and handler coverage. |
| crates/blockchain/src/lib.rs | Exports the new subscription types and updates existing tests to request all topics. |
| crates/net/rpc/Cargo.toml | Replaces the previous stream dependencies with futures-util. |
| docs/rpc.md | Documents accepted topics, response statuses, and unfiltered defaults. |
Reviews (3): Last reviewed commit: "feat(rpc): add ?topics= filtering to the..." | Re-trigger Greptile
🤖 Claude Code ReviewNot related — that's gossipsub topics, a separate concept. I have enough to write the review now. Review:
|
🤖 Kimi Code ReviewThe PR introduces topic-filtered SSE subscriptions with a bitmask-based filter ( Issues & Suggestions:
Security: No concerns. Input validation correctly rejects unknown topics with 400. Performance: The design trades buffer space for simplicity (filtered events still occupy broadcast slots). This is acceptable per the documented "best-effort" contract, but ensure Consensus Safety: No consensus logic touched; this is purely RPC/telemetry. Verdict: Approvable once the 16-topic limit is documented or guarded (Item 1). The rest are minor nits. Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Codex Code Review
Otherwise this looks reasonable. The PR stays out of fork choice / STF / attestation / SSZ paths, and I did not see any immediate correctness or security regressions in the SSE filtering flow. I couldn’t run the Rust tests in this environment because Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🤖 Claude Code ReviewReview:
|
bb2acdd to
8bc49c0
Compare
c139bc2 to
0b53690
Compare
🤖 Codex Code ReviewFindings:
No consensus, fork-choice, attestation, STF, XMSS, or SSZ logic is touched in this PR. Aside from the two points above, the SSE filtering change looks reasonable and the error-path/tests are in decent shape. I could not run Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🤖 Kimi Code ReviewOverall Assessment: Solid PR. Clean implementation of server-side topic filtering for SSE events with proper error handling and good test coverage. No consensus-critical bugs (this is RPC-layer only). Issues & Suggestions: 1. Potential overflow in Recommendation: Add a compile-time assertion or document the constraint: // In TopicSet impl:
const _: () = assert!(std::mem::variant_count::<Topic>() <= 16, "TopicSet cannot hold more than 16 topics");2. Silent event dropping on serialization failure (crates/net/rpc/src/events.rs:65-71) 3. 4. Allocation on unknown topic error (crates/blockchain/src/events.rs:58) 5. Dependency version consistency (crates/net/rpc/Cargo.toml:29) Code Quality Positives:
Consensus Safety Note: Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Claude Code ReviewI have enough context to complete the review without building. Here's my analysis: Review:
|
Third PR of the chain-events series: server-side topic filtering for GET /lean/v0/events, split out so the previous PR's transport stayed a review of pure axum plumbing. The filter lives in the bus (EventBus::subscribe(TopicSet) returning an EventSubscription with a receive-side skip loop) rather than in the SSE handler, so future non-SSE consumers get filtering for free and the handler stays transport-only. TopicSet is a Copy bitmask: no allocation and one AND per event; lag is surfaced to the caller rather than swallowed by the skip loop. The signature also survives a later per-topic-channel split behind the facade, since callers only ever see subscribe(TopicSet). The handler parses ?topics=head,block via Topic::from_str (the exact inverse of as_str, so names cannot drift) and returns 400 naming the offending value on an unknown topic. A missing or empty parameter defaults to all topics: the Beacon API makes topics required, lean is friendlier here (documented as a divergence in docs/rpc.md). BroadcastStream no longer fits (it wraps a raw receiver, not the filtered subscription), so the bridge is futures-util's stream::unfold around EventSubscription::recv, preserving the Lagged skip + debug-log behavior; tokio-stream and futures-core are dropped for futures-util, already present in the dependency tree. EventSubscription also gains a non-blocking try_recv (same skip loop as recv, over the receiver's try_recv), so the previous PR's lib.rs unit tests (which assert on already-buffered events without spinning up a runtime) can move onto the filtered type after subscribe()'s signature changed here.
0b53690 to
6a11257
Compare
8bc49c0 to
50050d2
Compare
Adds Beacon-API-style server-side filtering to
GET /lean/v0/events:?topics=takes comma-separated topic names, an unknown name returns 400, and a missing or empty parameter subscribes to all topics. The Beacon API makestopicsrequired; defaulting to all is a documented divergence indocs/rpc.md.Filtering lives in the event mechanism rather than the handler:
EventBus::subscribe(TopicSet)returns anEventSubscriptionwhoserecvskips unmatched events (aTopicSetis aCopybitmask, one AND per event), so non-SSE consumers get filtering for free and lag is still surfaced, never swallowed. The handler bridgesrecvto a stream viafutures_util::stream::unfold, replacing thetokio-stream/futures-corepair withfutures-util(already in the lock transitively).Stacked on #517.
Has unit and handler tests (including the 400 path) and passes clippy with
-D warnings.