ABCI 中现有的方法
Echo
- 请求:
Message (string): 要回显的字符串
- 响应:
Message (string): 输入字符串
- 用法:
- 回显一个字符串,以测试 ABCI 客户端/服务端实现
Flush
- 用法:
- 表示应将客户端中排队的消息刷新并发送到服务端。客户端实现会周期性调用它,以确保异步请求实际被发送;也会立即调用它来发起同步请求,该请求会在收到 Flush 响应后返回。
Info
-
请求:
名称 类型 描述 字段编号 version string CometBFT 软件的语义版本 1 block_version uint64 CometBFT Block 版本 2 p2p_version uint64 CometBFT P2P 版本 3 abci_version string CometBFT ABCI 语义版本 4 -
响应:
名称 类型 描述 字段编号 确定性 data string 任意信息 1 N/A version string 应用软件的语义版本 2 N/A app_version uint64 应用版本 3 N/A last_block_height int64 应用持久化其状态时对应的最新高度 4 N/A last_block_app_hash bytes FinalizeBlock返回的最新 AppHash5 N/A -
用法:
- 返回有关应用状态的信息。
- 用于在启动或恢复时发生的握手过程中,将 CometBFT 与应用进行同步。
- 返回的
app_version会包含在每个区块的 Header 中。 - CometBFT 期望在
Commit期间更新并持久化last_block_app_hash和last_block_height。
注意:语义版本指的是 semantic versioning。Info 中的语义版本会显示为 X.X.x。
InitChain
-
请求:
名称 类型 描述 字段编号 time google.protobuf.Timestamp 创世时间 1 chain_id string 区块链的 ID。 2 consensus_params ConsensusParams 初始的共识关键参数。 3 validators repeated ValidatorUpdate 初始创世验证者,按投票权排序。 4 app_state_bytes bytes 序列化后的初始应用状态,JSON 字节。 5 initial_height int64 初始区块高度(通常为 1)。6 -
响应:
名称 类型 描述 字段编号 确定性 consensus_params ConsensusParams 初始的共识关键参数(可选) 1 是 validators repeated ValidatorUpdate 初始验证者集合(可选)。 2 是 app_hash bytes 初始应用哈希。 3 是 -
用法:
- 在创世时调用一次。
- 如果
ResponseInitChain.Validators为空,则初始验证者集合将采用RequestInitChain.Validators。 - 如果
ResponseInitChain.Validators非空,则它将作为初始验证者集合(无论RequestInitChain.Validators中是什么)。 - 这使应用能够决定是接受 CometBFT 提议的初始验证者集合(即创世文件中的集合),还是使用不同的集合(可能基于创世文件中的某些应用特定信息计算得到)。
RequestInitChain.Validators和ResponseInitChain.Validators都是 ValidatorUpdate 结构体。 因此,从技术上讲,它们都是在从空集合开始对验证者集合进行“更新”。
Query
-
请求:
名称 类型 描述 字段编号 data bytes 供应用解释的请求参数,其语义类似于 URI query component。可与 path配合使用,或替代path。1 path string 供应用解释的请求路径,其语义类似于例如路由中的 URI path component。可与 data配合使用,或替代data。应用 MUST 将"/store"或任何以"/store/"开头的路径解释为对底层存储按键查询,此时 SHOULD 在data中指定键。应用 SHOULD 允许对特定类型进行查询,例如/accounts/...或/votes/...。2 height int64 要查询的区块高度(默认值 0返回最新已提交区块的数据)。注意,这里的高度是包含应用 Merkle 根哈希的区块高度,它表示的是在提交 Height-1 区块之后的状态。3 prove bool 如果可能,在响应中返回 Merkle 证明。 4 -
响应:
名称 类型 描述 字段编号 确定性 code uint32 响应码。 1 N/A log string 应用日志记录器的输出。 3 N/A info string 附加信息。 4 N/A index int64 该键在树中的索引。 5 N/A key bytes 匹配数据的键。 6 N/A value bytes 匹配数据的值。 7 N/A proof_ops ProofOps 如果请求了证明,则为值数据的序列化证明,可针对给定 Height 的 app_hash进行验证。8 N/A height int64 数据来源的区块高度。注意,这里的高度是包含应用 Merkle 根哈希的区块高度,它表示的是在提交 Height-1 区块之后的状态。 9 N/A codespace string code的命名空间。10 N/A -
用法:
- 在当前高度或历史高度向应用查询数据。
- 可选地返回 Merkle 证明。
- Merkle 证明包含自描述的
type字段,以支持多种 Merkle 树类型和编码格式。
CheckTx
-
请求:
名称 类型 描述 字段编号 tx bytes 请求中的交易字节 1 type CheckTxType CheckTx_New或CheckTx_Recheck之一。CheckTx_New是默认值,表示需要对交易进行完整检查。CheckTx_Recheck用于内存池对交易发起常规重新检查时。2 -
响应:
名称 类型 描述 字段编号 确定性 code uint32 响应码。 1 N/A data bytes 结果字节(如果有)。 2 N/A log string 应用日志记录器的输出。 3 N/A info string 附加信息。 4 N/A gas_wanted int64 交易请求的 gas 数量。 5 N/A gas_used int64 交易消耗的 gas 数量。 6 N/A events repeated Event 用于索引交易的类型与键值事件(例如按账户索引)。 7 N/A codespace string code的命名空间。8 N/A -
用法:
- 从技术上讲是可选的,不参与区块处理。
- 内存池的守门人:每个节点都会在允许交易进入本地 mempool 之前运行
CheckTx。 - 交易可能来自外部用户,也可能来自其他节点。
CheckTx会根据应用当前状态验证交易,例如检查签名和账户余额,但不会应用交易描述的任何状态变更。- 当
ResponseCheckTx.Code != 0时,交易会被拒绝,不会广播给其他节点,也不会包含在提议区块中。 CometBFT 不对该响应码赋予其他含义。
Commit
参数与类型
- 请求: Commit 表示通知应用持久化应用状态。它不接收任何参数。
-
响应:
名称 类型 描述 字段编号 确定性 retain_height int64 低于该高度的区块可以被移除。默认值为 0(全部保留)。3 否 -
用法:
- 通知应用持久化应用状态。
预期应用会在此次调用结束时、调用
ResponseCommit之前持久化其状态。 - 请谨慎使用
ResponseCommit.retain_height!如果网络中的所有节点都删除历史区块,那么这些数据将永久丢失,除非链上启用了状态同步,否则新节点将无法加入网络并完成引导。历史区块也可能用于其他目的,例如审计、重放未持久化高度、轻客户端验证等。
- 通知应用持久化应用状态。
预期应用会在此次调用结束时、调用
ListSnapshots
- 请求: 空请求,要求应用返回快照列表。
-
响应:
名称 类型 描述 字段编号 确定性 snapshots repeated Snapshot 本地状态快照列表。 1 N/A -
用法:
- 在状态同步期间用于发现对等节点上可用的快照。
- 详情见
Snapshot数据类型。
LoadSnapshotChunk
-
请求:
名称 类型 描述 字段编号 height uint64 该分块所属快照的高度。 1 format uint32 该分块所属快照的应用特定格式。 2 chunk uint32 分块索引,从初始分块的 0开始。3 -
响应:
名称 类型 描述 字段编号 确定性 chunk bytes 任意格式的二进制分块内容。分块消息大小不能超过 16 MB(包括元数据),因此 10 MB 是一个不错的起点。 1 N/A -
用法:
- 在状态同步期间用于从对等节点检索快照分块。
OfferSnapshot
-
请求:
名称 类型 描述 字段编号 snapshot Snapshot 提供用于恢复的快照。 1 app_hash bytes 该高度对应、来自区块链并经轻客户端验证的 app hash。 2 -
响应:
名称 类型 描述 字段编号 确定性 result Result 快照提供的处理结果。 1 N/A
Result
- 用法:
- 使用状态同步为节点引导时会调用
OfferSnapshot。应用可以按需接受或拒绝快照。接受后,CometBFT 将通过ApplySnapshotChunk获取并应用快照分块。应用也可以选择在分块响应阶段拒绝某个快照,此时它应准备好接受后续的OfferSnapshot调用。 - 只有
AppHash可以被信任,因为它已经过轻客户端验证。其他任何数据都可能被对手伪造,因此应用应采用额外的校验机制,以避免拒绝服务攻击。已验证的AppHash会在快照恢复结束时自动与恢复后的应用进行校验。 - 更多信息请参见
Snapshot数据类型或状态同步章节。
- 使用状态同步为节点引导时会调用
ApplySnapshotChunk
-
请求:
名称 类型 描述 字段编号 index uint32 分块索引,从 0开始。CometBFT 按顺序应用分块。1 chunk bytes 二进制分块内容,由 LoadSnapshotChunk返回。2 sender string 发送该分块的节点的 P2P ID。 3 -
响应:
名称 类型 描述 字段编号 确定性 result Result (see below) 应用该分块的结果。 1 N/A refetch_chunks repeated uint32 无论 result如何,都重新获取并重新应用给定分块。只会重新获取列出的分块,并按顺序重新应用。2 N/A reject_senders repeated string 无论 Result如何,都拒绝给定的 P2P 发送者。已应用的分块不会被重新获取,除非显式请求;但来自这些发送者的排队分块会被丢弃,新的分块或其他快照也会被拒绝。3 N/A
- 用法:
- 应用可以按需选择重新获取分块和/或封禁 P2P 对等节点。除非应用明确指示,否则 CometBFT 不会这样做。
- 应用可能希望验证每个分块,例如在
Snapshot.Metadata中附加分块哈希,和/或针对AppHash增量校验内容。 - 当所有分块都被接受后,CometBFT 会发起一次 ABCI
Info调用,以验证LastBlockAppHash和LastBlockHeight是否与预期值一致,并将AppVersion记录到节点状态中。随后它会切换到区块同步或共识流程并加入网络。 - 如果 CometBFT 在一段时间后仍无法获取下一个分块(例如因为没有合适的对等节点可用),它会拒绝该快照,并通过
OfferSnapshot尝试另一个快照。应用应准备好按需重置并接受它,或中止流程。
ABCI 2.0 中引入的新方法
PrepareProposal
参数与类型
-
请求:
名称 类型 描述 字段编号 max_tx_bytes int64 当前配置下,修改后交易总共允许占用的最大字节数。 1 txs repeated bytes 作为待提议区块一部分而初步选出的交易列表。 2 local_last_commit ExtendedCommitInfo 从 CometBFT 本地数据结构中获取的上一轮提交信息。 3 misbehavior repeated Misbehavior 关于作恶验证者的信息列表。 4 height int64 将要被提议的区块高度。 5 time google.protobuf.Timestamp 将要被提议的区块的时间戳。 6 next_validators_hash bytes 下一验证者集合的 Merkle 根。 7 proposer_address bytes 创建该提议的验证者的 Address。 8 -
响应:
名称 类型 描述 字段编号 确定性 txs repeated bytes 可能经过修改的交易列表,将作为提议区块的一部分。 2 否 -
用法:
RequestPrepareProposal的参数txs、misbehavior、height、time、next_validators_hash和proposer_address与RequestProcessProposal和RequestFinalizeBlock中相同。RequestPrepareProposal.local_last_commit是前一高度的 precommit 投票集合,其中包括促成前一个区块决议的那些投票,以及它们对应的 vote extension。height、time和proposer_address的值与提议区块头中的值一致。RequestPrepareProposal包含一组由 CometBFT 从 mempool 中取出的初步交易txs,称为 raw proposal。应用可以修改该集合,并通过ResponsePrepareProposal.txs返回修改后的交易集合。- 应用 可以 修改原始提议:可以重排、删除或新增交易。
设
tx为txs(即RequestPrepareProposal中的交易集合)中的一笔交易:- 如果应用认为
tx不应在该区块中被提议,例如存在优先级更高的其他交易,则不应在ResponsePrepareProposal.txs中包含它。但这不会将tx从 mempool 中移除。 - 如果应用想向提议区块中新增一笔交易,则应将其包含在
ResponsePrepareProposal.txs中。CometBFT 不会将该交易加入 mempool。
- 如果应用认为
- 应用应注意,删除和新增交易可能会破坏 traceability。
考虑如下示例:应用将客户端提交的交易
t1转换为第二笔交易t2,也就是说,应用要求 CometBFT 将t1从区块中移除,并将t2加入区块。如果客户端最终想检查t1发生了什么,它会发现t1不在任何已提交区块中(假设一次 re-CheckTx 将其从 mempool 中驱逐),从而错误地认为t1没有进入区块。注意,t2会 出现在某个已提交区块中,但除非应用自行跟踪这一信息,否则没有任何组件会知道这一点。因此,如果应用希望具备可追踪性,支持它就是应用自身的责任。例如,应用可以在转换后的交易上附加一个列表,其中包含它所派生自的交易哈希。
- 应用 可以 修改原始提议:可以重排、删除或新增交易。
设
- 应用 MAY 配置 CometBFT,使其在
RequestPrepareProposal.txs中包含一组交易,这些交易的总字节大小可能超过RequestPrepareProposal.max_tx_bytes。 如果应用将ConsensusParams.Block.MaxBytes设为 -1,CometBFT 将把 mempool 中当前的 所有 交易都放入RequestPrepareProposal.txs,这可能无法放入RequestPrepareProposal.max_tx_bytes。 因此,如果RequestPrepareProposal.txs的大小大于RequestPrepareProposal.max_tx_bytes,应用 MUST 移除部分交易,以确保ResponsePrepareProposal.txs返回的交易满足RequestPrepareProposal.max_tx_bytes限制。 这一点在 Requirement 2 中有说明。 - 作为执行已准备提议的结果,应用可能会生成区块事件或交易事件。
应用必须保留这些事件,直到区块被决定,然后通过
ResponseFinalizeBlock将它们传递给 CometBFT。 - CometBFT 不会提供任何额外的有效性检查(例如检查重复交易)。
- 如果 CometBFT 无法验证
ResponsePrepareProposal,它将认为应用有故障并崩溃。 PrepareProposal的实现 MAY 是非确定性的。
CometBFT 在什么时候调用 PrepareProposal?
当验证者 p 进入共识轮次 r、高度 h,且在该轮中 p 是 proposer,
并且 p 的 validValue 为 nil 时:
- CometBFT 从 p 的 mempool 收集待处理交易
- 交易将按优先级顺序收集
- p 的 CometBFT 会创建一个区块头。
- p 的 CometBFT 使用新生成的区块、前一高度的本地 commit(含 vote extension)以及任何待处理的作恶证据来调用
RequestPrepareProposal。该调用是同步的:CometBFT 的执行会阻塞,直到应用从调用中返回。 - 应用使用收到的信息(交易、commit 信息、作恶信息、时间)来(可能地)修改提议。
- 应用 MAY 完整执行该区块并生成候选状态(即时执行)
- 应用可以操作交易:
- 保持交易不变
- 向提议中添加新交易(最初不存在的交易)
- 从提议中移除交易(但不从 mempool 中移除,因此实际上只是 延后 它们) - 应用不在
ResponsePrepareProposal.txs中包含该交易。 - 修改交易(例如聚合交易)。如上所述,这会破坏客户端可追踪性,除非在应用层实现了相应支持。
- 重新排序交易 - 应用对列表中的交易重新排序
- 应用 MAY 使用 commit 信息中的 vote extension 来修改提议;在这种情况下,建议按
VerifyVoteExtension中的方式验证这些 extension,因为在达到最小 +2/3 之后才包含进 commit 信息的投票 extension 并未被验证。
- 应用在返回参数中包含交易列表(无论是否修改,参见 用法 一节中的规则),并从调用中返回。
- p 在轮次 r、高度 h 中将(可能已修改的)区块作为 p 的提议。
nil 的 validValue,
则共识算法会直接将其用作提议,而不会调用 RequestPrepareProposal。
ProcessProposal
参数与类型
-
请求:
名称 类型 描述 字段编号 txs repeated bytes 提议区块中的交易列表。 1 proposed_last_commit CommitInfo 从提议区块中的信息获得的上一轮提交信息。 2 misbehavior repeated Misbehavior 关于作恶验证者的信息列表。 3 hash bytes 提议区块的哈希。 4 height int64 提议区块的高度。 5 time google.protobuf.Timestamp 提议区块的时间戳。 6 next_validators_hash bytes 下一验证者集合的 Merkle 根。 7 proposer_address bytes 创建该提议的验证者的 Address。 8 -
响应:
名称 类型 描述 字段编号 确定性 status ProposalStatus 用于表示应用是否认为该提议有效的 enum。1 是 -
用法:
- 包含完整执行提议区块所需的全部信息。
- 应用可以像处理
RequestFinalizeBlock一样完整执行该区块。 - 但是,任何由此产生的状态变更都必须保留为 candidate state,并且应用应准备好在最终决定的是其他区块时将其丢弃。
- 应用可以像处理
RequestProcessProposal也会在某一轮的 proposer 节点上被调用。 通常,RequestProcessProposal会在RequestPrepareProposal调用之后立刻发生,且RequestProcessProposal会与基于ResponsePrepareProposal生成的区块相匹配(即RequestPrepareProposal.txs等于RequestProcessProposal.txs)。 但是并不保证这一点,因为在存在故障时,RequestProcessProposal可能匹配更早一次调用的ResponsePrepareProposal,或者ProcessProposal可能根本不会被调用。- 高度和时间值与提议区块头中的值一致。
- 如果
ResponseProcessProposal.status为REJECT,共识会认为收到的提议无效。 - 应用 MAY 完整执行该区块(即时执行)。
ProcessProposal的实现 MUST 是确定性的。此外,ResponseProcessProposal.status的值 MUST 仅 依赖于传入RequestProcessProposal调用的参数,以及最近一次已提交的应用状态(参见 Requirements 章节)。- 此外,应用实现者 SHOULD 始终将
ResponseProcessProposal.status设为ACCEPT,除非他们 确实 清楚返回REJECT可能带来的活性影响。
- 包含完整执行提议区块所需的全部信息。
CometBFT 在什么时候调用 ProcessProposal?
当节点 p 进入共识轮次 r、高度 h,且在该轮中 q 是 proposer(可能 p = q)时:
- p 设置定时器
ProposeTimeout。 - 如果 p 是 proposer,则 p 执行 PrepareProposal 中的步骤 1-6。
- 当收到来自 q 的轮次 r、高度 h 的 Proposal 消息(其中包含区块头)时,p 验证区块头。
- 当收到来自 q 的轮次 r、高度 h 的 Proposal 消息以及所有区块部分后,p 按照验证者算法检查自己应当为所提议区块还是
nil投 prevote。 - 如果验证者的共识算法表明 p 应为非 nil 值投 prevote:
- CometBFT 使用该区块调用
RequestProcessProposal。该调用是同步的。 - 应用检查/处理该提议区块(只读),并在
ResponseProcessProposal.status字段中返回ACCEPT或REJECT。- 应用可根据自身需求调用
ResponseProcessProposal- 要么在完整处理完该区块后再返回(即时执行),
- 要么只做一些基础检查后返回,并异步处理该区块。在这种情况下,应用之后将无法再拒绝该区块,或强制 prevote/precommit
nil。 - 或者如果 p 不是验证者且应用不希望非验证节点处理
ProcessProposal,则可以立即返回ACCEPT。
- 应用可根据自身需求调用
- 如果 p 是验证者,且返回值为
ACCEPT:p 在轮次 r、高度 h 为该提议投 prevote。REJECT:p 投nil的 prevote。
- CometBFT 使用该区块调用
ExtendVote
参数与类型
-
请求:
名称 类型 描述 字段编号 hash bytes vote extension 所引用的提议区块的头部哈希。 1 height int64 提议区块的高度(用于健全性检查)。 2 time google.protobuf.Timestamp 提议区块的时间戳(vote extension 将引用它)。 3 txs repeated bytes vote extension 将引用的区块交易列表。 4 proposed_last_commit CommitInfo 上一个提议区块的上一轮提交信息。 5 misbehavior repeated Misbehavior 提议区块中包含的关于作恶验证者的信息列表。 6 next_validators_hash bytes 提议区块中包含的下一验证者集合的 Merkle 根。 7 proposer_address bytes 创建该提议的验证者的 Address。 8 -
响应:
名称 类型 描述 字段编号 确定性 vote_extension bytes 由 CometBFT 签名的信息。长度可以为 0。 1 否 -
用法:
ResponseExtendVote.vote_extension是由应用生成的信息,会由 CometBFT 签名并附加到 Precommit 消息上。- 应用可以选择使用空的 vote extension(长度为 0)。
RequestExtendVote的内容对应于共识算法将要发送 Precommit 消息的那个提议区块。ResponseExtendVote.vote_extension只会附加到非nil的 Precommit 消息上。如果共识算法将要 precommitnil,则不会调用RequestExtendVote。- 生成该 extension 的应用逻辑可以是非确定性的。
CometBFT 在什么时候调用 ExtendVote?
当验证者 p 处于轮次 r、高度 h 的共识状态 prevote,其中 q 是 proposer;且 p 已收到
- 来自 q 的轮次 r、高度 h 的 Proposal 消息 v 以及所有区块部分,
- 来自 2f + 1 个验证者投票权、针对轮次 r、高度 h、为同一区块 id(v) 投 prevote 的
Prevote消息,
- p 将 lockedValue 和 validValue 设为 v,并将 lockedRound 和 validRound 设为 r
- p 的 CometBFT 使用 v(
RequestExtendVote)调用RequestExtendVote。该调用是同步的。 - 应用返回一个字节数组
ResponseExtendVote.extension,共识算法不会解释其内容。 - p 将
ResponseExtendVote.extension设为类型为 CanonicalVoteExtension 的extension字段值,填充 CanonicalVoteExtension 中的其他字段,并对填充后的数据结构进行签名。 - p 构造并签名 CanonicalVote 结构。
- p 使用 CanonicalVoteExtension 和 CanonicalVote 构造 Precommit 消息(即 Vote 结构)。
- p 广播 Precommit 消息。
precommit nil 消息时(无论是收到 2f+1 个 prevote nil 消息,还是触发了 timeoutPrevote),p 的 CometBFT 不会 调用 RequestExtendVote,也不会在 precommit nil 消息中包含 CanonicalVoteExtension 字段。
VerifyVoteExtension
参数与类型
-
请求:
名称 类型 描述 字段编号 hash bytes vote extension 所引用的提议区块的哈希。 1 validator_address bytes 对该 extension 进行签名的验证者的 Address。 2 height int64 区块高度(用于健全性检查)。 3 vote_extension bytes 由 CometBFT 签名的应用特定信息。长度可以为 0。 4 -
响应:
名称 类型 描述 字段编号 确定性 status VerifyStatus 用于表示应用是否接受该 vote extension 的 enum1 是 -
用法:
RequestVerifyVoteExtension.vote_extension可以是空字节数组。应用对此的解释应是:发送该投票的进程上运行的应用选择不扩展它。即便 vote extension 长度为 0,CometBFT 仍然总会调用RequestVerifyVoteExtension。RequestVerifyVoteExtension不会针对本地进程发送的 precommit 投票被调用。RequestVerifyVoteExtension.hash指向一个提议区块。不能保证该提议区块此前一定已通过ProcessProposal暴露给应用。- 如果
ResponseVerifyVoteExtension.status为REJECT,共识算法将拒绝整个收到的投票。 请参见 Requirements 章节,以了解这对活性的潜在影响。 VerifyVoteExtension的实现 MUST 是确定性的。此外,ResponseVerifyVoteExtension.status的值 MUST 仅 依赖于传入RequestVerifyVoteExtension调用的参数,以及最近一次已提交的应用状态(参见 Requirements 章节)。- 此外,应用实现者 SHOULD 始终将
ResponseVerifyVoteExtension.status设为ACCEPT,除非他们 确实 清楚返回REJECT可能带来的活性影响。
CometBFT 在什么时候调用 VerifyVoteExtension?
当节点 p 处于共识轮次 r、高度 h,且 p 收到来自验证者 q(q ≠ p)的轮次 r、高度 h 的 Precommit 消息时:
- 如果 Precommit 消息不包含带有有效签名的 vote extension,p 会将该 Precommit 消息作为无效消息丢弃。
- 长度为 0 的 vote extension 只要其附带签名同样有效,就是有效的。
- 否则,p 的 CometBFT 调用
RequestVerifyVoteExtension。 - 应用通过
ResponseVerifyVoteExtension.status返回ACCEPT或REJECT。 - 如果应用返回
ACCEPT,p 会保留收到的投票及其对应的 vote extension,并存入其内部数据结构。在高度 h + 1 的某些轮次中、当 p 是 proposer 时,这些信息会用于填充RequestPrepareProposal调用中的 ExtendedCommitInfo 结构。REJECT,p 会将该 Precommit 消息视为无效并丢弃。
RequestVerifyVoteExtension 进行验证的情况下,将该 Precommit 消息及其关联 extension 添加到 ExtendedCommitInfo 中。
FinalizeBlock
参数与类型
-
请求:
名称 类型 描述 字段编号 txs repeated bytes 作为该区块一部分被提交的交易列表。 1 decided_last_commit CommitInfo 刚刚被决定的区块中获得的上一轮提交信息。 2 misbehavior repeated Misbehavior 关于作恶验证者的信息列表。 3 hash bytes 该区块的哈希。 4 height int64 已完成最终确定的区块高度。 5 time google.protobuf.Timestamp 已完成最终确定的区块时间戳。 6 next_validators_hash bytes 下一验证者集合的 Merkle 根。 7 proposer_address bytes 创建该提议的验证者的 Address。 8 -
响应:
名称 类型 描述 字段编号 确定性 events repeated Event 用于索引的类型与键值事件 1 否 tx_results repeated ExecTxResult 包含执行交易后结果数据的结构列表 2 是 validator_updates repeated ValidatorUpdate 验证者集合的变更(将投票权设为 0 以移除)。 3 是 consensus_param_updates ConsensusParams 对 gas、大小及其他共识相关参数的变更。 4 是 app_hash bytes 应用状态的 Merkle 根哈希。 5 是 -
用法:
- 包含新近决定的区块字段。
- 该方法等价于 ABCI 1.0 中的调用序列
BeginBlock、[DeliverTx] 和EndBlock。 - 高度和时间值与提议区块头中的值一致。
- 应用可以使用
RequestFinalizeBlock.decided_last_commit和RequestFinalizeBlock.misbehavior来确定验证者的奖励和惩罚。 - 应用会按照自身设定的规则,以确定性的方式执行
RequestFinalizeBlock.txs中的交易,然后再将控制权返回给 CometBFT。 或者,它也可以应用先前通过PrepareProposal或ProcessProposal执行过的同一区块对应的候选状态。 - 仅当第 i 笔交易完全有效时,
ResponseFinalizeBlock.tx_results[i].Code == 0。 - 应用必须基于区块执行结果,为
ResponseFinalizeBlock.app_hash、ResponseFinalizeBlock.tx_results、ResponseFinalizeBlock.validator_updates和ResponseFinalizeBlock.consensus_param_updates提供值。ResponseFinalizeBlock.validator_updates或ResponseFinalizeBlock.consensus_param_updates的值可以为空。在这种情况下,CometBFT 将保留当前值。- 由区块
H触发的ResponseFinalizeBlock.validator_updates会影响区块H+1、H+2和H+3的验证。验证者更新后的高度影响如下:- 高度
H+1:NextValidatorsHash包含新的validator_updates值。 - 高度
H+2:验证者集合变更生效,ValidatorsHash被更新。 - 高度
H+3:PrepareProposal、ProcessProposal和FinalizeBlock中的*_last_commit字段现在包含变更后的验证者集合。
- 高度
- 为区块
H返回的ResponseFinalizeBlock.consensus_param_updates会应用到区块H+1的共识参数。关于共识参数的更多信息,请参见共识参数章节。
ResponseFinalizeBlock.app_hash包含应用状态的(可选)Merkle 根哈希。ResponseFinalizeBlock.app_hash会作为下一个区块中的Header.AppHash被包含进去。ResponseFinalizeBlock.app_hash也可以为空或写死,但 MUST 是 确定性的,即它不能依赖于RequestFinalizeBlock参数和先前已提交状态之外的任何内容。
- 后续对
Query的调用可以返回以该 Merkle 根哈希为锚点的应用状态证明。 FinalizeBlock的实现 MUST 是确定性的,因为它会在状态机复制的上下文中推动应用状态演进。- 目前,即便
RequestPrepareProposal或RequestProcessProposal已将相关字段传给应用,CometBFT 仍会填充RequestFinalizeBlock的所有字段。 - 当对某个区块调用
FinalizeBlock时,CometBFT 运行的共识算法保证至少有一个非拜占庭验证者已经对该区块运行过ProcessProposal。
CometBFT 在什么时候调用 FinalizeBlock?
当节点 p 处于共识高度 h,且 p 收到
- 来自 q 的轮次 r、高度 h 的 Proposal 消息及其区块 v 的所有区块部分,其中 q 是该轮次的 proposer,
- 来自 2f + 1 个验证者投票权、针对轮次 r、高度 h、为同一区块 id(v) 投 precommit 的
Precommit消息,
- p 将 v 持久化为高度 h 的决议结果。
- p 的 CometBFT 使用 v 的数据调用
RequestFinalizeBlock。该调用是同步的。 - p 的应用执行区块 v。
- p 的应用计算并返回 AppHash,以及一个包含每笔已执行交易输出的列表。
- p 的 CometBFT 对所有交易输出进行哈希,并将其存储在 ResultHash 中。
- p 的 CometBFT 持久化交易输出、AppHash 和 ResultsHash。
- p 的 CometBFT 锁定 mempool — 不再对新交易调用
CheckTx。 - p 的 CometBFT 调用
RequestCommit,指示应用持久化其状态。 - p 的 CometBFT 可选地根据新持久化的应用状态,重新检查 mempool 中所有待处理交易。
- p 的 CometBFT 解锁 mempool — 新收到的交易现在可以被检查。
- p 在高度 h+1、轮次 0 开始新一轮共识
ABCI 中现有的数据类型
ABCI 中使用的大多数数据结构都是共享的通用数据结构。在某些情况下,ABCI 使用了不同的数据结构,这些结构在此处记录:Validator
-
字段:
名称 类型 描述 字段编号 address bytes 验证者的 Address 1 power int64 验证者的投票权 3 -
用法:
- 通过地址标识验证者
- 作为
CommitInfo中VoteInfo的一部分使用(用于ProcessProposal和FinalizeBlock),以及ExtendedCommitInfo(用于PrepareProposal)。 - 不包含 PubKey,以避免通过 ABCI 发送可能很大的量子公钥
ValidatorUpdate
-
字段:
名称 类型 描述 字段编号 确定性 pub_key Public Key 验证者的公钥 1 是 power int64 验证者的投票权 2 是 -
用法:
- 通过 PubKey 标识验证者
- 用于告知 CometBFT 更新验证者集合
Misbehavior
-
字段:
名称 类型 描述 字段编号 type MisbehaviorType 作恶类型。一个可能作恶行为的枚举。 1 validator Validator 违规的验证者 2 height int64 违规发生时的高度 3 time google.protobuf.Timestamp 在高度 height提交的区块时间戳4 total_voting_power int64 在高度 height时验证者集合的总投票权5
MisbehaviorType
-
字段
MisbehaviorType 是一个枚举,包含以下字段:
名称 字段编号 UNKNOWN 0 DUPLICATE_VOTE 1 LIGHT_CLIENT_ATTACK 2
ConsensusParams
-
字段:
名称 类型 描述 字段编号 确定性 block BlockParams 限制区块大小和相邻区块间时间的参数。 1 是 evidence EvidenceParams 限制作恶行为证据有效性的参数。 2 是 validator ValidatorParams 限制验证者可使用公钥类型的参数。 3 是 version VersionsParams ABCI 应用版本。 4 是
ProofOps
-
字段:
名称 类型 描述 字段编号 确定性 ops repeated ProofOp 链式 Merkle 证明列表,可能包含不同类型。某个 op 的 Merkle 根是下一个 op 中被证明的值。最终 op 的 Merkle 根应等于要进行验证的最终根哈希。 1 N/A
ProofOp
-
字段:
名称 类型 描述 字段编号 确定性 type string Merkle 证明的类型及其编码方式。 1 N/A key bytes 该证明对应的 Merkle 树中的键。 2 N/A data bytes 该键对应的编码后 Merkle 证明。 3 N/A
Snapshot
-
字段:
名称 类型 描述 字段编号 确定性 height uint64 生成快照时的高度(在 commit 之后)。 1 N/A format uint32 应用特定的快照格式,允许应用对快照数据格式进行版本化并进行不向后兼容的变更。CometBFT 不解释该值。 2 N/A chunks uint32 快照中的分块数。必须至少为 1(即便为空)。 3 N/A hash bytes 任意的快照哈希。只有当跨节点的快照完全相同时,它才必须相等。CometBFT 不解释该哈希,只做比较。 4 N/A metadata bytes 任意的应用元数据,例如分块哈希或其他校验数据。 5 N/A -
用法:
- 用于状态同步快照,详情请参见状态同步章节。
- 只有当 所有 字段都相等(包括
Metadata)时,快照才会被视为跨节点相同。分块可以从所有拥有相同快照的节点获取。 - 在网络上传输时,快照消息最大不能超过 4 MB。
ABCI++ 中引入或修改的数据类型
VoteInfo
-
字段:
名称 类型 描述 字段编号 validator Validator 发送投票的验证者。 1 block_id_flag BlockIDFlag 表示验证者是为上一个区块投票、为 nil 投票,还是其投票未被收到。 3 -
用法:
- 表示验证者是否签署了上一个区块,从而可以基于验证者可用性进行奖励。
- 该信息通常从提议区块或已决定区块中提取。
ExtendedVoteInfo
-
字段:
名称 类型 描述 字段编号 validator Validator 发送投票的验证者。 1 vote_extension bytes 由发送方验证者的应用提供的非确定性扩展。 3 extension_signature bytes 由发送方验证者生成并经 CometBFT 验证的 vote extension 签名。 4 block_id_flag BlockIDFlag 表示验证者是为上一个区块投票、为 nil 投票,还是其投票未被收到。 5 -
用法:
- 表示验证者是否签署了上一个区块,从而可以基于验证者可用性进行奖励。
- 该信息从本地进程中的 CometBFT 数据结构提取。
vote_extension包含发送方验证者的 vote extension,其签名已经过 CometBFT 验证。它可以为空。extension_signature是 vote extension 的签名,该签名已经过 CometBFT 验证。这样应用便可以暴露该签名,以便进一步处理或验证。
CommitInfo
-
字段:
名称 类型 描述 字段编号 round int32 提交轮次。反映区块 proposer 在上一高度作出决议时所在的轮次。 1 votes repeated VoteInfo 上一个验证者集合中各验证者地址及其投票信息的列表。 2 -
说明
votes中的VoteInfo按验证者投票权排序(降序,从高到低)。- CometBFT 通过其更新验证者集合的逻辑来保证
votes的顺序;在该逻辑结束时,验证者会按投票权降序排列。 - 当验证者集合被保存到存储中时,这一顺序也会被持久化。
- 构建
CommitInfo时,验证者集合会从存储中加载,从而确保沿用持久化验证者集合的顺序。
ExtendedCommitInfo
-
字段:
名称 类型 描述 字段编号 round int32 提交轮次。反映区块 proposer 在上一高度作出决议时所在的轮次。 1 votes repeated ExtendedVoteInfo 上一个验证者集合中各验证者地址及其投票信息的列表,包含 vote extension。 2 -
说明
votes中的ExtendedVoteInfo按验证者投票权排序(降序,从高到低)。- CometBFT 通过其更新验证者集合的逻辑来保证
votes的顺序;在该逻辑结束时,验证者会按投票权降序排列。 - 当验证者集合被保存到存储中时,这一顺序也会被持久化。
- 构建
ExtendedCommitInfo时,验证者集合会从存储中加载,从而确保沿用持久化验证者集合的顺序。
ExecTxResult
-
字段:
名称 类型 描述 字段编号 确定性 code uint32 响应码。 1 是 data bytes 结果字节(如果有)。 2 是 log string 应用日志记录器的输出。 3 否 info string 附加信息。 4 否 gas_wanted int64 交易请求的 gas 数量。 5 是 gas_used int64 交易消耗的 gas 数量。 6 是 events repeated Event 用于索引交易的类型与键值事件(例如按账户索引)。 7 否 codespace string code的命名空间。8 是
ProposalStatus
- 用法:
- 用于 ProcessProposal 的响应中。
- 如果
Status为UNKNOWN,说明应用发生了问题。CometBFT 会认为应用有故障并崩溃。 - 如果
Status为ACCEPT,共识算法会接受该提议,并为其发出 Prevote 消息。 - 如果
Status为REJECT,共识算法会拒绝该提议,并改为为nil发出 Prevote。
- 如果
- 用于 ProcessProposal 的响应中。
VerifyStatus
- 用法:
- 用于 VerifyVoteExtension 的响应中。
- 如果
Status为UNKNOWN,说明应用发生了问题。CometBFT 会认为应用有故障并崩溃。 - 如果
Status为ACCEPT,共识算法会接受该投票并认为其有效。 - 如果
Status为REJECT,共识算法会拒绝该投票并认为其无效。
- 如果
- 用于 VerifyVoteExtension 的响应中。
Methods existing in ABCI
Echo
- Request:
Message (string): A string to echo back
- Response:
Message (string): The input string
- Usage:
- Echo a string to test an ABCI client/server implementation
Flush
- Usage:
- Signals that messages queued on the client should be flushed to the server. It is called periodically by the client implementation to ensure asynchronous requests are actually sent, and is called immediately to make a synchronous request, which returns when the Flush response comes back.
Info
-
Request:
Name Type Description Field Number version string The CometBFT software semantic version 1 block_version uint64 The CometBFT Block version 2 p2p_version uint64 The CometBFT P2P version 3 abci_version string The CometBFT ABCI semantic version 4 -
Response:
Name Type Description Field Number Deterministic data string Some arbitrary information 1 N/A version string The application software semantic version 2 N/A app_version uint64 The application version 3 N/A last_block_height int64 Latest height for which the app persisted its state 4 N/A last_block_app_hash bytes Latest AppHash returned by FinalizeBlock5 N/A -
Usage:
- Return information about the application state.
- Used to sync CometBFT with the application during a handshake that happens on startup or on recovery.
- The returned
app_versionwill be included in the Header of every block. - CometBFT expects
last_block_app_hashandlast_block_heightto be updated and persisted duringCommit.
Note: Semantic version is a reference to semantic versioning. Semantic versions in info will be displayed as X.X.x.
InitChain
-
Request:
Name Type Description Field Number time google.protobuf.Timestamp Genesis time 1 chain_id string ID of the blockchain. 2 consensus_params ConsensusParams Initial consensus-critical parameters. 3 validators repeated ValidatorUpdate Initial genesis validators, sorted by voting power. 4 app_state_bytes bytes Serialized initial application state. JSON bytes. 5 initial_height int64 Height of the initial block (typically 1).6 -
Response:
Name Type Description Field Number Deterministic consensus_params ConsensusParams Initial consensus-critical parameters (optional) 1 Yes validators repeated ValidatorUpdate Initial validator set (optional). 2 Yes app_hash bytes Initial application hash. 3 Yes -
Usage:
- Called once upon genesis.
- If
ResponseInitChain.Validatorsis empty, the initial validator set will be theRequestInitChain.Validators - If
ResponseInitChain.Validatorsis not empty, it will be the initial validator set (regardless of what is inRequestInitChain.Validators). - This allows the app to decide if it wants to accept the initial validator set proposed by CometBFT (ie. in the genesis file), or if it wants to use a different one (perhaps computed based on some application specific information in the genesis file).
- Both
RequestInitChain.ValidatorsandResponseInitChain.Validatorsare ValidatorUpdate structs. So, technically, they both are updating the set of validators from the empty set.
Query
-
Request:
Name Type Description Field Number data bytes Request parameters for the application to interpret analogously to a URI query component. Can be used with or in lieu of path.1 path string A request path for the application to interpret analogously to a URI path component in e.g. routing. Can be used with or in lieu of data. Applications MUST interpret “/store” or any path starting with “/store/” as a query by key on the underlying store, in which case a key SHOULD be specified indata. Applications SHOULD allow queries over specific types like/accounts/...or/votes/....2 height int64 The block height against which to query (default=0 returns data for the latest committed block). Note that this is the height of the block containing the application’s Merkle root hash, which represents the state as it was after committing the block at Height-1. 3 prove bool Return Merkle proof with response if possible. 4 -
Response:
Name Type Description Field Number Deterministic code uint32 Response code. 1 N/A log string The output of the application’s logger. 3 N/A info string Additional information. 4 N/A index int64 The index of the key in the tree. 5 N/A key bytes The key of the matching data. 6 N/A value bytes The value of the matching data. 7 N/A proof_ops ProofOps Serialized proof for the value data, if requested, to be verified against the app_hashfor the given Height.8 N/A height int64 The block height from which data was derived. Note that this is the height of the block containing the application’s Merkle root hash, which represents the state as it was after committing the block at Height-1 9 N/A codespace string Namespace for the code.10 N/A -
Usage:
- Query for data from the application at current or past height.
- Optionally return Merkle proof.
- Merkle proof includes self-describing
typefield to support many types of Merkle trees and encoding formats.
CheckTx
-
Request:
Name Type Description Field Number tx bytes The request transaction bytes 1 type CheckTxType One of CheckTx_NeworCheckTx_Recheck.CheckTx_Newis the default and means that a full check of the tranasaction is required.CheckTx_Rechecktypes are used when the mempool is initiating a normal recheck of a transaction.2 -
Response:
Name Type Description Field Number Deterministic code uint32 Response code. 1 N/A data bytes Result bytes, if any. 2 N/A log string The output of the application’s logger. 3 N/A info string Additional information. 4 N/A gas_wanted int64 Amount of gas requested for transaction. 5 N/A gas_used int64 Amount of gas consumed by transaction. 6 N/A events repeated Event Type & Key-Value events for indexing transactions (e.g. by account). 7 N/A codespace string Namespace for the code.8 N/A -
Usage:
- Technically optional - not involved in processing blocks.
- Guardian of the mempool: every node runs
CheckTxbefore letting a transaction into its local mempool. - The transaction may come from an external user or another node
CheckTxvalidates the transaction against the current state of the application, for example, checking signatures and account balances, but does not apply any of the state changes described in the transaction.- Transactions where
ResponseCheckTx.Code != 0will be rejected - they will not be broadcast to other nodes or included in a proposal block. CometBFT attributes no other value to the response code.
Commit
Parameters and Types
- Request: Commit signals the application to persist application state. It takes no parameters.
-
Response:
Name Type Description Field Number Deterministic retain_height int64 Blocks below this height may be removed. Defaults to 0(retain all).3 No -
Usage:
- Signal the Application to persist the application state.
Application is expected to persist its state at the end of this call, before calling
ResponseCommit. - Use
ResponseCommit.retain_heightwith caution! If all nodes in the network remove historical blocks then this data is permanently lost, and no new nodes will be able to join the network and bootstrap, unless state sync is enabled on the chain. Historical blocks may also be required for other purposes, e.g. auditing, replay of non-persisted heights, light client verification, and so on.
- Signal the Application to persist the application state.
Application is expected to persist its state at the end of this call, before calling
ListSnapshots
- Request: Empty request asking the application for a list of snapshots.
-
Response:
Name Type Description Field Number Deterministic snapshots repeated Snapshot List of local state snapshots. 1 N/A -
Usage:
- Used during state sync to discover available snapshots on peers.
- See
Snapshotdata type for details.
LoadSnapshotChunk
-
Request:
Name Type Description Field Number height uint64 The height of the snapshot the chunk belongs to. 1 format uint32 The application-specific format of the snapshot the chunk belongs to. 2 chunk uint32 The chunk index, starting from 0for the initial chunk.3 -
Response:
Name Type Description Field Number Deterministic chunk bytes The binary chunk contents, in an arbitrary format. Chunk messages cannot be larger than 16 MB including metadata, so 10 MB is a good starting point. 1 N/A -
Usage:
- Used during state sync to retrieve snapshot chunks from peers.
OfferSnapshot
-
Request:
Name Type Description Field Number snapshot Snapshot The snapshot offered for restoration. 1 app_hash bytes The light client-verified app hash for this height, from the blockchain. 2 -
Response:
Name Type Description Field Number Deterministic result Result The result of the snapshot offer. 1 N/A
Result
- Usage:
OfferSnapshotis called when bootstrapping a node using state sync. The application may accept or reject snapshots as appropriate. Upon accepting, CometBFT will retrieve and apply snapshot chunks viaApplySnapshotChunk. The application may also choose to reject a snapshot in the chunk response, in which case it should be prepared to accept furtherOfferSnapshotcalls.- Only
AppHashcan be trusted, as it has been verified by the light client. Any other data can be spoofed by adversaries, so applications should employ additional verification schemes to avoid denial-of-service attacks. The verifiedAppHashis automatically checked against the restored application at the end of snapshot restoration. - For more information, see the
Snapshotdata type or the state sync section.
ApplySnapshotChunk
-
Request:
Name Type Description Field Number index uint32 The chunk index, starting from 0. CometBFT applies chunks sequentially.1 chunk bytes The binary chunk contents, as returned by LoadSnapshotChunk.2 sender string The P2P ID of the node who sent this chunk. 3 -
Response:
Name Type Description Field Number Deterministic result Result (see below) The result of applying this chunk. 1 N/A refetch_chunks repeated uint32 Refetch and reapply the given chunks, regardless of result. Only the listed chunks will be refetched, and reapplied in sequential order.2 N/A reject_senders repeated string Reject the given P2P senders, regardless of Result. Any chunks already applied will not be refetched unless explicitly requested, but queued chunks from these senders will be discarded, and new chunks or other snapshots rejected.3 N/A
- Usage:
- The application can choose to refetch chunks and/or ban P2P peers as appropriate. CometBFT will not do this unless instructed by the application.
- The application may want to verify each chunk, e.g. by attaching chunk hashes in
Snapshot.Metadataand/or incrementally verifying contents againstAppHash. - When all chunks have been accepted, CometBFT will make an ABCI
Infocall to verify thatLastBlockAppHashandLastBlockHeightmatches the expected values, and record theAppVersionin the node state. It then switches to block sync or consensus and joins the network. - If CometBFT is unable to retrieve the next chunk after some time (e.g. because no suitable
peers are available), it will reject the snapshot and try a different one via
OfferSnapshot. The application should be prepared to reset and accept it or abort as appropriate.
New methods introduced in ABCI 2.0
PrepareProposal
Parameters and Types
-
Request:
Name Type Description Field Number max_tx_bytes int64 Currently configured maximum size in bytes taken by the modified transactions. 1 txs repeated bytes Preliminary list of transactions that have been picked as part of the block to propose. 2 local_last_commit ExtendedCommitInfo Info about the last commit, obtained locally from CometBFT’s data structures. 3 misbehavior repeated Misbehavior List of information about validators that misbehaved. 4 height int64 The height of the block that will be proposed. 5 time google.protobuf.Timestamp Timestamp of the block that that will be proposed. 6 next_validators_hash bytes Merkle root of the next validator set. 7 proposer_address bytes Address of the validator that is creating the proposal. 8 -
Response:
Name Type Description Field Number Deterministic txs repeated bytes Possibly modified list of transactions that have been picked as part of the proposed block. 2 No -
Usage:
RequestPrepareProposal’s parameterstxs,misbehavior,height,time,next_validators_hash, andproposer_addressare the same as inRequestProcessProposalandRequestFinalizeBlock.RequestPrepareProposal.local_last_commitis a set of the precommit votes for the previous height, including the ones that led to the decision of the previous block, together with their corresponding vote extensions.- The
height,time, andproposer_addressvalues match the values from the header of the proposed block. RequestPrepareProposalcontains a preliminary set of transactionstxsthat CometBFT retrieved from the mempool, called raw proposal. The Application can modify this set and return a modified set of transactions viaResponsePrepareProposal.txs.- The Application can modify the raw proposal: it can reorder, remove or add transactions.
Let
txbe a transaction intxs(set of transactions withinRequestPrepareProposal):- If the Application considers that
txshould not be proposed in this block, e.g., there are other transactions with higher priority, then it should not include it inResponsePrepareProposal.txs. However, this will not removetxfrom the mempool. - If the Application wants to add a new transaction to the proposed block, then the
Application includes it in
ResponsePrepareProposal.txs. CometBFT will not add the transaction to the mempool.
- If the Application considers that
- The Application should be aware that removing and adding transactions may compromise
traceability.
Consider the following example: the Application transforms a client-submitted transaction
t1into a second transactiont2, i.e., the Application asks CometBFT to removet1from the block and addt2to the block. If a client wants to eventually check what happened tot1, it will discover thatt1is not in a committed block (assuming a re-CheckTx evicted it from the mempool), getting the wrong idea thatt1did not make it into a block. Note thatt2will be in a committed block, but unless the Application tracks this information, no component will be aware of it. Thus, if the Application wants traceability, it is its responsibility’s to support it. For instance, the Application could attach to a transformed transaction a list with the hashes of the transactions it derives from.
- The Application can modify the raw proposal: it can reorder, remove or add transactions.
Let
- The Application MAY configure CometBFT to include a list of transactions in
RequestPrepareProposal.txswhose total size in bytes exceedsRequestPrepareProposal.max_tx_bytes. If the Application setsConsensusParams.Block.MaxBytesto -1, CometBFT will include all transactions currently in the mempool inRequestPrepareProposal.txs, which may not fit inRequestPrepareProposal.max_tx_bytes. Therefore, if the size ofRequestPrepareProposal.txsis greater thanRequestPrepareProposal.max_tx_bytes, the Application MUST remove transactions to ensure that theRequestPrepareProposal.max_tx_byteslimit is respected by those transactions returned inResponsePrepareProposal.txs. This is specified in Requirement 2. - As a result of executing the prepared proposal, the Application may produce block events or transaction events.
The Application must keep those events until a block is decided and then pass them on to CometBFT via
ResponseFinalizeBlock. - CometBFT does NOT provide any additional validity checks (such as checking for duplicate transactions).
- If CometBFT fails to validate the
ResponsePrepareProposal, CometBFT will assume the Application is faulty and crash. - The implementation of
PrepareProposalMAY be non-deterministic.
When does CometBFT call “PrepareProposal” ?
When a validator p enters consensus round r, height h, in which p is the proposer, and p’s validValue isnil:
- CometBFT collects outstanding transactions from p’s mempool
- the transactions will be collected in order of priority
- p’s CometBFT creates a block header.
- p’s CometBFT calls
RequestPrepareProposalwith the newly generated block, the local commit of the previous height (with vote extensions), and any outstanding evidence of misbehavior. The call is synchronous: CometBFT’s execution will block until the Application returns from the call. - The Application uses the information received (transactions, commit info, misbehavior, time) to
(potentially) modify the proposal.
- the Application MAY fully execute the block and produce a candidate state (immediate execution)
- the Application can manipulate transactions:
- leave transactions untouched
- add new transactions (not present initially) to the proposal
- remove transactions from the proposal (but not from the mempool thus effectively delaying them) - the
Application does not include the transaction in
ResponsePrepareProposal.txs. - modify transactions (e.g. aggregate them). As explained above, this compromises client traceability, unless it is implemented at the Application level.
- reorder transactions - the Application reorders transactions in the list
- the Application MAY use the vote extensions in the commit info to modify the proposal, in which case it is suggested
that extensions be validated in the same maner as done in
VerifyVoteExtension, since extensions of votes included in the commit info after the minimum of +2/3 had been reached are not verified.
- The Application includes the transaction list (whether modified or not) in the return parameters (see the rules in section Usage), and returns from the call.
- p uses the (possibly) modified block as p’s proposal in round r, height h.
nil validValue in round r, height h,
the consensus algorithm will use it as proposal and will not call RequestPrepareProposal.
ProcessProposal
Parameters and Types
-
Request:
Name Type Description Field Number txs repeated bytes List of transactions of the proposed block. 1 proposed_last_commit CommitInfo Info about the last commit, obtained from the information in the proposed block. 2 misbehavior repeated Misbehavior List of information about validators that misbehaved. 3 hash bytes The hash of the proposed block. 4 height int64 The height of the proposed block. 5 time google.protobuf.Timestamp Timestamp of the proposed block. 6 next_validators_hash bytes Merkle root of the next validator set. 7 proposer_address bytes Address of the validator that created the proposal. 8 -
Response:
Name Type Description Field Number Deterministic status ProposalStatus enumthat signals if the application finds the proposal valid.1 Yes -
Usage:
- Contains all information on the proposed block needed to fully execute it.
- The Application may fully execute the block as though it was handling
RequestFinalizeBlock. - However, any resulting state changes must be kept as candidate state, and the Application should be ready to discard it in case another block is decided.
- The Application may fully execute the block as though it was handling
RequestProcessProposalis also called at the proposer of a round. Normally the call toRequestProcessProposaloccurs right after the call toRequestPrepareProposalandRequestProcessProposalmatches the block produced based onResponsePrepareProposal(i.e.,RequestPrepareProposal.txsequalsRequestProcessProposal.txs). However, no such guarantee is made since, in the presence of failures,RequestProcessProposalmay matchResponsePrepareProposalfrom an earlier invocation orProcessProposalmay not be invoked at all.- The height and time values match the values from the header of the proposed block.
- If
ResponseProcessProposal.statusisREJECT, consensus assumes the proposal received is not valid. - The Application MAY fully execute the block (immediate execution)
- The implementation of
ProcessProposalMUST be deterministic. Moreover, the value ofResponseProcessProposal.statusMUST exclusively depend on the parameters passed in the call toRequestProcessProposal, and the last committed Application state (see Requirements section). - Moreover, application implementors SHOULD always set
ResponseProcessProposal.statustoACCEPT, unless they really know what the potential liveness implications of returningREJECTare.
- Contains all information on the proposed block needed to fully execute it.
When does CometBFT call “ProcessProposal” ?
When a node p enters consensus round r, height h, in which q is the proposer (possibly p = q):- p sets up timer
ProposeTimeout. - If p is the proposer, p executes steps 1-6 in PrepareProposal.
- Upon reception of Proposal message (which contains the header) for round r, height h from q, p verifies the block header.
- Upon reception of Proposal message, along with all the block parts, for round r, height h
from q, p follows the validators’ algorithm to check whether it should prevote for the
proposed block, or
nil. - If the validators’ consensus algorithm indicates p should prevote non-nil:
- CometBFT calls
RequestProcessProposalwith the block. The call is synchronous. - The Application checks/processes the proposed block, which is read-only, and returns
ACCEPTorREJECTin theResponseProcessProposal.statusfield.- The Application, depending on its needs, may call
ResponseProcessProposal- either after it has completely processed the block (immediate execution),
- or after doing some basic checks, and process the block asynchronously. In this case the
Application will not be able to reject the block, or force prevote/precommit
nilafterwards. - or immediately, returning
ACCEPT, if p is not a validator and the Application does not want non-validating nodes to handleProcessProposal
- The Application, depending on its needs, may call
- If p is a validator and the returned value is
ACCEPT: p prevotes on this proposal for round r, height h.REJECT: p prevotesnil.
- CometBFT calls
ExtendVote
Parameters and Types
-
Request:
Name Type Description Field Number hash bytes The header hash of the proposed block that the vote extension is to refer to. 1 height int64 Height of the proposed block (for sanity check). 2 time google.protobuf.Timestamp Timestamp of the proposed block (that the extension is to refer to). 3 txs repeated bytes List of transactions of the block that the extension is to refer to. 4 proposed_last_commit CommitInfo Info about the last proposed block’s last commit. 5 misbehavior repeated Misbehavior List of information about validators that misbehaved contained in the proposed block. 6 next_validators_hash bytes Merkle root of the next validator set contained in the proposed block. 7 proposer_address bytes Address of the validator that created the proposal. 8 -
Response:
Name Type Description Field Number Deterministic vote_extension bytes Information signed by by CometBFT. Can have 0 length. 1 No -
Usage:
ResponseExtendVote.vote_extensionis application-generated information that will be signed by CometBFT and attached to the Precommit message.- The Application may choose to use an empty vote extension (0 length).
- The contents of
RequestExtendVotecorrespond to the proposed block on which the consensus algorithm will send the Precommit message. ResponseExtendVote.vote_extensionwill only be attached to a non-nilPrecommit message. If the consensus algorithm is to precommitnil, it will not callRequestExtendVote.- The Application logic that creates the extension can be non-deterministic.
When does CometBFT call ExtendVote?
When a validator p is in consensus state prevote of round r, height h, in which q is the proposer; and p has received
- the Proposal message v for round r, height h, along with all the block parts, from q,
Prevotemessages from 2f + 1 validators’ voting power for round r, height h, prevoting for the same block id(v),
- p sets lockedValue and validValue to v, and sets lockedRound and validRound to r
- p’s CometBFT calls
RequestExtendVotewith v (RequestExtendVote). The call is synchronous. - The Application returns an array of bytes,
ResponseExtendVote.extension, which is not interpreted by the consensus algorithm. - p sets
ResponseExtendVote.extensionas the value of theextensionfield of type CanonicalVoteExtension, populates the other fields in CanonicalVoteExtension, and signs the populated data structure. - p constructs and signs the CanonicalVote structure.
- p constructs the Precommit message (i.e. Vote structure) using CanonicalVoteExtension and CanonicalVote.
- p broadcasts the Precommit message.
precommit nil messages (either 2f+1 prevote nil messages received,
or timeoutPrevote triggered), p’s CometBFT does not call RequestExtendVote and will not include
a CanonicalVoteExtension field in the precommit nil message.
VerifyVoteExtension
Parameters and Types
-
Request:
Name Type Description Field Number hash bytes The hash of the proposed block that the vote extension refers to. 1 validator_address bytes Address of the validator that signed the extension. 2 height int64 Height of the block (for sanity check). 3 vote_extension bytes Application-specific information signed by CometBFT. Can have 0 length. 4 -
Response:
Name Type Description Field Number Deterministic status VerifyStatus enumsignaling if the application accepts the vote extension1 Yes -
Usage:
RequestVerifyVoteExtension.vote_extensioncan be an empty byte array. The Application’s interpretation of it should be that the Application running at the process that sent the vote chose not to extend it. CometBFT will always callRequestVerifyVoteExtension, even for 0 length vote extensions.RequestVerifyVoteExtensionis not called for precommit votes sent by the local process.RequestVerifyVoteExtension.hashrefers to a proposed block. There is not guarantee that this proposed block has previously been exposed to the Application viaProcessProposal.- If
ResponseVerifyVoteExtension.statusisREJECT, the consensus algorithm will reject the whole received vote. See the Requirements section to understand the potential liveness implications of this. - The implementation of
VerifyVoteExtensionMUST be deterministic. Moreover, the value ofResponseVerifyVoteExtension.statusMUST exclusively depend on the parameters passed in the call toRequestVerifyVoteExtension, and the last committed Application state (see Requirements section). - Moreover, application implementers SHOULD always set
ResponseVerifyVoteExtension.statustoACCEPT, unless they really know what the potential liveness implications of returningREJECTare.
When does CometBFT call VerifyVoteExtension?
When a node p is in consensus round r, height h, and p receives a Precommit
message for round r, height h from validator q (q ≠ p):
- If the Precommit message does not contain a vote extension with a valid signature, p
discards the Precommit message as invalid.
- a 0-length vote extension is valid as long as its accompanying signature is also valid.
- Else, p’s CometBFT calls
RequestVerifyVoteExtension. - The Application returns
ACCEPTorREJECTviaResponseVerifyVoteExtension.status. - If the Application returns
ACCEPT, p will keep the received vote, together with its corresponding vote extension in its internal data structures. It will be used to populate the ExtendedCommitInfo structure in calls toRequestPrepareProposal, in rounds of height h + 1 where p is the proposer.REJECT, p will deem the Precommit message invalid and discard it.
RequestVerifyVoteExtension to verify it.
FinalizeBlock
Parameters and Types
-
Request:
Name Type Description Field Number txs repeated bytes List of transactions committed as part of the block. 1 decided_last_commit CommitInfo Info about the last commit, obtained from the block that was just decided. 2 misbehavior repeated Misbehavior List of information about validators that misbehaved. 3 hash bytes The block’s hash. 4 height int64 The height of the finalized block. 5 time google.protobuf.Timestamp Timestamp of the finalized block. 6 next_validators_hash bytes Merkle root of the next validator set. 7 proposer_address bytes Address of the validator that created the proposal. 8 -
Response:
Name Type Description Field Number Deterministic events repeated Event Type & Key-Value events for indexing 1 No tx_results repeated ExecTxResult List of structures containing the data resulting from executing the transactions 2 Yes validator_updates repeated ValidatorUpdate Changes to validator set (set voting power to 0 to remove). 3 Yes consensus_param_updates ConsensusParams Changes to gas, size, and other consensus-related parameters. 4 Yes app_hash bytes The Merkle root hash of the application state. 5 Yes -
Usage:
- Contains the fields of the newly decided block.
- This method is equivalent to the call sequence
BeginBlock, [DeliverTx], andEndBlockin ABCI 1.0. - The height and time values match the values from the header of the proposed block.
- The Application can use
RequestFinalizeBlock.decided_last_commitandRequestFinalizeBlock.misbehaviorto determine rewards and punishments for the validators. - The Application executes the transactions in
RequestFinalizeBlock.txsdeterministically, according to the rules set up by the Application, before returning control to CometBFT. Alternatively, it can apply the candidate state corresponding to the same block previously executed viaPrepareProposalorProcessProposal. ResponseFinalizeBlock.tx_results[i].Code == 0only if the i-th transaction is fully valid.- The Application must provide values for
ResponseFinalizeBlock.app_hash,ResponseFinalizeBlock.tx_results,ResponseFinalizeBlock.validator_updates, andResponseFinalizeBlock.consensus_param_updatesas a result of executing the block.- The values for
ResponseFinalizeBlock.validator_updates, orResponseFinalizeBlock.consensus_param_updatesmay be empty. In this case, CometBFT will keep the current values. ResponseFinalizeBlock.validator_updates, triggered by blockH, affect validation for blocksH+1,H+2, andH+3. Heights following a validator update are affected in the following way:- Height
H+1:NextValidatorsHashincludes the newvalidator_updatesvalue. - Height
H+2: The validator set change takes effect andValidatorsHashis updated. - Height
H+3:*_last_commitfields inPrepareProposal,ProcessProposal, andFinalizeBlocknow include the altered validator set.
- Height
ResponseFinalizeBlock.consensus_param_updatesreturned for blockHapply to the consensus params for blockH+1. For more information on the consensus parameters, see the consensus parameters section.
- The values for
ResponseFinalizeBlock.app_hashcontains an (optional) Merkle root hash of the application state.ResponseFinalizeBlock.app_hashis included as theHeader.AppHashin the next block.ResponseFinalizeBlock.app_hashmay also be empty or hard-coded, but MUST be deterministic - it must not be a function of anything that did not come from the parameters ofRequestFinalizeBlockand the previous committed state.
- Later calls to
Querycan return proofs about the application state anchored in this Merkle root hash. - The implementation of
FinalizeBlockMUST be deterministic, since it is making the Application’s state evolve in the context of state machine replication. - Currently, CometBFT will fill up all fields in
RequestFinalizeBlock, even if they were already passed on to the Application viaRequestPrepareProposalorRequestProcessProposal. - When calling
FinalizeBlockwith a block, the consensus algorithm run by CometBFT guarantees that at least one non-byzantine validator has runProcessProposalon that block.
When does CometBFT call FinalizeBlock?
When a node p is in consensus height h, and p receives
- the Proposal message with block v for a round r, along with all its block parts, from q, which is the proposer of round r, height h,
Precommitmessages from 2f + 1 validators’ voting power for round r, height h, precommitting the same block id(v),
- p persists v as the decision for height h.
- p’s CometBFT calls
RequestFinalizeBlockwith v’s data. The call is synchronous. - p’s Application executes block v.
- p’s Application calculates and returns the AppHash, along with a list containing the outputs of each of the transactions executed.
- p’s CometBFT hashes all the transaction outputs and stores it in ResultHash.
- p’s CometBFT persists the transaction outputs, AppHash, and ResultsHash.
- p’s CometBFT locks the mempool — no calls to
CheckTxon new transactions. - p’s CometBFT calls
RequestCommitto instruct the Application to persist its state. - p’s CometBFT, optionally, re-checks all outstanding transactions in the mempool against the newly persisted Application state.
- p’s CometBFT unlocks the mempool — newly received transactions can now be checked.
- p starts consensus for height h+1, round 0
Data Types existing in ABCI
Most of the data structures used in ABCI are shared common data structures. In certain cases, ABCI uses different data structures which are documented here:Validator
-
Fields:
Name Type Description Field Number address bytes Address of validator 1 power int64 Voting power of the validator 3 -
Usage:
- Validator identified by address
- Used as part of
VoteInfowithinCommitInfo(used inProcessProposalandFinalizeBlock), andExtendedCommitInfo(used inPrepareProposal). - Does not include PubKey to avoid sending potentially large quantum pubkeys over the ABCI
ValidatorUpdate
-
Fields:
Name Type Description Field Number Deterministic pub_key Public Key Public key of the validator 1 Yes power int64 Voting power of the validator 2 Yes -
Usage:
- Validator identified by PubKey
- Used to tell CometBFT to update the validator set
Misbehavior
-
Fields:
Name Type Description Field Number type MisbehaviorType Type of the misbehavior. An enum of possible misbehaviors. 1 validator Validator The offending validator 2 height int64 Height when the offense occurred 3 time google.protobuf.Timestamp Timestamp of the block that was committed at height height4 total_voting_power int64 Total voting power of the validator set at height height5
MisbehaviorType
-
Fields
MisbehaviorType is an enum with the listed fields:
Name Field Number UNKNOWN 0 DUPLICATE_VOTE 1 LIGHT_CLIENT_ATTACK 2
ConsensusParams
-
Fields:
Name Type Description Field Number Deterministic block BlockParams Parameters limiting the size of a block and time between consecutive blocks. 1 Yes evidence EvidenceParams Parameters limiting the validity of evidence of byzantine behaviour. 2 Yes validator ValidatorParams Parameters limiting the types of public keys validators can use. 3 Yes version VersionsParams The ABCI application version. 4 Yes
ProofOps
-
Fields:
Name Type Description Field Number Deterministic ops repeated ProofOp List of chained Merkle proofs, of possibly different types. The Merkle root of one op is the value being proven in the next op. The Merkle root of the final op should equal the ultimate root hash being verified against.. 1 N/A
ProofOp
-
Fields:
Name Type Description Field Number Deterministic type string Type of Merkle proof and how it’s encoded. 1 N/A key bytes Key in the Merkle tree that this proof is for. 2 N/A data bytes Encoded Merkle proof for the key. 3 N/A
Snapshot
-
Fields:
Name Type Description Field Number Deterministic height uint64 The height at which the snapshot was taken (after commit). 1 N/A format uint32 An application-specific snapshot format, allowing applications to version their snapshot data format and make backwards-incompatible changes. CometBFT does not interpret this. 2 N/A chunks uint32 The number of chunks in the snapshot. Must be at least 1 (even if empty). 3 N/A hash bytes An arbitrary snapshot hash. Must be equal only for identical snapshots across nodes. CometBFT does not interpret the hash, it only compares them. 4 N/A metadata bytes Arbitrary application metadata, for example chunk hashes or other verification data. 5 N/A -
Usage:
- Used for state sync snapshots, see the state sync section for details.
- A snapshot is considered identical across nodes only if all fields are equal (including
Metadata). Chunks may be retrieved from all nodes that have the same snapshot. - When sent across the network, a snapshot message can be at most 4 MB.
Data types introduced or modified in ABCI++
VoteInfo
-
Fields:
Name Type Description Field Number validator Validator The validator that sent the vote. 1 block_id_flag BlockIDFlag Indicates whether the validator voted the last block, nil, or its vote was not received. 3 -
Usage:
- Indicates whether a validator signed the last block, allowing for rewards based on validator availability.
- This information is typically extracted from a proposed or decided block.
ExtendedVoteInfo
-
Fields:
Name Type Description Field Number validator Validator The validator that sent the vote. 1 vote_extension bytes Non-deterministic extension provided by the sending validator’s Application. 3 extension_signature bytes Signature of the vote extension produced by the sending validator and verified by CometBFT. 4 block_id_flag BlockIDFlag Indicates whether the validator voted the last block, nil, or its vote was not received. 5 -
Usage:
- Indicates whether a validator signed the last block, allowing for rewards based on validator availability.
- This information is extracted from CometBFT’s data structures in the local process.
vote_extensioncontains the sending validator’s vote extension, whose signature was verified by CometBFT. It can be empty.extension_signatureis the signature of the vote extension, which was verified verified by CometBFT. This way, we expose the signature to the application for further processing or verification.
CommitInfo
-
Fields:
Name Type Description Field Number round int32 Commit round. Reflects the round at which the block proposer decided in the previous height. 1 votes repeated VoteInfo List of validators’ addresses in the last validator set with their voting information. 2 -
Notes
- The
VoteInfoinvotesare ordered by the voting power of the validators (descending order, highest to lowest voting power). - CometBFT guarantees the
votesordering through its logic to update the validator set in which, in the end, the validators are sorted (descending) by their voting power. - The ordering is also persisted when a validator set is saved in the store.
- The validator set is loaded from the store when building the
CommitInfo, ensuring order is maintained from the persisted validator set.
- The
ExtendedCommitInfo
-
Fields:
Name Type Description Field Number round int32 Commit round. Reflects the round at which the block proposer decided in the previous height. 1 votes repeated ExtendedVoteInfo List of validators’ addresses in the last validator set with their voting information, including vote extensions. 2 -
Notes
- The
ExtendedVoteInfoinvotesare ordered by the voting power of the validators (descending order, highest to lowest voting power). - CometBFT guarantees the
votesordering through its logic to update the validator set in which, in the end, the validators are sorted (descending) by their voting power. - The ordering is also persisted when a validator set is saved in the store.
- The validator set is loaded from the store when building the
ExtendedCommitInfo, ensuring order is maintained from the persisted validator set.
- The
ExecTxResult
-
Fields:
Name Type Description Field Number Deterministic code uint32 Response code. 1 Yes data bytes Result bytes, if any. 2 Yes log string The output of the application’s logger. 3 No info string Additional information. 4 No gas_wanted int64 Amount of gas requested for transaction. 5 Yes gas_used int64 Amount of gas consumed by transaction. 6 Yes events repeated Event Type & Key-Value events for indexing transactions (e.g. by account). 7 No codespace string Namespace for the code.8 Yes
ProposalStatus
- Usage:
- Used within the ProcessProposal response.
- If
StatusisUNKNOWN, a problem happened in the Application. CometBFT will assume the application is faulty and crash. - If
StatusisACCEPT, the consensus algorithm accepts the proposal and will issue a Prevote message for it. - If
StatusisREJECT, the consensus algorithm rejects the proposal and will issue a Prevote fornilinstead.
- If
- Used within the ProcessProposal response.
VerifyStatus
- Usage:
- Used within the VerifyVoteExtension response.
- If
StatusisUNKNOWN, a problem happened in the Application. CometBFT will assume the application is faulty and crash. - If
StatusisACCEPT, the consensus algorithm will accept the vote as valid. - If
StatusisREJECT, the consensus algorithm will reject the vote as invalid.
- If
- Used within the VerifyVoteExtension response.