大纲
通用方法
↑ 返回大纲 为表达错误条件,下面对子协议的规范使用宿主状态机的异常系统,该系统通过两个函数暴露出来(定义见 ICS 24):abortTransactionUnless 和 abortSystemUnless。
BeginBlock 与 EndBlock
↑ 返回大纲 函数BeginBlock() 和 EndBlock()(见已实现的接口)被拆分到 CCV 子协议中。
[CCV-PCF-BBLOCK.1]
- 调用者
- ABCI 应用。
- 触发事件
- 从共识引擎接收到一条
BeginBlock消息;BeginBlock消息每个区块发送一次。
- 从共识引擎接收到一条
- 前置条件
- True.
- 后置条件
- 调用
BeginBlockInit()(见 [CCV-PCF-BBLOCK-INIT.1],即它包含初始化子协议所需的BeginBlock()逻辑)。 - 调用
BeginBlockCCR()(见 [CCV-PCF-BBLOCK-CCR.1],即它包含消费者链移除子协议所需的BeginBlock()逻辑)。
- 调用
- 错误条件
- 无。
[CCV-PCF-EBLOCK.1]
- 调用者
- ABCI 应用。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息;EndBlock消息每个区块发送一次。
- 从共识引擎接收到一条
- 前置条件
- True.
- 后置条件
- 调用
EndBlockCIS()(见 [CCV-PCF-EBLOCK-CIS.1],即它包含消费者发起的惩罚子协议所需的EndBlock()逻辑)。 - 调用
EndBlockCCR()(见 [CCV-PCF-EBLOCK-CCR.1],即它包含消费者链移除子协议所需的EndBlock()逻辑)。 - 调用
EndBlockVSU()(见 [CCV-PCF-EBLOCK-VSU.1],即它包含验证者集合更新子协议所需的EndBlock()逻辑)。
- 调用
- 错误条件
- 无。
注意:提供者 CCV 模块期望提供者 Staking 模块在调用提供者 CCV 模块的EndBlock()之前,先更新其对验证者集合的视图。 一种解决方案是让提供者 Staking 模块在EndBlock()期间更新其视图,然后使提供者 Staking 模块的EndBlock()先于提供者 CCV 模块的EndBlock()执行。
[CCV-CCF-BBLOCK.1]
- 调用者
- ABCI 应用。
- 触发事件
- 从共识引擎接收到一条
BeginBlock消息;BeginBlock消息每个区块发送一次。
- 从共识引擎接收到一条
- 前置条件
- True.
- 后置条件
- 调用
BeginBlockInit()(见 [CCV-CCF-BBLOCK-INIT.1],即它包含通道初始化子协议所需的BeginBlock()逻辑)。 - 调用
BeginBlockCCR()(见 [CCV-CCF-BBLOCK-CCR.1],即它包含消费者链移除子协议所需的BeginBlock()逻辑)。 - 调用
BeginBlockCIS()(见 [CCV-CCF-BBLOCK-CIS.1],即它包含消费者发起的惩罚子协议所需的BeginBlock()逻辑)。
- 调用
- 错误条件
- 无。
[CCV-CCF-EBLOCK.1]
- 调用者
- ABCI 应用。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息;EndBlock消息每个区块发送一次。
- 从共识引擎接收到一条
- 前置条件
- True. x
- 后置条件
- 调用
EndBlockRD()(见 [CCV-PCF-EBLOCK-RD.1],即它包含奖励分配子协议所需的EndBlock()逻辑)。 - 调用
EndBlockVSU(),并将返回值返回给共识引擎(见 [CCV-CCF-EBLOCK-VSU.1],即它包含验证者集合更新子协议所需的EndBlock()逻辑)。
- 调用
- 错误条件
- 无。
数据包中继
↑ 返回大纲[CCV-PCF-RCVP.1]
- 调用者
- 提供者 IBC 路由模块。
- 触发事件
- 提供者 IBC 路由模块在由提供者 CCV 模块拥有的通道上接收到一个数据包。
- 前置条件
- True.
- 后置条件
- 如果该数据包是
VSCMaturedPacket,则返回调用onRecvVSCMaturedPacket方法得到的确认。 - 如果该数据包是
SlashPacket,则返回调用onRecvSlashPacket方法得到的确认。 - 否则,返回错误确认。
- 如果该数据包是
- 错误条件
- 无。
[CCV-PCF-ACKP.1]
- 调用者
- 提供者 IBC 路由模块。
- 触发事件
- 提供者 IBC 路由模块在由提供者 CCV 模块拥有的通道上接收到一个确认。
- 前置条件
- True.
- 后置条件
- 如果该确认对应于一个
VSCPacket,则调用onAcknowledgeVSCPacket方法。 - 否则,中止该交易。
- 如果该确认对应于一个
- 错误条件
- 无。
[CCV-PCF-TOP.1]
- 调用者
- 提供者 IBC 路由模块。
- 触发事件
- 前置条件
- Correct Relayer 假设被违反(见假设一节)。
- 后置条件
- 如果该超时对应于一个
VSCPacket,则调用onTimeoutVSCPacket方法。 - 否则,中止该交易。
- 如果该超时对应于一个
- 错误条件
- 无。
[CCV-CCF-RCVP.1]
- 调用方
- 消费者链 IBC 路由模块。
- 触发事件
- 消费者链 IBC 路由模块在一个由消费者 CCV 模块拥有的通道上接收到数据包。
- 前置条件
- True。
- 后置条件
- 如果该数据包是
VSCPacket,则返回调用onRecvVSCPacket方法所获得的确认。 - 否则,返回一个错误确认。
- 如果该数据包是
- 错误条件
- 无。
[CCV-CCF-ACKP.1]
- 调用方
- 消费者链 IBC 路由模块。
- 触发事件
- 消费者链 IBC 路由模块在一个由消费者 CCV 模块拥有的通道上接收到确认。
- 前置条件
- True。
- 后置条件
- 如果该确认对应的是
VSCMaturedPacket,则调用onAcknowledgeVSCMaturedPacket方法。 - 如果该确认对应的是
SlashPacket,则调用onAcknowledgeSlashPacket方法。 - 否则,中止交易。
- 如果该确认对应的是
- 错误条件
- 无。
[CCV-CCF-TOP.1]
- 调用方
- 消费者链 IBC 路由模块。
- 触发事件
- 前置条件
- 正确中继者 假设被违反(见假设一节)。
- 后置条件
- 如果超时对应的是
VSCMaturedPacket,则调用onTimeoutVSCMaturedPacket方法。 - 如果超时对应的是
SlashPacket,则调用onTimeoutSlashPacket方法。 - 否则,中止交易。
- 如果超时对应的是
- 错误条件
- 无。
子协议
初始化
↑ 返回大纲 初始化 子协议使提供者链和消费者链能够创建一个 CCV 通道,即一个用于交换数据包的唯一有序 IBC 通道。作为前提,初始化子协议必须创建两个 IBC 客户端,一个位于提供者链上并连接到消费者链,另一个位于消费者链上并连接到提供者链。这对于验证两条链的身份是必要的(只要这些客户端是可信的)。[CCV-PCF-INITG.1]
- 调用方
- ABCI 应用程序。
- 触发事件
- 从共识引擎接收到一条
InitChain消息;当提供者链首次启动时,会发送InitChain消息。
- 从共识引擎接收到一条
- 前置条件
- 提供者 CCV 模块处于初始状态。
- 后置条件
- 端口
ProviderPortId的 capability 被认领。 - 对于
ProviderGenesisState中的每个消费者状态,都会设置初始状态,即设置如下映射:chainToChannel、channelToChain。
- 端口
- 错误条件
- 端口
ProviderPortId的 capability 无法被认领。 - 对于
ProviderGenesisState中的任一消费者状态,其通道 ID 无效(参见 ICS 4 中定义的验证函数)。
- 端口
[CCV-PCF-HCAPROP.1]
- 调用方
- 治理模块的
EndBlock()方法。
- 治理模块的
- 触发事件
- 一项治理提案
ConsumerAdditionProposal已通过(即获得了所需票数)。
- 一项治理提案
- 前置条件
- True。
- 后置条件
- 该提案被追加到待处理新增提案列表中,即
pendingConsumerAdditionProposals。
- 该提案被追加到待处理新增提案列表中,即
- 错误条件
- 无。
[CCV-PCF-BBLOCK-INIT.1]
- 调用方
BeginBlock()方法。
- 触发事件
- 从共识引擎接收到一条
BeginBlock消息;BeginBlock消息每个区块发送一次。
- 从共识引擎接收到一条
- 前置条件
- True。
- 后置条件
- 对于待处理新增提案列表
pendingConsumerAdditionProposals中的每个ConsumerAdditionProposalp,如果currentTimestamp() > p.spawnTime,则:- 调用
CreateConsumerClient(p); - 从
pendingConsumerAdditionProposals中移除p。
- 调用
- 对于待处理新增提案列表
- 错误条件
- 无。
[CCV-PCF-CRCLIENT.1]
- 调用方
HandleConsumerAdditionProposal(见 CCV-PCF-HCAPROP.1)或BeginBlockInit()(见 CCV-PCF-BBLOCK-INIT.1)。
- 触发事件
- 治理提案
ConsumerAdditionProposalp已通过(即获得了所需票数)。
- 治理提案
- 前置条件
currentTimestamp() > p.spawnTime。
- 后置条件
- 如果
p.chainId的客户端已存在,则状态不变。 - 否则,
- 将提供者链在当前高度下自身共识状态的验证者集合设置为消费者链的初始验证者集合;
- 如果设置了
p.connId,则- 如果找不到 ID 为
p.connId的连接端,则状态不变; - 否则,
- 如果 ID 为
p.connId的连接未连接到 ID 为p.chainId的链,则状态不变; - 否则,
- 存储客户端 ID 和连接 ID;
- 创建并存储一个
ConsumerGenesisState;
- 如果 ID 为
- 如果找不到 ID 为
- 否则,
- 否则,
- 创建一个客户端状态,其中
chainId = p.chainId且unbondingPeriod = p.unbondingPeriod; - 创建一个共识状态,其中
validatorSet被设置为消费者链的初始验证者集合; - 创建消费者链客户端并存储客户端 ID;
- 创建并存储一个
ConsumerGenesisState;
- 创建一个客户端状态,其中
- 否则,
- 将
lockUnbondingOnTimeout[p.chainId]设置为p.lockUnbondingOnTimeout。 - 计算初始化超时时间戳并将其存储在
initTimeoutTimestamps[p.chainId]中。
- 如果
- 错误条件
- 无。
注意: 对于ConsumerAdditionProposal的clientId字段未设置的情况,创建远程链客户端需要一个ClientState和一个ConsensusState(示例可参见 ICS 7)。ConsensusState需要设置远程链的验证者集合。 提供者链利用这样一个事实:消费者链的验证者集合与其自身的验证者集合相同。 注意: 引导消费者 CCV 模块需要一个ConsumerGenesisState(见CCV 数据结构一节)。提供者 CCV 模块在处理治理提案ConsumerAdditionProposal时会创建这样的ConsumerGenesisState。 注意: 如果消费者链的通道初始化超过initTimeout周期,则提供者链会移除该消费者链。 因此,消费者侧此后所有建立 CCV 通道的尝试都会失败。 这意味着消费者链需要某种社会共识,来决定是重新启动成为消费者链的流程,还是重新转回主权链。
[CCV-PCF-COINIT.1]
- 调用方
- 提供者 IBC 路由模块。
- 触发事件
- 提供者 IBC 路由模块在提供者 CCV 模块所绑定的端口上接收到一条
ChanOpenInit消息。
- 提供者 IBC 路由模块在提供者 CCV 模块所绑定的端口上接收到一条
- 前置条件
- True。
- 后置条件
- 事务总是会被中止;因此,状态不变。
- 错误条件
- 无。
[CCV-PCF-COTRY.1]
- 调用者
- 提供者 IBC 路由模块。
- 触发事件
- 提供者 IBC 路由模块在提供者 CCV 模块绑定的端口上收到
ChanOpenTry消息。
- 提供者 IBC 路由模块在提供者 CCV 模块绑定的端口上收到
- 前置条件
- 真。
- 后置条件
- 如果以下任一条件为真,则中止该交易:
- 通道不是有序通道;
portIdentifier != ProviderPortId;counterpartyPortIdentifier != ConsumerPortId;counterpartyVersion != ccvVersion;- 不存在带有
portIdentifier和channelIdentifier的通道; - 该通道具有多于一个连接跳;
- 已为该消费者链存储了一条连接,且该连接与此通道的底层连接不匹配;
- 该通道并非构建在为该消费者链创建的客户端之上;
- 该消费者链已存在另一条 CCV 通道。
- 返回一个
CCVHandshakeMetadata,其中providerDistributionAccount设置为提供者链上 distribution 模块账户的地址,version设置为ccvVersion。 - 状态不发生改变。
- 如果以下任一条件为真,则中止该交易:
- 错误条件
- 无。
[CCV-PCF-COACK.1]
- 调用者
- 提供者 IBC 路由模块。
- 触发事件
- 提供者 IBC 路由模块在提供者 CCV 模块绑定的端口上收到
ChanOpenAck消息。
- 提供者 IBC 路由模块在提供者 CCV 模块绑定的端口上收到
- 前置条件
- 真。
- 后置条件
- 该交易总是会被中止;因此,状态不发生改变。
- 错误条件
- 无。
[CCV-PCF-COCONFIRM.1]
- 调用者
- 提供者 IBC 路由模块。
- 触发事件
- 提供者 IBC 路由模块在提供者 CCV 模块绑定的端口上收到
ChanOpenConfirm消息。
- 提供者 IBC 路由模块在提供者 CCV 模块绑定的端口上收到
- 前置条件
- 真。
- 后置条件
- 如果以下任一条件为真,则中止该交易:
- 不存在带有
portIdentifier和channelIdentifier的通道; - 该通道具有多于一个连接跳;
- 该消费者链已存在另一条 CCV 通道。
- 不存在带有
- 设置连接映射,即
chainToConnection。 - 设置通道映射,即
chainToChannel和channelToChain。 initialHeights[chainId]被设置为当前高度。- 移除 ID 为
clientState.chainId的消费者链的初始化超时时间戳。
- 如果以下任一条件为真,则中止该交易:
- 错误条件
- 无。
[CCV-CCF-INITG.1]
- 调用方
- ABCI 应用程序。
- 触发事件
- 从共识引擎接收到一条
InitChain消息;当消费者链首次启动时,会发送该InitChain消息。
- 从共识引擎接收到一条
- 前置条件
- 消费者 CCV 模块处于初始状态。
- 后置条件
- 端口
ConsumerPortId的 capability 已被认领。 preCCV被设置为gs.preCCV。- 如果
preCCV == true,则将基于gs.connId连接所构建的客户端 ID 存入providerClientId。 - 否则,会创建一个提供者链客户端,并将该客户端 ID 存入
providerClientId。 ConsumerUnbondingPeriod被设置为gs.unbondingPeriod。- 当前区块的
HtoVSC被设置为0。 ccvValidatorSet映射会用初始验证者集填充。- 分发代币转移通道的 ID 被设置为
gs.transferChannelId。 - 如果
preCCV == true,则初始化 CCV 通道打开握手。 - 否则,初始化连接打开握手。
- 初始验证者集会返回给共识引擎。
- 端口
- 错误条件
说明:CCV 假设消费者链初始验证者集中的所有正确验证者都会接收到相同的消费者链二进制文件和消费者链创世状态。 虽然传播该二进制文件和创世状态的机制不在本规范范围内,但一种可行方法是在提供者链上的治理提案中包含这些信息。
[CCV-CCF-COINIT.1]
- 调用方
- 消费者 IBC 路由模块。
- 触发事件
- 消费者 IBC 路由模块在消费者 CCV 模块所绑定的端口上接收到一条
ChanOpenInit消息。
- 消费者 IBC 路由模块在消费者 CCV 模块所绑定的端口上接收到一条
- 前置条件
- True。
- 后置条件
- 如果以下任一条件为真,则事务中止:
providerChannel已设置;portIdentifier != ConsumerPortId;version已设置但不是预期版本;counterpartyPortIdentifier != ProviderPortId;- 与该通道关联的客户端不是预期的提供者客户端。
- 返回
ccvVersion。 - 状态不发生变化。
- 如果以下任一条件为真,则事务中止:
- 错误条件
- 无。
[CCV-CCF-COTRY.1]
- 调用方
- 消费者 IBC 路由模块。
- 触发事件
- 消费者 IBC 路由模块在消费者 CCV 模块所绑定的端口上接收到一条
ChanOpenTry消息。
- 消费者 IBC 路由模块在消费者 CCV 模块所绑定的端口上接收到一条
- 前置条件
- True。
- 后置条件
- 事务总是会中止;因此,状态不会发生变化。
- 错误条件
- 无。
[CCV-CCF-COACK.1]
- 调用方
- 消费者 IBC 路由模块。
- 触发事件
- 消费者 IBC 路由模块在消费者 CCV 模块所绑定的端口上收到
ChanOpenAck消息。
- 消费者 IBC 路由模块在消费者 CCV 模块所绑定的端口上收到
- 前置条件
True。
- 后置条件
counterpartyVersion被反序列化为CCVHandshakeMetadata结构md。- 如果满足以下任一条件,则事务中止:
providerChannel已经被设置;md.version != ccvVersion。
- 提供者链上的分发模块账户地址被设置为
md.providerDistributionAccount。 - 如果
distributionChannelId尚未设置,则发起分发代币传输通道的打开握手,并将distributionChannelId设置为结果通道 ID。 - CCV 通道被标记为已建立,即将
providerChannel设置为该通道。 - 待处理的惩罚请求会被发送到提供者链(见 [CCV-CCF-SNDPESLASH.1])。
请注意,这只会在
preCCV == false时发生,因为 ABCI 应用只有在链升级为消费者链后才能调用SendSlashRequest(见 [CCV-CCF-BBLOCK-INIT.1])。 - 如果
preCCV == true,则质押模块中的验证者集合会被替换为ccvValidatorSet,即初始验证者集合。
- 错误条件
- 无。
[CCV-CCF-COCONFIRM.1]
- 调用方
- 消费者 IBC 路由模块。
- 触发事件
- 消费者 IBC 路由模块在消费者 CCV 模块所绑定的端口上收到
ChanOpenConfirm消息。
- 消费者 IBC 路由模块在消费者 CCV 模块所绑定的端口上收到
- 前置条件
True。
- 后置条件
- 事务总是会中止;因此,状态不会发生变化。
- 错误条件
- 无。
[CCV-CCF-BBLOCK-INIT.1]
- 调用方
BeginBlock()方法。
- 触发事件
- 从共识引擎接收到一条
BeginBlock消息;BeginBlock消息每个区块发送一次。
- 从共识引擎接收到一条
- 前置条件
True。
- 后置条件
- 如果
preCCV == true且当前验证者集合与ccvValidatorSet匹配(即初始验证者集合),则该链必须升级为完整的消费者链。 升级机制不在本规范的范围内。
- 如果
- 错误条件
- 无。
消费者链移除
↑ 返回大纲[CCV-PCF-HCRPROP.1]
- 调用方
- 治理模块的
EndBlock()方法。
- 治理模块的
- 触发事件
- 某个治理提案
ConsumerRemovalProposal已通过(即获得了所需票数)。
- 某个治理提案
- 前置条件
True。
- 后置条件
- 该提案会被追加到待处理移除提案列表中,即
pendingConsumerRemovalProposals。
- 该提案会被追加到待处理移除提案列表中,即
- 错误条件
- 无。
[CCV-PCF-BBLOCK-CCR.1]
- 调用方
BeginBlock()方法。
- 触发事件
- 从共识引擎接收到一条
BeginBlock消息;BeginBlock消息每个区块发送一次。
- 从共识引擎接收到一条
- 前置条件
True。
- 后置条件
- 对于待处理移除提案列表
pendingConsumerRemovalProposals中的每个ConsumerRemovalProposalp,如果currentTimestamp() > p.stopTime,则- 调用
StopConsumerChain(p.chainId, false); - 从
pendingConsumerRemovalProposals中移除p。
- 调用
- 对于待处理移除提案列表
- 错误条件
- 无。
[CCV-PCF-STCC.1]
- 调用方
HandleConsumerRemovalProposal(见 CCV-PCF-HCRPROP.1) 或BeginBlockCCR()(见 CCV-PCF-BBLOCK-CCR.1) 或onTimeoutVSCPacket()(见 CCV-PCF-TOVSC.1) 或EndBlockCCR()(见 CCV-PCF-EBLOCK-CCR.1)。
- 触发事件
- 以下事件之一:
- 停止
chainId对应消费者链的治理提案已通过(即获得了所需票数); - 通过 CCV 通道发送到
chainId对应消费者链的VSCPacket已超时; - 通道初始化已超时。
- 停止
- 以下事件之一:
- 前置条件
- 为真。
- 后置条件
- 如果
p.chainId的客户端不存在,则状态不发生变化。 - 否则,
- 从
chainToClient中移除映射到chainId的客户端 ID; - 从
lockUnbondingOnTimeout中移除映射到chainId的值; - 如果已建立到
chainId对应消费者链的 CCV 通道,则- 从
channelToChain中移除映射到chainToChannel[chainId]的链 ID; - 启动该 CCV 通道的关闭握手;
- 从
chainToChannel中移除映射到chainId的通道 ID。
- 从
- 从
pendingVSCPackets中移除所有映射到chainId的VSCPacketData; - 从
initialHeights中移除映射到chainId的高度; - 清空
downtimeSlashRequests[chainId]; - 如果
lockUnbonding == false,则- 从所有尚未完成的解绑定操作中移除
chainId; - 如果某个尚未完成的解绑定操作已在所有消费者链上成熟,
- 则将该已成熟的解绑定操作加入
maturedUnbondingOps; - 并从
unbondingOps中移除该已成熟的解绑定操作; - 从
vscToUnbondingOps映射中移除所有带有chainId的条目。
- 从所有尚未完成的解绑定操作中移除
- 从
- 如果
- 错误条件
- 无
注意:当lockUnbonding == FALSE时调用StopConsumerChain(chainId, lockUnbonding),意味着所有尚未完成的解绑定操作都可以在chainId对应消费者链上的ConsumerUnbondingPeriod到期前完成。 因此,对任意chainId调用StopConsumerChain(chainId, false)可能违反 Bond-Based Consumer Voting Power 和 Slashable Consumer Misbehavior 属性(见系统属性一节)。StopConsumerChain(chainId, false)会在两种场景下被调用(见上文“触发事件”)。
[CCV-PCF-EBLOCK-CCR.1]
- 调用方
EndBlock()方法。
- 触发事件
- 从共识引擎收到一条
EndBlock消息;EndBlock消息每个区块发送一次。
- 从共识引擎收到一条
- 前置条件
- 为真。
- 后置条件
- 对于
vscSendTimestamps.Keys()中的每个消费者链 IDchainId,- 如果
vscSendTimestamps[(chainId, vscId)] + vscTimeout小于当前时间戳,则停止 ID 为chainId的消费者链。
- 如果
- 对于
initTimeoutTimestamps.Keys()中的每个消费者链 IDchainId,- 如果
initTimeoutTimestamps[chainId]中的时间戳小于当前时间戳,则停止 ID 为chainId的消费者链。
- 如果
- 对于
- 错误条件
- 无。
注意:为避免误判而导致不必要地移除消费者链,vscTimeout必须大于consumerUnbondingPeriod,并且 应当将把VSCPacket中继到消费者链,以及将相应的VSCMaturedPacket中继回提供者链所需的时间考虑在内。
[CCV-PCF-CCINIT.1]
- 调用方
- 提供者 IBC 路由模块。
- 触发事件
- 提供者 IBC 路由模块在提供者 CCV 模块所绑定的端口上收到
ChanCloseInit消息。
- 提供者 IBC 路由模块在提供者 CCV 模块所绑定的端口上收到
- 前置条件
- 为真。
- 后置条件
- 事务总是会被中止;因此,状态不发生变化。
- 错误条件
- 无。
[CCV-PCF-CCCONFIRM.1]
- 调用方
- 提供者 IBC 路由模块。
- 触发事件
- 提供者 IBC 路由模块在提供者 CCV 模块所绑定的端口上收到
ChanCloseConfirm消息。
- 提供者 IBC 路由模块在提供者 CCV 模块所绑定的端口上收到
- 前置条件
- 为真。
- 后置条件
- 状态不发生变化。
- 错误条件
- 无。
[CCV-CCF-BBLOCK-CCR.1]
- 调用方
BeginBlock()方法。
- 触发事件
- 从共识引擎接收到一条
BeginBlock消息;BeginBlock消息每个区块发送一次。
- 从共识引擎接收到一条
- 前置条件
- True。
- 后置条件
- 如果 CCV 已建立,但随后进入
CLOSED状态,则清理 consumer CCV 模块的状态,例如取消设置providerChannel。
- 如果 CCV 已建立,但随后进入
- 错误条件
- 如果 CCV 已建立,但随后进入
CLOSED状态。
- 如果 CCV 已建立,但随后进入
注意:一旦 CCV 通道关闭,provider 链将无法再提供安全性。因此,consumer 链必须关闭。 关于在实践中如何实现,可参考 Cosmos SDK 的实现。
[CCV-CCF-CCINIT.1]
- 调用方
- consumer IBC 路由模块。
- 触发事件
- consumer IBC 路由模块在 consumer CCV 模块所绑定的端口上收到一条
ChanCloseInit消息。
- consumer IBC 路由模块在 consumer CCV 模块所绑定的端口上收到一条
- 前置条件
- True。
- 后置条件
- 如果
providerChannel未设置,或providerChannel与收到ChanCloseInit消息的通道 ID 匹配,则中止该交易。 - 状态不发生变化。
- 如果
- 错误条件
- 无。
[CCV-CCF-CCCONFIRM.1]
- 调用方
- consumer IBC 路由模块。
- 触发事件
- consumer IBC 路由模块在 consumer CCV 模块所绑定的端口上收到一条
ChanCloseConfirm消息。
- consumer IBC 路由模块在 consumer CCV 模块所绑定的端口上收到一条
- 前置条件
- True。
- 后置条件
- 状态不发生变化。
- 错误条件
- 无。
验证者集合更新
↑ 返回大纲 验证者集合更新子协议使 provider 链能够- 将 provider 链上分配给验证者的投票权更新到 consumer 链
- 并确保为在 consumer 链上出块的验证者正确完成解绑操作。
[CCV-PCF-EBLOCK-VSU.1]
- 调用方
EndBlock()方法。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息;EndBlock消息每个区块发送一次。
- 从共识引擎接收到一条
- 前置条件
- True。
- 后置条件
- 对于
maturedUnbondingOps中每一个已成熟的解绑操作,都会通知 Staking 模块该解绑可以完成。 maturedUnbondingOps中的所有解绑操作都会被移除。- 从 provider 的 Staking 模块获取验证者更新列表
valUpdates。 - 对于每条
chainId对应的 consumer 链- 如果
valUpdates非空,或者在当前区块期间发起了解绑操作,则- 创建一个
VSCPacket数据data,使得data.id = vscId、data.updates = valUpdates且data.downtimeSlashAcks = downtimeSlashRequests[chainId]; - 清空
downtimeSlashRequests[chainId]; - 将
packetData追加到与chainId关联的待发送VSCPacket列表,即pendingVSCPackets[chainId]。
- 创建一个
- 如果存在面向
chainId对应 consumer 链的已建立 CCV 通道,则- 对于与
chainId关联的待发送VSCPacket列表中的每个VSCPacketData- 在与
chainId对应 consumer 链关联的通道上发送一个携带该VSCPacketData的数据包; - 将
vscSendTimestamps[(vscId, chainId)]设为当前时间戳;
- 在与
- 移除与
chainId关联的所有待发送VSCPacket。
- 对于与
- 如果
vscId递增。
- 对于
- 错误条件
- 无。
[CCV-PCF-ACKVSC.1]
- 调用方
onAcknowledgePacket()方法。
- 触发事件
- provider IBC 路由模块在由 provider CCV 模块拥有的通道上收到一个
VSCPacket的确认。
- provider IBC 路由模块在由 provider CCV 模块拥有的通道上收到一个
- 前置条件
- True。
- 后置条件
- 状态不发生变化。
- 错误条件
- 该确认是
VSCPacketError。
- 该确认是
[CCV-PCF-TOVSC.1]
- 调用者
onTimeoutPacket()方法。
- 触发事件
- 前置条件
- Correct Relayer 假设被违反(见假设一节)。
- 后置条件
- 如果发送该数据包的通道 ID 没有映射到某个链 ID(在
channelToChain中),则中止该交易。 - 调用
StopConsumerChain(chainId, lockUnbondingOnTimeout[chainId]),其中chainId = channelToChain[packet.getDestinationChannel()]。
- 如果发送该数据包的通道 ID 没有映射到某个链 ID(在
- 错误条件
- 无
[CCV-PCF-RCVMAT.1]
- 调用者
onRecvPacket()方法。
- 触发事件
- provider IBC 路由模块在由 provider CCV 模块拥有的通道上接收到一个
VSCMaturedPacket。
- provider IBC 路由模块在由 provider CCV 模块拥有的通道上接收到一个
- 前置条件
- 真。
- 后置条件
- 如果接收该数据包的通道不是已建立的 CCV 通道(即不在
channelToChain中),则中止该交易。 chainId被设置为与接收该数据包的通道所映射的消费者链 ID。- 对于
GetUnbondingsFromVSC(chainId, packet.data.id)返回的每个解绑操作op:- 从
op.unbondingChainIds中移除chainId; - 如果
op.unbondingChainIds为空,- 则将
op.id加入maturedUnbondingOps; - 并从
unbondingOps中移除op.id。
- 则将
- 从
- 从
vscToUnbondingOps中移除(chainId, vscId)。 - 从
vscSendTimestamps中移除(chainId, vscId)。 - 返回成功确认。
- 如果接收该数据包的通道不是已建立的 CCV 通道(即不在
- 错误条件
- 无。
[CCV-PCF-GETUBS.1]
- 调用者
onRecvVSCMaturedPacket()方法。
- 触发事件
- provider IBC 路由模块在由 provider CCV 模块拥有的通道上接收到一个
VSCMaturedPacket。
- provider IBC 路由模块在由 provider CCV 模块拥有的通道上接收到一个
- 前置条件
- provider CCV 模块从 ID 为
chainId的消费者链接收到一个VSCMaturedPacketP,且P.data.id == _vscId。
- provider CCV 模块从 ID 为
- 后置条件
- 返回映射到
(chainId, _vscId)的解绑操作列表。
- 返回映射到
- 错误条件
- 无。
[CCV-PCF-HOOK-AFUBOPCR.1]
- 调用者
- Staking 模块。
- 触发事件
- 发起一个 ID 为
opId的解绑操作。
- 发起一个 ID 为
- 前置条件
- 真。
- 后置条件
chainIds被设置为所有在该 provider 链上注册的消费者链列表,即chainToClient.Keys()。- 如果
chainIds中至少有一条消费者链,则:- 创建一个
UnbondingOperationop并将其加入unbondingOps,使得op.id = opId且op.unbondingChainIds = chainIds。 - 将
opId追加到vscToUnbondingOps[(chainId, vscId)]的每个列表中,其中chainId是在该 provider 链上注册的某条消费者链的 ID,vscId是当前的 VSC ID。 - 调用 Staking 模块的
PutUnbondingOnHold(opId)。
- 创建一个
- 错误条件
- 无。
[CCV-CCF-RCVVSC.1]
- 调用者
onRecvPacket()方法。
- 触发事件
- consumer IBC 路由模块在由 consumer CCV 模块拥有的通道上接收到一个
VSCPacket。
- consumer IBC 路由模块在由 consumer CCV 模块拥有的通道上接收到一个
- 前置条件
- 真。
- 后置条件
- 如果已设置
providerChannel,且其与接收该数据包的通道(ID 为packet.getDestinationChannel())不匹配,则返回错误确认。 - 否则:
- 将后续区块的高度映射到
packet.data.id(即HtoVSC映射); - 将
packet.data追加到receivedVSCs。 - 返回成功确认。
- 将后续区块的高度映射到
- 如果已设置
- 错误条件
- 无。
[CCV-CCF-ACKMAT.1]
- 调用者
onAcknowledgePacket()方法。
- 触发事件
- consumer IBC 路由模块在由 consumer CCV 模块拥有的通道上接收到一个
VSCMaturedPacket的确认。
- consumer IBC 路由模块在由 consumer CCV 模块拥有的通道上接收到一个
- 前置条件
- 真。
- 后置条件
- 状态不发生变化。
- 错误条件
- 该确认为
VSCMaturedPacketError。
- 该确认为
[CCV-CCF-TOMAT.1]
- 调用者
onTimeoutPacket()方法。
- 触发事件
- 前置条件
- 正确中继者 假设被违反(见假设一节)。
- 后置条件
- 状态不发生变化。
- 错误条件
- 无
[CCV-CCF-EBLOCK-VSU.1]
- 调用者
EndBlock()方法。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息;每个区块会发送一次EndBlock消息。
- 从共识引擎接收到一条
- 前置条件
- True.
- 后置条件
- 如果
providerChannel != "",则调用UnbondMaturePackets(); - 如果
preCCV == true,状态不发生变化。 - 否则,
- 处理
receivedVSCs中的数据项(见 [CCV-CCF-HAREVSC.1]),其结果是得到一个验证者更新列表changes; - 调用
UpdateValidatorSet(changes); - 返回
changes。
- 处理
- 如果
- 错误条件
- 无。
[CCV-CCF-HAREVSC.1]
- 调用者
EndBlock()方法。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息。
- 从共识引擎接收到一条
- 前置条件
preCCV == false。
- 后置条件
- 对于列表
receivedVSCs中的每个data项,- 将
data.updates追加到changes,其中changes初始为空的验证者更新列表; - 将
(data.id, maturityTimestamp)添加到maturingVSCs,其中maturityTimestamp = currentTimestamp() + ConsumerUnbondingPeriod; - 对于从提供者链接收到的 slash 确认中的每个
valAddr,将outstandingDowntime[valAddr]设为 false。
- 将
- 清空
receivedVSCs。 - 对
changes中的更新进行聚合,即每个验证者只保留最新的一次更新,并将其返回。
- 对于列表
- 错误条件
- 无。
[CCV-CCF-UPVALS.1]
- 调用者
EndBlock()方法。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息。
- 从共识引擎接收到一条
- 前置条件
preCCV == false。
- 后置条件
- 对于
changes中的每个验证者update,- 如果该验证者不在验证者集合中且
update.power > 0,则- 将新的验证者添加到
ccvValidatorSet; - 调用
AfterCCValidatorBonded钩子;
- 将新的验证者添加到
- 否则,如果该验证者的新投票权为
0,则,- 将该验证者从
ccvValidatorSet中移除; - 调用
AfterCCValidatorBeginUnbonding钩子;
- 将该验证者从
- 否则,更新该验证者的投票权。
- 如果该验证者不在验证者集合中且
- 对于
- 错误条件
- 无。
[CCV-CCF-UMP.1]
- 调用者
EndBlock()方法。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息。
- 从共识引擎接收到一条
- 前置条件
- 到提供者链的 CCV 通道已建立,即
providerChannel != ""。
- 到提供者链的 CCV 通道已建立,即
- 后置条件
- 对于按成熟时间戳排序的待成熟 VSC 列表中的每个
(id, ts)- 如果
currentTimestamp() < ts,则停止循环; - 创建一个
VSCMaturedPacketData数据包数据; - 将携带所创建
VSCMaturedPacketData的数据包发送到提供者链; - 从
maturingVSCs中移除元组(id, ts)。
- 如果
- 对于按成熟时间戳排序的待成熟 VSC 列表中的每个
- 错误条件
- 无。
由消费者发起的 Slash
↑ 返回大纲[CCV-PCF-EBLOCK-CIS.1]
- 调用者
EndBlock()方法。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息;每个区块会发送一次EndBlock消息。
- 从共识引擎接收到一条
- 前置条件
- True.
- 后置条件
vscId被映射到后续区块的高度。
- 错误条件
- 无。
[CCV-PCF-RCVSLASH.1]
- 调用者
onRecvPacket()方法。
- 触发事件
- 提供者 IBC 路由模块在由提供者 CCV 模块拥有的通道上收到一个
SlashPacket。
- 提供者 IBC 路由模块在由提供者 CCV 模块拥有的通道上收到一个
- 前置条件
- True。
- 后置条件
- 如果收到该数据包的通道不是已建立的 CCV 通道,则返回错误确认。
- 否则,
- 若
packet.data.vscId == 0,则将infractionHeight设为initialHeights[chainId],其中chainId = channelToChain[packet.getDestinationChannel()],即到该消费者链的 CCV 通道建立时的高度; - 否则,将
infractionHeight设为VSCtoH[packet.data.vscId],即验证者更新在 ID 为packet.data.vscId的 VSC 中最后一次更新投票权重时的高度; - 向 Slashing 模块发出请求,对地址为
packet.data.valAddress的验证者在infractionHeight处质押的代币按slashFactor进行惩罚,其中slashFactor是提供者链上设置的惩罚因子; - 向 Slashing 模块发出请求,将地址为
packet.data.valAddress的验证者监禁一段jailTime时长,其中jailTime是提供者链上设置的监禁时长; - 如果该惩罚请求是针对宕机的,则将验证者地址
packet.data.valAddress添加到来自该chainId的宕机惩罚请求列表中; - 返回成功确认。
- 若
- 错误条件
- 无。
[CCV-CCF-BBLOCK-CIS.1]
- 调用者
BeginBlock()方法。
- 触发事件
- 从共识引擎接收到一条
BeginBlock消息;每个区块会发送一次BeginBlock消息。
- 从共识引擎接收到一条
- 前置条件
- True。
- 后置条件
- 后续区块高度对应的
HtoVSC被设置为与当前区块高度相同的 VSC ID。
- 后续区块高度对应的
- 错误条件
- 无。
[CCV-CCF-ACKSLASH.1]
- 调用者
onAcknowledgePacket()方法。
- 触发事件
- 消费者 IBC 路由模块在由消费者 CCV 模块拥有的通道上收到一个
SlashPacket的确认。
- 消费者 IBC 路由模块在由消费者 CCV 模块拥有的通道上收到一个
- 前置条件
- True。
- 后置条件
- 状态不发生变化。
- 错误条件
- 确认为
SlashPacketError。
- 确认为
[CCV-CCF-TOSLASH.1]
- 调用者
onTimeoutPacket()方法。
- 触发事件
- 前置条件
- 正确中继者 假设被违反(见假设一节)。
- 后置条件
- 状态不发生变化。
- 错误条件
- 无
[CCV-CCF-SNDSLASH.1]
- 调用方
- ABCI 应用程序(例如
Slashing模块)。
- ABCI 应用程序(例如
- 触发事件
- 收到地址为
valAddress的验证者存在不当行为的证据。
- 收到地址为
- 前置条件
- True.
- 后置条件
- 如果该请求针对宕机,并且已经存在针对该验证者宕机的待处理惩罚请求,则状态不发生变化。
- 否则,
- 创建
SlashPacket数据packetData,并满足packetData.vscId = VSCtoH[infractionHeight]; - 如果到提供者链的 CCV 通道已建立,则
- 将携带
packetData的数据包发送到提供者链; - 如果该请求针对宕机,则将
outstandingDowntime[data.valAddress]设为 true;
- 将携带
- 否则,将
SlashRequest{data: packetData, downtime: downtime}追加到pendingSlashRequests。
- 创建
- 错误条件
- 无。
注意:ABCI 应用程序在调用SendSlashRequest之前,必须先从违规高度中减去ValidatorUpdateDelay, 其中ValidatorUpdateDelay是验证者更新从返回给共识引擎到实际生效之间的延迟(以区块数计)。 例如,如果ValidatorUpdateDelay = x,并且在区块10结束时返回了一次包含新验证者的验证者集合更新, 那么这些新验证者应当从区块11+x开始对区块进行签名 (更多细节请参见 ABCI 规范)。 因此,消费者链 CCV 模块要求SendSlashRequest()的infractionHeight参数按此规则设置。 注意:在单链验证的上下文中,针对宕机的惩罚是一个原子操作,即一旦检测到宕机,就会立即对违规验证者执行惩罚并将其监禁。 因此,一旦某个验证者因宕机受到处罚,它就会从验证者集合中移除,并且不能再次因宕机受到处罚。 由于验证者不会被自动加入回验证者集合,这意味着验证者在重新加入并可能再次受罚之前,必然已经知晓该处罚。 在 CCV 的上下文中,针对宕机的惩罚不再是原子操作,也就是说,宕机是在消费者链上被检测到的,但监禁发生在提供者链上。 为了避免针对同一次宕机违规发送多个惩罚请求,消费者链 CCV 模块为每个验证者使用一个outstandingDowntime标志。 CCV 假设消费者链 ABCI 应用程序(例如 slashing 模块)不会将outstandingDowntime == TRUE的验证者宕机情况包含在宕机证据中。
[CCV-CCF-SNDPESLASH.1]
- 调用方
onRecvVSCPacket()方法(参见 CCV-CCF-RCVVSC.1)。
- 触发事件
- 收到来自提供者链的第一个
VSCPacket。
- 收到来自提供者链的第一个
- 前置条件
providerChannel != ""。
- 后置条件
- 按逆序遍历
pendingSlashRequests中的每个惩罚请求req,如果该惩罚请求不是针对宕机,或者当前不存在针对宕机的待处理惩罚请求,则- 将携带
req.data的数据包发送到提供者链; - 如果该请求针对宕机,则将
outstandingDowntime[req.data.valAddress]设为 true。
- 将携带
- 移除所有待处理的
SlashRequest。
- 按逆序遍历
- 错误条件
- 无。
注意:按逆序遍历待处理的 SlashRequest,可确保在通道初始化期间连续多个区块宕机的验证者,会依据最新的宕机证据受到惩罚。
奖励分配
↑ 返回大纲[CCV-CCF-EBLOCK-RD.1]
- 调用方
EndBlock()方法。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息;每个区块发送一次EndBlock消息。
- 从共识引擎接收到一条
- 前置条件
- True.
- 后置条件
- 如果
getCurrentHeight() - lastDistributionTransferHeight >= BlocksPerDistributionTransfer,则调用DistributeRewards()方法。
- 如果
- 错误条件
- 无。
[CCV-CCF-DISTRREW.1]
- 调用方
EndBlockRD()方法。
- 触发事件
- 从共识引擎接收到一条
EndBlock消息。
- 从共识引擎接收到一条
- 前置条件
getCurrentHeight() - lastDistributionTransferHeight >= BlocksPerDistributionTransfer
- 后置条件
- 对于
ccvAccount中定义的每一种代币类型对(denomination, amount),都会发起一次代币转移操作(定义见 ICS 20)。 lastDistributionTransferHeight被设置为当前高度。
- 对于
- 错误条件
- 无。
Outline
General Methods
↑ Back to Outline To express the error conditions, the following specification of the sub-protocols uses the exception system of the host state machine, which is exposed through two functions (as defined in ICS 24):abortTransactionUnless and abortSystemUnless.
BeginBlock and EndBlock
↑ Back to Outline The functionsBeginBlock() and EndBlock() (see Implemented Interfaces) are split across the CCV sub-protocols.
[CCV-PCF-BBLOCK.1]
- Caller
- The ABCI application.
- Trigger Event
- A
BeginBlockmessage is received from the consensus engine;BeginBlockmessages are sent once per block.
- A
- Precondition
- True.
- Postcondition
BeginBlockInit()is invoked (see [CCV-PCF-BBLOCK-INIT.1], i.e., it contains theBeginBlock()logic needed for the Initialization sub-protocol).BeginBlockCCR()is invoked (see [CCV-PCF-BBLOCK-CCR.1], i.e., it contains theBeginBlock()logic needed for the Consumer Chain Removal sub-protocol).
- Error Condition
- None.
[CCV-PCF-EBLOCK.1]
- Caller
- The ABCI application.
- Trigger Event
- An
EndBlockmessage is received from the consensus engine;EndBlockmessages are sent once per block.
- An
- Precondition
- True.
- Postcondition
EndBlockCIS()is invoked (see [CCV-PCF-EBLOCK-CIS.1], i.e., it contains theEndBlock()logic needed for the Consumer Initiated Slashing sub-protocol).EndBlockCCR()is invoked (see [CCV-PCF-EBLOCK-CCR.1], i.e., it contains theEndBlock()logic needed for the Consumer Chain Removal sub-protocol).EndBlockVSU()is invoked (see [CCV-PCF-EBLOCK-VSU.1], i.e., it contains theEndBlock()logic needed for the Validator Set Update sub-protocol).
- Error Condition
- None.
Note: The provider CCV module expects the provider Staking module to update its view of the validator set before theEndBlock()of the provider CCV module is invoked. A solution is for the provider Staking module to update its view duringEndBlock()and then, theEndBlock()of the provider Staking module to be executed before theEndBlock()of the provider CCV module.
[CCV-CCF-BBLOCK.1]
- Caller
- The ABCI application.
- Trigger Event
- A
BeginBlockmessage is received from the consensus engine;BeginBlockmessages are sent once per block.
- A
- Precondition
- True.
- Postcondition
BeginBlockInit()is invoked (see [CCV-CCF-BBLOCK-INIT.1], i.e., it contains theBeginBlock()logic needed for the Channel Initialization sub-protocol).BeginBlockCCR()is invoked (see [CCV-CCF-BBLOCK-CCR.1], i.e., it contains theBeginBlock()logic needed for the Consumer Chain Removal sub-protocol).BeginBlockCIS()is invoked (see [CCV-CCF-BBLOCK-CIS.1], i.e., it contains theBeginBlock()logic needed for the Consumer Initiated Slashing sub-protocol).
- Error Condition
- None.
[CCV-CCF-EBLOCK.1]
- Caller
- The ABCI application.
- Trigger Event
- An
EndBlockmessage is received from the consensus engine;EndBlockmessages are sent once per block.
- An
- Precondition
- True. x
- Postcondition
EndBlockRD()is invoked (see [CCV-PCF-EBLOCK-RD.1], i.e., it contains theEndBlock()logic needed for the Reward Distribution sub-protocol).EndBlockVSU()is invoked and the return value is returned to the consensus engine (see [CCV-CCF-EBLOCK-VSU.1], i.e., it contains theEndBlock()logic needed for the Validator Set Update sub-protocol).
- Error Condition
- None.
Packet Relay
↑ Back to Outline[CCV-PCF-RCVP.1]
- Caller
- The provider IBC routing module.
- Trigger Event
- The provider IBC routing module receives a packet on a channel owned by the provider CCV module.
- Precondition
- True.
- Postcondition
- If the packet is a
VSCMaturedPacket, the acknowledgement obtained from invoking theonRecvVSCMaturedPacketmethod is returned. - If the packet is a
SlashPacket, the acknowledgement obtained from invoking theonRecvSlashPacketmethod is returned. - Otherwise, an error acknowledgement is returned.
- If the packet is a
- Error Condition
- None.
[CCV-PCF-ACKP.1]
- Caller
- The provider IBC routing module.
- Trigger Event
- The provider IBC routing module receives an acknowledgement on a channel owned by the provider CCV module.
- Precondition
- True.
- Postcondition
- If the acknowledgement is for a
VSCPacket, theonAcknowledgeVSCPacketmethod is invoked. - Otherwise, the transaction is aborted.
- If the acknowledgement is for a
- Error Condition
- None.
[CCV-PCF-TOP.1]
- Caller
- The provider IBC routing module.
- Trigger Event
- A packet sent on a channel owned by the provider CCV module timed out as a result of either
- Precondition
- The Correct Relayer assumption is violated (see the Assumptions section).
- Postcondition
- If the timeout is for a
VSCPacket, theonTimeoutVSCPacketmethod is invoked. - Otherwise, the transaction is aborted.
- If the timeout is for a
- Error Condition
- None.
[CCV-CCF-RCVP.1]
- Caller
- The consumer IBC routing module.
- Trigger Event
- The consumer IBC routing module receives a packet on a channel owned by the consumer CCV module.
- Precondition
- True.
- Postcondition
- If the packet is a
VSCPacket, the acknowledgement obtained from invoking theonRecvVSCPacketmethod is returned. - Otherwise, an error acknowledgement is returned.
- If the packet is a
- Error Condition
- None.
[CCV-CCF-ACKP.1]
- Caller
- The consumer IBC routing module.
- Trigger Event
- The consumer IBC routing module receives an acknowledgement on a channel owned by the consumer CCV module.
- Precondition
- True.
- Postcondition
- If the acknowledgement is for a
VSCMaturedPacket, theonAcknowledgeVSCMaturedPacketmethod is invoked. - If the acknowledgement is for a
SlashPacket, theonAcknowledgeSlashPacketmethod is invoked. - Otherwise, the transaction is aborted.
- If the acknowledgement is for a
- Error Condition
- None.
[CCV-CCF-TOP.1]
- Caller
- The consumer IBC routing module.
- Trigger Event
- A packet sent on a channel owned by the consumer CCV module timed out as a result of either
- Precondition
- The Correct Relayer assumption is violated (see the Assumptions section).
- Postcondition
- If the timeout is for a
VSCMaturedPacket, theonTimeoutVSCMaturedPacketmethod is invoked. - If the timeout is for a
SlashPacket, theonTimeoutSlashPacketmethod is invoked. - Otherwise, the transaction is aborted.
- If the timeout is for a
- Error Condition
- None.
Sub-protocols
Initialization
↑ Back to Outline The initialization sub-protocol enables a provider chain and a consumer chain to create a CCV channel — a unique, ordered IBC channel for exchanging packets. As a prerequisite, the initialization sub-protocol MUST create two IBC clients, one on the provider chain to the consumer chain and one on the consumer chain to the provider chain. This is necessary to verify the identity of the two chains (as long as the clients are trusted).[CCV-PCF-INITG.1]
- Caller
- The ABCI application.
- Trigger Event
- An
InitChainmessage is received from the consensus engine; theInitChainmessage is sent when the provider chain is first started.
- An
- Precondition
- The provider CCV module is in the initial state.
- Postcondition
- The capability for the port
ProviderPortIdis claimed. - For each consumer state in the
ProviderGenesisState, the initial state is set, i.e., the following mappingschainToChannel,channelToChainare set.
- The capability for the port
- Error Condition
- The capability for the port
ProviderPortIdcannot be claimed. - For any consumer state in the
ProviderGenesisState, the channel ID is not valid (cf. the validation function defined in ICS 4).
- The capability for the port
[CCV-PCF-HCAPROP.1]
- Caller
EndBlock()method of Governance module.
- Trigger Event
- A governance proposal
ConsumerAdditionProposalhas passed (i.e., it got the necessary votes).
- A governance proposal
- Precondition
- True.
- Postcondition
- The proposal is appended to the list of pending addition proposals, i.e.,
pendingConsumerAdditionProposals.
- The proposal is appended to the list of pending addition proposals, i.e.,
- Error Condition
- None.
[CCV-PCF-BBLOCK-INIT.1]
- Caller
- The
BeginBlock()method.
- The
- Trigger Event
- A
BeginBlockmessage is received from the consensus engine;BeginBlockmessages are sent once per block.
- A
- Precondition
- True.
- Postcondition
- For each
ConsumerAdditionProposalpin the list of pending addition proposalspendingConsumerAdditionProposals, ifcurrentTimestamp() > p.spawnTime, thenCreateConsumerClient(p)is invoked;pis removed frompendingConsumerAdditionProposals.
- For each
- Error Condition
- None.
[CCV-PCF-CRCLIENT.1]
- Caller
- Either
HandleConsumerAdditionProposal(see CCV-PCF-HCAPROP.1) orBeginBlockInit()(see CCV-PCF-BBLOCK-INIT.1).
- Either
- Trigger Event
- A governance proposal
ConsumerAdditionProposalphas passed (i.e., it got the necessary votes).
- A governance proposal
- Precondition
currentTimestamp() > p.spawnTime.
- Postcondition
- If a client for
p.chainIdalready exists, the state is not changed. - Otherwise,
- the validator set of the provider chain own consensus state at current height is set as the initial validator set of the consumer chain;
- if
p.connIdis set, then- if a connection end with ID
p.connIdcannot be found, the state is not changed; - otherwise,
- if the connection with ID
p.connIdis not to the chain with IDp.chainId, the state is not changed; - otherwise,
- both the client ID and connection ID are stored;
- a
ConsumerGenesisStateis created and stored;
- if the connection with ID
- if a connection end with ID
- otherwise,
- otherwise,
- a client state is created with
chainId = p.chainIdandunbondingPeriod = p.unbondingPeriod; - a consensus state is created with
validatorSetset to the initial validator set of the consumer chain; - a client of the consumer chain is created and the client ID is stored;
- a
ConsumerGenesisStateis created and stored;
- a client state is created with
- otherwise,
lockUnbondingOnTimeout[p.chainId]is set top.lockUnbondingOnTimeout.- The init timeout timestamp is computed and stored in
initTimeoutTimestamps[p.chainId].
- If a client for
- Error Condition
- None.
Note: For the case when theclientIdfield of theConsumerAdditionProposalis not set, creating a client of a remote chain requires aClientStateand aConsensusState(for an example, take a look at ICS 7).ConsensusStaterequires setting a validator set of the remote chain. The provider chain uses the fact that the validator set of the consumer chain is the same as its own validator set. Note: Bootstrapping the consumer CCV module requires aConsumerGenesisState(see the CCV Data Structures section). The provider CCV module creates such aConsumerGenesisStatewhen handling a governance proposalConsumerAdditionProposal. Note: If the channel initialization for a consumer chain exceeds theinitTimeoutperiod, then the provider chain removes that consumer. As a result, all further attempts on the consumer side to established the CCV channel will fail. This means that the consumer chain requires some sort of social consensus to either restart the process of becoming a consumer chain or transitioning back to a sovereign chain.
[CCV-PCF-COINIT.1]
- Caller
- The provider IBC routing module.
- Trigger Event
- The provider IBC routing module receives a
ChanOpenInitmessage on a port the provider CCV module is bounded to.
- The provider IBC routing module receives a
- Precondition
- True.
- Postcondition
- The transaction is always aborted; hence, the state is not changed.
- Error Condition
- None.
[CCV-PCF-COTRY.1]
- Caller
- The provider IBC routing module.
- Trigger Event
- The provider IBC routing module receives a
ChanOpenTrymessage on a port the provider CCV module is bounded to.
- The provider IBC routing module receives a
- Precondition
- True.
- Postcondition
- The transaction is aborted if any of the following conditions are true:
- the channel is not ordered;
portIdentifier != ProviderPortId;counterpartyPortIdentifier != ConsumerPortId;counterpartyVersion != ccvVersion;- no channel with
portIdentifierandchannelIdentifierexists; - the channel has more than one connection hop;
- a connection is stored for this consumer chain and doesn’t match the underlying connection of this channel;
- the channel is not built on top of the client created for this consumer chain;
- another CCV channel for this consumer chain already exists.
- A
CCVHandshakeMetadatais returned, withproviderDistributionAccountset to the address of the distribution module account on the provider chain andversionset toccvVersion. - The state is not changed.
- The transaction is aborted if any of the following conditions are true:
- Error Condition
- None.
[CCV-PCF-COACK.1]
- Caller
- The provider IBC routing module.
- Trigger Event
- The provider IBC routing module receives a
ChanOpenAckmessage on a port the provider CCV module is bounded to.
- The provider IBC routing module receives a
- Precondition
- True.
- Postcondition
- The transaction is always aborted; hence, the state is not changed.
- Error Condition
- None.
[CCV-PCF-COCONFIRM.1]
- Caller
- The provider IBC routing module.
- Trigger Event
- The provider IBC routing module receives a
ChanOpenConfirmmessage on a port the provider CCV module is bounded to.
- The provider IBC routing module receives a
- Precondition
- True.
- Postcondition
- The transaction is aborted if any of the following conditions are true:
- no channel with
portIdentifierandchannelIdentifierexists; - the channel has more than one connection hop;
- another CCV channel for this consumer chain already exists.
- no channel with
- The connection mapping is set, i.e.,
chainToConnection. - The channel mappings are set, i.e.,
chainToChannelandchannelToChain. initialHeights[chainId]is set to the current height.- The init timeout timestamp for the consumer chain with ID
clientState.chainIdis removed.
- The transaction is aborted if any of the following conditions are true:
- Error Condition
- None.
[CCV-CCF-INITG.1]
- Caller
- The ABCI application.
- Trigger Event
- An
InitChainmessage is received from the consensus engine; theInitChainmessage is sent when the consumer chain is first started.
- An
- Precondition
- The consumer CCV module is in the initial state.
- Postcondition
- The capability for the port
ConsumerPortIdis claimed. preCCVis set togs.preCCV.- If
preCCV == true, the ID of the client on which the connection withgs.connIdis built is stored intoproviderClientId. - Otherwise, a client of the provider chain is created and the client ID is stored into
providerClientId. ConsumerUnbondingPeriodis set togs.unbondingPeriod.HtoVSCfor the current block is set to0.- The
ccvValidatorSetmapping is populated with the initial validator set. - The ID of the distribution token transfer channel is set to
gs.transferChannelId. - If
preCCV == true, the CCV channel opening handshake is initialized. - Otherwise, the connection opening handshake is initialized.
- The initial validator set is returned to the consensus engine.
- The capability for the port
- Error Condition
- The genesis state contains an empty initial validator set.
- If the genesis state
preCCVfield is set totrue, then the genesis state contains no valid connection ID. - Otherwise,
- the genesis state contains no valid provider client state, where the validity is defined in the corresponding client specification (e.g., ICS 7;
- the genesis state contains no valid provider consensus state, where the validity is defined in the corresponding client specification (e.g., ICS 7);
- the genesis state contains an initial validator set that does not match the validator set in the provider consensus state;
- The genesis state contains an invalid distribution channel ID.
- The capability for the port
ConsumerPortIdcannot be claimed.
Note: CCV assumes that all the correct validators in the initial validator set of the consumer chain receive the same consumer chain binary and consumer chain genesis state. Although the mechanism of disseminating the binary and the genesis state is outside the scope of this specification, a possible approach would entail including this information in the governance proposal on the provider chain.
[CCV-CCF-COINIT.1]
- Caller
- The consumer IBC routing module.
- Trigger Event
- The consumer IBC routing module receives a
ChanOpenInitmessage on a port the consumer CCV module is bounded to.
- The consumer IBC routing module receives a
- Precondition
- True.
- Postcondition
- The transaction is aborted if any of the following conditions are true:
providerChannelis already set;portIdentifier != ConsumerPortId;versionis set but not to the expected version;counterpartyPortIdentifier != ProviderPortId;- the client associated with this channel is not the expected provider client.
ccvVersionis returned.- The state is not changed.
- The transaction is aborted if any of the following conditions are true:
- Error Condition
- None.
[CCV-CCF-COTRY.1]
- Caller
- The consumer IBC routing module.
- Trigger Event
- The consumer IBC routing module receives a
ChanOpenTrymessage on a port the consumer CCV module is bounded to.
- The consumer IBC routing module receives a
- Precondition
- True.
- Postcondition
- The transaction is always aborted; hence, the state is not changed.
- Error Condition
- None.
[CCV-CCF-COACK.1]
- Caller
- The consumer IBC routing module.
- Trigger Event
- The consumer IBC routing module receives a
ChanOpenAckmessage on a port the consumer CCV module is bounded to.
- The consumer IBC routing module receives a
- Precondition
- True.
- Postcondition
counterpartyVersionis unmarshaled into aCCVHandshakeMetadatastructuremd.- The transaction is aborted if any of the following conditions are true:
providerChannelis already set;md.version != ccvVersion.
- The address of the distribution module account on the provider chain is set to
md.providerDistributionAccount. - If
distributionChannelIdis not set, the distribution token transfer channel opening handshake is initiated anddistributionChannelIdis set to the resulting channel ID. - The CCV channel is marked as established, i.e.,
providerChannelis set to this channel. - The pending slash requests are sent to the provider chain (see [CCV-CCF-SNDPESLASH.1]).
Note that this can happen only if
preCCV == false, as the ABCI application can invokeSendSlashRequestonly once the chain is upgraded to a consumer chain (see [CCV-CCF-BBLOCK-INIT.1]). - If
preCCV == true, the valset in the staking module is replaced with theccvValidatorSet, i.e., the initial validator set.
- Error Condition
- None.
[CCV-CCF-COCONFIRM.1]
- Caller
- The consumer IBC routing module.
- Trigger Event
- The consumer IBC routing module receives a
ChanOpenConfirmmessage on a port the consumer CCV module is bounded to.
- The consumer IBC routing module receives a
- Precondition
- True.
- Postcondition
- The transaction is always aborted; hence, the state is not changed.
- Error Condition
- None.
[CCV-CCF-BBLOCK-INIT.1]
- Caller
- The
BeginBlock()method.
- The
- Trigger Event
- A
BeginBlockmessage is received from the consensus engine;BeginBlockmessages are sent once per block.
- A
- Precondition
- True.
- Postcondition
- If
preCCV == trueand the current validator set matches theccvValidatorSet(i.e., the initial validator set), then the chain MUST be upgraded to a full consumer chain. The upgrade mechanism is outside the scope of this specification.
- If
- Error Condition
- None.
Consumer Chain Removal
↑ Back to Outline[CCV-PCF-HCRPROP.1]
- Caller
EndBlock()method of Governance module.
- Trigger Event
- A governance proposal
ConsumerRemovalProposalhas passed (i.e., it got the necessary votes).
- A governance proposal
- Precondition
- True.
- Postcondition
- The proposal is appended to the list of pending removal proposals, i.e.,
pendingConsumerRemovalProposals.
- The proposal is appended to the list of pending removal proposals, i.e.,
- Error Condition
- None.
[CCV-PCF-BBLOCK-CCR.1]
- Caller
- The
BeginBlock()method.
- The
- Trigger Event
- A
BeginBlockmessage is received from the consensus engine;BeginBlockmessages are sent once per block.
- A
- Precondition
- True.
- Postcondition
- For each
ConsumerRemovalProposalpin the list of pending removal proposalspendingConsumerRemovalProposals, ifcurrentTimestamp() > p.stopTime, thenStopConsumerChain(p.chainId, false)is invoked;pis removed frompendingConsumerRemovalProposals.
- For each
- Error Condition
- None.
[CCV-PCF-STCC.1]
- Caller
HandleConsumerRemovalProposal(see CCV-PCF-HCRPROP.1) orBeginBlockCCR()(see CCV-PCF-BBLOCK-CCR.1) oronTimeoutVSCPacket()(see CCV-PCF-TOVSC.1) orEndBlockCCR()(see CCV-PCF-EBLOCK-CCR.1).
- Trigger Event
- One of the following events:
- a governance proposal to stop the consumer chain with
chainIdhas passed (i.e., it got the necessary votes); - a
VSCPacketsent on the CCV channel to the consumer chain withchainIdhas timed out; - the channel initialization has timed out.
- a governance proposal to stop the consumer chain with
- One of the following events:
- Precondition
- True.
- Postcondition
- If a client for
p.chainIddoes not exist, the state is not changed. - Otherwise,
- the client ID mapped to
chainIdinchainToClientis removed; - the value mapped to
chainIdinlockUnbondingOnTimeoutis removed; - if the CCV channel to the consumer chain with
chainIdis established, then- the chain ID mapped to
chainToChannel[chainId]inchannelToChainis removed; - the channel closing handshake is initiated for the CCV channel;
- the channel ID mapped to
chainIdinchainToChannelis removed.
- the chain ID mapped to
- all the
VSCPacketDatamapped tochainIdinpendingVSCPacketsare removed; - the height mapped to
chainIdininitialHeightsis removed; downtimeSlashRequests[chainId]is emptied;- if
lockUnbonding == false, thenchainIdis removed from all outstanding unbonding operations;- if an outstanding unbonding operation has matured on all consumer chains,
- the matured unbonding operation is added to
maturedUnbondingOps; - the matured unbonding operation is removed from
unbondingOps; - all the entries with
chainIdare removed from thevscToUnbondingOpsmapping.
- the client ID mapped to
- If a client for
- Error Condition
- None
Note: InvokingStopConsumerChain(chainId, lockUnbonding)withlockUnbonding == FALSEentails that all outstanding unbonding operations can complete beforeConsumerUnbondingPeriodelapses on the consumer chain withchainId. Thus, invokingStopConsumerChain(chainId, false)for anychainIdMAY violate the Bond-Based Consumer Voting Power and Slashable Consumer Misbehavior properties (see the System Properties section).StopConsumerChain(chainId, false)is invoked in two scenarios (see Trigger Event above).
- In the first scenario (i.e., a governance proposal to stop the consumer chain with
chainId), the validators on the provider chain MUST make sure that it is safe to stop the consumer chain. Since a governance proposal needs a majority of the voting power to pass, the safety of invokingStopConsumerChain(chainId, false)is ensured by the Safe Blockchain assumption (see the Assumptions section).- The second scenario (i.e., a timeout) is only possible if the Correct Relayer assumption is violated (see the Assumptions section), which is necessary to guarantee both the Bond-Based Consumer Voting Power and Slashable Consumer Misbehavior properties (see the Assumptions section).
[CCV-PCF-EBLOCK-CCR.1]
- Caller
- The
EndBlock()method.
- The
- Trigger Event
- An
EndBlockmessage is received from the consensus engine;EndBlockmessages are sent once per block.
- An
- Precondition
- True.
- Postcondition
- For each consumer chain ID
chainIdinvscSendTimestamps.Keys(),- if
vscSendTimestamps[(chainId, vscId)] + vscTimeoutis smaller than the current timestamp, then the consumer chain with IDchainIdis stopped.
- if
- For each consumer chain ID
chainIdininitTimeoutTimestamps.Keys(),- if the timestamp in
initTimeoutTimestamps[chainId]is smaller than the current timestamp, then the consumer chain with IDchainIdis stopped.
- if the timestamp in
- For each consumer chain ID
- Error Condition
- None.
Note: To avoid false positives where a consumer chain is unnecessarily removed,vscTimeoutMUST be larger thanconsumerUnbondingPeriodand SHOULD account for the time needed to relay theVSCPacketto the consumer and the correspondingVSCMaturedPacketback to the provider.
[CCV-PCF-CCINIT.1]
- Caller
- The provider IBC routing module.
- Trigger Event
- The provider IBC routing module receives a
ChanCloseInitmessage on a port the provider CCV module is bounded to.
- The provider IBC routing module receives a
- Precondition
- True.
- Postcondition
- The transaction is always aborted; hence, the state is not changed.
- Error Condition
- None.
[CCV-PCF-CCCONFIRM.1]
- Caller
- The provider IBC routing module.
- Trigger Event
- The provider IBC routing module receives a
ChanCloseConfirmmessage on a port the provider CCV module is bounded to.
- The provider IBC routing module receives a
- Precondition
- True.
- Postcondition
- The state is not changed.
- Error Condition
- None.
[CCV-CCF-BBLOCK-CCR.1]
- Caller
- The
BeginBlock()method.
- The
- Trigger Event
- A
BeginBlockmessage is received from the consensus engine;BeginBlockmessages are sent once per block.
- A
- Precondition
- True.
- Postcondition
- If the CCV was established, but then was moved to the
CLOSEDstate, then the state of the consumer CCV module is cleaned up, e.g., theproviderChannelis unset.
- If the CCV was established, but then was moved to the
- Error Condition
- If the CCV was established, but then was moved to the
CLOSEDstate.
- If the CCV was established, but then was moved to the
Note: Once the CCV channel is closed, the provider chain can no longer provider security. As a result, the consumer chain MUST be shut down. For an example of how to do this in practice, see the Cosmos SDK implementation.
[CCV-CCF-CCINIT.1]
- Caller
- The consumer IBC routing module.
- Trigger Event
- The consumer IBC routing module receives a
ChanCloseInitmessage on a port the consumer CCV module is bounded to.
- The consumer IBC routing module receives a
- Precondition
- True.
- Postcondition
- If
providerChannelis not set orproviderChannelmatches the ID of the channel theChanCloseInitmessage was received on, then the transaction is aborted. - The state is not changed.
- If
- Error Condition
- None.
[CCV-CCF-CCCONFIRM.1]
- Caller
- The consumer IBC routing module.
- Trigger Event
- The consumer IBC routing module receives a
ChanCloseConfirmmessage on a port the consumer CCV module is bounded to.
- The consumer IBC routing module receives a
- Precondition
- True.
- Postcondition
- The state is not changed.
- Error Condition
- None.
Validator Set Update
↑ Back to Outline The validator set update sub-protocol enables the provider chain- to update the consumer chain on the voting power granted to validators on the provider chain
- and to ensure the correct completion of unbonding operations for validators that produce blocks on the consumer chain.
[CCV-PCF-EBLOCK-VSU.1]
- Caller
- The
EndBlock()method.
- The
- Trigger Event
- An
EndBlockmessage is received from the consensus engine;EndBlockmessages are sent once per block.
- An
- Precondition
- True.
- Postcondition
- For every matured unbonding operation in
maturedUnbondingOps, the Staking module is notified that the unbonding can complete. - All unbonding operation in
maturedUnbondingOpsare removed. - A list of validator updates
valUpdatesis obtained from the provider Staking module. - For every consumer chain with
chainId- If either
valUpdatesis not empty or there were unbonding operations initiated during this block, then- a
VSCPacketdatadatais created such thatdata.id = vscId,data.updates = valUpdates, anddata.downtimeSlashAcks = downtimeSlashRequests[chainId]; downtimeSlashRequests[chainId]is emptied;packetDatais appended to the list of pendingVSCPackets associated tochainId, i.e.,pendingVSCPackets[chainId].
- a
- If there is an established CCV channel for the consumer chain with
chainId, then- for each
VSCPacketDatain the list of pending VSCPackets associated tochainId- a packet with the
VSCPacketDatais sent on the channel associated with the consumer chain withchainId; vscSendTimestamps[(vscId, chainId)]is set to the current timestamp;
- a packet with the
- all the pending VSCPackets associated to
chainIdare removed.
- for each
- If either
vscIdis incremented.
- For every matured unbonding operation in
- Error Condition
- None.
[CCV-PCF-ACKVSC.1]
- Caller
- The
onAcknowledgePacket()method.
- The
- Trigger Event
- The provider IBC routing module receives an acknowledgement of a
VSCPacketon a channel owned by the provider CCV module.
- The provider IBC routing module receives an acknowledgement of a
- Precondition
- True.
- Postcondition
- The state is not changed.
- Error Condition
- The acknowledgement is
VSCPacketError.
- The acknowledgement is
[CCV-PCF-TOVSC.1]
- Caller
- The
onTimeoutPacket()method.
- The
- Trigger Event
- A
VSCPacketsent on a channel owned by the provider CCV module timed out as a result of either
- A
- Precondition
- The Correct Relayer assumption is violated (see the Assumptions section).
- Postcondition
- The transaction is aborted if the ID of the channel on which the packet was sent is not mapped to a chain ID (in
channelToChain). StopConsumerChain(chainId, lockUnbondingOnTimeout[chainId])is invoked, wherechainId = channelToChain[packet.getDestinationChannel()].
- The transaction is aborted if the ID of the channel on which the packet was sent is not mapped to a chain ID (in
- Error Condition
- None
[CCV-PCF-RCVMAT.1]
- Caller
- The
onRecvPacket()method.
- The
- Trigger Event
- The provider IBC routing module receives a
VSCMaturedPacketon a channel owned by the provider CCV module.
- The provider IBC routing module receives a
- Precondition
- True.
- Postcondition
- The transaction is aborted if the channel on which the packet was received is not an established CCV channel (i.e., not in
channelToChain). chainIdis set to the ID of the consumer chain mapped to the channel on which the packet was received.- For each unbonding operation
opreturned byGetUnbondingsFromVSC(chainId, packet.data.id)chainIdis removed fromop.unbondingChainIds;- if
op.unbondingChainIdsis empty,op.idis added tomaturedUnbondingOps;op.idis removed fromunbondingOps.
(chainId, vscId)is removed fromvscToUnbondingOps.(chainId, vscId)is removed fromvscSendTimestamps.- A successful acknowledgment is returned.
- The transaction is aborted if the channel on which the packet was received is not an established CCV channel (i.e., not in
- Error Condition
- None.
[CCV-PCF-GETUBS.1]
- Caller
- The
onRecvVSCMaturedPacket()method.
- The
- Trigger Event
- The provider IBC routing module receives a
VSCMaturedPacketon a channel owned by the provider CCV module.
- The provider IBC routing module receives a
- Precondition
- The provider CCV module received a
VSCMaturedPacketPfrom a consumer chain with IDchainId, such thatP.data.id == _vscId.
- The provider CCV module received a
- Postcondition
- Return the list of unbonding operations mapped to
(chainId, _vscId).
- Return the list of unbonding operations mapped to
- Error Condition
- None.
[CCV-PCF-HOOK-AFUBOPCR.1]
- Caller
- The Staking module.
- Trigger Event
- An unbonding operation with id
opIdis initiated.
- An unbonding operation with id
- Precondition
- True.
- Postcondition
chainIdsis set to the list of all consumer chains registered with this provider chain, i.e.,chainToClient.Keys().- If there is at least one consumer chain in
chainIds, then- an
UnbondingOperationopis created and added tounbondingOps, such thatop.id = opIdandop.unbondingChainIds = chainIds. opIdis appended to every list invscToUnbondingOps[(chainId, vscId)], wherechainIdis an ID of a consumer chains registered with this provider chain andvscIdis the current VSC ID.- the
PutUnbondingOnHold(opId)of the Staking module is invoked.
- an
- Error Condition
- None.
[CCV-CCF-RCVVSC.1]
- Caller
- The
onRecvPacket()method.
- The
- Trigger Event
- The consumer IBC routing module receives a
VSCPacketon a channel owned by the consumer CCV module.
- The consumer IBC routing module receives a
- Precondition
- True.
- Postcondition
- If
providerChannelis set and does not match the channel (with IDpacket.getDestinationChannel()) on which the packet was received, then an error acknowledgement is returned. - Otherwise,
- the height of the subsequent block is mapped to
packet.data.id(i.e., theHtoVSCmapping) ; packet.datais appended toreceivedVSCs.- a successful acknowledgement is returned.
- the height of the subsequent block is mapped to
- If
- Error Condition
- None.
[CCV-CCF-ACKMAT.1]
- Caller
- The
onAcknowledgePacket()method.
- The
- Trigger Event
- The consumer IBC routing module receives an acknowledgement of a
VSCMaturedPacketon a channel owned by the consumer CCV module.
- The consumer IBC routing module receives an acknowledgement of a
- Precondition
- True.
- Postcondition
- The state is not changed.
- Error Condition
- The acknowledgement is
VSCMaturedPacketError.
- The acknowledgement is
[CCV-CCF-TOMAT.1]
- Caller
- The
onTimeoutPacket()method.
- The
- Trigger Event
- A
VSCMaturedPacketsent on a channel owned by the consumer CCV module timed out as a result of either
- A
- Precondition
- The Correct Relayer assumption is violated (see the Assumptions section).
- Postcondition
- The state is not changed.
- Error Condition
- None
[CCV-CCF-EBLOCK-VSU.1]
- Caller
- The
EndBlock()method.
- The
- Trigger Event
- An
EndBlockmessage is received from the consensus engine;EndBlockmessages are sent once per block.
- An
- Precondition
- True.
- Postcondition
- If
providerChannel != "",UnbondMaturePackets()is invoked; - If
preCCV == true, the state is not changed. - Otherwise,
- the data items in
receivedVSCsare handled (see [CCV-CCF-HAREVSC.1]), which results in a listchangesof validator updates; UpdateValidatorSet(changes)is invoked;changesis returned.
- the data items in
- If
- Error Condition
- None.
[CCV-CCF-HAREVSC.1]
- Caller
- The
EndBlock()method.
- The
- Trigger Event
- An
EndBlockmessage is received from the consensus engine.
- An
- Precondition
preCCV == false.
- Postcondition
- For each
dataitem in the listreceivedVSCs,data.updatesare appended tochanges, wherechangesis initially an empty list of validator updates;(data.id, maturityTimestamp)is added tomaturingVSCs, wherematurityTimestamp = currentTimestamp() + ConsumerUnbondingPeriod;- for each
valAddrin the slash acknowledgments received from the provider chain,outstandingDowntime[valAddr]is set to false.
receivedVSCsis emptied.- The updates in
changesare aggregated, i.e., only the latest update per validator is kept, and returned.
- For each
- Error Condition
- None.
[CCV-CCF-UPVALS.1]
- Caller
- The
EndBlock()method.
- The
- Trigger Event
- An
EndBlockmessage is received from the consensus engine.
- An
- Precondition
preCCV == false.
- Postcondition
- For each validator
updateinchanges,- if the validator is not in the validator set and
update.power > 0, then- a new validator is added to
ccvValidatorSet; - the
AfterCCValidatorBondedhook is called;
- a new validator is added to
- otherwise, if the validator’s new power is
0, then,- the validator is removed from
ccvValidatorSet; - the
AfterCCValidatorBeginUnbondinghook is called;
- the validator is removed from
- otherwise, the validator’s power is updated.
- if the validator is not in the validator set and
- For each validator
- Error Condition
- None.
[CCV-CCF-UMP.1]
- Caller
- The
EndBlock()method.
- The
- Trigger Event
- An
EndBlockmessage is received from the consensus engine.
- An
- Precondition
- The CCV channel to the provider chain is established, i.e.,
providerChannel != "".
- The CCV channel to the provider chain is established, i.e.,
- Postcondition
- For each
(id, ts)in the list of maturing VSCs sorted by maturity timestamps- if
currentTimestamp() < ts, the loop is stopped; - a
VSCMaturedPacketDatapacket data is created; - a packet with the created
VSCMaturedPacketDatais sent to the provider chain; - the tuple
(id, ts)is removed frommaturingVSCs.
- if
- For each
- Error Condition
- None.
Consumer Initiated Slashing
↑ Back to Outline[CCV-PCF-EBLOCK-CIS.1]
- Caller
- The
EndBlock()method.
- The
- Trigger Event
- An
EndBlockmessage is received from the consensus engine;EndBlockmessages are sent once per block.
- An
- Precondition
- True.
- Postcondition
vscIdis mapped to the height of the subsequent block.
- Error Condition
- None.
[CCV-PCF-RCVSLASH.1]
- Caller
- The
onRecvPacket()method.
- The
- Trigger Event
- The provider IBC routing module receives a
SlashPacketon a channel owned by the provider CCV module.
- The provider IBC routing module receives a
- Precondition
- True.
- Postcondition
- If the channel the packet was received on is not an established CCV channel, then an error acknowledgment is returned.
- Otherwise,
- if
packet.data.vscId == 0,infractionHeightis set toinitialHeights[chainId], withchainId = channelToChain[packet.getDestinationChannel()], i.e., the height when the CCV channel to this consumer chain is established; - otherwise,
infractionHeightis set toVSCtoH[packet.data.vscId], i.e., the height at which the voting power was last updated by the validator updates in the VSC with IDpacket.data.vscId; - a request is made to the Slashing module to slash
slashFactorof the tokens bonded atinfractionHeightby the validator with addresspacket.data.valAddress, whereslashFactoris the slashing factor set on the provider chain; - a request is made to the Slashing module to jail the validator with address
packet.data.valAddressfor a periodjailTime, wherejailTimeis the jailing time set on the provider chain; - if the slash request is for downtime, the validator’s address
packet.data.valAddressis added to the list of downtime slash requests from thischainId; - a successful acknowledgment is returned.
- if
- Error Condition
- None.
[CCV-CCF-BBLOCK-CIS.1]
- Caller
- The
BeginBlock()method.
- The
- Trigger Event
- A
BeginBlockmessage is received from the consensus engine;BeginBlockmessages are sent once per block.
- A
- Precondition
- True.
- Postcondition
HtoVSCfor the subsequent block height is set to the same VSC ID as the current block height.
- Error Condition
- None.
[CCV-CCF-ACKSLASH.1]
- Caller
- The
onAcknowledgePacket()method.
- The
- Trigger Event
- The consumer IBC routing module receives an acknowledgement of a
SlashPacketon a channel owned by the consumer CCV module.
- The consumer IBC routing module receives an acknowledgement of a
- Precondition
- True.
- Postcondition
- The state is not changed.
- Error Condition
- The acknowledgement is
SlashPacketError.
- The acknowledgement is
[CCV-CCF-TOSLASH.1]
- Caller
- The
onTimeoutPacket()method.
- The
- Trigger Event
- A
SlashPacketsent on a channel owned by the consumer CCV module timed out as a result of either
- A
- Precondition
- The Correct Relayer assumption is violated (see the Assumptions section).
- Postcondition
- The state is not changed.
- Error Condition
- None
[CCV-CCF-SNDSLASH.1]
- Caller
- The ABCI application (e.g., the Slashing module).
- Trigger Event
- Evidence of misbehavior for a validator with address
valAddresswas received.
- Evidence of misbehavior for a validator with address
- Precondition
- True.
- Postcondition
- If the request is for downtime and there is an outstanding request to slash this validator for downtime, then the state is not changed.
- Otherwise,
- a
SlashPacketdatapacketDatais created, such thatpacketData.vscId = VSCtoH[infractionHeight]; - if the CCV channel to the provider chain is established, then
- a packet with the
packetDatais sent to the provider chain; - if the request is for downtime,
outstandingDowntime[data.valAddress]is set to true;
- a packet with the
- otherwise
SlashRequest{data: packetData, downtime: downtime}is appended topendingSlashRequests.
- a
- Error Condition
- None.
Note: The ABCI application MUST subtractValidatorUpdateDelayfrom the infraction height before invokingSendSlashRequest, whereValidatorUpdateDelayis a delay (in blocks) between when validator updates are returned to the consensus-engine and when they are applied. For example, ifValidatorUpdateDelay = xand a validator set update is returned with new validators at the end of block10, then the new validators are expected to sign blocks beginning at block11+x(for more details, take a look at the ABCI specification). Consequently, the consumer CCV module expects theinfractionHeightparameter of theSendSlashRequest()to be set accordingly. Note: In the context of single-chain validation, slashing for downtime is an atomic operation, i.e., once the downtime is detected, the misbehaving validator is slashed and jailed immediately. Consequently, once a validator is punished for downtime, it is removed from the validator set and cannot be punished again for downtime. Since validators are not automatically added back to the validator set, it entails that the validator is aware of the punishment before it can rejoin and be potentially punished again. In the context of CCV, slashing for downtime is no longer atomic, i.e., downtime is detected on the consumer chain, but the jailing happens on the provider chain. To avoid sending multiple slash requests for the same downtime infraction, the consumer CCV module uses anoutstandingDowntimeflag per validator. CCV assumes that the consumer ABCI application (e.g., the slashing module) is not including the downtime of a validator withoutstandingDowntime == TRUEin the evidence for downtime.
[CCV-CCF-SNDPESLASH.1]
- Caller
- The
onRecvVSCPacket()method (see CCV-CCF-RCVVSC.1).
- The
- Trigger Event
- The first
VSCPacketis received from the provider chain.
- The first
- Precondition
providerChannel != "".
- Postcondition
- For each slash request
reqinpendingSlashRequestsin reverse order, such that either the slash request is not for downtime or there is no outstanding slash request for downtime,- a packet with the data
req.datais sent to the provider chain; - if the request is for downtime,
outstandingDowntime[req.data.valAddress]is set to true.
- a packet with the data
- All the pending
SlashRequests are removed.
- For each slash request
- Error Condition
- None.
Note: Iterating over pending SlashRequests in reverse order ensures that validators that are down for multiple blocks during channel initialization will be slashed for the latest downtime evidence.
Reward Distribution
↑ Back to Outline[CCV-CCF-EBLOCK-RD.1]
- Caller
- The
EndBlock()method.
- The
- Trigger Event
- An
EndBlockmessage is received from the consensus engine;EndBlockmessages are sent once per block.
- An
- Precondition
- True.
- Postcondition
- If
getCurrentHeight() - lastDistributionTransferHeight >= BlocksPerDistributionTransfer, theDistributeRewards()method is invoked.
- If
- Error Condition
- None.
[CCV-CCF-DISTRREW.1]
- Caller
- The
EndBlockRD()method.
- The
- Trigger Event
- An
EndBlockmessage is received from the consensus engine.
- An
- Precondition
getCurrentHeight() - lastDistributionTransferHeight >= BlocksPerDistributionTransfer
- Postcondition
- For each token type defined as a pair
(denomination, amount)inccvAccount, a transfer token (as defined in ICS 20) is initiated. lastDistributionTransferHeightis set to the current height.
- For each token type defined as a pair
- Error Condition
- None.