fix(relay): stop overcounting NIP-45 COUNT for non-pushable filter constraints - #3437
Closed
1nderboi wants to merge 1 commit into
Closed
fix(relay): stop overcounting NIP-45 COUNT for non-pushable filter constraints#34371nderboi wants to merge 1 commit into
1nderboi wants to merge 1 commit into
Conversation
…nstraints filter_fully_pushable() let several constraints through that filter_to_query_params() silently drops instead of pushing as SQL predicates, causing the fast COUNT path to overcount: - A present-but-empty constraint (authors: [], ids: [], or any generic tag with zero values) matches nothing under filters_match, but the query builder just omits it rather than emitting a match-nothing predicate. - A single #h value that isn't a channel UUID (e.g. a bare NIP-29 group id) was treated as pushable, but only UUID-valued #h is pushed as channel_id — a non-UUID value needs post-filtering since events can legitimately carry it as a literal tag. - Any other generic tag (#t, #a, etc.) with a non-empty value list was allowed through when it should always require post-filtering. Reject all of these so COUNT falls back to the exact post-filtered path instead of returning an inflated count. Added unit tests for: UUID vs non-UUID single #h, multi-#h, empty authors/ids/generic-tag constraints, non-empty #t, and the plain kind+author baseline that should stay pushable. Note: could not run `cargo test`/`cargo check` to completion locally — this machine's shared disk repeatedly hit ENOSPC mid-build (0 bytes free at one point) even after cleaning target/ dirs; the buzz-relay dependency tree alone exceeds available headroom. Verified via cargo fmt --check (clean) and manual trace of filter_fully_pushable against filters_match/filter_to_query_params. Please have CI confirm cargo test passes. Signed-off-by: 1nderboi <201919958+1nderboi@users.noreply.github.com>
Author
|
Closing in favor of #3374, which fixes the identical bug (filter_fully_pushable letting a non-UUID single #h and any present-but-empty constraint through to the fast COUNT path) the same way, was opened first, and additionally has an e2e wire-level regression test against a real relay (test_count_unpushable_filters_do_not_count_all_channels) on top of unit tests — stronger coverage than this PR's unit-tests-only approach. For the record: locally confirmed this branch's fix works too — cargo test -p buzz-relay --lib req:: → 51 passed, 0 failed — but no need for two competing fixes on the same issue. Thanks @beardthelion for #3374. |
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.
Summary
Fixes #3373.
filter_fully_pushable()was letting several filter shapes through to the fast SQLCOUNTpath thatfilter_to_query_params()actually drops instead of pushing as predicates — causingCOUNTto overcount:authors: [],ids: [], or any generic tag with zero values) matches nothing underfilters_match, but the query builder just omits it rather than emitting a match-nothing predicate.#hvalue that isn't a channel UUID (e.g. a bare NIP-29 group id) was treated as pushable, but only UUID-valued#his pushed aschannel_id— a non-UUID value needs post-filtering since events can legitimately carry it as a literal tag.#t,#a, etc.) with a non-empty value list was allowed through when it should always require post-filtering.All three now correctly fall back to the exact post-filtered COUNT path.
Changes
crates/buzz-relay/src/handlers/req.rs: reject emptyauthors/ids/generic-tag constraints, reject non-UUID single#h, reject any non-empty non-h/p/d/egeneric tag.#h, multi-#h, empty authors/ids/generic-tag constraints, non-empty#t, and the plain kind+author baseline that should stay pushable.Test plan
cargo fmt -p buzz-relay --check— cleanfilter_fully_pushableagainstfilters_match/filter_to_query_paramsfor each new casecargo test -p buzz-relay— could not run to completion locally. This shared dev machine's disk repeatedly hit ENOSPC mid-build (down to 0 bytes free at one point) even aftercargo clean-ing target dirs; thebuzz-relaydependency tree (aws-lc-sys, sqlx-postgres, opentelemetry_sdk, mesh-llm-native-runtime) alone exceeds available local headroom. Requesting CI run the full suite including the new tests inreq.rs'smod tests.🤖 Generated with Claude Code