diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 0b7711e47..a7a376459 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -69,6 +69,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [evidence] [\#4532](https://github.com/tendermint/tendermint/pull/4532) Handle evidence from light clients (@melekes) - [light] [\#4532](https://github.com/tendermint/tendermint/pull/4532) Submit conflicting headers, if any, to a full node & all witnesses (@melekes) - [rpc] [\#4532](https://github.com/tendermint/tendermint/pull/4923) Support `BlockByHash` query (@fedekunze) +- [rpc] \#4979 Support EXISTS operator in `/tx_search` query (@melekes) - [p2p] \#4981 Expose `SaveAs` func on NodeKey (@melekes) ### IMPROVEMENTS: diff --git a/rpc/swagger/swagger.yaml b/rpc/swagger/swagger.yaml index 700270388..b195ac935 100644 --- a/rpc/swagger/swagger.yaml +++ b/rpc/swagger/swagger.yaml @@ -833,6 +833,10 @@ paths: /tx_search: get: summary: Search for transactions + description: | + Search for transactions w/ their results. + + See /subscribe for the query syntax. operationId: tx_search parameters: - in: query @@ -876,8 +880,6 @@ paths: example: "asc" tags: - Info - description: | - Get list of unconfirmed transactions responses: 200: description: List of unconfirmed transactions diff --git a/state/txindex/kv/kv.go b/state/txindex/kv/kv.go index da672aef5..586120e35 100644 --- a/state/txindex/kv/kv.go +++ b/state/txindex/kv/kv.go @@ -425,6 +425,32 @@ func (txi *TxIndex) match( default: } } + if err := it.Error(); err != nil { + panic(err) + } + + case c.Op == query.OpExists: + // XXX: can't use startKeyBz here because c.Operand is nil + // (e.g. "account.owner//" won't match w/ a single row) + it, err := dbm.IteratePrefix(txi.store, startKey(c.CompositeKey)) + if err != nil { + panic(err) + } + defer it.Close() + + for ; it.Valid(); it.Next() { + tmpHashes[string(it.Value())] = it.Value() + + // Potentially exit early. + select { + case <-ctx.Done(): + break + default: + } + } + if err := it.Error(); err != nil { + panic(err) + } case c.Op == query.OpContains: // XXX: startKey does not apply here. @@ -452,6 +478,9 @@ func (txi *TxIndex) match( default: } } + if err := it.Error(); err != nil { + panic(err) + } default: panic("other operators should be handled already") } @@ -553,6 +582,9 @@ LOOP: default: } } + if err := it.Error(); err != nil { + panic(err) + } if len(tmpHashes) == 0 || firstRun { // Either: diff --git a/state/txindex/kv/kv_test.go b/state/txindex/kv/kv_test.go index 209fa8bae..21b18608c 100644 --- a/state/txindex/kv/kv_test.go +++ b/state/txindex/kv/kv_test.go @@ -117,6 +117,10 @@ func TestTxSearch(t *testing.T) { {"account.owner CONTAINS 'Vlad'", 0}, // search using the wrong key (of numeric type) using CONTAINS {"account.number CONTAINS 'Iv'", 0}, + // search using EXISTS + {"account.number EXISTS", 1}, + // search using EXISTS for non existing key + {"account.date EXISTS", 0}, } ctx := context.Background()