-
Notifications
You must be signed in to change notification settings - Fork 636
v0.37.x:state/kvindexer: port 0.34 query fix #77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b6d99be
6fe2b13
b9f5a5b
bd9ed68
c52ffdc
65dac51
44113d7
bc44f40
2ef62aa
b677ace
f7a0740
81c37b4
5f84a1e
4cfc9cb
ca08390
16ffabc
81caedc
225e7d6
8db6226
233fd53
6ccb03e
34c3cff
52ab759
2efdd22
896b509
8589f14
3796592
1d25966
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
- `[state/kvindexer]` \#77 Fixed the default behaviour of the kvindexer to index and query attributes by events in which they occur. In 0.34.25 this was mitigated by a separated RPC flag. (@jmalicevic) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,9 @@ the block itself is never stored. | |
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](https://github.com/cometbft/cometbft/blob/v0.37.x/spec/abci/abci++_basic_concepts.md#events) | ||
|
||
documentation. | ||
|
||
An `Event` has a composite key associated with it. A `compositeKey` is | ||
|
@@ -34,6 +36,9 @@ would be equal to the composite key of `jack.account.number`. | |
By default, CometBFT will index all transactions by their respective hashes | ||
and height and blocks by their height. | ||
|
||
CometBFT allows for different events within the same height to have | ||
equal attributes. | ||
|
||
## Configuration | ||
|
||
Operators can configure indexing via the `[tx_index]` section. The `indexer` | ||
|
@@ -67,6 +72,60 @@ for block and transaction events directly against CometBFT's RPC. However, the | |
query syntax is limited and so this indexer type might be deprecated or removed | ||
entirely in the future. | ||
|
||
**Implementation and data layout** | ||
|
||
The kv indexer stores each attribute of an event individually, by creating a composite key | ||
with | ||
- event type, | ||
- attribute key, | ||
- attribute value, | ||
- event generator (e.g. `EndBlock` and `BeginBlock`) | ||
- the height, and | ||
- event counter. | ||
For example the following events: | ||
|
||
``` | ||
Type: "transfer", | ||
Attributes: []abci.EventAttribute{ | ||
{Key: "sender", Value: "Bob", Index: true}, | ||
{Key: "recipient", Value: "Alice", Index: true}, | ||
{Key: "balance", Value: "100", Index: true}, | ||
{Key: "note", Value: "nothing", Index: true}, | ||
}, | ||
|
||
``` | ||
|
||
``` | ||
Type: "transfer", | ||
Attributes: []abci.EventAttribute{ | ||
{Key: "sender", Value: "Tom", Index: true}, | ||
{Key: "recipient", Value: "Alice", Index: true}, | ||
{Key: "balance", Value: "200", Index: true}, | ||
{Key: "note", Value: "nothing", Index: true}, | ||
}, | ||
``` | ||
|
||
will be represented as follows in the store, assuming these events result from the EndBlock call for height 1: | ||
|
||
``` | ||
Key value | ||
---- event1 ------ | ||
transferSenderBobEndBlock11 1 | ||
transferRecipientAliceEndBlock11 1 | ||
transferBalance100EndBlock11 1 | ||
transferNodeNothingEndblock11 1 | ||
---- event2 ------ | ||
transferSenderTomEndBlock12 1 | ||
transferRecepientAliceEndBlock12 1 | ||
transferBalance200EndBlock12 1 | ||
transferNodeNothingEndblock12 1 | ||
|
||
``` | ||
The event number is a local variable kept by the indexer and incremented when a new event is processed. | ||
It is an `int64` variable and has no other semantics besides being used to associate attributes belonging to the same events within a height. | ||
This variable is not atomically incremented as event indexing is deterministic. **Should this ever change**, the event id generation | ||
will be broken. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a problem with this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm you are right, these two sentences at the beginning are really a bit contradicting each other: "Applications are free to define which events to index. Tendermint does not The index field is indeed set by the application if the event is to be indexed. I don't know what the original author was referring to with "TM does not ..." .. I will edit this paragraph. |
||
#### PostgreSQL | ||
|
||
The `psql` indexer type allows an operator to enable block and transaction event | ||
|
@@ -122,10 +181,10 @@ func (app *KVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.Resul | |
{ | ||
Type: "transfer", | ||
Attributes: []abci.EventAttribute{ | ||
{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}, | ||
{Key: "sender ", Value: "Bob ", Index: true}, | ||
{Key: "recipient ", Value: "Alice ", Index: true}, | ||
{Key: "balance ", Value: "100 ", Index: true}, | ||
{Key: "note ", Value: "nothing ", Index: true}, | ||
}, | ||
}, | ||
} | ||
|
@@ -168,7 +227,7 @@ a query to `/subscribe` RPC endpoint. | |
Check out [API docs](https://docs.cometbft.com/v0.37/rpc/#subscribe) for more information | ||
on query syntax and other options. | ||
|
||
## Querying Blocks Events | ||
## Querying Block Events | ||
|
||
You can query for a paginated set of blocks by their events by calling the | ||
`/block_search` RPC endpoint: | ||
|
@@ -177,5 +236,12 @@ You can query for a paginated set of blocks by their events by calling the | |
curl "localhost:26657/block_search?query=\"block.height > 10 AND val_set.num_changed > 0\"" | ||
``` | ||
|
||
Check out [API docs](https://docs.cometbft.com/v0.37/rpc/#/Info/block_search) | ||
for more information on query syntax and other options. | ||
|
||
Storing the event sequence was introduced in CometBFT 0.34.26. Before that, up until Tendermint Core 0.34.26, | ||
the event sequence was not stored in the kvstore and events were stored only by height. That means that queries | ||
returned blocks and transactions whose event attributes match within the height but can match across different | ||
events on that height. | ||
This behavior was fixed with CometBFT 0.34.26+. However, if the data was indexed with earlier versions of | ||
Tendermint Core and not re-indexed, that data will be queried as if all the attributes within a height | ||
occurred within the same event. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use something derived from Height as values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll clean this up a bit, you are right we could add the % condition in the event value. In principle, the only reason why I separated these two use cases is to make sure there are events that do not occur at every height.