mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-10 18:16:07 +00:00
indexer: remove index filtering (#5006)
Co-authored-by: Anton Kaliaev <anton.kalyaev@gmail.com>
This commit is contained in:
@@ -52,6 +52,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
- [types] \#4852 Vote & Proposal `SignBytes` is now func `VoteSignBytes` & `ProposalSignBytes`
|
||||
- [privval] \#4985 `privval` reactor migration to Protobuf encoding
|
||||
- [evidence] \#4949 `evidence` reactor migration to Protobuf encoding
|
||||
- [indexer] \#5006 Tx indexer now relies on the application to tell it what to index. `tx.height` & `tx.hash` will always be indexed when using the `kv` indexer.
|
||||
- [proto] \#5025 All proto files have been moved to `/proto` directory.
|
||||
- Using the recommended the file layout from buf, [see here for more info](https://buf.build/docs/lint-checkers#file_layout)
|
||||
- [types] \#5029 Rename all values from `PartsHeader` to `PartSetHeader` to have consistency
|
||||
|
||||
+21
-3
@@ -38,10 +38,28 @@ validator and ABCI
|
||||
built from `ResponseDeliverTx(Code, Data)` responses, became the root hash of a
|
||||
Merkle tree built from:
|
||||
|
||||
- `BeginBlock#Events`;
|
||||
- root hash of a Merkle tree built from `ResponseDeliverTx(Code, Data,
|
||||
- `BeginBlock#Events`;
|
||||
- root hash of a Merkle tree built from `ResponseDeliverTx(Code, Data,
|
||||
GasWanted, GasUsed, Events)` responses;
|
||||
- `BeginBlock#Events`.
|
||||
- `BeginBlock#Events`.
|
||||
|
||||
### Tx Indexing
|
||||
|
||||
- Tendermint will now rely on the application entirely to tell it what txs to index. This means that in the `config.toml`,
|
||||
generated by Tendermint, there will not be a way to specify which txs to index. `tx.height` & `tx.hash` will always be indexed when using the `kv` indexer.
|
||||
The application will need to decide if they would like to allow the node operator to decide what to index or if it will enable
|
||||
indexing for all txs. Application's can notify Tendermint to index a specific tx by setting `Index: bool` to true in the Event Attribute.
|
||||
|
||||
```go
|
||||
[]types.Event{
|
||||
{
|
||||
Type: "app",
|
||||
Attributes: []types.EventAttribute{
|
||||
{Key: []byte("creator"), Value: []byte("Cosmoshi Netowoko"), Index: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Protobuf
|
||||
|
||||
|
||||
@@ -99,8 +99,8 @@ func (app *Application) DeliverTx(req types.RequestDeliverTx) types.ResponseDeli
|
||||
{
|
||||
Type: "app",
|
||||
Attributes: []types.EventAttribute{
|
||||
{Key: []byte("creator"), Value: []byte("Cosmoshi Netowoko")},
|
||||
{Key: []byte("key"), Value: key},
|
||||
{Key: []byte("creator"), Value: []byte("Cosmoshi Netowoko"), Index: true},
|
||||
{Key: []byte("key"), Value: key, Index: true},
|
||||
{Key: []byte("index_key"), Value: []byte("index is working"), Index: true},
|
||||
{Key: []byte("noindex_key"), Value: []byte("index is working"), Index: false},
|
||||
},
|
||||
|
||||
+1
-20
@@ -964,31 +964,12 @@ type TxIndexConfig struct {
|
||||
// 2) "kv" (default) - the simplest possible indexer,
|
||||
// backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
Indexer string `mapstructure:"indexer"`
|
||||
|
||||
// Comma-separated list of compositeKeys to index (by default the only key is "tx.hash")
|
||||
//
|
||||
// You can also index transactions by height by adding "tx.height" key here.
|
||||
//
|
||||
// It's recommended to index only a subset of keys due to possible memory
|
||||
// bloat. This is, of course, depends on the indexer's DB and the volume of
|
||||
// transactions.
|
||||
IndexKeys string `mapstructure:"index_keys"`
|
||||
|
||||
// When set to true, tells indexer to index all compositeKeys (predefined keys:
|
||||
// "tx.hash", "tx.height" and all keys from DeliverTx responses).
|
||||
//
|
||||
// Note this may be not desirable (see the comment above). IndexKeys has a
|
||||
// precedence over IndexAllKeys (i.e. when given both, IndexKeys will be
|
||||
// indexed).
|
||||
IndexAllKeys bool `mapstructure:"index_all_keys"`
|
||||
}
|
||||
|
||||
// DefaultTxIndexConfig returns a default configuration for the transaction indexer.
|
||||
func DefaultTxIndexConfig() *TxIndexConfig {
|
||||
return &TxIndexConfig{
|
||||
Indexer: "kv",
|
||||
IndexKeys: "",
|
||||
IndexAllKeys: false,
|
||||
Indexer: "kv",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-22
@@ -395,34 +395,16 @@ peer_query_maj23_sleep_duration = "{{ .Consensus.PeerQueryMaj23SleepDuration }}"
|
||||
[tx_index]
|
||||
|
||||
# What indexer to use for transactions
|
||||
#
|
||||
# The application will set which txs to index. In some cases a node operator will be able
|
||||
# to decide which txs to index based on configuration set in the application.
|
||||
#
|
||||
# Options:
|
||||
# 1) "null"
|
||||
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
# - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed.
|
||||
indexer = "{{ .TxIndex.Indexer }}"
|
||||
|
||||
# Comma-separated list of compositeKeys to index (by default the only key is "tx.hash")
|
||||
# Remember that Event has the following structure: type.key
|
||||
# type: [
|
||||
# key: value,
|
||||
# ...
|
||||
# ]
|
||||
#
|
||||
# You can also index transactions by height by adding "tx.height" key here.
|
||||
#
|
||||
# It's recommended to index only a subset of keys due to possible memory
|
||||
# bloat. This is, of course, depends on the indexer's DB and the volume of
|
||||
# transactions.
|
||||
index_keys = "{{ .TxIndex.IndexKeys }}"
|
||||
|
||||
# When set to true, tells indexer to index all compositeKeys (predefined keys:
|
||||
# "tx.hash", "tx.height" and all keys from DeliverTx responses).
|
||||
#
|
||||
# Note this may be not desirable (see the comment above). IndexKeys has a
|
||||
# precedence over IndexAllKeys (i.e. when given both, IndexKeys will be
|
||||
# indexed).
|
||||
index_all_keys = {{ .TxIndex.IndexAllKeys }}
|
||||
|
||||
#######################################################
|
||||
### Instrumentation Configuration Options ###
|
||||
#######################################################
|
||||
|
||||
@@ -39,23 +39,6 @@ Let's take a look at the `[tx_index]` config section:
|
||||
# 1) "null"
|
||||
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
indexer = "kv"
|
||||
|
||||
# Comma-separated list of composite keys to index (by default the only key is "tx.hash")
|
||||
#
|
||||
# You can also index transactions by height by adding "tx.height" key here.
|
||||
#
|
||||
# It's recommended to index only a subset of keys due to possible memory
|
||||
# bloat. This is, of course, depends on the indexer's DB and the volume of
|
||||
# transactions.
|
||||
index_keys = ""
|
||||
|
||||
# When set to true, tells indexer to index all compositeKeys (predefined keys:
|
||||
# "tx.hash", "tx.height" and all keys from DeliverTx responses).
|
||||
#
|
||||
# Note this may be not desirable (see the comment above). Indexkeys has a
|
||||
# precedence over IndexAllKeys (i.e. when given both, IndexKeys will be
|
||||
# indexed).
|
||||
index_all_keys = false
|
||||
```
|
||||
|
||||
By default, Tendermint will index all transactions by their respective
|
||||
@@ -64,7 +47,9 @@ more options in the future (e.g., PostgreSQL indexer).
|
||||
|
||||
## Adding Events
|
||||
|
||||
In your application's `DeliverTx` method, add the `Events` field with pairs of
|
||||
|
||||
Applications are free to define which events to index. Tendermint does not expose functionality to define
|
||||
which events to index and which to ignore. In your application's `DeliverTx` method, add the `Events` field with pairs of
|
||||
UTF-8 encoded strings (e.g. "transfer.sender": "Bob", "transfer.recipient": "Alice",
|
||||
"transfer.balance": "100").
|
||||
|
||||
@@ -77,9 +62,9 @@ func (app *KVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.Resul
|
||||
{
|
||||
Type: "transfer",
|
||||
Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("sender"), Value: []byte("Bob")},
|
||||
{Key: []byte("recipient"), Value: []byte("Alice")},
|
||||
{Key: []byte("balance"), Value: []byte("100")},
|
||||
{Key: []byte("sender"), Value: []byte("Bob"), Index: true},
|
||||
{Key: []byte("recipient"), Value: []byte("Alice"), Index: true},
|
||||
{Key: []byte("balance"), Value: []byte("100"), Index: true},
|
||||
{Key: []byte("note"), Value: []byte("nothing"), Index: true},
|
||||
},
|
||||
},
|
||||
@@ -88,19 +73,7 @@ func (app *KVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.Resul
|
||||
}
|
||||
```
|
||||
|
||||
If you want Tendermint to only index transactions by "transfer.sender" event type,
|
||||
in the config set `tx_index.index_tags="transfer.sender"`. If you to index all events,
|
||||
set `index_all_tags=true`
|
||||
|
||||
Note, there are a few predefined event types:
|
||||
|
||||
- `tx.hash` (transaction's hash)
|
||||
- `tx.height` (height of the block transaction was committed in)
|
||||
|
||||
Tendermint will throw a warning if you try to use any of the above keys.
|
||||
|
||||
The index will be added if the `Index` field of attribute is set to true. In above example, querying
|
||||
using `transfer.note` will work.
|
||||
The index will be added if the `Index` field of attribute is set to true. In above example, all events will be indexed.
|
||||
|
||||
## Querying Transactions
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@@ -246,6 +247,7 @@ github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
|
||||
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
||||
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
@@ -460,6 +462,7 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
|
||||
+1
-8
@@ -248,14 +248,7 @@ func createAndStartIndexerService(config *cfg.Config, dbProvider DBProvider,
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
switch {
|
||||
case config.TxIndex.IndexKeys != "":
|
||||
txIndexer = kv.NewTxIndex(store, kv.IndexEvents(splitAndTrimEmpty(config.TxIndex.IndexKeys, ",", " ")))
|
||||
case config.TxIndex.IndexAllKeys:
|
||||
txIndexer = kv.NewTxIndex(store, kv.IndexAllEvents())
|
||||
default:
|
||||
txIndexer = kv.NewTxIndex(store)
|
||||
}
|
||||
txIndexer = kv.NewTxIndex(store)
|
||||
default:
|
||||
txIndexer = &null.TxIndex{}
|
||||
}
|
||||
|
||||
+11
-17
@@ -464,12 +464,14 @@ func TestTxSearchWithTimeout(t *testing.T) {
|
||||
// Get a client with a time-out of 10 secs.
|
||||
timeoutClient := getHTTPClientWithTimeout(10)
|
||||
|
||||
_, _, tx := MakeTxKV()
|
||||
_, err := timeoutClient.BroadcastTxCommit(tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// query using a compositeKey (see kvstore application)
|
||||
result, err := timeoutClient.TxSearch("app.creator='Cosmoshi Netowoko'", false, nil, nil, "asc")
|
||||
require.Nil(t, err)
|
||||
if len(result.Txs) == 0 {
|
||||
t.Fatal("expected a lot of transactions")
|
||||
}
|
||||
require.Greater(t, len(result.Txs), 0, "expected a lot of transactions")
|
||||
}
|
||||
|
||||
func TestTxSearch(t *testing.T) {
|
||||
@@ -526,30 +528,22 @@ func TestTxSearch(t *testing.T) {
|
||||
// query using a compositeKey (see kvstore application)
|
||||
result, err = c.TxSearch("app.creator='Cosmoshi Netowoko'", false, nil, nil, "asc")
|
||||
require.Nil(t, err)
|
||||
if len(result.Txs) == 0 {
|
||||
t.Fatal("expected a lot of transactions")
|
||||
}
|
||||
require.Greater(t, len(result.Txs), 0, "expected a lot of transactions")
|
||||
|
||||
// query using an index key
|
||||
result, err = c.TxSearch("app.index_key='index is working'", false, nil, nil, "asc")
|
||||
require.Nil(t, err)
|
||||
if len(result.Txs) == 0 {
|
||||
t.Fatal("expected a lot of transactions")
|
||||
}
|
||||
require.Greater(t, len(result.Txs), 0, "expected a lot of transactions")
|
||||
|
||||
// query using an noindex key
|
||||
result, err = c.TxSearch("app.noindex_key='index is working'", false, nil, nil, "asc")
|
||||
require.Nil(t, err)
|
||||
if len(result.Txs) != 0 {
|
||||
t.Fatal("expected no transaction")
|
||||
}
|
||||
require.Equal(t, len(result.Txs), 0, "expected a lot of transactions")
|
||||
|
||||
// query using a compositeKey (see kvstore application) and height
|
||||
result, err = c.TxSearch("app.creator='Cosmoshi Netowoko' AND tx.height<10000", true, nil, nil, "asc")
|
||||
require.Nil(t, err)
|
||||
if len(result.Txs) == 0 {
|
||||
t.Fatal("expected a lot of transactions")
|
||||
}
|
||||
require.Greater(t, len(result.Txs), 0, "expected a lot of transactions")
|
||||
|
||||
// query a non existing tx with page 1 and txsPerPage 1
|
||||
perPage := 1
|
||||
@@ -571,7 +565,6 @@ func TestTxSearch(t *testing.T) {
|
||||
require.GreaterOrEqual(t, result.Txs[k].Height, result.Txs[k+1].Height)
|
||||
require.GreaterOrEqual(t, result.Txs[k].Index, result.Txs[k+1].Index)
|
||||
}
|
||||
|
||||
// check pagination
|
||||
perPage = 3
|
||||
var (
|
||||
@@ -579,9 +572,10 @@ func TestTxSearch(t *testing.T) {
|
||||
maxHeight int64
|
||||
pages = int(math.Ceil(float64(txCount) / float64(perPage)))
|
||||
)
|
||||
|
||||
for page := 1; page <= pages; page++ {
|
||||
page := page
|
||||
result, err = c.TxSearch("tx.height >= 1", false, &page, &perPage, "asc")
|
||||
result, err := c.TxSearch("tx.height >= 1", false, &page, &perPage, "asc")
|
||||
require.NoError(t, err)
|
||||
if page < pages {
|
||||
require.Len(t, result.Txs, perPage)
|
||||
|
||||
@@ -99,7 +99,6 @@ func createConfig() *cfg.Config {
|
||||
c.RPC.ListenAddress = rpc
|
||||
c.RPC.CORSAllowedOrigins = []string{"https://tendermint.com/"}
|
||||
c.RPC.GRPCListenAddress = grpc
|
||||
c.TxIndex.IndexKeys = "app.creator,tx.height" // see kvstore application
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ func TestIndexerServiceIndexesBlocks(t *testing.T) {
|
||||
|
||||
// tx indexer
|
||||
store := db.NewMemDB()
|
||||
txIndexer := kv.NewTxIndex(store, kv.IndexAllEvents())
|
||||
txIndexer := kv.NewTxIndex(store)
|
||||
|
||||
service := txindex.NewIndexerService(txIndexer, eventBus)
|
||||
service.SetLogger(log.TestingLogger())
|
||||
|
||||
+16
-36
@@ -14,7 +14,6 @@ import (
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/pubsub/query"
|
||||
tmstring "github.com/tendermint/tendermint/libs/strings"
|
||||
"github.com/tendermint/tendermint/state/txindex"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
@@ -27,31 +26,13 @@ var _ txindex.TxIndexer = (*TxIndex)(nil)
|
||||
|
||||
// TxIndex is the simplest possible indexer, backed by key-value storage (levelDB).
|
||||
type TxIndex struct {
|
||||
store dbm.DB
|
||||
compositeKeysToIndex []string
|
||||
indexAllEvents bool
|
||||
store dbm.DB
|
||||
}
|
||||
|
||||
// NewTxIndex creates new KV indexer.
|
||||
func NewTxIndex(store dbm.DB, options ...func(*TxIndex)) *TxIndex {
|
||||
txi := &TxIndex{store: store, compositeKeysToIndex: make([]string, 0), indexAllEvents: false}
|
||||
for _, o := range options {
|
||||
o(txi)
|
||||
}
|
||||
return txi
|
||||
}
|
||||
|
||||
// IndexEvents is an option for setting which composite keys to index.
|
||||
func IndexEvents(compositeKeys []string) func(*TxIndex) {
|
||||
return func(txi *TxIndex) {
|
||||
txi.compositeKeysToIndex = compositeKeys
|
||||
}
|
||||
}
|
||||
|
||||
// IndexAllEvents is an option for indexing all events.
|
||||
func IndexAllEvents() func(*TxIndex) {
|
||||
return func(txi *TxIndex) {
|
||||
txi.indexAllEvents = true
|
||||
func NewTxIndex(store dbm.DB) *TxIndex {
|
||||
return &TxIndex{
|
||||
store: store,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,16 +74,14 @@ func (txi *TxIndex) AddBatch(b *txindex.Batch) error {
|
||||
// index tx by events
|
||||
txi.indexEvents(result, hash, storeBatch)
|
||||
|
||||
// index tx by height
|
||||
if txi.indexAllEvents || tmstring.StringInSlice(types.TxHeightKey, txi.compositeKeysToIndex) {
|
||||
storeBatch.Set(keyForHeight(result), hash)
|
||||
}
|
||||
// index by height (always)
|
||||
storeBatch.Set(keyForHeight(result), hash)
|
||||
|
||||
// index tx by hash
|
||||
rawBytes, err := proto.Marshal(result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// index by hash (always)
|
||||
storeBatch.Set(hash, rawBytes)
|
||||
}
|
||||
|
||||
@@ -123,24 +102,22 @@ func (txi *TxIndex) Index(result *abci.TxResult) error {
|
||||
// index tx by events
|
||||
txi.indexEvents(result, hash, b)
|
||||
|
||||
// index tx by height
|
||||
if txi.indexAllEvents || tmstring.StringInSlice(types.TxHeightKey, txi.compositeKeysToIndex) {
|
||||
b.Set(keyForHeight(result), hash)
|
||||
}
|
||||
// index by height (always)
|
||||
b.Set(keyForHeight(result), hash)
|
||||
|
||||
// index tx by hash
|
||||
rawBytes, err := proto.Marshal(result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// index by hash (always)
|
||||
b.Set(hash, rawBytes)
|
||||
|
||||
b.WriteSync()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (txi *TxIndex) indexEvents(result *abci.TxResult, hash []byte, store dbm.SetDeleter) {
|
||||
func (txi *TxIndex) indexEvents(result *abci.TxResult, hash []byte, store dbm.SetDeleter) error {
|
||||
for _, event := range result.Result.Events {
|
||||
// only index events with a non-empty type
|
||||
if len(event.Type) == 0 {
|
||||
@@ -152,12 +129,15 @@ func (txi *TxIndex) indexEvents(result *abci.TxResult, hash []byte, store dbm.Se
|
||||
continue
|
||||
}
|
||||
|
||||
// index if `index: true` is set
|
||||
compositeTag := fmt.Sprintf("%s.%s", event.Type, string(attr.Key))
|
||||
if txi.indexAllEvents || tmstring.StringInSlice(compositeTag, txi.compositeKeysToIndex) || attr.GetIndex() {
|
||||
if attr.GetIndex() {
|
||||
store.Set(keyForEvent(compositeTag, attr.Value, result), hash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Search performs a search using the given query.
|
||||
|
||||
@@ -25,16 +25,15 @@ func BenchmarkTxSearch(b *testing.B) {
|
||||
b.Errorf("failed to create database: %s", err)
|
||||
}
|
||||
|
||||
allowedKeys := []string{"transfer.address", "transfer.amount"}
|
||||
indexer := NewTxIndex(db, IndexEvents(allowedKeys))
|
||||
indexer := NewTxIndex(db)
|
||||
|
||||
for i := 0; i < 35000; i++ {
|
||||
events := []abci.Event{
|
||||
{
|
||||
Type: "transfer",
|
||||
Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("address"), Value: []byte(fmt.Sprintf("address_%d", i%100))},
|
||||
{Key: []byte("amount"), Value: []byte("50")},
|
||||
{Key: []byte("address"), Value: []byte(fmt.Sprintf("address_%d", i%100)), Index: true},
|
||||
{Key: []byte("amount"), Value: []byte("50"), Index: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
+18
-23
@@ -67,13 +67,12 @@ func TestTxIndex(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTxSearch(t *testing.T) {
|
||||
allowedKeys := []string{"account.number", "account.owner", "account.date"}
|
||||
indexer := NewTxIndex(db.NewMemDB(), IndexEvents(allowedKeys))
|
||||
indexer := NewTxIndex(db.NewMemDB())
|
||||
|
||||
txResult := txResultWithEvents([]abci.Event{
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("owner"), Value: []byte("Ivan")}}},
|
||||
{Type: "", Attributes: []abci.EventAttribute{{Key: []byte("not_allowed"), Value: []byte("Vlad")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1"), Index: true}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("owner"), Value: []byte("Ivan"), Index: true}}},
|
||||
{Type: "", Attributes: []abci.EventAttribute{{Key: []byte("not_allowed"), Value: []byte("Vlad"), Index: true}}},
|
||||
})
|
||||
hash := types.Tx(txResult.Tx).Hash()
|
||||
|
||||
@@ -142,13 +141,12 @@ func TestTxSearch(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTxSearchWithCancelation(t *testing.T) {
|
||||
allowedKeys := []string{"account.number", "account.owner", "account.date"}
|
||||
indexer := NewTxIndex(db.NewMemDB(), IndexEvents(allowedKeys))
|
||||
indexer := NewTxIndex(db.NewMemDB())
|
||||
|
||||
txResult := txResultWithEvents([]abci.Event{
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("owner"), Value: []byte("Ivan")}}},
|
||||
{Type: "", Attributes: []abci.EventAttribute{{Key: []byte("not_allowed"), Value: []byte("Vlad")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1"), Index: true}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("owner"), Value: []byte("Ivan"), Index: true}}},
|
||||
{Type: "", Attributes: []abci.EventAttribute{{Key: []byte("not_allowed"), Value: []byte("Vlad"), Index: true}}},
|
||||
})
|
||||
err := indexer.Index(txResult)
|
||||
require.NoError(t, err)
|
||||
@@ -161,12 +159,11 @@ func TestTxSearchWithCancelation(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTxSearchDeprecatedIndexing(t *testing.T) {
|
||||
allowedKeys := []string{"account.number", "sender"}
|
||||
indexer := NewTxIndex(db.NewMemDB(), IndexEvents(allowedKeys))
|
||||
indexer := NewTxIndex(db.NewMemDB())
|
||||
|
||||
// index tx using events indexing (composite key)
|
||||
txResult1 := txResultWithEvents([]abci.Event{
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1"), Index: true}}},
|
||||
})
|
||||
hash1 := types.Tx(txResult1.Tx).Hash()
|
||||
|
||||
@@ -237,12 +234,11 @@ func TestTxSearchDeprecatedIndexing(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTxSearchOneTxWithMultipleSameTagsButDifferentValues(t *testing.T) {
|
||||
allowedKeys := []string{"account.number"}
|
||||
indexer := NewTxIndex(db.NewMemDB(), IndexEvents(allowedKeys))
|
||||
indexer := NewTxIndex(db.NewMemDB())
|
||||
|
||||
txResult := txResultWithEvents([]abci.Event{
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("2")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1"), Index: true}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("2"), Index: true}}},
|
||||
})
|
||||
|
||||
err := indexer.Index(txResult)
|
||||
@@ -260,12 +256,11 @@ func TestTxSearchOneTxWithMultipleSameTagsButDifferentValues(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTxSearchMultipleTxs(t *testing.T) {
|
||||
allowedKeys := []string{"account.number", "account.number.id"}
|
||||
indexer := NewTxIndex(db.NewMemDB(), IndexEvents(allowedKeys))
|
||||
indexer := NewTxIndex(db.NewMemDB())
|
||||
|
||||
// indexed first, but bigger height (to test the order of transactions)
|
||||
txResult := txResultWithEvents([]abci.Event{
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("1"), Index: true}}},
|
||||
})
|
||||
|
||||
txResult.Tx = types.Tx("Bob's account")
|
||||
@@ -276,7 +271,7 @@ func TestTxSearchMultipleTxs(t *testing.T) {
|
||||
|
||||
// indexed second, but smaller height (to test the order of transactions)
|
||||
txResult2 := txResultWithEvents([]abci.Event{
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("2")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("2"), Index: true}}},
|
||||
})
|
||||
txResult2.Tx = types.Tx("Alice's account")
|
||||
txResult2.Height = 1
|
||||
@@ -287,7 +282,7 @@ func TestTxSearchMultipleTxs(t *testing.T) {
|
||||
|
||||
// indexed third (to test the order of transactions)
|
||||
txResult3 := txResultWithEvents([]abci.Event{
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("3")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number"), Value: []byte("3"), Index: true}}},
|
||||
})
|
||||
txResult3.Tx = types.Tx("Jack's account")
|
||||
txResult3.Height = 1
|
||||
@@ -298,7 +293,7 @@ func TestTxSearchMultipleTxs(t *testing.T) {
|
||||
// indexed fourth (to test we don't include txs with similar events)
|
||||
// https://github.com/tendermint/tendermint/issues/2908
|
||||
txResult4 := txResultWithEvents([]abci.Event{
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number.id"), Value: []byte("1")}}},
|
||||
{Type: "account", Attributes: []abci.EventAttribute{{Key: []byte("number.id"), Value: []byte("1"), Index: true}}},
|
||||
})
|
||||
txResult4.Tx = types.Tx("Mike's account")
|
||||
txResult4.Height = 2
|
||||
|
||||
Reference in New Issue
Block a user