CCV: Technical Specification - Methods
CCV: Technical Specification - Methods
↑ Back to technical specification
<!-- omit in toc -->Outline
General Methods
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
The functions BeginBlock() and EndBlock() (see Implemented Interfaces) are split across the CCV sub-protocols.
[CCV-PCF-BBLOCK.1]
// PCF: Provider Chain Function
// implements the AppModule interface
function BeginBlock() {
BeginBlockInit()
BeginBlockCCR()
}
- 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]
// PCF: Provider Chain Function
// implements the AppModule interface
function EndBlock(): [ValidatorUpdate] {
EndBlockCIS()
EndBlockCCR()
EndBlockVSU()
// do not return anything to the consensus engine
return []
}
- 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 the
EndBlock()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.
<!-- omit in toc -->
[CCV-CCF-BBLOCK.1]
// CCF: Consumer Chain Function
// implements the AppModule interface
function BeginBlock() {
BeginBlockInit()
BeginBlockCCR()
BeginBlockCIS()
}
- 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]
// CCF: Consumer Chain Function
// implements the AppModule interface
function EndBlock(): [ValidatorUpdate] {
EndBlockRD()
// return the validator set updates to the consensus engine
return EndBlockVSU()
}
- 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
<!-- omit in toc -->[CCV-PCF-RCVP.1]
// PCF: Provider Chain Function
// implements the ModuleCallbacks interface defined in ICS26
function onRecvPacket(packet: Packet): bytes {
switch typeof(packet.data) {
case VSCMaturedPacketData:
return onRecvVSCMaturedPacket(packet)
case SlashPacketData:
return onRecvSlashPacket(packet)
default:
// unexpected packet type
return PacketError
}
}
- 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]
// PCF: Provider Chain Function
// implements the ModuleCallbacks interface defined in ICS26
function onAcknowledgePacket(packet: Packet, ack: bytes) {
switch typeof(packet.data) {
case VSCPacketData:
onAcknowledgeVSCPacket(packet, ack)
default:
// unexpected packet type
abortTransactionUnless(FALSE)
}
}
- 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]
// PCF: Provider Chain Function
// implements the ModuleCallbacks interface defined in ICS26
function onTimeoutPacket(packet Packet) {
switch typeof(packet.data) {
case VSCPacketData:
onTimeoutVSCPacket(packet)
default:
// unexpected packet type
abortTransactionUnless(FALSE)
}
}
- 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.
<!-- omit in toc -->
[CCV-CCF-RCVP.1]
// CCF: Consumer Chain Function
// implements the ModuleCallbacks interface defined in ICS26
function onRecvPacket(packet: Packet): bytes {
switch typeof(packet.data) {
case VSCPacketData:
return onRecvVSCPacket(packet)
default:
// unexpected packet type
return PacketError
}
}
- 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]
// CCF: Consumer Chain Function
// implements the ModuleCallbacks interface defined in ICS26
function onAcknowledgePacket(packet: Packet, ack: bytes) {
switch typeof(packet.data) {
case VSCMaturedPacketData:
onAcknowledgeVSCMaturedPacket(packet, ack)
case SlashPacketData:
onAcknowledgeSlashPacket(packet, ack)
default:
// unexpected packet type
abortTransactionUnless(FALSE)
}
}
- 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]
// CCF: Consumer Chain Function
// implements the ModuleCallbacks interface defined in ICS26
function onTimeoutPacket(packet Packet) {
switch typeof(packet.data) {
case VSCMaturedPacketData:
onTimeoutVSCMaturedPacket(packet)
case SlashPacketData:
onTimeoutSlashPacket(packet)
default:
// unexpected packet type
abortTransactionUnless(FALSE)
}
}
- 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
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).
<!-- omit in toc -->[CCV-PCF-INITG.1]
// PCF: Provider Chain Function
// implements the AppModule interface
function InitGenesis(state: ProviderGenesisState): [ValidatorUpdate] {
// bind to ProviderPortId port
err = portKeeper.bindPort(ProviderPortId)
// check whether the capability for the port can be claimed
abortSystemUnless(err == nil)
foreach cs in state.consumerStates {
abortSystemUnless(validateChannelIdentifier(cs.channelId))
chainToChannel[cs.chainId] = cs.channelId
channelToChain[cs.channelId] = cc.chainId
}
// do not return anything to the consensus engine
return []
}
- 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]
// PCF: Provider Chain Function
// implements governance proposal Handler
function HandleConsumerAdditionProposal(p: ConsumerAdditionProposal) {
// store the proposal as a pending addition proposal
pendingConsumerAdditionProposals.Append(p)
}
- 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]
// PCF: Provider Chain Function
function BeginBlockInit() {
// iterate over the pending addition proposals and create
// the consumer client if the spawn time has passed
foreach p IN pendingConsumerAdditionProposals {
if currentTimestamp() > p.spawnTime {
CreateConsumerClient(p)
pendingConsumerAdditionProposals.Remove(p)
}
}
}
- 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]
// PCF: Provider Chain Function
// Utility method
function CreateConsumerClient(p: ConsumerAdditionProposal) {
// check that no other consumer chain with the same chain ID exists
if p.chainId IN chainToClient.Keys() {
// ignore governance proposal
return
}
// set consumer chain initial validator set, i.e.,
// the validator set is the same as the validator set
// from own consensus state at current height
//
// TODO: ownConsensusState.validatorSet VS consensusState.nextValidatorsHash
// specify which validator set is used as the initial val set
ownConsensusState = getConsensusState(getCurrentHeight())
initialValSet = ownConsensusState.validatorSet
if p.connId != "" { // connection ID provided
// check validity
connectionEnd = provableStore.get("connections/{p.connId}")
if connectionEnd == nil {
// invalid proposal: cannot find connection
return
}
clientState = provableStore.get("clients/{connectionEnd.clientIdentifier}/clientState")
if clientState.chainID != p.chainId {
// invalid proposal: connection not to expected chain ID
return
}
// store client ID
chainToClient[p.chainId] = connectionEnd.clientIdentifier
// store connection ID
chainToConnection[p.chainId] = connId
// create and store ConsumerGenesisState
consumerGenesisState[p.chainId] = ConsumerGenesisState {
// consumer chain MUST start in pre-CCV state, i.e.,
// the consumer CCV module MUST NOT pass validator updates
// to the underlying consensus engine
preCCV: true,
unbondingPeriod: p.unbondingPeriod,
connId: connectionEnd.counterpartyConnectionIdentifier,
providerClientState: nil,
providerConsensusState: nil,
counterpartyClientId: "",
initialValSet: initialValSet,
transferChannelId: p.transferChannelId,
}
}
else {
// create client state
clientState = ClientState{
chainId: p.chainId,
unbondingPeriod: p.unbondingPeriod,
// the height when the client was last updated is set to the first possible height;
// for example, in the case of a Tendermint Client, this is Height{0, 1} (see ICS-7)
latestHeight: 0,
}
// create consensus state
consensusState = ConsensusState{
validatorSet: initialValSet,
}
// create consumer chain client and store it
clientId = clientKeeper.CreateClient(clientState, consensusState)
chainToClient[p.chainId] = clientId
// create and store ConsumerGenesisState
consumerGenesisState[p.chainId] = ConsumerGenesisState {
// consumer chain MUST NOT start in pre-CCV state, i.e.,
// the consumer CCV module MUST pass validator updates
// to the underlying consensus engine
preCCV: false,
unbondingPeriod: p.unbondingPeriod,
connId: "",
providerClientState: getHostClientState(getCurrentHeight()),
providerConsensusState: ownConsensusState,
counterpartyClientId: clientId,
initialValSet: initialValSet,
transferChannelId: p.transferChannelId,
}
}
// store lockUnbondingOnTimeout flag
lockUnbondingOnTimeout[p.chainId] = p.lockUnbondingOnTimeout
// add init timeout timestamp for this consumer chain
initTimeoutTimestamps[p.chainId] = currentTimestamp().Add(initTimeout)
}
- 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
- If a client for
Excerpt (19997 of 89116 characters). Read the whole page on cosmos/ibc (ICS specifications) ↗