ResponseFinalizeBlock.tx_results.events 建立索引,区块通过 ResponseFinalizeBlock.events 建立索引。不过,交易还会通过一个主键建立索引,该主键包含交易哈希,并映射到且存储相应的交易结果。区块也会通过一个主键建立索引,该主键包含区块高度,并映射到且存储区块高度,也就是说,区块本身永远不会被存储。
每个事件都包含一个类型和一组属性,属性是键值对,用来表示该方法执行期间发生了什么。有关 Events 的更多细节,请参阅 [ABCI][/cometbft/latest/spec/abci/Outline#events] 文档。
一个 Event 会关联一个复合键。compositeKey 由事件类型和键组成,中间用点号分隔。
例如:
jack.account.number。
默认情况下,CometBFT 会按各自的哈希和高度为所有交易建立索引,并按高度为区块建立索引。
CometBFT 允许同一高度内的不同事件拥有相同的属性。
配置
运维人员可以通过[tx_index] 配置索引。indexer 字段接受一组受支持的索引器。如果其中包含 null,无论同时提供了什么其他值,索引都会被关闭。
支持的索引器
KV
kv 索引器类型是一个嵌入式键值存储,由 CometBFT 底层主数据库支持。使用 kv 索引器类型时,你可以直接通过 CometBFT 的 RPC 查询区块和交易事件。不过,查询语法比较受限,因此这种索引器类型未来可能会被弃用或完全移除。
实现与数据布局
kv 索引器会为事件的每个属性分别存储一条记录,方法是创建一个包含以下部分的复合键:
- 事件类型
- 属性键
- 属性值
- 事件生成器(例如
FinalizeBlock) - 高度
- 事件计数器
FinalizeBlock 调用,那么它们会在存储中表示为:
int64 变量,除了用于在同一高度内关联属于同一事件的属性之外,没有其他语义。
由于事件索引是确定性的,这个变量不会以原子方式递增。如果这一点将来发生变化,事件 ID 的生成就会失效。
PostgreSQL
psql 索引器类型允许运维人员通过代理到外部 PostgreSQL 实例来启用区块和交易事件索引,从而以关系模型的形式存储这些事件。由于事件被存储在关系型数据库管理系统中,运维人员可以利用 SQL 执行一系列 kv 索引器类型不支持的丰富而复杂的查询。由于运维人员可以直接使用 SQL,CometBFT 的 RPC 不支持通过 psql 索引器类型进行搜索,任何此类查询都会失败。
请注意,SQL schema 存放在 state/indexer/sink/psql/schema.sql 中,运维人员必须在启动 CometBFT 并启用 psql 索引器类型之前显式创建这些关系。
示例:
默认索引
CometBFT 的交易和区块事件索引器默认会为少量保留事件建立索引。交易
默认会建立以下索引:tx.heighttx.hash
区块
默认会建立以下索引:block.height
添加事件
应用可以自由定义要建立索引的事件。CometBFT 本身不提供用于定义哪些事件应建立索引、哪些事件应忽略的功能。在你的应用FinalizeBlock 方法中,添加 Events 字段,并填入 UTF-8 编码字符串的键值对(例如,“transfer.sender”: “Bob”、“transfer.recipient”: “Alice”、“transfer.balance”: “100”)。
示例:
null,该交易就会被建立索引。每个事件都会使用如下形式的复合键建立索引:{eventType}.{eventAttribute}={eventValue},例如 transfer.sender=bob。
查询交易事件
你可以通过调用/tx_search RPC 端点,根据事件查询一组分页交易:
tx_search 端点的 RPC API reference。
订阅交易
客户端可以通过 WebSocket 向/subscribe RPC 端点提供查询条件,以订阅带有指定标签的交易。
查询区块事件
你可以通过调用/block_search RPC 端点,根据事件查询一组分页区块:
事件属性值类型
用户可以将任意内容用作事件值。不过,如果事件属性值是数字,则需要注意以下几点:- 负数在查询索引器时无法被正确检索。
- 事件值会被转换为大浮点数(来自
big/math包)。浮点数的精度会设置为它所表示整数的位长度,以确保不会因为精度不足而丢失信息。在 CometBFT v0.38.x 之前并没有这一行为,当时所有浮点值都会被忽略。 - 从 CometBFT v0.38.x 开始,查询中也可以包含浮点数。
- 需要注意的是,当小数位很多时,与浮点数进行比较可能并不精确。
事件类型与属性键格式
事件类型/属性键是一个字符串,可以包含任意 Unicode 字母或数字,以及以下字符:.(点号)、-(短横线)、_(下划线)。事件类型/属性键不能以 -(短横线)或 .(点号)开头。
CometBFT allows you to index transactions and blocks and later query or subscribe to their results. Transactions are indexed by
ResponseFinalizeBlock.tx_results.events and
blocks are indexed by ResponseFinalizeBlock.events. However, transactions
are also indexed by a primary key which includes the transaction hash and maps
to and stores the corresponding transaction results. Blocks are indexed by a primary key
which includes the block height and maps to and stores the block height, i.e.,
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][/cometbft/latest/spec/abci/Outline#events] 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:
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
field takes a series of supported indexers. If null is included, indexing will
be turned off regardless of other values provided.
Supported Indexers
KV
Thekv indexer type is an embedded key-value store supported by the main
underlying CometBFT database. Using the kv indexer type allows you to query
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.,
FinalizeBlock), - the height, and
- event counter.
FinalizeBlock call for height 1:
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.
PostgreSQL
Thepsql indexer type allows an operator to enable block and transaction event
indexing by proxying it to an external PostgreSQL instance, allowing for the events
to be stored in relational models. Since the events are stored in an RDBMS, operators
can leverage SQL to perform a series of rich and complex queries that are not
supported by the kv indexer type. Since operators can leverage SQL directly,
searching is not enabled for the psql indexer type via CometBFT’s RPC—any
such query will fail.
Note that the SQL schema is stored in state/indexer/sink/psql/schema.sql, and operators
must explicitly create the relations prior to starting CometBFT and enabling
the psql indexer type.
Example:
Default Indexes
The CometBFT transaction and block event indexer indexes a few select reserved events by default.Transactions
The following indexes are indexed by default:tx.heighttx.hash
Blocks
The following indexes are indexed by default:block.height
Adding Events
Applications are free to define which events to index. CometBFT does not expose functionality to define which events to index and which to ignore. In your application’sFinalizeBlock method, add the Events field with pairs of
UTF-8 encoded strings (e.g., “transfer.sender”: “Bob”, “transfer.recipient”:
“Alice”, “transfer.balance”: “100”).
Example:
null, the transaction will be indexed. Each event is
indexed using a composite key in the form of {eventType}.{eventAttribute}={eventValue},
e.g., transfer.sender=bob.
Querying Transaction Events
You can query for a paginated set of transactions by their events by calling the/tx_search RPC endpoint:
tx_search endpoint
for more information on query syntax and other options.
Subscribing to Transactions
Clients can subscribe to transactions with the given tags via WebSocket by providing a query to the/subscribe RPC endpoint.
Querying Block Events
You can query for a paginated set of blocks by their events by calling the/block_search RPC endpoint:
Event Attribute Value Types
Users can use anything as an event value. However, if the event attribute value is a number, the following needs to be taken into account:- Negative numbers will not be properly retrieved when querying the indexer.
- Event values are converted to big floats (from the
big/mathpackage). The precision of the floating-point number is set to the bit length of the integer it is supposed to represent, so that there is no loss of information due to insufficient precision. This was not present before CometBFT v0.38.x, and all float values were ignored. - As of CometBFT v0.38.x, queries can contain floating-point numbers as well.
- Note that comparing to floats can be imprecise with a high number of decimals.
Event Type and Attribute Key Format
An event type/attribute key is a string that can contain any Unicode letter or digit, as well as the following characters:. (dot), - (dash), _
(underscore). The event type/attribute key must not start with - (dash) or
. (dot).