Skip to main content

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 functions BeginBlock() and EndBlock() (see Implemented Interfaces) are split across the CCV sub-protocols.

[CCV-PCF-BBLOCK.1]

  • Caller
    • The ABCI application.
  • Trigger Event
    • A BeginBlock message is received from the consensus engine; BeginBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • BeginBlockInit() is invoked (see [CCV-PCF-BBLOCK-INIT.1], i.e., it contains the BeginBlock() logic needed for the Initialization sub-protocol).
    • BeginBlockCCR() is invoked (see [CCV-PCF-BBLOCK-CCR.1], i.e., it contains the BeginBlock() logic needed for the Consumer Chain Removal sub-protocol).
  • Error Condition
    • None.

[CCV-PCF-EBLOCK.1]

  • Caller
    • The ABCI application.
  • Trigger Event
    • An EndBlock message is received from the consensus engine; EndBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • EndBlockCIS() is invoked (see [CCV-PCF-EBLOCK-CIS.1], i.e., it contains the EndBlock() logic needed for the Consumer Initiated Slashing sub-protocol).
    • EndBlockCCR() is invoked (see [CCV-PCF-EBLOCK-CCR.1], i.e., it contains the EndBlock() logic needed for the Consumer Chain Removal sub-protocol).
    • EndBlockVSU() is invoked (see [CCV-PCF-EBLOCK-VSU.1], i.e., it contains the EndBlock() 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 during EndBlock() and then, the EndBlock() of the provider Staking module to be executed before the EndBlock() of the provider CCV module.

[CCV-CCF-BBLOCK.1]

  • Caller
    • The ABCI application.
  • Trigger Event
    • A BeginBlock message is received from the consensus engine; BeginBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • BeginBlockInit() is invoked (see [CCV-CCF-BBLOCK-INIT.1], i.e., it contains the BeginBlock() logic needed for the Channel Initialization sub-protocol).
    • BeginBlockCCR() is invoked (see [CCV-CCF-BBLOCK-CCR.1], i.e., it contains the BeginBlock() logic needed for the Consumer Chain Removal sub-protocol).
    • BeginBlockCIS() is invoked (see [CCV-CCF-BBLOCK-CIS.1], i.e., it contains the BeginBlock() logic needed for the Consumer Initiated Slashing sub-protocol).
  • Error Condition
    • None.

[CCV-CCF-EBLOCK.1]

  • Caller
    • The ABCI application.
  • Trigger Event
    • An EndBlock message is received from the consensus engine; EndBlock messages are sent once per block.
  • Precondition
    • True. x
  • Postcondition
    • EndBlockRD() is invoked (see [CCV-PCF-EBLOCK-RD.1], i.e., it contains the EndBlock() 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 the EndBlock() 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 the onRecvVSCMaturedPacket method is returned.
    • If the packet is a SlashPacket, the acknowledgement obtained from invoking the onRecvSlashPacket method is returned.
    • Otherwise, an error acknowledgement is returned.
  • 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, the onAcknowledgeVSCPacket method is invoked.
    • Otherwise, the transaction is aborted.
  • 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
      • the timeout height or timeout timestamp passing on the consumer chain without the packet being received (see timeoutPacket defined in ICS4);
      • or the channel being closed without the packet being received (see timeoutOnClose defined in ICS4).
  • Precondition
    • The Correct Relayer assumption is violated (see the Assumptions section).
  • Postcondition
    • If the timeout is for a VSCPacket, the onTimeoutVSCPacket method is invoked.
    • Otherwise, the transaction is aborted.
  • 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 the onRecvVSCPacket method is returned.
    • Otherwise, an error acknowledgement is returned.
  • 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, the onAcknowledgeVSCMaturedPacket method is invoked.
    • If the acknowledgement is for a SlashPacket, the onAcknowledgeSlashPacket method is invoked.
    • Otherwise, the transaction is aborted.
  • 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
      • the timeout height or timeout timestamp passing on the provider chain without the packet being received (see timeoutPacket defined in ICS4);
      • or the channel being closed without the packet being received (see timeoutOnClose defined in ICS4).
  • Precondition
    • The Correct Relayer assumption is violated (see the Assumptions section).
  • Postcondition
    • If the timeout is for a VSCMaturedPacket, the onTimeoutVSCMaturedPacket method is invoked.
    • If the timeout is for a SlashPacket, the onTimeoutSlashPacket method is invoked.
    • Otherwise, the transaction is aborted.
  • 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 InitChain message is received from the consensus engine; the InitChain message is sent when the provider chain is first started.
  • Precondition
    • The provider CCV module is in the initial state.
  • Postcondition
    • The capability for the port ProviderPortId is claimed.
    • For each consumer state in the ProviderGenesisState, the initial state is set, i.e., the following mappings chainToChannel, channelToChain are set.
  • Error Condition
    • The capability for the port ProviderPortId cannot be claimed.
    • For any consumer state in the ProviderGenesisState, the channel ID is not valid (cf. the validation function defined in ICS 4).

[CCV-PCF-HCAPROP.1]

  • Caller
    • EndBlock() method of Governance module.
  • Trigger Event
    • A governance proposal ConsumerAdditionProposal has passed (i.e., it got the necessary votes).
  • Precondition
    • True.
  • Postcondition
    • The proposal is appended to the list of pending addition proposals, i.e., pendingConsumerAdditionProposals.
  • Error Condition
    • None.

[CCV-PCF-BBLOCK-INIT.1]

  • Caller
    • The BeginBlock() method.
  • Trigger Event
    • A BeginBlock message is received from the consensus engine; BeginBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • For each ConsumerAdditionProposal p in the list of pending addition proposals pendingConsumerAdditionProposals, if currentTimestamp() > p.spawnTime, then
      • CreateConsumerClient(p) is invoked;
      • p is removed from pendingConsumerAdditionProposals.
  • Error Condition
    • None.

[CCV-PCF-CRCLIENT.1]

  • Caller
  • Trigger Event
    • A governance proposal ConsumerAdditionProposal p has passed (i.e., it got the necessary votes).
  • Precondition
    • currentTimestamp() > p.spawnTime.
  • Postcondition
    • If a client for p.chainId already 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.connId is set, then
        • if a connection end with ID p.connId cannot be found, the state is not changed;
        • otherwise,
          • if the connection with ID p.connId is not to the chain with ID p.chainId, the state is not changed;
          • otherwise,
            • both the client ID and connection ID are stored;
            • a ConsumerGenesisState is created and stored;
      • otherwise,
        • otherwise,
          • a client state is created with chainId = p.chainId and unbondingPeriod = p.unbondingPeriod;
          • a consensus state is created with validatorSet set to the initial validator set of the consumer chain;
          • a client of the consumer chain is created and the client ID is stored;
          • a ConsumerGenesisState is created and stored;
      • lockUnbondingOnTimeout[p.chainId] is set to p.lockUnbondingOnTimeout.
      • The init timeout timestamp is computed and stored in initTimeoutTimestamps[p.chainId].
  • Error Condition
    • None.
Note: For the case when the clientId field of the ConsumerAdditionProposal is not set, creating a client of a remote chain requires a ClientState and a ConsensusState (for an example, take a look at ICS 7). ConsensusState requires 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 a ConsumerGenesisState (see the CCV Data Structures section). The provider CCV module creates such a ConsumerGenesisState when handling a governance proposal ConsumerAdditionProposal. Note: If the channel initialization for a consumer chain exceeds the initTimeout period, 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 ChanOpenInit message on a port the provider CCV module is bounded to.
  • 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 ChanOpenTry message on a port the provider CCV module is bounded to.
  • 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 portIdentifier and channelIdentifier exists;
      • 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 CCVHandshakeMetadata is returned, with providerDistributionAccount set to the address of the distribution module account on the provider chain and version set to ccvVersion.
    • The state is not changed.
  • Error Condition
    • None.

[CCV-PCF-COACK.1]

  • Caller
    • The provider IBC routing module.
  • Trigger Event
    • The provider IBC routing module receives a ChanOpenAck message on a port the provider CCV module is bounded to.
  • 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 ChanOpenConfirm message on a port the provider CCV module is bounded to.
  • Precondition
    • True.
  • Postcondition
    • The transaction is aborted if any of the following conditions are true:
      • no channel with portIdentifier and channelIdentifier exists;
      • the channel has more than one connection hop;
      • another CCV channel for this consumer chain already exists.
    • The connection mapping is set, i.e., chainToConnection.
    • The channel mappings are set, i.e., chainToChannel and channelToChain.
    • initialHeights[chainId] is set to the current height.
    • The init timeout timestamp for the consumer chain with ID clientState.chainId is removed.
  • Error Condition
    • None.

[CCV-CCF-INITG.1]

  • Caller
    • The ABCI application.
  • Trigger Event
    • An InitChain message is received from the consensus engine; the InitChain message is sent when the consumer chain is first started.
  • Precondition
    • The consumer CCV module is in the initial state.
  • Postcondition
    • The capability for the port ConsumerPortId is claimed.
    • preCCV is set to gs.preCCV.
    • If preCCV == true, the ID of the client on which the connection with gs.connId is built is stored into providerClientId.
    • Otherwise, a client of the provider chain is created and the client ID is stored into providerClientId.
    • ConsumerUnbondingPeriod is set to gs.unbondingPeriod.
    • HtoVSC for the current block is set to 0.
    • The ccvValidatorSet mapping 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.
  • Error Condition
    • The genesis state contains an empty initial validator set.
    • If the genesis state preCCV field is set to true, 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 ConsumerPortId cannot 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 ChanOpenInit message on a port the consumer CCV module is bounded to.
  • Precondition
    • True.
  • Postcondition
    • The transaction is aborted if any of the following conditions are true:
      • providerChannel is already set;
      • portIdentifier != ConsumerPortId;
      • version is set but not to the expected version;
      • counterpartyPortIdentifier != ProviderPortId;
      • the client associated with this channel is not the expected provider client.
    • ccvVersion is returned.
    • The state is not changed.
  • Error Condition
    • None.

[CCV-CCF-COTRY.1]

  • Caller
    • The consumer IBC routing module.
  • Trigger Event
    • The consumer IBC routing module receives a ChanOpenTry message on a port the consumer CCV module is bounded to.
  • 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 ChanOpenAck message on a port the consumer CCV module is bounded to.
  • Precondition
    • True.
  • Postcondition
    • counterpartyVersion is unmarshaled into a CCVHandshakeMetadata structure md.
    • The transaction is aborted if any of the following conditions are true:
      • providerChannel is already set;
      • md.version != ccvVersion.
    • The address of the distribution module account on the provider chain is set to md.providerDistributionAccount.
    • If distributionChannelId is not set, the distribution token transfer channel opening handshake is initiated and distributionChannelId is set to the resulting channel ID.
    • The CCV channel is marked as established, i.e., providerChannel is 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 invoke SendSlashRequest only 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 the ccvValidatorSet, 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 ChanOpenConfirm message on a port the consumer CCV module is bounded to.
  • 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.
  • Trigger Event
    • A BeginBlock message is received from the consensus engine; BeginBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • If preCCV == true and the current validator set matches the ccvValidatorSet (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.
  • Error Condition
    • None.

Consumer Chain Removal

↑ Back to Outline

[CCV-PCF-HCRPROP.1]

  • Caller
    • EndBlock() method of Governance module.
  • Trigger Event
    • A governance proposal ConsumerRemovalProposal has passed (i.e., it got the necessary votes).
  • Precondition
    • True.
  • Postcondition
    • The proposal is appended to the list of pending removal proposals, i.e., pendingConsumerRemovalProposals.
  • Error Condition
    • None.

[CCV-PCF-BBLOCK-CCR.1]

  • Caller
    • The BeginBlock() method.
  • Trigger Event
    • A BeginBlock message is received from the consensus engine; BeginBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • For each ConsumerRemovalProposal p in the list of pending removal proposals pendingConsumerRemovalProposals, if currentTimestamp() > p.stopTime, then
      • StopConsumerChain(p.chainId, false) is invoked;
      • p is removed from pendingConsumerRemovalProposals.
  • Error Condition
    • None.

[CCV-PCF-STCC.1]

  • Caller
  • Trigger Event
    • One of the following events:
      • a governance proposal to stop the consumer chain with chainId has passed (i.e., it got the necessary votes);
      • a VSCPacket sent on the CCV channel to the consumer chain with chainId has timed out;
      • the channel initialization has timed out.
  • Precondition
    • True.
  • Postcondition
    • If a client for p.chainId does not exist, the state is not changed.
    • Otherwise,
      • the client ID mapped to chainId in chainToClient is removed;
      • the value mapped to chainId in lockUnbondingOnTimeout is removed;
      • if the CCV channel to the consumer chain with chainId is established, then
        • the chain ID mapped to chainToChannel[chainId] in channelToChain is removed;
        • the channel closing handshake is initiated for the CCV channel;
        • the channel ID mapped to chainId in chainToChannel is removed.
      • all the VSCPacketData mapped to chainId in pendingVSCPackets are removed;
      • the height mapped to chainId in initialHeights is removed;
      • downtimeSlashRequests[chainId] is emptied;
      • if lockUnbonding == false, then
        • chainId is 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 chainId are removed from the vscToUnbondingOps mapping.
  • Error Condition
    • None
Note: Invoking StopConsumerChain(chainId, lockUnbonding) with lockUnbonding == FALSE entails that all outstanding unbonding operations can complete before ConsumerUnbondingPeriod elapses on the consumer chain with chainId. Thus, invoking StopConsumerChain(chainId, false) for any chainId MAY 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 invoking StopConsumerChain(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.
  • Trigger Event
    • An EndBlock message is received from the consensus engine; EndBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • For each consumer chain ID chainId in vscSendTimestamps.Keys(),
      • if vscSendTimestamps[(chainId, vscId)] + vscTimeout is smaller than the current timestamp, then the consumer chain with ID chainId is stopped.
    • For each consumer chain ID chainId in initTimeoutTimestamps.Keys(),
      • if the timestamp in initTimeoutTimestamps[chainId] is smaller than the current timestamp, then the consumer chain with ID chainId is stopped.
  • Error Condition
    • None.
Note: To avoid false positives where a consumer chain is unnecessarily removed, vscTimeout MUST be larger than consumerUnbondingPeriod and SHOULD account for the time needed to relay the VSCPacket to the consumer and the corresponding VSCMaturedPacket back to the provider.

[CCV-PCF-CCINIT.1]

  • Caller
    • The provider IBC routing module.
  • Trigger Event
    • The provider IBC routing module receives a ChanCloseInit message on a port the provider CCV module is bounded to.
  • 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 ChanCloseConfirm message on a port the provider CCV module is bounded to.
  • Precondition
    • True.
  • Postcondition
    • The state is not changed.
  • Error Condition
    • None.

[CCV-CCF-BBLOCK-CCR.1]

  • Caller
    • The BeginBlock() method.
  • Trigger Event
    • A BeginBlock message is received from the consensus engine; BeginBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • If the CCV was established, but then was moved to the CLOSED state, then the state of the consumer CCV module is cleaned up, e.g., the providerChannel is unset.
  • Error Condition
    • If the CCV was established, but then was moved to the CLOSED state.
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 ChanCloseInit message on a port the consumer CCV module is bounded to.
  • Precondition
    • True.
  • Postcondition
    • If providerChannel is not set or providerChannel matches the ID of the channel the ChanCloseInit message was received on, then the transaction is aborted.
    • The state is not changed.
  • Error Condition
    • None.

[CCV-CCF-CCCONFIRM.1]

  • Caller
    • The consumer IBC routing module.
  • Trigger Event
    • The consumer IBC routing module receives a ChanCloseConfirm message on a port the consumer CCV module is bounded to.
  • 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.
  • Trigger Event
    • An EndBlock message is received from the consensus engine; EndBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • For every matured unbonding operation in maturedUnbondingOps, the Staking module is notified that the unbonding can complete.
    • All unbonding operation in maturedUnbondingOps are removed.
    • A list of validator updates valUpdates is obtained from the provider Staking module.
    • For every consumer chain with chainId
      • If either valUpdates is not empty or there were unbonding operations initiated during this block, then
        • a VSCPacket data data is created such that data.id = vscId, data.updates = valUpdates, and data.downtimeSlashAcks = downtimeSlashRequests[chainId];
        • downtimeSlashRequests[chainId] is emptied;
        • packetData is appended to the list of pending VSCPackets associated to chainId, i.e., pendingVSCPackets[chainId].
      • If there is an established CCV channel for the consumer chain with chainId, then
        • for each VSCPacketData in the list of pending VSCPackets associated to chainId
          • a packet with the VSCPacketData is sent on the channel associated with the consumer chain with chainId;
          • vscSendTimestamps[(vscId, chainId)] is set to the current timestamp;
        • all the pending VSCPackets associated to chainId are removed.
    • vscId is incremented.
  • Error Condition
    • None.

[CCV-PCF-ACKVSC.1]

  • Caller
    • The onAcknowledgePacket() method.
  • Trigger Event
    • The provider IBC routing module receives an acknowledgement of a VSCPacket on a channel owned by the provider CCV module.
  • Precondition
    • True.
  • Postcondition
    • The state is not changed.
  • Error Condition
    • The acknowledgement is VSCPacketError.

[CCV-PCF-TOVSC.1]

  • Caller
    • The onTimeoutPacket() method.
  • Trigger Event
    • A VSCPacket sent on a channel owned by the provider CCV module timed out as a result of either
      • the timeout height or timeout timestamp passing on the consumer chain without the packet being received (see timeoutPacket defined in ICS4);
      • or the channel being closed without the packet being received (see timeoutOnClose defined in ICS4).
  • 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, where chainId = channelToChain[packet.getDestinationChannel()].
  • Error Condition
    • None

[CCV-PCF-RCVMAT.1]

  • Caller
    • The onRecvPacket() method.
  • Trigger Event
    • The provider IBC routing module receives a VSCMaturedPacket on a channel owned by the provider CCV module.
  • 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).
    • chainId is set to the ID of the consumer chain mapped to the channel on which the packet was received.
    • For each unbonding operation op returned by GetUnbondingsFromVSC(chainId, packet.data.id)
      • chainId is removed from op.unbondingChainIds;
      • if op.unbondingChainIds is empty,
        • op.id is added to maturedUnbondingOps;
        • op.id is removed from unbondingOps.
    • (chainId, vscId) is removed from vscToUnbondingOps.
    • (chainId, vscId) is removed from vscSendTimestamps.
    • A successful acknowledgment is returned.
  • Error Condition
    • None.

[CCV-PCF-GETUBS.1]

  • Caller
    • The onRecvVSCMaturedPacket() method.
  • Trigger Event
    • The provider IBC routing module receives a VSCMaturedPacket on a channel owned by the provider CCV module.
  • Precondition
    • The provider CCV module received a VSCMaturedPacket P from a consumer chain with ID chainId, such that P.data.id == _vscId.
  • Postcondition
    • Return the list of unbonding operations mapped to (chainId, _vscId).
  • Error Condition
    • None.

[CCV-PCF-HOOK-AFUBOPCR.1]

  • Caller
    • The Staking module.
  • Trigger Event
    • An unbonding operation with id opId is initiated.
  • Precondition
    • True.
  • Postcondition
    • chainIds is 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 UnbondingOperation op is created and added to unbondingOps, such that op.id = opId and op.unbondingChainIds = chainIds.
      • opId is appended to every list in vscToUnbondingOps[(chainId, vscId)], where chainId is an ID of a consumer chains registered with this provider chain and vscId is the current VSC ID.
      • the PutUnbondingOnHold(opId) of the Staking module is invoked.
  • Error Condition
    • None.

[CCV-CCF-RCVVSC.1]

  • Caller
    • The onRecvPacket() method.
  • Trigger Event
    • The consumer IBC routing module receives a VSCPacket on a channel owned by the consumer CCV module.
  • Precondition
    • True.
  • Postcondition
    • If providerChannel is set and does not match the channel (with ID packet.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., the HtoVSC mapping) ;
      • packet.data is appended to receivedVSCs.
      • a successful acknowledgement is returned.
  • Error Condition
    • None.

[CCV-CCF-ACKMAT.1]

  • Caller
    • The onAcknowledgePacket() method.
  • Trigger Event
    • The consumer IBC routing module receives an acknowledgement of a VSCMaturedPacket on a channel owned by the consumer CCV module.
  • Precondition
    • True.
  • Postcondition
    • The state is not changed.
  • Error Condition
    • The acknowledgement is VSCMaturedPacketError.

[CCV-CCF-TOMAT.1]

  • Caller
    • The onTimeoutPacket() method.
  • Trigger Event
    • A VSCMaturedPacket sent on a channel owned by the consumer CCV module timed out as a result of either
      • the timeout height or timeout timestamp passing on the provider chain without the packet being received (see timeoutPacket defined in ICS4);
      • or the channel being closed without the packet being received (see timeoutOnClose defined in ICS4).
  • 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.
  • Trigger Event
    • An EndBlock message is received from the consensus engine; EndBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • If providerChannel != "", UnbondMaturePackets() is invoked;
    • If preCCV == true, the state is not changed.
    • Otherwise,
      • the data items in receivedVSCs are handled (see [CCV-CCF-HAREVSC.1]), which results in a list changes of validator updates;
      • UpdateValidatorSet(changes) is invoked;
      • changes is returned.
  • Error Condition
    • None.

[CCV-CCF-HAREVSC.1]

  • Caller
    • The EndBlock() method.
  • Trigger Event
    • An EndBlock message is received from the consensus engine.
  • Precondition
    • preCCV == false.
  • Postcondition
    • For each data item in the list receivedVSCs,
      • data.updates are appended to changes, where changes is initially an empty list of validator updates;
      • (data.id, maturityTimestamp) is added to maturingVSCs, where maturityTimestamp = currentTimestamp() + ConsumerUnbondingPeriod;
      • for each valAddr in the slash acknowledgments received from the provider chain, outstandingDowntime[valAddr] is set to false.
    • receivedVSCs is emptied.
    • The updates in changes are aggregated, i.e., only the latest update per validator is kept, and returned.
  • Error Condition
    • None.

[CCV-CCF-UPVALS.1]

  • Caller
    • The EndBlock() method.
  • Trigger Event
    • An EndBlock message is received from the consensus engine.
  • Precondition
    • preCCV == false.
  • Postcondition
    • For each validator update in changes,
      • if the validator is not in the validator set and update.power > 0, then
        • a new validator is added to ccvValidatorSet;
        • the AfterCCValidatorBonded hook is called;
      • otherwise, if the validator’s new power is 0, then,
        • the validator is removed from ccvValidatorSet;
        • the AfterCCValidatorBeginUnbonding hook is called;
      • otherwise, the validator’s power is updated.
  • Error Condition
    • None.

[CCV-CCF-UMP.1]

  • Caller
    • The EndBlock() method.
  • Trigger Event
    • An EndBlock message is received from the consensus engine.
  • Precondition
    • The CCV channel to the provider chain is established, i.e., providerChannel != "".
  • Postcondition
    • For each (id, ts) in the list of maturing VSCs sorted by maturity timestamps
      • if currentTimestamp() < ts, the loop is stopped;
      • a VSCMaturedPacketData packet data is created;
      • a packet with the created VSCMaturedPacketData is sent to the provider chain;
      • the tuple (id, ts) is removed from maturingVSCs.
  • Error Condition
    • None.

Consumer Initiated Slashing

↑ Back to Outline

[CCV-PCF-EBLOCK-CIS.1]

  • Caller
    • The EndBlock() method.
  • Trigger Event
    • An EndBlock message is received from the consensus engine; EndBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • vscId is mapped to the height of the subsequent block.
  • Error Condition
    • None.

[CCV-PCF-RCVSLASH.1]

  • Caller
    • The onRecvPacket() method.
  • Trigger Event
    • The provider IBC routing module receives a SlashPacket on a channel owned by the provider CCV module.
  • 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, infractionHeight is set to initialHeights[chainId], with chainId = channelToChain[packet.getDestinationChannel()], i.e., the height when the CCV channel to this consumer chain is established;
      • otherwise, infractionHeight is set to VSCtoH[packet.data.vscId], i.e., the height at which the voting power was last updated by the validator updates in the VSC with ID packet.data.vscId;
      • a request is made to the Slashing module to slash slashFactor of the tokens bonded at infractionHeight by the validator with address packet.data.valAddress, where slashFactor is the slashing factor set on the provider chain;
      • a request is made to the Slashing module to jail the validator with address packet.data.valAddress for a period jailTime, where jailTime is the jailing time set on the provider chain;
      • if the slash request is for downtime, the validator’s address packet.data.valAddress is added to the list of downtime slash requests from this chainId;
      • a successful acknowledgment is returned.
  • Error Condition
    • None.

[CCV-CCF-BBLOCK-CIS.1]

  • Caller
    • The BeginBlock() method.
  • Trigger Event
    • A BeginBlock message is received from the consensus engine; BeginBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • HtoVSC for 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.
  • Trigger Event
    • The consumer IBC routing module receives an acknowledgement of a SlashPacket on a channel owned by the consumer CCV module.
  • Precondition
    • True.
  • Postcondition
    • The state is not changed.
  • Error Condition
    • The acknowledgement is SlashPacketError.

[CCV-CCF-TOSLASH.1]

  • Caller
    • The onTimeoutPacket() method.
  • Trigger Event
    • A SlashPacket sent on a channel owned by the consumer CCV module timed out as a result of either
      • the timeout height or timeout timestamp passing on the provider chain without the packet being received (see timeoutPacket defined in ICS4);
      • or the channel being closed without the packet being received (see timeoutOnClose defined in ICS4).
  • 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 valAddress was received.
  • 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 SlashPacket data packetData is created, such that packetData.vscId = VSCtoH[infractionHeight];
      • if the CCV channel to the provider chain is established, then
        • a packet with the packetData is sent to the provider chain;
        • if the request is for downtime, outstandingDowntime[data.valAddress] is set to true;
      • otherwise SlashRequest{data: packetData, downtime: downtime} is appended to pendingSlashRequests.
  • Error Condition
    • None.
Note: The ABCI application MUST subtract ValidatorUpdateDelay from the infraction height before invoking SendSlashRequest, where ValidatorUpdateDelay is a delay (in blocks) between when validator updates are returned to the consensus-engine and when they are applied. For example, if ValidatorUpdateDelay = x and a validator set update is returned with new validators at the end of block 10, then the new validators are expected to sign blocks beginning at block 11+x (for more details, take a look at the ABCI specification). Consequently, the consumer CCV module expects the infractionHeight parameter of the SendSlashRequest() 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 an outstandingDowntime flag per validator. CCV assumes that the consumer ABCI application (e.g., the slashing module) is not including the downtime of a validator with outstandingDowntime == TRUE in the evidence for downtime.

[CCV-CCF-SNDPESLASH.1]

  • Caller
  • Trigger Event
    • The first VSCPacket is received from the provider chain.
  • Precondition
    • providerChannel != "".
  • Postcondition
    • For each slash request req in pendingSlashRequests in 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.data is sent to the provider chain;
      • if the request is for downtime, outstandingDowntime[req.data.valAddress] is set to true.
    • All the pending SlashRequests are removed.
  • 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.
  • Trigger Event
    • An EndBlock message is received from the consensus engine; EndBlock messages are sent once per block.
  • Precondition
    • True.
  • Postcondition
    • If getCurrentHeight() - lastDistributionTransferHeight >= BlocksPerDistributionTransfer, the DistributeRewards() method is invoked.
  • Error Condition
    • None.

[CCV-CCF-DISTRREW.1]

  • Caller
    • The EndBlockRD() method.
  • Trigger Event
    • An EndBlock message is received from the consensus engine.
  • Precondition
    • getCurrentHeight() - lastDistributionTransferHeight >= BlocksPerDistributionTransfer
  • Postcondition
    • For each token type defined as a pair (denomination, amount) in ccvAccount, a transfer token (as defined in ICS 20) is initiated.
    • lastDistributionTransferHeight is set to the current height.
  • Error Condition
    • None.