区块
一个区块由头部、交易、投票(即提交)以及恶意行为证据列表组成(例如签署相互冲突的投票)。| 名称 | 类型 | 描述 | 验证 |
|---|---|---|---|
| 头部 | Header | 与区块对应的头部。该字段包含在整个共识过程及协议其他部分中使用的信息。要了解其包含的内容,请参见 header | 必须遵循 header 的验证规则 |
| 数据 | Data | 数据包含交易列表。交易的内容对 CometBFT 来说是未知的。 | 该字段可以为空或有内容,但不会执行验证。应用程序可以在创建区块前,使用 checkTx 对单笔交易执行验证。 |
| 证据 | EvidenceList | 证据包含验证者所犯违规行为的列表。 | 可以为空,但当有内容时,适用 evidenceList 中的验证规则 |
| 上一次提交 | Commit | LastCommit 为每个验证者包含一张投票。所有投票都必须是针对前一个区块、nil 或缺失。如果某张投票是针对前一个区块,它必须带有相应验证者的有效签名。已投票验证者的投票权总和必须大于完整验证者集合总投票权的 2/3。一次提交中的投票数量上限为 10000(见 types.MaxVotesCount)。 | 在初始高度时必须为空,并且必须遵循 commit 的验证规则。 |
执行
一旦区块通过验证,就可以针对状态执行它。 状态遵循以下递归方程:InitialState 包含初始共识参数和验证者集合,
而 ABCIApp 是一个 ABCI 应用程序,它可以返回结果以及对验证者
集合的变更(TODO)。Execute 定义如下:
prevote、precommit 和 finalizeCommit 阶段之前完成。
验证新区块的步骤如下:
- 检查区块及其字段的有效性规则。
- 检查版本(Block 和 App)是否与本地状态中的版本一致。
- 检查 chainID 是否匹配。
- 检查高度是否正确。
- 检查
LastBlockID是否与当前状态中的 BlockID 对应。 - 检查头部中的哈希是否与状态中的哈希匹配。
- 根据状态验证 LastCommit,在初始高度时跳过此步骤。
- 这里会检查签名是否对应正确的区块。
- 确保提议者属于验证者集合。
- 验证区块时间。
- 确保新区块时间晚于前一个区块时间。
- 计算 medianTime 并将其与区块时间进行校验。
- 如果区块高度是初始高度,则检查它是否与创世时间匹配。
- 验证区块中的证据。注意:证据可以为空
区块头
区块头包含关于区块和共识的元数据,以及对当前区块数据、前一个区块数据以及应用返回结果的承诺:| 名称 | 类型 | 描述 | 验证 |
|---|---|---|---|
| Version | 版本 | Version 定义了正在使用的应用版本和区块版本。 | 必须遵循 Version 的验证规则 |
| ChainID | String | ChainID 是链的 ID。它在你的链中必须是唯一的。 | ChainID 必须小于 50 字节。 |
| Height | uint64 | Height 是该区块头对应的高度。 | 必须 > 0、>= initialHeight,且 == 前一个 Height + 1 |
| Time | 时间 | 时间戳等于上一次提交中参与验证者的加权中位数。有关时间的更多信息,请参阅 BFT-time 部分。注意:投票的时间戳必须至少比被投票区块的时间戳大 1 毫秒。 | Time 必须 >= 前一个区块头时间戳 + 共识参数 TimeIotaMs。第一个区块的时间戳必须等于创世时间(因为没有投票可用于计算中位数)。 |
| LastBlockID | BlockID | 前一个区块的 BlockID。 | 必须遵循 blockID 的验证规则。第一个区块满足 block.Header.LastBlockID == BlockID{}。 |
| LastCommitHash | 字节切片([]byte) | lastCommit 签名的 MerkleRoot。这些签名表示提交了上一个区块的验证者。第一个区块的该哈希为空字节切片。 | 长度必须为 32 |
| DataHash | 字节切片([]byte) | 交易哈希的 MerkleRoot。注意:交易在被纳入 Merkle 树之前会先进行哈希,因此 Merkle 树的叶子节点是这些哈希,而不是交易本身。 | 长度必须为 32 |
| ValidatorHash | 字节切片([]byte) | 当前验证者集合的 MerkleRoot。在计算 MerkleRoot 之前,会先按投票权重降序排序验证者,再按地址升序排序。 | 长度必须为 32 |
| NextValidatorHash | 字节切片([]byte) | 下一个验证者集合的 MerkleRoot。在计算 MerkleRoot 之前,会先按投票权重降序排序验证者,再按地址升序排序。 | 长度必须为 32 |
| ConsensusHash | 字节切片([]byte) | protobuf 编码后的共识参数哈希。 | 长度必须为 32 |
| AppHash | 字节切片([]byte) | 应用在执行并提交前一个区块后返回的任意字节数组。它作为校验来自 ABCI 应用的任意 merkle 证明的基础,表示的是实际应用的状态,而不是区块链本身的状态。第一个区块的 block.Header.AppHash 由 ResponseInitChain.app_hash 给出。 | 该哈希由应用决定,CometBFT 无法对其执行验证。 |
| LastResultHash | 字节切片([]byte) | LastResultsHash 是基于 ResponseDeliverTx 响应构建的 Merkle 树的根哈希(会忽略 Log、Info、Codespace 和 Events 字段)。 | 长度必须为 32。第一个区块满足 block.Header.ResultsHash == MerkleRoot(nil),即空输入的哈希,以符合 RFC-6962。 |
| EvidenceHash | 字节切片([]byte) | 本区块中包含的拜占庭行为证据的 MerkleRoot。 | 长度必须为 32 |
| ProposerAddress | 字节切片([]byte) | 区块原始提议者的地址。该验证者必须位于当前 validatorSet 中。 | 长度必须为 20 |
版本
注意:这里更具体地说是共识版本,不包含 P2P Version 之类的信息。(TODO:我们应该编写一份关于版本管理的完整文档,以便此处引用)| 名称 | 类型 | 描述 | 验证 |
|---|---|---|---|
| Block | uint64 | 该数值表示区块版本,并且在一个运行中的网络中必须始终保持一致 | 必须等于网络中正在使用的区块版本(block.Version.Block == state.Version.Consensus.Block) |
| App | uint64 | App 版本由应用决定。请阅读此处 | block.Version.App == state.Version.Consensus.App |
BlockID
BlockID 包含区块的两个不同的 Merkle 根。BlockID 包含这两个哈希,以及分片数量(即 len(MakeParts(block)))
| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| Hash | slice of bytes ([]byte) | 头部中所有字段的 MerkleRoot(即 MerkleRoot(header))。 | hash 长度必须为 32 |
| PartSetHeader | PartSetHeader | 用于在共识期间安全地传播区块,是将完整序列化区块切分为多个 part 后的 MerkleRoot(即 MerkleRoot(MakeParts(block)))。 | 必须遵循 PartSetHeader 的校验规则 |
PartSetHeader
| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| Total | int32 | 一个区块的 part 总数 | 必须 > 0 |
| Hash | slice of bytes ([]byte) | 序列化区块的 MerkleRoot | 长度必须为 32 |
Part
Part 定义了区块的一部分。在 CometBFT 中,为了进行 gossip,区块会被拆分为parts。
| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| index | int32 | 一个区块的 part 总数 | 必须 > 0 |
| bytes | bytes | 序列化区块的 MerkleRoot | 长度必须为 32 |
| proof | Proof | 序列化区块的 MerkleRoot | 长度必须为 32 |
Time
CometBFT 使用 Google.Protobuf.Timestamp 格式,该格式使用两个整数:一个 64 位整数表示 Seconds,一个 32 位整数表示 Nanoseconds。Data
Data 只是事务列表的一个封装,其中事务是任意字节数组:| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| Txs | Matrix of bytes ([][]byte) | 事务切片。 | 不对该字段进行校验,这些数据对 CometBFT 来说是未知的 |
Commit
Commit 是签名列表的一个简单封装,每个验证者各有一个签名。它还包含相关的 BlockID、高度和轮次:ExtendedCommit
ExtendedCommit 与 Commit 类似,封装了一个带签名的投票列表,以及验证这些投票所需的其他数据。
此外,它还包含已验证的投票扩展,对每个非 nil 投票各有一个,并带有扩展签名。
| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| Height | int64 | 创建此 commit 时的高度。 | 必须 > 0 |
| Round | int32 | 此 commit 对应的轮次。 | 必须 > 0 |
| BlockID | BlockID | 对应区块的 blockID。 | 必须遵循 BlockID 的校验规则。 |
| ExtendedSignatures | Array of ExtendedCommitSig | 当前验证者集合的 commit 签名、扩展以及扩展签名。 | signatures 的长度必须 > 0,并且每个单独的 ExtendedCommitSig 都必须通过各自的校验 |
CommitSig
CommitSig 表示一个验证者的签名,该验证者要么对 nil 投票,
要么对某个特定的 BlockID 投票,或者处于缺席状态。它是 Commit 的一部分,并且在给定验证者集合时可用于
重建投票集合。
| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| BlockIDFlag | BlockIDFlag | 表示验证者在共识中的参与情况:其投票未被接收、投给了获得多数的区块,或投给了 nil | 必须是 BlockIDFlag 枚举中的字段之一 |
| ValidatorAddress | Address | 验证者地址 | 长度必须为 20 |
| Timestamp | Time | 该字段在不同的 CommitSig 之间会有所不同。它表示验证者的时间戳。 | Time |
| Signature | Signature | 与验证者在共识中的参与情况对应的签名。 | 签名长度必须 > 0 且 < 64 |
ValidatorAddress 和 Timestamp 字段未来可能会被移除
(参见 ADR-25)。
ExtendedCommitSig
ExtendedCommitSig 表示一个验证者的签名,该验证者要么对 nil 投票,
要么对某个特定的 BlockID 投票,或者处于缺席状态。它是 ExtendedCommit 的一部分,并且在给定验证者集合时可用于
重建投票集合。
此外,它还包含附加到每个非 nil precommit 投票上的投票扩展。
所有这些扩展都已经由签名验证者节点上运行的应用完成校验。
| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| BlockIDFlag | BlockIDFlag | 表示验证者在共识中的参与情况:其投票未被接收、投给了获得多数的区块,或投给了 nil | 必须是 BlockIDFlag 枚举中的字段之一 |
| ValidatorAddress | Address | 验证者地址 | 长度必须为 20 |
| Timestamp | Time | 该字段在不同的 CommitSig 之间会有所不同。它表示验证者的时间戳。 | |
| Signature | Signature | 与验证者在共识中的参与情况对应的签名。 | 长度必须 > 0 且 < 64 |
| Extension | bytes | 由运行在 precommit 投票发送者上的应用提供、并由本地应用验证的投票扩展。 | 如果 BlockIDFlag 不是 Commit,长度必须为零 |
| ExtensionSignature | Signature | 投票扩展的签名。 | 如果 BlockIDFlag 是 Commit,长度必须 > 0 且 < 64,否则为 0 |
BlockIDFlag
BlockIDFlag 表示签名对应的是哪个 BlockID。Vote
投票是验证者针对某个特定区块签名的消息。 投票包含签名验证者的信息。在存储到区块链中或通过网络传播时,投票会使用 Protobuf 编码。| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| Type | SignedMsgType | 投票所指消息的类型 | 必须是 PrevoteType 或 PrecommitType |
| Height | int64 | 创建该投票所对应的高度 | 必须 > 0 |
| Round | int32 | 提交所对应的轮次。 | 必须 > 0 |
| BlockID | BlockID | 对应区块的 blockID。 | |
| Timestamp | Time | Timestamp 表示验证者签名时的时间。 | |
| ValidatorAddress | bytes | 验证者地址 | 长度必须等于 20 |
| ValidatorIndex | int32 | 特定区块高度下的索引,对应于该验证者在验证者集合中的索引。 | 必须 > 0 |
| Signature | bytes | 如果验证者参与了对应区块的共识,则为该验证者的签名。 | 长度必须 > 0 且 < 64 |
| Extension | bytes | 由验证者节点上运行的应用程序提供的投票扩展。 | 长度可以为 0 |
| ExtensionSignature | bytes | 扩展的签名 | 长度必须 > 0 且 < 64 |
CanonicalVote
CanonicalVote 用于验证者签名。该类型不会出现在区块中。 投票通过CanonicalVote 表示,并且还会通过 type.SignBytes 使用 protobuf 编码,其中包含 ChainID,
并且字段顺序与通常情况不同。
| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| Type | SignedMsgType | 投票所指消息的类型 | 必须是 PrevoteType 或 PrecommitType |
| Height | int64 | 提供该投票时所在的高度。 | 必须 > 0 |
| Round | int64 | 提供该投票时所在的轮次。 | 必须 > 0 |
| BlockID | string | 投票所指区块的 ID。 | |
| Timestamp | string | 投票的时间。 | |
| ChainID | string | 运行共识的区块链 ID。 |
CanonicalVote 表示,并且还会通过 protobuf 使用
type.SignBytes 编码,其中包含 ChainID,并且字段顺序与通常情况不同。
我们定义一个 Verify 方法:如果签名能够基于给定 ChainID 下的 SignBytes 通过公钥验证,则返回 true:
CanonicalVoteExtension
投票扩展使用与投票类似的表示形式进行签名。 这是为了获得待签名字节或验证签名而需要编组的结构。| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| Extension | bytes | 应用程序提供的投票扩展。 | 可以为零长度 |
| Height | int64 | 提供该扩展时所在的高度。 | 必须 > 0 |
| Round | int64 | 提供该扩展时所在的轮次。 | 必须 > 0 |
| ChainID | string | 运行共识的区块链 ID。 |
Proposal
Proposal 包含该提案对应的高度和轮次、作为提议区块唯一标识的 BlockID、时间戳,以及用于 终止共识的 POLRound(即所谓的 Proof-of-Lock,POL 轮次)。如果 POLRound >= 0,则 BlockID 对应于在 POLRound 中被锁定的区块。该消息由验证者私钥签名。| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| Type | SignedMsgType | 表示一个 Proposal 的 SignedMsgType | 必须是 ProposalType signedMsgType |
| Height | uint64 | 创建该投票所对应的高度 | 必须 > 0 |
| Round | int32 | 提交所对应的轮次。 | 必须 > 0 |
| POLRound | int64 | 锁定证明 | 必须 > 0 |
| BlockID | BlockID | 对应区块的 blockID。 | BlockID |
| Timestamp | Time | Timestamp 表示验证者签名时的时间。 | Time |
| Signature | slice of bytes ([]byte) | 如果验证者参与了对应区块的共识,则为该验证者的签名。 | 签名长度必须 > 0 且 < 64 |
SignedMsgType
签名消息类型表示共识中的签名消息。Signature
CometBFT 中的签名是表示底层签名的原始字节。 更多信息请参见签名规范。EvidenceList
EvidenceList 是证据列表的简单包装:Evidence
CometBFT 中的证据用于表明验证者在共识中存在违规行为。 关于 CometBFT 中证据如何工作的更多信息可参见此处DuplicateVoteEvidence
DuplicateVoteEvidence 表示某个验证者在同一高度的同一轮次中对两个不同区块进行了投票。
投票会按 BlockID 的字典序排序。
LightClientAttackEvidence
LightClientAttackEvidence 是一种通用证据,用于捕获针对轻客户端的所有已知攻击形式,使全节点能够验证、提议并将该证据提交上链,以惩罚恶意验证者。攻击共有三种形式:Lunatic、Equivocation 和 Amnesia。这些攻击形式是穷尽的。你可以在此处找到更详细的概览。
| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| ConflictingBlock | LightBlock | 见下文 | 必须遵循 lightBlock 的校验规则 |
| CommonHeight | int64 | 见下文 | 必须 > 0 |
| Byzantine Validators | Array of Validators | 作恶的验证者 | 见下文 |
| TotalVotingPower | int64 | 发生违规时该高度下验证者集合的总投票权 | 必须与节点自身保存的数据副本一致 |
| Timestamp | Time | 发生违规的区块时间 | 必须与节点自身保存的数据副本一致 |
LightBlock
LightBlock 是轻客户端的核心数据结构。它组合了验证所需的两个数据结构(signedHeader 和 validatorSet)。| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| SignedHeader | SignedHeader | Header 和 Commit,它们用于验证。更多信息请参见轻客户端文档 | 不能为空,并且必须遵循 signedHeader 的校验规则 |
| ValidatorSet | ValidatorSet | validatorSet 用于辅助验证提交该违规行为的验证者是否确实属于该验证者集合。 | 不能为空,并且必须遵循 validatorSet 的校验规则 |
SignedHeader 和 ValidatorSet 通过验证者集合的哈希关联(SignedHeader.ValidatorsHash == ValidatorSet.Hash()。
SignedHeader
SignedhHeader 是附带用于证明它的 commit 的 header。ValidatorSet
Validator
| 名称 | 类型 | 描述 | 校验 |
|---|---|---|---|
| Address | Address | 验证者地址 | 长度必须为 20 |
| Pubkey | slice of bytes ([]byte) | 验证者公钥 | 长度必须大于 0 |
| VotingPower | int64 | 验证者投票权 | 不能小于 0 |
| ProposerPriority | int64 | 验证者的提议优先级,用于衡量某个验证者何时轮到下一次提议区块 | 无校验,值可以为负也可以为正 |
Address
Address 是字节切片类型的别名。该地址通过使用 sha256 对公钥进行哈希并截断为切片的前 20 个字节计算得到。ConsensusParams
| 名称 | 类型 | 描述 | 字段编号 |
|---|---|---|---|
| block | BlockParams | 限制区块大小以及连续区块之间时间间隔的参数。 | 1 |
| evidence | EvidenceParams | 限制拜占庭行为证据有效性的参数。 | 2 |
| validator | ValidatorParams | 限制验证者可使用公钥类型的参数。 | 3 |
| version | BlockParams | ABCI 应用版本。 | 4 |
BlockParams
| 名称 | 类型 | 描述 | 字段编号 |
|---|---|---|---|
| max_bytes | int64 | 区块的最大大小,单位为字节。 | 1 |
| max_gas | int64 | 提议区块中 GasWanted 的最大总和。注意:如果存在拜占庭提议者,违反此限制的区块仍可能被提交。应用程序在处理区块时有责任处理这种情况。 | 2 |
EvidenceParams
| 名称 | 类型 | 描述 | 字段编号 |
|---|---|---|---|
| max_age_num_blocks | int64 | 证据的最大区块年龄。 | 1 |
| max_age_duration | google.protobuf.Duration | 证据的最大时间年龄。它应与应用的“解绑期”或其他用于处理 Nothing-At-Stake 攻击的类似机制相对应。 | 2 |
| max_bytes | int64 | 允许写入区块的全部证据的最大字节大小 | 3 |
ValidatorParams
| 名称 | 类型 | 描述 | 字段编号 |
|---|---|---|---|
| pub_key_types | repeated string | 接受的公钥类型列表。使用与 PubKey.Type 相同的命名。 | 1 |
VersionParams
| 名称 | 类型 | 描述 | 字段编号 |
|---|---|---|---|
| app_version | uint64 | ABCI 应用版本。 | 1 |
Proof
| 名称 | 类型 | 描述 | 字段编号 |
|---|---|---|---|
| total | int64 | 项目总数。 | 1 |
| index | int64 | 需要证明的项目索引。 | 2 |
| leaf_hash | bytes | 项目值的哈希。 | 3 |
| aunts | repeated bytes | 从叶子节点的兄弟节点到根节点子节点的哈希。 | 4 |
Here we describe the data structures in the CometBFT blockchain and the rules for validating them. The CometBFT blockchain consists of a short list of data types:
- Data Structures
Block
A block consists of a header, transactions, votes (the commit), and a list of evidence of malfeasance (ie. signing conflicting votes).| Name | Type | Description | Validation |
|---|---|---|---|
| Header | Header | Header corresponding to the block. This field contains information used throughout consensus and other areas of the protocol. To find out what it contains, visit header | Must adhere to the validation rules of header |
| Data | Data | Data contains a list of transactions. The contents of the transaction is unknown to CometBFT. | This field can be empty or populated, but no validation is performed. Applications can perform validation on individual transactions prior to block creation using checkTx. |
| Evidence | EvidenceList | Evidence contains a list of infractions committed by validators. | Can be empty, but when populated the validations rules from evidenceList apply |
| LastCommit | Commit | LastCommit includes one vote for every validator. All votes must either be for the previous block, nil or absent. If a vote is for the previous block it must have a valid signature from the corresponding validator. The sum of the voting power of the validators that voted must be greater than 2/3 of the total voting power of the complete validator set. The number of votes in a commit is limited to 10000 (see types.MaxVotesCount). | Must be empty for the initial height and must adhere to the validation rules of commit. |
Execution
Once a block is validated, it can be executed against the state. The state follows this recursive equation:InitialState includes the initial consensus parameters and validator set,
and ABCIApp is an ABCI application that can return results and changes to the validator
set (TODO). Execute is defined as:
prevote, precommit & finalizeCommit stages.
The steps to validate a new block are:
- Check the validity rules of the block and its fields.
- Check the versions (Block & App) are the same as in local state.
- Check the chainID’s match.
- Check the height is correct.
- Check the
LastBlockIDcorresponds to BlockID currently in state. - Check the hashes in the header match those in state.
- Verify the LastCommit against state, this step is skipped for the initial height.
- This is where checking the signatures correspond to the correct block will be made.
- Make sure the proposer is part of the validator set.
- Validate bock time.
- Make sure the new blocks time is after the previous blocks time.
- Calculate the medianTime and check it against the blocks time.
- If the blocks height is the initial height then check if it matches the genesis time.
- Validate the evidence in the block. Note: Evidence can be empty
Header
A block header contains metadata about the block and about the consensus, as well as commitments to the data in the current block, the previous block, and the results returned by the application:| Name | Type | Description | Validation |
|---|---|---|---|
| Version | Version | Version defines the application and block versions being used. | Must adhere to the validation rules of Version |
| ChainID | String | ChainID is the ID of the chain. This must be unique to your chain. | ChainID must be less than 50 bytes. |
| Height | uint64 | Height is the height for this header. | Must be > 0, >= initialHeight, and == previous Height+1 |
| Time | Time | The timestamp is equal to the weighted median of validators present in the last commit. Read more on time in the BFT-time section. Note: the timestamp of a vote must be greater by at least one millisecond than that of the block being voted on. | Time must be >= previous header timestamp + consensus parameters TimeIotaMs. The timestamp of the first block must be equal to the genesis time (since there’s no votes to compute the median). |
| LastBlockID | BlockID | BlockID of the previous block. | Must adhere to the validation rules of blockID. The first block has block.Header.LastBlockID == BlockID{}. |
| LastCommitHash | slice of bytes ([]byte) | MerkleRoot of the lastCommit’s signatures. The signatures represent the validators that committed to the last block. The first block has an empty slices of bytes for the hash. | Must be of length 32 |
| DataHash | slice of bytes ([]byte) | MerkleRoot of the hash of transactions. Note: The transactions are hashed before being included in the merkle tree, the leaves of the Merkle tree are the hashes, not the transactions themselves. | Must be of length 32 |
| ValidatorHash | slice of bytes ([]byte) | MerkleRoot of the current validator set. The validators are first sorted by voting power (descending), then by address (ascending) prior to computing the MerkleRoot. | Must be of length 32 |
| NextValidatorHash | slice of bytes ([]byte) | MerkleRoot of the next validator set. The validators are first sorted by voting power (descending), then by address (ascending) prior to computing the MerkleRoot. | Must be of length 32 |
| ConsensusHash | slice of bytes ([]byte) | Hash of the protobuf encoded consensus parameters. | Must be of length 32 |
| AppHash | slice of bytes ([]byte) | Arbitrary byte array returned by the application after executing and commiting the previous block. It serves as the basis for validating any merkle proofs that comes from the ABCI application and represents the state of the actual application rather than the state of the blockchain itself. The first block’s block.Header.AppHash is given by ResponseInitChain.app_hash. | This hash is determined by the application, CometBFT can not perform validation on it. |
| LastResultHash | slice of bytes ([]byte) | LastResultsHash is the root hash of a Merkle tree built from ResponseDeliverTx responses (Log,Info, Codespace and Events fields are ignored). | Must be of length 32. The first block has block.Header.ResultsHash == MerkleRoot(nil), i.e. the hash of an empty input, for RFC-6962 conformance. |
| EvidenceHash | slice of bytes ([]byte) | MerkleRoot of the evidence of Byzantine behavior included in this block. | Must be of length 32 |
| ProposerAddress | slice of bytes ([]byte) | Address of the original proposer of the block. Validator must be in the current validatorSet. | Must be of length 20 |
Version
NOTE: that this is more specifically the consensus version and doesn’t include information like the P2P Version. (TODO: we should write a comprehensive document about versioning that this can refer to)| Name | type | Description | Validation |
|---|---|---|---|
| Block | uint64 | This number represents the block version and must be the same throughout an operational network | Must be equal to block version being used in a network (block.Version.Block == state.Version.Consensus.Block) |
| App | uint64 | App version is decided on by the application. Read here | block.Version.App == state.Version.Consensus.App |
BlockID
TheBlockID contains two distinct Merkle roots of the block. The BlockID includes these two hashes, as well as the number of parts (ie. len(MakeParts(block)))
| Name | Type | Description | Validation |
|---|---|---|---|
| Hash | slice of bytes ([]byte) | MerkleRoot of all the fields in the header (ie. MerkleRoot(header). | hash must be of length 32 |
| PartSetHeader | PartSetHeader | Used for secure gossiping of the block during consensus, is the MerkleRoot of the complete serialized block cut into parts (ie. MerkleRoot(MakeParts(block))). | Must adhere to the validation rules of PartSetHeader |
PartSetHeader
| Name | Type | Description | Validation |
|---|---|---|---|
| Total | int32 | Total amount of parts for a block | Must be > 0 |
| Hash | slice of bytes ([]byte) | MerkleRoot of a serialized block | Must be of length 32 |
Part
Part defines a part of a block. In CometBFT blocks are broken intoparts for gossip.
| Name | Type | Description | Validation |
|---|---|---|---|
| index | int32 | Total amount of parts for a block | Must be > 0 |
| bytes | bytes | MerkleRoot of a serialized block | Must be of length 32 |
| proof | Proof | MerkleRoot of a serialized block | Must be of length 32 |
Time
CometBFT uses the Google.Protobuf.Timestamp format, which uses two integers, one 64 bit integer for Seconds and a 32 bit integer for Nanoseconds.Data
Data is just a wrapper for a list of transactions, where transactions are arbitrary byte arrays:| Name | Type | Description | Validation |
|---|---|---|---|
| Txs | Matrix of bytes ([][]byte) | Slice of transactions. | Validation does not occur on this field, this data is unknown to CometBFT |
Commit
Commit is a simple wrapper for a list of signatures, with one for each validator. It also contains the relevant BlockID, height and round:| Name | Type | Description | Validation |
|---|---|---|---|
| Height | int64 | Height at which this commit was created. | Must be > 0 |
| Round | int32 | Round that the commit corresponds to. | Must be > 0 |
| BlockID | BlockID | The blockID of the corresponding block. | Must adhere to the validation rules of BlockID. |
| Signatures | Array of CommitSig | Array of commit signatures that correspond to current validator set. | Length of signatures must be > 0 and adhere to the validation of each individual Commitsig |
ExtendedCommit
ExtendedCommit, similarly to Commit, wraps a list of votes with signatures together with other data needed to verify them.
In addition, it contains the verified vote extensions, one for each non-nil vote, along with the extension signatures.
| Name | Type | Description | Validation |
|---|---|---|---|
| Height | int64 | Height at which this commit was created. | Must be > 0 |
| Round | int32 | Round that the commit corresponds to. | Must be > 0 |
| BlockID | BlockID | The blockID of the corresponding block. | Must adhere to the validation rules of BlockID. |
| ExtendedSignatures | Array of ExtendedCommitSig | The current validator set’s commit signatures, extension, and extension signatures. | Length of signatures must be > 0 and adhere to the validation of each individual ExtendedCommitSig |
CommitSig
CommitSig represents a signature of a validator, who has voted either for nil,
a particular BlockID or was absent. It’s a part of the Commit and can be used
to reconstruct the vote set given the validator set.
| Name | Type | Description | Validation |
|---|---|---|---|
| BlockIDFlag | BlockIDFlag | Represents the validators participation in consensus: its vote was not received, voted for the block that received the majority, or voted for nil | Must be one of the fields in the BlockIDFlag enum |
| ValidatorAddress | Address | Address of the validator | Must be of length 20 |
| Timestamp | Time | This field will vary from CommitSig to CommitSig. It represents the timestamp of the validator. | Time |
| Signature | Signature | Signature corresponding to the validators participation in consensus. | The length of the signature must be > 0 and < than 64 |
ValidatorAddress and Timestamp fields may be removed in the future
(see ADR-25).
ExtendedCommitSig
ExtendedCommitSig represents a signature of a validator that has voted either for nil,
a particular BlockID or was absent. It is part of the ExtendedCommit and can be used
to reconstruct the vote set given the validator set.
Additionally it contains the vote extensions that were attached to each non-nil precommit vote.
All these extensions have been verified by the application operating at the signing validator’s node.
| Name | Type | Description | Validation |
|---|---|---|---|
| BlockIDFlag | BlockIDFlag | Represents the validators participation in consensus: its vote was not received, voted for the block that received the majority, or voted for nil | Must be one of the fields in the BlockIDFlag enum |
| ValidatorAddress | Address | Address of the validator | Must be of length 20 |
| Timestamp | Time | This field will vary from CommitSig to CommitSig. It represents the timestamp of the validator. | |
| Signature | Signature | Signature corresponding to the validators participation in consensus. | Length must be > 0 and < 64 |
| Extension | bytes | Vote extension provided by the Application running on the sender of the precommit vote, and verified by the local application. | Length must be zero if BlockIDFlag is not Commit |
| ExtensionSignature | Signature | Signature of the vote extension. | Length must be > 0 and < than 64 if BlockIDFlag is Commit, else 0 |
BlockIDFlag
BlockIDFlag represents which BlockID the signature is for.Vote
A vote is a signed message from a validator for a particular block. The vote includes information about the validator signing it. When stored in the blockchain or propagated over the network, votes are encoded in Protobuf.| Name | Type | Description | Validation |
|---|---|---|---|
| Type | SignedMsgType | The type of message the vote refers to | Must be PrevoteType or PrecommitType |
| Height | int64 | Height for which this vote was created for | Must be > 0 |
| Round | int32 | Round that the commit corresponds to. | Must be > 0 |
| BlockID | BlockID | The blockID of the corresponding block. | |
| Timestamp | Time | Timestamp represents the time at which a validator signed. | |
| ValidatorAddress | bytes | Address of the validator | Length must be equal to 20 |
| ValidatorIndex | int32 | Index at a specific block height corresponding to the Index of the validator in the set. | Must be > 0 |
| Signature | bytes | Signature by the validator if they participated in consensus for the associated block. | Length must be > 0 and < 64 |
| Extension | bytes | Vote extension provided by the Application running at the validator’s node. | Length can be 0 |
| ExtensionSignature | bytes | Signature for the extension | Length must be > 0 and < 64 |
CanonicalVote
CanonicalVote is for validator signing. This type will not be present in a block. Votes are represented viaCanonicalVote and also encoded using protobuf via type.SignBytes which includes the ChainID,
and uses a different ordering of the fields.
| Name | Type | Description | Validation |
|---|---|---|---|
| Type | SignedMsgType | The type of message the vote refers to | Must be PrevoteType or PrecommitType |
| Height | int64 | Height in which the vote was provided. | Must be > 0 |
| Round | int64 | Round in which the vote was provided. | Must be > 0 |
| BlockID | string | ID of the block the vote refers to. | |
| Timestamp | string | Time of the vote. | |
| ChainID | string | ID of the blockchain running consensus. |
CanonicalVote and also encoded using protobuf via
type.SignBytes which includes the ChainID, and uses a different ordering of
the fields.
We define a method Verify that returns true if the signature verifies against the pubkey for the SignBytes
using the given ChainID:
CanonicalVoteExtension
Vote extensions are signed using a representation similar to votes. This is the structure to marshall in order to obtain the bytes to sign or verify the signature.| Name | Type | Description | Validation |
|---|---|---|---|
| Extension | bytes | Vote extension provided by the Application. | Can have zero length |
| Height | int64 | Height in which the extension was provided. | Must be > 0 |
| Round | int64 | Round in which the extension was provided. | Must be > 0 |
| ChainID | string | ID of the blockchain running consensus. |
Proposal
Proposal contains height and round for which this proposal is made, BlockID as a unique identifier of proposed block, timestamp, and POLRound (a so-called Proof-of-Lock (POL) round) that is needed for termination of the consensus. If POLRound >= 0, then BlockID corresponds to the block that is locked in POLRound. The message is signed by the validator private key.| Name | Type | Description | Validation |
|---|---|---|---|
| Type | SignedMsgType | Represents a Proposal SignedMsgType | Must be ProposalType signedMsgType |
| Height | uint64 | Height for which this vote was created for | Must be > 0 |
| Round | int32 | Round that the commit corresponds to. | Must be > 0 |
| POLRound | int64 | Proof of lock | Must be > 0 |
| BlockID | BlockID | The blockID of the corresponding block. | BlockID |
| Timestamp | Time | Timestamp represents the time at which a validator signed. | Time |
| Signature | slice of bytes ([]byte) | Signature by the validator if they participated in consensus for the associated bock. | Length of signature must be > 0 and < 64 |
SignedMsgType
Signed message type represents a signed messages in consensus.Signature
Signatures in CometBFT are raw bytes representing the underlying signature. See the signature spec for more.EvidenceList
EvidenceList is a simple wrapper for a list of evidence:Evidence
Evidence in CometBFT is used to indicate breaches in the consensus by a validator. More information on how evidence works in CometBFT can be found hereDuplicateVoteEvidence
DuplicateVoteEvidence represents a validator that has voted for two different blocks
in the same round of the same height. Votes are lexicographically sorted on BlockID.
| Name | Type | Description | Validation |
|---|---|---|---|
| VoteA | Vote | One of the votes submitted by a validator when they equivocated | VoteA must adhere to Vote validation rules |
| VoteB | Vote | The second vote submitted by a validator when they equivocated | VoteB must adhere to Vote validation rules |
| TotalVotingPower | int64 | The total power of the validator set at the height of equivocation | Must be equal to nodes own copy of the data |
| ValidatorPower | int64 | Power of the equivocating validator at the height | Must be equal to the nodes own copy of the data |
| Timestamp | Time | Time of the block where the equivocation occurred | Must be equal to the nodes own copy of the data |
LightClientAttackEvidence
LightClientAttackEvidence is a generalized evidence that captures all forms of known attacks on
a light client such that a full node can verify, propose and commit the evidence on-chain for
punishment of the malicious validators. There are three forms of attacks: Lunatic, Equivocation
and Amnesia. These attacks are exhaustive. You can find a more detailed overview of this here
| Name | Type | Description | Validation |
|---|---|---|---|
| ConflictingBlock | LightBlock | Read Below | Must adhere to the validation rules of lightBlock |
| CommonHeight | int64 | Read Below | must be > 0 |
| Byzantine Validators | Array of Validators | validators that acted maliciously | Read Below |
| TotalVotingPower | int64 | The total power of the validator set at the height of the infraction | Must be equal to the nodes own copy of the data |
| Timestamp | Time | Time of the block where the infraction occurred | Must be equal to the nodes own copy of the data |
LightBlock
LightBlock is the core data structure of the light client. It combines two data structures needed for verification (signedHeader & validatorSet).| Name | Type | Description | Validation |
|---|---|---|---|
| SignedHeader | SignedHeader | The header and commit, these are used for verification purposes. To find out more visit light client docs | Must not be nil and adhere to the validation rules of signedHeader |
| ValidatorSet | ValidatorSet | The validatorSet is used to help with verify that the validators in that committed the infraction were truly in the validator set. | Must not be nil and adhere to the validation rules of validatorSet |
SignedHeader and ValidatorSet are linked by the hash of the validator set(SignedHeader.ValidatorsHash == ValidatorSet.Hash().
SignedHeader
The SignedhHeader is the header accompanied by the commit to prove it.ValidatorSet
| Name | Type | Description | Validation |
|---|---|---|---|
| Validators | Array of validator | List of the active validators at a specific height | The list of validators can not be empty or nil and must adhere to the validation rules of validator |
| Proposer | validator | The block proposer for the corresponding block | The proposer cannot be nil and must adhere to the validation rules of validator |
Validator
| Name | Type | Description | Validation |
|---|---|---|---|
| Address | Address | Validators Address | Length must be of size 20 |
| Pubkey | slice of bytes ([]byte) | Validators Public Key | must be a length greater than 0 |
| VotingPower | int64 | Validators voting power | cannot be < 0 |
| ProposerPriority | int64 | Validators proposer priority. This is used to gauge when a validator is up next to propose blocks | No validation, value can be negative and positive |
Address
Address is a type alias of a slice of bytes. The address is calculated by hashing the public key using sha256 and truncating it to only use the first 20 bytes of the slice.ConsensusParams
| Name | Type | Description | Field Number |
|---|---|---|---|
| block | BlockParams | Parameters limiting the size of a block and time between consecutive blocks. | 1 |
| evidence | EvidenceParams | Parameters limiting the validity of evidence of byzantine behavior. | 2 |
| validator | ValidatorParams | Parameters limiting the types of public keys validators can use. | 3 |
| version | BlockParams | The ABCI application version. | 4 |
BlockParams
| Name | Type | Description | Field Number |
|---|---|---|---|
| max_bytes | int64 | Max size of a block, in bytes. | 1 |
| max_gas | int64 | Max sum of GasWanted in a proposed block. NOTE: blocks that violate this may be committed if there are Byzantine proposers. It’s the application’s responsibility to handle this when processing a block! | 2 |
EvidenceParams
| Name | Type | Description | Field Number |
|---|---|---|---|
| max_age_num_blocks | int64 | Max age of evidence, in blocks. | 1 |
| max_age_duration | google.protobuf.Duration | Max age of evidence, in time. It should correspond with an app’s “unbonding period” or other similar mechanism for handling Nothing-At-Stake attacks. | 2 |
| max_bytes | int64 | maximum size in bytes of total evidence allowed to be entered into a block | 3 |
ValidatorParams
| Name | Type | Description | Field Number |
|---|---|---|---|
| pub_key_types | repeated string | List of accepted public key types. Uses same naming as PubKey.Type. | 1 |
VersionParams
| Name | Type | Description | Field Number |
|---|---|---|---|
| app_version | uint64 | The ABCI application version. | 1 |
Proof
| Name | Type | Description | Field Number |
|---|---|---|---|
| total | int64 | Total number of items. | 1 |
| index | int64 | Index item to prove. | 2 |
| leaf_hash | bytes | Hash of item value. | 3 |
| aunts | repeated bytes | Hashes from leaf’s sibling to a root’s child. | 4 |