Skip to content

methods: fix getEvents missing events on multi-filter requests#832

Open
urvisavla wants to merge 1 commit into
stellar:mainfrom
urvisavla:fix-getevents-filter-domination
Open

methods: fix getEvents missing events on multi-filter requests#832
urvisavla wants to merge 1 commit into
stellar:mainfrom
urvisavla:fix-getevents-filter-domination

Conversation

@urvisavla

Copy link
Copy Markdown
Contributor

Problem

getEvents filters are OR-ed together: an event should be returned if it matches any filter. Within a single filter, an empty contractIds or type field means that filter matches any contract or any event type.

The handler pushes a combined prefilter down to SQL before applying exact per-filter matching in memory. For correctness the prefilter must be a superset of what the filters accept, but combineContractIDs and combineEventTypes built it from only the explicitly listed values. When one filter listed values and another left the field empty, the empty filter's "match any" semantics were lost, and the SQL prefilter excluded rows the in-memory pass never got to see.

Example

{
  "filters": [
    // filter 1: counter events from contract A
    {
      "contractIds": ["CCONTRACT_A..."],
      "topics": [["<counter symbol>"]]
    },

    // filter 2: transfer events from ANY contract
    {
      "topics": [["<transfer symbol>"]]
    }
  ]
}

Filter 2 should match transfer events from any contract. Instead the query ran with contract_id IN ('CONTRACT_A'), so transfer events from every other contract were silently missing from the response. The same happened with event types: {"type": "system"} in one filter suppressed the contract-type events matched by other filters.

Notably, combineTopics already handles this case correctly for topics; the contract ID and event type paths were missing the same rule.

Fix

Apply the rule combineTopics already uses: if any filter leaves a dimension unconstrained, drop that dimension's SQL restriction entirely. Exact filter semantics are still enforced by the existing in-memory request.Matches pass; the SQL prefilter goes back to being a pure narrowing optimization.

Testing

  • Unit tests for combineContractIDs and combineEventTypes covering union/dedup, the unconstrained-filter case, no filters, and invalid input.
  • Two end-to-end regression tests through the handler and a real DB (one per dimension) that fail without this fix.

🤖 Generated with Claude Code

…lters

getEvents filters are OR-ed together, and within a filter an empty
contractIds or type field means "match any". But combineContractIDs and
combineEventTypes unioned only the explicitly-listed values into the SQL
prefilter, so a request like

  {"filters": [
    {"contractIds": ["CA..."]},
    {"topics": [["<transfer>"]]}
  ]}

restricted the DB scan to contract_id IN (CA...), silently dropping
events from other contracts that the second filter should match. The
same applied to event types.

Fix both the same way combineTopics already handles this: if any filter
leaves the dimension unconstrained, drop that DB-level restriction
entirely. The in-memory request.Matches pass still enforces the exact
per-filter semantics; the prefilter is only ever a superset again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 2, 2026 09:06
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes getEvents correctness when multiple OR-ed filters are provided and one filter leaves contractIds or type unconstrained (“match any”), by ensuring the SQL prefilter remains a superset of per-filter semantics (with final exact matching still enforced in-memory via request.Matches).

Changes:

  • Drop the DB-level contract_id restriction when any filter has empty contractIds.
  • Drop the DB-level event_type restriction when any filter has empty type.
  • Add unit tests for the combine helpers plus end-to-end regression tests exercising the handler against a real DB.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
cmd/stellar-rpc/internal/methods/get_events.go Adjusts contract ID / event type prefilter combination so “match any” filters don’t get starved by other filters’ SQL restrictions.
cmd/stellar-rpc/internal/methods/get_events_test.go Adds focused unit tests for the combination helpers and regression tests proving multi-filter OR semantics through the handler+DB.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cmd/stellar-rpc/internal/methods/get_events.go
@urvisavla urvisavla requested a review from a team July 2, 2026 18:14

@tamirms tamirms left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good! we should include this in the changelog though

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.

3 participants