Browse Source

Rename Tag(s) to Event(s) (#4046)

* Rename Tag(s) to Event(s)

- tag was replaced with event, but in some places it still mentions tag, would be easier to understand if we tried to replace it with event to not confuse people.

Signed-off-by: Marko Baricevic <marbar3778@yahoo.com>

* more  changes from tag -> event

* rename events to compositeKeys and keys

* Apply suggestions from code review

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>

* add minor documentation on how composite keys are constructed

* rename eventkey to compositekey

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>

* add changelog entry & add info to regenerate confid to changelog entry
pull/4219/head
Marko 5 years ago
committed by GitHub
parent
commit
92d18d7fcd
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 157 additions and 129 deletions
  1. +3
    -1
      CHANGELOG_PENDING.md
  2. +19
    -13
      config/config.go
  3. +14
    -9
      config/toml.go
  4. +28
    -17
      docs/app-dev/indexing-transactions.md
  5. +15
    -11
      docs/tendermint-core/configuration.md
  6. +2
    -2
      docs/tendermint-core/running-in-production.md
  7. +1
    -1
      libs/pubsub/query/empty.go
  8. +6
    -6
      libs/pubsub/query/query.go
  9. +5
    -5
      libs/pubsub/query/query_test.go
  10. +3
    -3
      libs/pubsub/subscription.go
  11. +4
    -4
      node/node.go
  12. +2
    -2
      rpc/client/rpc_test.go
  13. +1
    -1
      rpc/test/helpers.go
  14. +1
    -1
      state/txindex/indexer_service.go
  15. +1
    -1
      state/txindex/indexer_service_test.go
  16. +22
    -22
      state/txindex/kv/kv.go
  17. +2
    -2
      state/txindex/kv/kv_bench_test.go
  18. +21
    -21
      state/txindex/kv/kv_test.go
  19. +3
    -3
      types/event_bus.go
  20. +3
    -3
      types/event_bus_test.go
  21. +1
    -1
      types/events.go

+ 3
- 1
CHANGELOG_PENDING.md View File

@ -55,6 +55,8 @@ program](https://hackerone.com/tendermint).
```
- ID is unique for each request;
- Request.ID is now optional. Notification is a Request without an ID. Previously ID="" or ID=0 were considered as notifications.
- [config] \#4046 Rename tag(s) to CompositeKey & places where tag is still present it was renamed to event or events. Find how a compositeKey is constructed [here](https://github.com/tendermint/tendermint/blob/6d05c531f7efef6f0619155cf10ae8557dd7832f/docs/app-dev/indexing-transactions.md)
- You will have to generate a new config for your Tendermint node(s)
- Apps
@ -98,7 +100,7 @@ program](https://hackerone.com/tendermint).
### BUG FIXES:
- [rpc/lib] [\#4051](https://github.com/tendermint/tendermint/pull/4131) Fix RPC client, which was previously resolving https protocol to http (@yenkhoon)
- [rpc/lib][\#4051](https://github.com/tendermint/tendermint/pull/4131) Fix RPC client, which was previously resolving https protocol to http (@yenkhoon)
- [rpc] [\#4141](https://github.com/tendermint/tendermint/pull/4141) JSONRPCClient: validate that Response.ID matches Request.ID
- [rpc] [\#4141](https://github.com/tendermint/tendermint/pull/4141) WSClient: check for unsolicited responses
- [types] [\4164](https://github.com/tendermint/tendermint/pull/4164) Prevent temporary power overflows on validator updates


+ 19
- 13
config/config.go View File

@ -883,9 +883,15 @@ func (cfg *ConsensusConfig) ValidateBasic() error {
//-----------------------------------------------------------------------------
// TxIndexConfig
// Remember that Event has the following structure:
// type: [
// key: value,
// ...
// ]
//
// CompositeKeys are constructed by `type.key`
// TxIndexConfig defines the configuration for the transaction indexer,
// including tags to index.
// including composite keys to index.
type TxIndexConfig struct {
// What indexer to use for transactions
//
@ -895,30 +901,30 @@ type TxIndexConfig struct {
// backed by key-value storage (defaults to levelDB; see DBBackend).
Indexer string `mapstructure:"indexer"`
// Comma-separated list of tags to index (by default the only tag is "tx.hash")
// 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" tag here.
// You can also index transactions by height by adding "tx.height" key here.
//
// It's recommended to index only a subset of tags due to possible memory
// 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.
IndexTags string `mapstructure:"index_tags"`
IndexKeys string `mapstructure:"index_keys"`
// When set to true, tells indexer to index all tags (predefined tags:
// "tx.hash", "tx.height" and all tags from DeliverTx responses).
// 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). IndexTags has a
// precedence over IndexAllTags (i.e. when given both, IndexTags will be
// 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).
IndexAllTags bool `mapstructure:"index_all_tags"`
IndexAllKeys bool `mapstructure:"index_all_keys"`
}
// DefaultTxIndexConfig returns a default configuration for the transaction indexer.
func DefaultTxIndexConfig() *TxIndexConfig {
return &TxIndexConfig{
Indexer: "kv",
IndexTags: "",
IndexAllTags: false,
IndexKeys: "",
IndexAllKeys: false,
}
}


+ 14
- 9
config/toml.go View File

@ -353,22 +353,27 @@ peer_query_maj23_sleep_duration = "{{ .Consensus.PeerQueryMaj23SleepDuration }}"
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
indexer = "{{ .TxIndex.Indexer }}"
# Comma-separated list of tags to index (by default the only tag is "tx.hash")
# 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" tag here.
# You can also index transactions by height by adding "tx.height" key here.
#
# It's recommended to index only a subset of tags due to possible memory
# 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_tags = "{{ .TxIndex.IndexTags }}"
index_keys = "{{ .TxIndex.IndexKeys }}"
# When set to true, tells indexer to index all tags (predefined tags:
# "tx.hash", "tx.height" and all tags from DeliverTx responses).
# 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). IndexTags has a
# precedence over IndexAllTags (i.e. when given both, IndexTags will be
# 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_tags = {{ .TxIndex.IndexAllTags }}
index_all_keys = {{ .TxIndex.IndexAllKeys }}
##### instrumentation configuration options #####
[instrumentation]


+ 28
- 17
docs/app-dev/indexing-transactions.md View File

@ -10,12 +10,23 @@ to their results.
Events can be used to index transactions and blocks according to what happened
during their execution. Note that the set of events returned for a block from
`BeginBlock` and `EndBlock` are merged. In case both methods return the same
tag, only the value defined in `EndBlock` is used.
type, only the key-value pairs defined in `EndBlock` are used.
Each event contains a type and a list of attributes, which are key-value pairs
denoting something about what happened during the method's execution. For more
details on `Events`, see the [ABCI](../spec/abci/abci.md) documentation.
An Event has a composite key associated with it. A `compositeKey` is constructed by its type and key separated by a dot.
For example:
```json
"jack": [
"account.number": 100
]
```
would be equal to the composite key of `jack.account.number`.
Let's take a look at the `[tx_index]` config section:
```toml
@ -29,22 +40,22 @@ Let's take a look at the `[tx_index]` config section:
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
indexer = "kv"
# Comma-separated list of tags to index (by default the only tag is "tx.hash")
# 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" tag here.
# You can also index transactions by height by adding "tx.height" key here.
#
# It's recommended to index only a subset of tags due to possible memory
# 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_tags = ""
index_keys = ""
# When set to true, tells indexer to index all tags (predefined tags:
# "tx.hash", "tx.height" and all tags from DeliverTx responses).
# 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). IndexTags has a
# precedence over IndexAllTags (i.e. when given both, IndexTags will be
# 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_tags = false
index_all_keys = false
```
By default, Tendermint will index all transactions by their respective
@ -100,17 +111,17 @@ on query syntax and other options.
## Subscribing to Transactions
Clients can subscribe to transactions with the given tags via Websocket by providing
Clients can subscribe to transactions with the given tags via WebSocket by providing
a query to `/subscribe` RPC endpoint.
```json
{
"jsonrpc": "2.0",
"method": "subscribe",
"id": "0",
"params": {
"query": "account.name='igor'"
}
"jsonrpc": "2.0",
"method": "subscribe",
"id": "0",
"params": {
"query": "account.name='igor'"
}
}
```


+ 15
- 11
docs/tendermint-core/configuration.md View File

@ -6,8 +6,7 @@ order: 3
Tendermint Core can be configured via a TOML file in
`$TMHOME/config/config.toml`. Some of these parameters can be overridden by
command-line flags. For most users, the options in the `##### main base
configuration options #####` are intended to be modified while config options
command-line flags. For most users, the options in the `##### main base configuration options #####` are intended to be modified while config options
further below are intended for advance power users.
## Options
@ -299,22 +298,27 @@ blocktime_iota = "1s"
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
indexer = "kv"
# Comma-separated list of tags to index (by default the only tag is "tx.hash")
# 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" tag here.
# You can also index transactions by height by adding "tx.height" event here.
#
# It's recommended to index only a subset of tags due to possible memory
# 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_tags = ""
index_keys = ""
# When set to true, tells indexer to index all tags (predefined tags:
# "tx.hash", "tx.height" and all tags from DeliverTx responses).
# 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). IndexTags has a
# precedence over IndexAllTags (i.e. when given both, IndexTags will be
# Note this may be not desirable (see the comment above). IndexEvents has a
# precedence over IndexAllEvents (i.e. when given both, IndexEvents will be
# indexed).
index_all_tags = false
index_all_keys = false
##### instrumentation configuration options #####
[instrumentation]


+ 2
- 2
docs/tendermint-core/running-in-production.md View File

@ -21,10 +21,10 @@ Tendermint keeps multiple distinct databases in the `$TMROOT/data`:
- `state.db`: Stores the current blockchain state (ie. height, validators,
consensus params). Only grows if consensus params or validators change. Also
used to temporarily store intermediate results during block processing.
- `tx_index.db`: Indexes txs (and their results) by tx hash and by DeliverTx result tags.
- `tx_index.db`: Indexes txs (and their results) by tx hash and by DeliverTx result events.
By default, Tendermint will only index txs by their hash, not by their DeliverTx
result tags. See [indexing transactions](../app-dev/indexing-transactions.md) for
result events. See [indexing transactions](../app-dev/indexing-transactions.md) for
details.
There is no current strategy for pruning the databases. Consider reducing


+ 1
- 1
libs/pubsub/query/empty.go View File

@ -1,6 +1,6 @@
package query
// Empty query matches any set of tags.
// Empty query matches any set of events.
type Empty struct {
}


+ 6
- 6
libs/pubsub/query/query.go View File

@ -29,12 +29,12 @@ type Query struct {
parser *QueryParser
}
// Condition represents a single condition within a query and consists of tag
// Condition represents a single condition within a query and consists of composite key
// (e.g. "tx.gas"), operator (e.g. "=") and operand (e.g. "7").
type Condition struct {
Tag string
Op Operator
Operand interface{}
CompositeKey string
Op Operator
Operand interface{}
}
// New parses the given string and returns a query or error if the string is
@ -63,7 +63,7 @@ func (q *Query) String() string {
return q.str
}
// Operator is an operator that defines some kind of relation between tag and
// Operator is an operator that defines some kind of relation between composite key and
// operand (equality, etc.).
type Operator uint8
@ -399,7 +399,7 @@ func matchValue(value string, op Operator, operand reflect.Value) (bool, error)
case reflect.Struct: // time
operandAsTime := operand.Interface().(time.Time)
// try our best to convert value from tags to time.Time
// try our best to convert value from events to time.Time
var (
v time.Time
err error


+ 5
- 5
libs/pubsub/query/query_test.go View File

@ -187,26 +187,26 @@ func TestConditions(t *testing.T) {
{
s: "tm.events.type='NewBlock'",
conditions: []query.Condition{
{Tag: "tm.events.type", Op: query.OpEqual, Operand: "NewBlock"},
{CompositeKey: "tm.events.type", Op: query.OpEqual, Operand: "NewBlock"},
},
},
{
s: "tx.gas > 7 AND tx.gas < 9",
conditions: []query.Condition{
{Tag: "tx.gas", Op: query.OpGreater, Operand: int64(7)},
{Tag: "tx.gas", Op: query.OpLess, Operand: int64(9)},
{CompositeKey: "tx.gas", Op: query.OpGreater, Operand: int64(7)},
{CompositeKey: "tx.gas", Op: query.OpLess, Operand: int64(9)},
},
},
{
s: "tx.time >= TIME 2013-05-03T14:45:00Z",
conditions: []query.Condition{
{Tag: "tx.time", Op: query.OpGreaterEqual, Operand: txTime},
{CompositeKey: "tx.time", Op: query.OpGreaterEqual, Operand: txTime},
},
},
{
s: "slashing EXISTS",
conditions: []query.Condition{
{Tag: "slashing", Op: query.OpExists},
{CompositeKey: "slashing", Op: query.OpExists},
},
},
}


+ 3
- 3
libs/pubsub/subscription.go View File

@ -16,7 +16,7 @@ var (
// A Subscription represents a client subscription for a particular query and
// consists of three things:
// 1) channel onto which messages and tags are published
// 1) channel onto which messages and events are published
// 2) channel which is closed if a client is too slow or choose to unsubscribe
// 3) err indicating the reason for (2)
type Subscription struct {
@ -35,7 +35,7 @@ func NewSubscription(outCapacity int) *Subscription {
}
}
// Out returns a channel onto which messages and tags are published.
// Out returns a channel onto which messages and events are published.
// Unsubscribe/UnsubscribeAll does not close the channel to avoid clients from
// receiving a nil message.
func (s *Subscription) Out() <-chan Message {
@ -68,7 +68,7 @@ func (s *Subscription) cancel(err error) {
close(s.cancelled)
}
// Message glues data and tags together.
// Message glues data and events together.
type Message struct {
data interface{}
events map[string][]string


+ 4
- 4
node/node.go View File

@ -247,10 +247,10 @@ func createAndStartIndexerService(config *cfg.Config, dbProvider DBProvider,
return nil, nil, err
}
switch {
case config.TxIndex.IndexTags != "":
txIndexer = kv.NewTxIndex(store, kv.IndexTags(splitAndTrimEmpty(config.TxIndex.IndexTags, ",", " ")))
case config.TxIndex.IndexAllTags:
txIndexer = kv.NewTxIndex(store, kv.IndexAllTags())
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)
}


+ 2
- 2
rpc/client/rpc_test.go View File

@ -452,14 +452,14 @@ func TestTxSearch(t *testing.T) {
require.Nil(t, err, "%+v", err)
require.Len(t, result.Txs, 0)
// query using a tag (see kvstore application)
// query using a compositeKey (see kvstore application)
result, err = c.TxSearch("app.creator='Cosmoshi Netowoko'", false, 1, 30)
require.Nil(t, err, "%+v", err)
if len(result.Txs) == 0 {
t.Fatal("expected a lot of transactions")
}
// query using a tag (see kvstore application) and height
// query using a compositeKey (see kvstore application) and height
result, err = c.TxSearch("app.creator='Cosmoshi Netowoko' AND tx.height<10000", true, 1, 30)
require.Nil(t, err, "%+v", err)
if len(result.Txs) == 0 {


+ 1
- 1
rpc/test/helpers.go View File

@ -97,7 +97,7 @@ func createConfig() *cfg.Config {
c.RPC.ListenAddress = rpc
c.RPC.CORSAllowedOrigins = []string{"https://tendermint.com/"}
c.RPC.GRPCListenAddress = grpc
c.TxIndex.IndexTags = "app.creator,tx.height" // see kvstore application
c.TxIndex.IndexKeys = "app.creator,tx.height" // see kvstore application
return c
}


+ 1
- 1
state/txindex/indexer_service.go View File

@ -29,7 +29,7 @@ func NewIndexerService(idr TxIndexer, eventBus *types.EventBus) *IndexerService
}
// OnStart implements cmn.Service by subscribing for all transactions
// and indexing them by tags.
// and indexing them by events.
func (is *IndexerService) OnStart() error {
// Use SubscribeUnbuffered here to ensure both subscriptions does not get
// cancelled due to not pulling messages fast enough. Cause this might


+ 1
- 1
state/txindex/indexer_service_test.go View File

@ -25,7 +25,7 @@ func TestIndexerServiceIndexesBlocks(t *testing.T) {
// tx indexer
store := db.NewMemDB()
txIndexer := kv.NewTxIndex(store, kv.IndexAllTags())
txIndexer := kv.NewTxIndex(store, kv.IndexAllEvents())
service := txindex.NewIndexerService(txIndexer, eventBus)
service.SetLogger(log.TestingLogger())


+ 22
- 22
state/txindex/kv/kv.go View File

@ -27,31 +27,31 @@ var _ txindex.TxIndexer = (*TxIndex)(nil)
// TxIndex is the simplest possible indexer, backed by key-value storage (levelDB).
type TxIndex struct {
store dbm.DB
tagsToIndex []string
indexAllTags bool
store dbm.DB
compositeKeysToIndex []string
indexAllEvents bool
}
// NewTxIndex creates new KV indexer.
func NewTxIndex(store dbm.DB, options ...func(*TxIndex)) *TxIndex {
txi := &TxIndex{store: store, tagsToIndex: make([]string, 0), indexAllTags: false}
txi := &TxIndex{store: store, compositeKeysToIndex: make([]string, 0), indexAllEvents: false}
for _, o := range options {
o(txi)
}
return txi
}
// IndexTags is an option for setting which tags to index.
func IndexTags(tags []string) func(*TxIndex) {
// IndexEvents is an option for setting which composite keys to index.
func IndexEvents(compositeKeys []string) func(*TxIndex) {
return func(txi *TxIndex) {
txi.tagsToIndex = tags
txi.compositeKeysToIndex = compositeKeys
}
}
// IndexAllTags is an option for indexing all tags.
func IndexAllTags() func(*TxIndex) {
// IndexAllEvents is an option for indexing all events.
func IndexAllEvents() func(*TxIndex) {
return func(txi *TxIndex) {
txi.indexAllTags = true
txi.indexAllEvents = true
}
}
@ -91,7 +91,7 @@ func (txi *TxIndex) AddBatch(b *txindex.Batch) error {
txi.indexEvents(result, hash, storeBatch)
// index tx by height
if txi.indexAllTags || cmn.StringInSlice(types.TxHeightKey, txi.tagsToIndex) {
if txi.indexAllEvents || cmn.StringInSlice(types.TxHeightKey, txi.compositeKeysToIndex) {
storeBatch.Set(keyForHeight(result), hash)
}
@ -121,7 +121,7 @@ func (txi *TxIndex) Index(result *types.TxResult) error {
txi.indexEvents(result, hash, b)
// index tx by height
if txi.indexAllTags || cmn.StringInSlice(types.TxHeightKey, txi.tagsToIndex) {
if txi.indexAllEvents || cmn.StringInSlice(types.TxHeightKey, txi.compositeKeysToIndex) {
b.Set(keyForHeight(result), hash)
}
@ -150,7 +150,7 @@ func (txi *TxIndex) indexEvents(result *types.TxResult, hash []byte, store dbm.S
}
compositeTag := fmt.Sprintf("%s.%s", event.Type, string(attr.Key))
if txi.indexAllTags || cmn.StringInSlice(compositeTag, txi.tagsToIndex) {
if txi.indexAllEvents || cmn.StringInSlice(compositeTag, txi.compositeKeysToIndex) {
store.Set(keyForEvent(compositeTag, attr.Value, result), hash)
}
}
@ -260,7 +260,7 @@ func (txi *TxIndex) Search(q *query.Query) ([]*types.TxResult, error) {
func lookForHash(conditions []query.Condition) (hash []byte, ok bool, err error) {
for _, c := range conditions {
if c.Tag == types.TxHashKey {
if c.CompositeKey == types.TxHashKey {
decoded, err := hex.DecodeString(c.Operand.(string))
return decoded, true, err
}
@ -271,7 +271,7 @@ func lookForHash(conditions []query.Condition) (hash []byte, ok bool, err error)
// lookForHeight returns a height if there is an "height=X" condition.
func lookForHeight(conditions []query.Condition) (height int64) {
for _, c := range conditions {
if c.Tag == types.TxHeightKey && c.Op == query.OpEqual {
if c.CompositeKey == types.TxHeightKey && c.Op == query.OpEqual {
return c.Operand.(int64)
}
}
@ -340,9 +340,9 @@ func lookForRanges(conditions []query.Condition) (ranges queryRanges, indexes []
ranges = make(queryRanges)
for i, c := range conditions {
if isRangeOperation(c.Op) {
r, ok := ranges[c.Tag]
r, ok := ranges[c.CompositeKey]
if !ok {
r = queryRange{key: c.Tag}
r = queryRange{key: c.CompositeKey}
}
switch c.Op {
case query.OpGreater:
@ -356,7 +356,7 @@ func lookForRanges(conditions []query.Condition) (ranges queryRanges, indexes []
r.includeUpperBound = true
r.upperBound = c.Operand
}
ranges[c.Tag] = r
ranges[c.CompositeKey] = r
indexes = append(indexes, i)
}
}
@ -404,7 +404,7 @@ func (txi *TxIndex) match(
// XXX: startKey does not apply here.
// For example, if startKey = "account.owner/an/" and search query = "account.owner CONTAINS an"
// we can't iterate with prefix "account.owner/an/" because we might miss keys like "account.owner/Ulan/"
it := dbm.IteratePrefix(txi.store, startKey(c.Tag))
it := dbm.IteratePrefix(txi.store, startKey(c.CompositeKey))
defer it.Close()
for ; it.Valid(); it.Next() {
@ -491,7 +491,7 @@ LOOP:
tmpHashes[string(it.Value())] = it.Value()
}
// XXX: passing time in a ABCI Tags is not yet implemented
// XXX: passing time in a ABCI Events is not yet implemented
// case time.Time:
// v := strconv.ParseInt(extractValueFromKey(it.Key()), 10, 64)
// if v == r.upperBound {
@ -554,9 +554,9 @@ func keyForHeight(result *types.TxResult) []byte {
func startKeyForCondition(c query.Condition, height int64) []byte {
if height > 0 {
return startKey(c.Tag, c.Operand, height)
return startKey(c.CompositeKey, c.Operand, height)
}
return startKey(c.Tag, c.Operand)
return startKey(c.CompositeKey, c.Operand)
}
func startKey(fields ...interface{}) []byte {


+ 2
- 2
state/txindex/kv/kv_bench_test.go View File

@ -24,8 +24,8 @@ func BenchmarkTxSearch(b *testing.B) {
b.Errorf("failed to create database: %s", err)
}
allowedTags := []string{"transfer.address", "transfer.amount"}
indexer := NewTxIndex(db, IndexTags(allowedTags))
allowedKeys := []string{"transfer.address", "transfer.amount"}
indexer := NewTxIndex(db, IndexEvents(allowedKeys))
for i := 0; i < 35000; i++ {
events := []abci.Event{


+ 21
- 21
state/txindex/kv/kv_test.go View File

@ -65,8 +65,8 @@ func TestTxIndex(t *testing.T) {
}
func TestTxSearch(t *testing.T) {
allowedTags := []string{"account.number", "account.owner", "account.date"}
indexer := NewTxIndex(db.NewMemDB(), IndexTags(allowedTags))
allowedKeys := []string{"account.number", "account.owner", "account.date"}
indexer := NewTxIndex(db.NewMemDB(), IndexEvents(allowedKeys))
txResult := txResultWithEvents([]abci.Event{
{Type: "account", Attributes: []cmn.KVPair{{Key: []byte("number"), Value: []byte("1")}}},
@ -84,11 +84,11 @@ func TestTxSearch(t *testing.T) {
}{
// search by hash
{fmt.Sprintf("tx.hash = '%X'", hash), 1},
// search by exact match (one tag)
// search by exact match (one key)
{"account.number = 1", 1},
// search by exact match (two tags)
// search by exact match (two keys)
{"account.number = 1 AND account.owner = 'Ivan'", 1},
// search by exact match (two tags)
// search by exact match (two keys)
{"account.number = 1 AND account.owner = 'Vlad'", 0},
{"account.owner = 'Vlad' AND account.number = 1", 0},
{"account.number >= 1 AND account.owner = 'Vlad'", 0},
@ -103,17 +103,17 @@ func TestTxSearch(t *testing.T) {
{"account.number >= 1", 1},
// search by range (upper bound)
{"account.number <= 5", 1},
// search using not allowed tag
// search using not allowed key
{"not_allowed = 'boom'", 0},
// search for not existing tx result
{"account.number >= 2 AND account.number <= 5", 0},
// search using not existing tag
// search using not existing key
{"account.date >= TIME 2013-05-03T14:45:00Z", 0},
// search using CONTAINS
{"account.owner CONTAINS 'an'", 1},
// search for non existing value using CONTAINS
{"account.owner CONTAINS 'Vlad'", 0},
// search using the wrong tag (of numeric type) using CONTAINS
// search using the wrong key (of numeric type) using CONTAINS
{"account.number CONTAINS 'Iv'", 0},
}
@ -132,8 +132,8 @@ func TestTxSearch(t *testing.T) {
}
func TestTxSearchDeprecatedIndexing(t *testing.T) {
allowedTags := []string{"account.number", "sender"}
indexer := NewTxIndex(db.NewMemDB(), IndexTags(allowedTags))
allowedKeys := []string{"account.number", "sender"}
indexer := NewTxIndex(db.NewMemDB(), IndexEvents(allowedKeys))
// index tx using events indexing (composite key)
txResult1 := txResultWithEvents([]abci.Event{
@ -144,7 +144,7 @@ func TestTxSearchDeprecatedIndexing(t *testing.T) {
err := indexer.Index(txResult1)
require.NoError(t, err)
// index tx also using deprecated indexing (tag as key)
// index tx also using deprecated indexing (event as key)
txResult2 := txResultWithEvents(nil)
txResult2.Tx = types.Tx("HELLO WORLD 2")
@ -174,20 +174,20 @@ func TestTxSearchDeprecatedIndexing(t *testing.T) {
{fmt.Sprintf("tx.hash = '%X'", hash1), []*types.TxResult{txResult1}},
// search by hash
{fmt.Sprintf("tx.hash = '%X'", hash2), []*types.TxResult{txResult2}},
// search by exact match (one tag)
// search by exact match (one key)
{"account.number = 1", []*types.TxResult{txResult1}},
{"account.number >= 1 AND account.number <= 5", []*types.TxResult{txResult1}},
// search by range (lower bound)
{"account.number >= 1", []*types.TxResult{txResult1}},
// search by range (upper bound)
{"account.number <= 5", []*types.TxResult{txResult1}},
// search using not allowed tag
// search using not allowed key
{"not_allowed = 'boom'", []*types.TxResult{}},
// search for not existing tx result
{"account.number >= 2 AND account.number <= 5", []*types.TxResult{}},
// search using not existing tag
// search using not existing key
{"account.date >= TIME 2013-05-03T14:45:00Z", []*types.TxResult{}},
// search by deprecated tag
// search by deprecated key
{"sender = 'addr1'", []*types.TxResult{txResult2}},
}
@ -202,8 +202,8 @@ func TestTxSearchDeprecatedIndexing(t *testing.T) {
}
func TestTxSearchOneTxWithMultipleSameTagsButDifferentValues(t *testing.T) {
allowedTags := []string{"account.number"}
indexer := NewTxIndex(db.NewMemDB(), IndexTags(allowedTags))
allowedKeys := []string{"account.number"}
indexer := NewTxIndex(db.NewMemDB(), IndexEvents(allowedKeys))
txResult := txResultWithEvents([]abci.Event{
{Type: "account", Attributes: []cmn.KVPair{{Key: []byte("number"), Value: []byte("1")}}},
@ -221,8 +221,8 @@ func TestTxSearchOneTxWithMultipleSameTagsButDifferentValues(t *testing.T) {
}
func TestTxSearchMultipleTxs(t *testing.T) {
allowedTags := []string{"account.number", "account.number.id"}
indexer := NewTxIndex(db.NewMemDB(), IndexTags(allowedTags))
allowedKeys := []string{"account.number", "account.number.id"}
indexer := NewTxIndex(db.NewMemDB(), IndexEvents(allowedKeys))
// indexed first, but bigger height (to test the order of transactions)
txResult := txResultWithEvents([]abci.Event{
@ -256,7 +256,7 @@ func TestTxSearchMultipleTxs(t *testing.T) {
err = indexer.Index(txResult3)
require.NoError(t, err)
// indexed fourth (to test we don't include txs with similar tags)
// 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: []cmn.KVPair{{Key: []byte("number.id"), Value: []byte("1")}}},
@ -275,7 +275,7 @@ func TestTxSearchMultipleTxs(t *testing.T) {
}
func TestIndexAllTags(t *testing.T) {
indexer := NewTxIndex(db.NewMemDB(), IndexAllTags())
indexer := NewTxIndex(db.NewMemDB(), IndexAllEvents())
txResult := txResultWithEvents([]abci.Event{
{Type: "account", Attributes: []cmn.KVPair{{Key: []byte("owner"), Value: []byte("Ivan")}}},


+ 3
- 3
types/event_bus.go View File

@ -164,8 +164,8 @@ func (b *EventBus) PublishEventValidBlock(data EventDataRoundState) error {
return b.Publish(EventValidBlock, data)
}
// PublishEventTx publishes tx event with tags from Result. Note it will add
// predefined tags (EventTypeKey, TxHashKey). Existing tags with the same names
// PublishEventTx publishes tx event with events from Result. Note it will add
// predefined keys (EventTypeKey, TxHashKey). Existing events with the same keys
// will be overwritten.
func (b *EventBus) PublishEventTx(data EventDataTx) error {
// no explicit deadline for publishing events
@ -173,7 +173,7 @@ func (b *EventBus) PublishEventTx(data EventDataTx) error {
events := b.validateAndStringifyEvents(data.Result.Events, b.Logger.With("tx", data.Tx))
// add predefined tags
// add predefined compositeKeys
events[EventTypeKey] = append(events[EventTypeKey], EventTx)
events[TxHashKey] = append(events[TxHashKey], fmt.Sprintf("%X", data.Tx.Hash()))
events[TxHeightKey] = append(events[TxHeightKey], fmt.Sprintf("%d", data.Height))


+ 3
- 3
types/event_bus_test.go View File

@ -29,7 +29,7 @@ func TestEventBusPublishEventTx(t *testing.T) {
},
}
// PublishEventTx adds all these 3 tags, so the query below should work
// PublishEventTx adds 3 composite keys, so the query below should work
query := fmt.Sprintf("tm.event='Tx' AND tx.height=1 AND tx.hash='%X' AND testType.baz=1", tx.Hash())
txsSub, err := eventBus.Subscribe(context.Background(), "test", tmquery.MustParse(query))
require.NoError(t, err)
@ -78,7 +78,7 @@ func TestEventBusPublishEventNewBlock(t *testing.T) {
},
}
// PublishEventNewBlock adds the tm.event tag, so the query below should work
// PublishEventNewBlock adds the tm.event compositeKey, so the query below should work
query := "tm.event='NewBlock' AND testType.baz=1 AND testType.foz=2"
blocksSub, err := eventBus.Subscribe(context.Background(), "test", tmquery.MustParse(query))
require.NoError(t, err)
@ -225,7 +225,7 @@ func TestEventBusPublishEventNewBlockHeader(t *testing.T) {
},
}
// PublishEventNewBlockHeader adds the tm.event tag, so the query below should work
// PublishEventNewBlockHeader adds the tm.event compositeKey, so the query below should work
query := "tm.event='NewBlockHeader' AND testType.baz=1 AND testType.foz=2"
headersSub, err := eventBus.Subscribe(context.Background(), "test", tmquery.MustParse(query))
require.NoError(t, err)


+ 1
- 1
types/events.go View File

@ -125,7 +125,7 @@ type EventDataValidatorSetUpdates struct {
///////////////////////////////////////////////////////////////////////////////
const (
// EventTypeKey is a reserved key, used to specify event type in tags.
// EventTypeKey is a reserved composite key for event name.
EventTypeKey = "tm.event"
// TxHashKey is a reserved key, used to specify transaction's hash.
// see EventBus#PublishEventTx


Loading…
Cancel
Save