KeyAssignment is the name of the feature that allows validator operators to use different consensus keys for each consumer chain validator node that they operate.
ValidatorByConsumerAddr - Stores the mapping from validator addresses on consumer chains to validator addresses on the provider chain. Needed for the consumer initiated slashing sub-protocol.
On receiving a MsgAssignConsumerKey(chainID, providerAddr, consumerKey) message:
+
// get validator from staking module validator, found := stakingKeeper.GetValidator(providerAddr) if !found { return ErrNoValidatorFound } providerConsAddr := validator.GetConsAddr() // make sure consumer key is not in use consumerAddr := utils.TMCryptoPublicKeyToConsAddr(consumerKey) if _, found := GetValidatorByConsumerAddr(ChainID, consumerAddr); found { return ErrInvalidConsumerConsensusPubKey } // check whether the consumer chain is already registered // i.e., a client to the consumer was already created if _, consumerRegistered := GetConsumerClientId(chainID); consumerRegistered { // get the previous key assigned for this validator on this consumer chain oldConsumerKey, found := GetValidatorConsumerPubKey(chainID, providerConsAddr) if found { // mark this old consumer key as prunable once the VSCMaturedPacket // for the current VSC ID is received oldConsumerAddr := utils.TMCryptoPublicKeyToConsAddr(oldConsumerKey) vscID := GetValidatorSetUpdateId() AppendConsumerAddrsToPrune(chainID, vscID, oldConsumerAddr) } } else { // if the consumer chain is not registered, then remove the previous reverse mapping if oldConsumerKey, found := GetValidatorConsumerPubKey(chainID, providerConsAddr); found { oldConsumerAddr := utils.TMCryptoPublicKeyToConsAddr(oldConsumerKey) DeleteValidatorByConsumerAddr(chainID, oldConsumerAddr) } } // set the mapping from this validator's provider address to the new consumer key SetValidatorConsumerPubKey(chainID, providerConsAddr, consumerKey) // set the reverse mapping: from this validator's new consensus address // on the consumer to its consensus address on the provider SetValidatorByConsumerAddr(chainID, consumerAddr, providerConsAddr)
+
When a new consumer chain is registered, i.e., a client to the consumer chain is created, the provider constructs the consumer CCV module part of the genesis state (see MakeConsumerGenesis).
+
func (k Keeper) MakeConsumerGenesis(chainID string) (gen consumertypes.GenesisState, nextValidatorsHash []byte, err error) { // ... // get initial valset from the staking module var updates []abci.ValidatorUpdate{} stakingKeeper.IterateLastValidatorPowers(func(providerAddr sdk.ValAddress, power int64) (stop bool) { validator := stakingKeeper.GetValidator(providerAddr) providerKey := validator.TmConsPublicKey() updates = append(updates, abci.ValidatorUpdate{PubKey: providerKey, Power: power}) return false }) // applies the key assignment to the initial validator for i, update := range updates { providerAddr := utils.TMCryptoPublicKeyToConsAddr(update.PubKey) if consumerKey, found := GetValidatorConsumerPubKey(chainID, providerAddr); found { updates[i].PubKey = consumerKey } } gen.InitialValSet = updates // get a hash of the consumer validator set from the update updatesAsValSet := tendermint.PB2TM.ValidatorUpdates(updates) hash := tendermint.NewValidatorSet(updatesAsValSet).Hash() return gen, hash, nil }
+
Note that key assignment works hand-in-hand with epochs.
+For each consumer chain, we store the consumer validator set that is currently (i.e., in this epoch) validating the consumer chain.
+Specifically, for each validator in the set we store among others, the public key that it is using on the consumer chain during the current (i.e., ongoing) epoch.
+At the end of every epoch, if there were validator set changes on the provider, then for every consumer chain, we construct a VSCPacket
+with all the validator updates and add it to the list of PendingVSCPackets. We compute the validator updates needed by a consumer chain by
+comparing the stored list of consumer validators with the current bonded validators on the provider, with something similar to this:
+
// get the valset that has been validating the consumer chain during this epoch currentValidators := GetConsumerValSet(consumerChain) // generate the validator updates needed to be sent through a `VSCPacket` by comparing the current validators // in the epoch with the latest bonded validators valUpdates := DiffValidators(currentValidators, stakingmodule.GetBondedValidators()) // update the current validators set for the upcoming epoch to be the latest bonded validators instead SetConsumerValSet(stakingmodule.GetBondedValidators())
+
where DiffValidators internally checks if the consumer public key for a validator has changed since the last
+epoch and if so generates a validator update. This way, a validator can change its consumer public key for a consumer
+chain an arbitrary amount of times and only the last set consumer public key would be taken into account.
+
On receiving a SlashPacket from a consumer chain with id chainID for a infraction of a validator data.Validator:
+
func HandleSlashPacket(chainID string, data ccv.SlashPacketData) (success bool, err error) { // ... // the slash packet validator address may be known only on the consumer chain; // in this case, it must be mapped back to the consensus address on the provider chain consumerAddr := sdk.ConsAddress(data.Validator.Address) providerAddr, found := GetValidatorByConsumerAddr(chainID, consumerAddr) if !found { // the validator has the same key on the consumer as on the provider providerAddr = consumerAddr } // ... }
+
On receiving a VSCMatured:
+
func OnRecvVSCMaturedPacket(packet channeltypes.Packet, data ccv.VSCMaturedPacketData) exported.Acknowledgement { // ... // prune previous consumer validator address that are no longer needed consumerAddrs := GetConsumerAddrsToPrune(chainID, data.ValsetUpdateId) for _, addr := range consumerAddrs { DeleteValidatorByConsumerAddr(chainID, addr) } DeleteConsumerAddrsToPrune(chainID, data.ValsetUpdateId) // ... }
+
On stopping a consumer chain:
+
func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan bool) (err error) { // ... // deletes all the state needed for key assignments on this consumer chain // ... }
The consensus state necessary to create a client to the consumer chain must use the hash returned by the MakeConsumerGenesis method as the nextValsHash.
+
The consumer chain can no longer check the initial validator set against the consensus state on InitGenesis.
The CCV spec is based around the assumption that the provider binary and all consumers binaries are non-malicious, and follow the defined protocols.
+In practice, this assumption may not hold.
+A malicious consumer binary could potentially include code which is able to send many slash/jail packets at once to the provider.
+
Before the throttling feature was implemented, the following attack was possible.
+Attacker(s) would create provider validators just below the provider's active set.
+Using a malicious consumer binary, slash packets would be relayed to the provider, that would slash/jail a significant portion (or all) of honest validator at once.
+Control of the provider would then pass over to the attackers' validators.
+This enables the attacker(s) to halt the provider.
+Or even worse, commit arbitrary state on the provider, potentially stealing all tokens bridged to the provider over IBC.
The throttling feature was designed to slow down the mentioned attack from above, allowing validators and the community to appropriately respond to the attack,
+i.e., this feature limits (enforced by on-chain params) the rate that the provider validator set can be jailed over time.
Slash meter: There exists one slash meter on the provider which stores an amount of voting power (integer), corresponding to an allowance of validators that can be jailed over time.
+This meter is initialized to a certain value on genesis, decremented by the amount of voting power jailed whenever a slash packet is handled, and periodically replenished as decided by on-chain params.
+
Global entry queue: There exists a single queue which stores "global slash entries".
+These entries allow the provider to appropriately handle slash packets sent from any consumer in FIFO ordering.
+This queue is responsible for coordinating the order that slash packets (from multiple chains) are handled over time.
+
Per-chain data queue: For each established consumer, there exists a queue which stores "throttled packet data",
+i.e.,pending slash packet data is queued together with pending VSC matured packet data in FIFO ordering.
+Order is enforced by IBC sequence number.
+These "per-chain" queues are responsible for coordinating the order that slash packets are handled in relation to VSC matured packets from the same chain.
+
Note: The reason for a multiple-queue design is the VSC Maturity and Slashing Order property (see spec).
+There are other ways to ensure such a property (like a queue of linked lists, etc.), but the proposed approach seemed to be the most understandable and easiest to implement with a KV store.
SlashMeterReplenishPeriod -- the period after which the slash meter is replenished.
+
SlashMeterReplenishFraction -- the portion (in range [0, 1]) of total voting power that is replenished to the slash meter when a replenishment occurs. This param also serves as a maximum fraction of total voting power that the slash meter can hold.
+
MaxThrottledPackets -- the maximum amount of throttled slash or vsc matured packets that can be queued from a single consumer before the provider chain halts, it should be set to a large value.
+This param would allow provider binaries to panic deterministically in the event that packet throttling results in a large amount of state-bloat. In such a scenario, packet throttling could prevent a violation of safety caused by a malicious consumer, at the cost of provider liveness.
Upon the provider receiving a VSCMatured packet from any of the established consumers during block execution, the VSCMatured packet data is added to the per-chain queue.
Once the slash meter becomes not full, it'll be replenished after SlashMeterReplenishPeriod by incrementing the meter with its allowance for the replenishment block, where allowance = SlashMeterReplenishFraction * currentTotalVotingPower.
+The slash meter will never exceed its current allowance (function of the total voting power for the block) in value.
+
Note a few things:
+
+
The slash meter can go negative in value, and will do so when handling a single slash packet that jails a validator with significant voting power.
+In such a scenario, the slash meter may take multiple replenishment periods to once again reach a positive value (or 0), meaning no other slash packets may be handled for multiple replenishment periods.
+
Total voting power of a chain changes over time, especially as validators are jailed.
+As validators are jailed, total voting power decreases, and so does the jailing allowance.
+See below for more detailed throttling property discussion.
+
The voting power allowance added to the slash meter during replenishment will always be greater than or equal to 1.
+If the SlashMeterReplenishFraction is set too low, integer rounding will put this minimum value into effect.
+That is, if SlashMeterReplenishFraction * currentTotalVotingPower < 1, then the effective allowance would be 1.
+This min value of allowance ensures that there's some packets handled over time, even if that is a very long time.
+It's a crude solution to an edge case caused by too small of a replenishment fraction.
+
+
The behavior described above is achieved by executing CheckForSlashMeterReplenishment() every EndBlock, BEFORE HandleThrottleQueues() is executed.
In every block, it is possible that VSCMaturedPacket data was queued before any slash packet data.
+Since this "leading" VSCMatured packet data does not have to be throttled (see VSC Maturity and Slashing Order), we can handle all VSCMatured packet data at the head of the queue, before the any throttling or packet data handling logic executes.
In every EndBlock, the following logic is executed to handle data from the throttle queues.
+
meter :=getSlashMeter() // Keep iterating as long as the meter has a positive (or 0) value, and global slash entries exist while meter.IsPositiveOrZero()&&entriesExist(){ // Get next entry in queue entry :=getNextGlobalSlashEntry() // Decrement slash meter by the voting power that will be removed from the valset from handling this slash packet valPower := entry.getValPower() meter = meter - valPower // Using the per-chain queue, handle the single slash packet using its queued data, // then handle all trailing VSCMatured packets for this consumer handleSlashPacketAndTrailingVSCMaturedPackets(entry) // Delete entry in global queue, delete handled data entry.Delete() deleteThrottledSlashPacketData() deleteTrailingVSCMaturedPacketData() }
One implementation-specific property introduced is that if any of the chain-specific packet data queues become larger than MaxThrottledPackets, then the provider binary will panic, and the provider chain will halt.
+Therefore this param should be set carefully. See SetThrottledPacketDataSize.
+This behavior ensures that if the provider binaries are queuing up more packet data than machines can handle, the provider chain halts deterministically between validators.
Using on-chain params and the sub protocol defined, slash packet throttling is implemented such that the following property holds under some conditions.
+
First, we introduce the following definitions:
+
+
A consumer initiated slash attack "starts" when the first slash packet from such an attack is received by the provider.
+
The "initial validator set" for the attack is the validator set that existed on the provider when the attack started.
+
There is a list of honest validators such that if they are jailed, X% of the initial validator set will be jailed.
+
+
For the Throttling Property to hold, the following assumptions must be true:
+
+
We assume the total voting power of the chain (as a function of delegations) does not increase over the course of the attack.
+
No validator has more than SlashMeterReplenishFraction of total voting power on the provider.
+
SlashMeterReplenishFraction is large enough that SlashMeterReplenishFraction * currentTotalVotingPower > 1,
+i.e., the replenish fraction is set high enough that we can ignore the effects of rounding.
+
SlashMeterReplenishPeriod is sufficiently longer than the time it takes to produce a block.
+
+
Note if these assumptions do not hold, throttling will still slow down the described attack in most cases, just not in a way that can be succinctly described. It's possible that more complex properties can be defined.
+
Throttling Property: The time it takes to jail/tombstone X% of the initial validator set will be greater than or equal to
+SlashMeterReplenishPeriod⋅SlashMeterReplenishFractionX−2⋅SlashMeterReplenishPeriod.
+
+
Intuition
+
Let's use the following notation:
+
+
C: Number of replenishment cycles
+
P: SlashMeterReplenishPeriod
+
F: SlashMeterReplenishFraction
+
Vmax: Max power of a validator as a fraction of total voting power
+
+
In C number of replenishment cycles, the fraction of total voting power that can be removed, a, is a≤F⋅C+Vmax (where Vmax is there to account for the power fraction of the last validator removed, one which pushes the meter to the negative value).
+
So, we need at least C≥Fa−Vmax cycles to remove a fraction of the total voting power.
+
Since we defined the start of the attack to be the moment when the first slash request arrives, then F fraction of the initial validator set can be jailed immediately. For the remaining X−F fraction of the initial validator set to be jailed, it takes at least C≥F(X−F)−Vmax cycles. Using the assumption that Vmax≤F (assumption 2), we get C≥FX−2F cycles.
+
In order to execute C cycles, we need C⋅P time.
+
Thus, jailing the remaining X−F fraction of the initial validator set corresponds to FP⋅(X−2F) time.
+
In other words, the attack must take at least FP⋅X−2P time (in the units of replenish period P).
+
+
This property is useful because it allows us to reason about the time it takes to jail a certain percentage of the initial provider validator set from consumer initiated slash requests.
+For example, if SlashMeterReplenishFraction is set to 0.06, then it takes no less than 4 replenishment periods to jail 33% of the initial provider validator set on the Cosmos Hub.
+Note that as of writing this on 11/29/22, the Cosmos Hub does not have a validator with more than 6% of total voting power.
+
Note also that 4 replenishment period is a worst case scenario that depends on well crafted attack timings.
+
How Unjailing Affects the Main Throttling Property
+
Note that the jailing allowance is directly proportional to the current total voting power of the provider chain. Therefore, if honest validators don't unjail themselves during the attack, the total voting power of the provider chain will decrease over the course of the attack, and the attack will be slowed down, main throttling property is maintained.
+
If honest validators do unjail themselves, the total voting power of the provider chain will still not become higher than when the attack started (unless new token delegations happen), therefore the main property is still maintained. Moreover, honest validators unjailing themselves helps prevent the attacking validators from gaining control of the provider.
+
In summary, the throttling mechanism as designed has desirable properties whether or not honest validators unjail themselves over the course of the attack.
Throttling introduces a vector for a malicious consumer chain to halt the provider, see issue below.
+However, this is sacrificing liveness in a edge case scenario for the sake of security.
+As an improvement, using retries would fully prevent this attack vector.
Note: ADR deprecated as the equivocation proposal was removed by the
+cryptographic verification of equivocation feature
+(see ADR-005 and
+ADR-013).
+
We want to limit the possibilities of a consumer chain to execute actions on the provider chain to maintain and ensure optimum security of the provider chain.
+
For instance, a malicious consumer consumer chain can send slash packet to the provider chain, which will slash a validator without the need of providing an evidence.
To protect against a malicious consumer chain, slash packets unrelated to downtime are ignored by the provider chain. Thus, an other mechanism is required to punish validators that have committed a double-sign on a consumer chain.
+
A new kind of governance proposal is added to the provider module, allowing to slash and tombstone a validator for double-signing in case of any harmful action on the consumer chain.
+
If such proposal passes, the proposal handler delegates to the evidence module to process the equivocation. This module ensures the evidence isn’t too old, or else ignores it (see code). Too old is determined by 2 consensus params :
+
+
evidence.max_age_duration number of nanoseconds before an evidence is considered too old
+
evidence.max_age_numblocks number of blocks before an evidence is considered too old.
A governance proposal takes 14 days, so those parameters must be big enough so the evidence provided in the proposal is not ignored by the evidence module when the proposal passes and is handled by the hub.
+
For max_age_num_blocks=1M, the parameter is big enough if we consider the hub produces 12k blocks per day (blocks_per_year/365 = 436,0000/365). The evidence can be up to 83 days old (1,000,000/12,000) and not be ignored.
+
For max_age_duration=172,800,000,000,000, the parameter is too low, because the value is in nanoseconds so it’s 2 days. Fortunately the condition that checks those 2 parameters uses a AND, so if max_age_num_blocks condition passes, the evidence won’t be ignored.
The provider and consumer modules are vulnerable to similar issues involving an attacker sending millions of denoms to certain addresses and causing the chain to halt. This ADR outlines both fixes since they are similar. Both fixes involve processing only denoms that are on a whitelist to avoid iterating over millions of junk denoms but have different requirements and are implemented in different ways.
Put the distribution module's FeePoolAddress back on the blocklist so that it cannot receive funds from users.
+
Create a new address called ConsumerRewardPool and unblock it, allowing funds to be sent to it.
+
Create a set of strings in the store for allowed ConsumerRewardDenoms.
+
Create an endpoint called RegisterConsumerRewardDenom which deducts a fee from the sender's account, sends it to the community pool and adds a string to the ConsumerRewardDenoms set.
+
Create a parameter called ConsumerRewardDenomRegistrationFee which determines the fee which is charged to register a consumer reward denom in the step above.
+
Create a function called TransferRewardsToFeeCollector which gets the entire ConsumerRewardDenoms set from the store, iterates over it, and for each entry:
+
+
Gets the balance of this denom for the ConsumerRewardPool account
+
Sends the entire balance out to the FeePoolAddress using SendCoinsFromModuleToModule which is not affected by the blocklist.
+
+
+
Run TransferRewardsToFeeCollector in the endblock
+
+
Now, nobody can send millions of junk denoms to the FeePoolAddress because it is on the block list. If they send millions of junk denoms to the ConsumerRewardPool, this does not matter because all balances are not iterated over, only those which are in the ConsumerRewardDenoms set.
+
We also add a new tx: register-consumer-reward-denom, and a new query: registered-consumer-reward-denoms
Create a new param RewardDenoms with a list of strings
+
Create a new param ProviderRewardDenoms with a list of strings
+
Create a function AllowedRewardDenoms which iterates over ProviderRewardDenoms and converts each denom to its ibc-prefixed denom using the provider chain's ibc channel information, then concatenates the RewardDenoms list and returns the combined list of allowed denoms.
+
In SendRewardsToProvider, instead of iterating over the balances of all denoms in the ToSendToProvider address, iterate over AllowedRewardDenoms
+
+
Now, if somebody sends millions of junk denoms to ToSendToProvider, they will not be iterated over. Only the RewardDenoms and ProviderRewardDenoms will be iterated over. Since we do not require this feature to be permissionless on the consumer, the registration fee process is not needed.
Currently, we use a governance proposal to slash validators for equivocation (double signing and light client attacks).
+Every proposal needs to go through a (two weeks) voting period before it can be approved.
+Given a three-week unbonding period, this means that an equivocation proposal needs to be submitted within one week since the infraction occurred.
+
This ADR proposes a system to slash validators automatically for equivocation, immediately upon the provider chain's receipt of the evidence. Another thing to note is that we intend to introduce this system in stages, since even the partial ability to slash and/or tombstone is a strict improvement in security.
+The feature is implemented in two parts, each with its dedicated endpoint. One endpoint handles light client attacks, while the other handles double signing attacks.
In a nutshell, the light client is a process that solely verifies a specific state machine's
+consensus without executing the transactions. The light clients get new headers by querying
+multiple nodes, called primary and witness nodes.
+
Light clients download new headers committed on chain from a primary. Headers can be verified in two ways: sequentially,
+where the block height of headers is serial, or using skipping. This second verification method allows light clients to download headers
+with nonconsecutive block height, where some intermediate headers are skipped (see Tendermint Light Client, Figure 1 and Figure 3).
+Additionally, light clients are cross-checking new headers obtained from a primary with witnesses to ensure all nodes share the same state.
+
A light client attack occurs when a Byzantine validator sends invalid headers to a light client.
+As the light client doesn't execute transactions, it can be deceived into trusting corrupted application state transitions.
+For instance, if a light client receives header A from the primary and header B from a witness for the same block height H,
+and both headers are successfully verified, it indicates a light client attack.
+Note that in this case, either the primary or the witness or both are malicious.
+
The types of light client attacks are defined by analyzing the differences between the conflicting headers.
+There are three types of light client attacks: lunatic attack, equivocation attack, and amnesia attack.
+For details, see the CometBFT specification.
+
When a light client agent detects two conflicting headers, it will initially verify their traces (see cometBFT detector) using its primary and witness nodes.
+If these headers pass successful verification, the Byzantine validators will be identified based on the header's commit signatures
+and the type of light client attack. The agent will then transmit this information to its nodes using a LightClientAttackEvidence evidence to be eventually voted on and added to a block.
+Note that from a light client agent perspective, it is not possible to establish whether a primary or a witness node, or both, are malicious.
+Therefore, it will create and send two evidences: one against the primary (sent to the witness), and one against the witness (sent to the primary).
+Both nodes will then verify it before broadcasting it and adding it to the evidence pool.
+If an evidence is finally committed to a block, the chain's evidence module will execute it, resulting in the jailing and the slashing of the validators responsible for the light client attack.
+
Light clients are a core component of IBC. In the event of a light client attack, IBC relayers notify the affected chains by submitting an IBC misbehavior message.
+A misbehavior message includes the conflicting headers that constitute a light client attack evidence. Upon receiving such a message,
+a chain will first verify whether these headers would have convinced its light client. This verification is achieved by checking
+the header states against the light client consensus states (see IBC misbehaviour handler). If the misbehaviour is successfully verified, the chain will then "freeze" the
+light client, halting any further trust in or updating of its states.
A double signing attack, also known as equivocation,
+occurs when a validator votes for two different blocks in the same round of the CometBFT consensus.
+This consensus mechanism operates with multiple voting rounds at each block height,
+and it strictly prohibits sending two votes of the same type during a round
+(see CometBFT State Machine Overview).
+
When a node observes two votes from the same peer, it will use these two votes to create
+a DuplicateVoteEvidence
+evidence and gossip it to the other nodes in the network
+(see CometBFT equivocation detection).
+Each node will then verify the evidence according to the CometBFT rules that define a valid double signing infraction, and based on this verification, they will decide whether to add the evidence to a block.
+During the evidence verification process, the signatures of the conflicting votes must be verified successfully.
+Note that this is achieved using the public key of the misbehaving validator, along with the chain ID of the chain where the infraction occurred (see CometBFT equivocation verification).
+
Once a double signing evidence is committed to a block, the consensus layer will report the equivocation to the evidence module of the Cosmos SDK application layer.
+The application will, in turn, punish the malicious validator through jailing, tombstoning and slashing
+(see handleEquivocationEvidence).
In the first part of the feature, we introduce a new endpoint: HandleConsumerMisbehaviour(ctx sdk.Context, misbehaviour ibctmtypes.Misbehaviour).
+The main idea is to leverage the current IBC misbehaviour handling and update it to solely jail and slash the validators that
+performed a light client attack. Note that in this context, we assume that chains connected via a light client
+share a subset of the validator set of the provider.
+
This endpoint reuses the IBC client libraries to verify that the misbehaviour headers would have fooled the light client.
+Additionally, it’s crucial that the endpoint logic results in the slashing and jailing of validators under the same conditions
+as a light client agent detector. Therefore, the endpoint ensures that the two conditions are met:
+the headers in the misbehaviour message have the same block height, and
+the light client isn’t expired.
+
After having successfully verified a misbehaviour, the endpoint executes the jailing and slashing of the malicious validators similarly as in the evidence module.
In the second part of the feature, we introduce a new endpoint HandleConsumerDoubleVoting( ctx sdk.Context, evidence *tmtypes.DuplicateVoteEvidence, chainID string, pubkey cryptotypes.PubKey).
+Simply put, the handling logic verifies a double signing evidence against a provided
+public key and chain ID and, if successful, executes the jailing of the malicious validator who double voted.
+
We define a new
+MsgSubmitConsumerDoubleVoting message to report a double voting evidence observed
+on a consumer chain to the endpoint of the provider chain. This message contains two fields:
+a double signing evidence
+duplicate_vote_evidence and a light client header for the infraction block height,
+referred to as infraction_block_header.
+The latter provides the malicious validator's public key and the chain ID required to verify the signature of the votes contained in the evidence.
+
Note that double signing evidence is not verified using the same conditions as in the implementation CometBFT (see
+verify(evidence types.Evidence) method). Specifically, we do not check that the evidence hasn't expired.
+More details can be found in the "Current limitations" section below.
+
Upon a successful equivocation verification, the misbehaving validator is jailed for the maximum time
+(see DoubleSignJailEndTime
+in the SDK evidence module).
We cannot derive an infraction height from the evidence, so it is only possible to jail validators, not actually slash them.
+To explain the technical reasons behind this limitation, let's recap the initial consumer initiated slashing logic.
+In a nutshell, consumer heights are mapped to provider heights through VSCPackets, namely through the so called vscIDs.
+When an infraction occurs on the consumer, a SlashPacket containing the vscID obtained from mapping the consumer infraction height
+is sent to the provider. Upon receiving the packet, the provider maps the consumer infraction height to a local infraction height,
+which is used to slash the misbehaving validator. In the context of untrusted consumer chains, all their states, including vscIDs,
+could be corrupted and therefore cannot be used for slashing purposes.
+
+
+
For the same reasons explained above, the age of a consumer double signing evidence can't be verified,
+either using its infraction height or its unsigned timestamp. Note that changes the jailing behaviour, potentially leading to a validator's jailing based on some "old" evidence from a consumer, which wouldn't occur if the consumer were a standalone chain.
+
+
+
In the first stage of this feature, validators are jailed indefinitely without being tombstoned.
+The underlying reason is that a malicious validator could take advantage of getting tombstoned
+to avoid being slashed on the provider (see comment).
+
+
+
Currently, the endpoint can only handle equivocation light client attacks. This is because the lunatic attacks require the endpoint to possess the ability to dissociate which header is conflicted or trusted upon receiving a misbehavior message. Without this information, it's not possible to extract the Byzantine validators from the conflicting headers (see comment). In addition, "amnesia" attacks are ignored, similar to CometBFT (see ADR-056).
Note: ADR rejected as the equivocation proposal was removed by the
+cryptographic verification of equivocation feature
+(see ADR-005 and
+ADR-013).
+
Currently, if an equivocation slashing proposal is created after more than one
+week has passed since the equivocation, it is possible that the validator in
+question could unbond and get away without being slashed, since the unbonding
+period is 3 weeks, and the voting period is 2 weeks. For this reason, it might
+be good to pause unbondings for validators named in an equivocation slashing
+proposal until the proposal's voting period is over.
Pausing the unbonding period is already possible thanks to the changes in the
+staking module of the cosmos-sdk:
+
+
stakingKeeper.PutUnbondingOnHold pauses an unbonding period
+
stakingKeeper.UnbondingCanComplete unpauses an unbonding period
+
+
These methods use a reference counter under the hood, that gets incremented
+every time PutUnbondingOnHold is called, and decreased when
+UnbondingCanComplete is called instead. A specific unbonding is considered
+fully unpaused when its underlying reference counter reaches 0. Therefore, as
+long as we safeguard consistency - i.e. we make sure we eventually decrement
+the reference counter for each time we have incremented it - we can safely use
+this existing mechanism without conflicts with the Completion of Unbonding
+Operations system.
The unbonding period (if there is any unbonding) should be paused once an
+equivocation proposal enters the voting period. For that, the gov module's
+hook AfterProposalDeposit can be used.
+
If the hook is triggered with a an equivocation proposal in voting period, then
+for each equivocation of the proposal, the unbonding operations of the related
+validator that were initiated after the equivocation block time must be paused
+
+
i.e. the underlying reference counter has to be increased.
+
+
Note that even after the voting period has started, a proposal can receive
+additional deposits. The hook is triggered however at arrival of a deposit, so
+a check to verify that the proposal is not already in voting period is
+required.
We can use a gov module's hook also here and it is
+AfterProposalVotingPeriodEnded.
+
If the hook is triggered with an equivocation proposal, then for each
+associated equivocation, the unbonding operations of the related validator that
+were initiated between the equivocation block time and the start of the
+proposal voting period must be unpaused - i.e. decrease the underlying
+reference counter - regardless of the proposal outcome.
A malicious consumer chain could forge slash packets enabling submission of
+an equivocation proposal on the provider chain, resulting in the freezing of
+validator's unbondings for an undeterminated amount of time.
+
Misbehavior on a consumer chain can potentially go unpunished, if no one
+submits an equivocation proposal in time, or if the proposal doesn't pass.
This feature can't be used for social slashing, because an equivocation
+proposal is only accepted if there's a slash log for the related
+validator(s), meaning the consumer chain has reported the equivocation to
+the provider chain.
For context on why the throttling mechanism exists, see ADR 002.
+
Note the terms slash throttling and jail throttling are synonymous, since in Interchain Security a SlashPacket simply jails a validator for downtime infractions.
+
Currently the throttling mechanism is designed so that provider logic (slash meter, etc.) dictates how many SlashPackets can be handled over time.
+Throttled SlashPackets are persisted on the provider, leading to multiple possible issues. Namely:
+
+
If SlashPackets or VSCMaturedPackets are actually throttled/queued on the provider, state can grow and potentially lead to a DoS attack.
+We have short term solutions around this, but overall they come with their own weaknesses.
+See #594.
+
If a jailing attack described in ADR 002 were actually to be carried out with the current throttling design, we'd likely have to halt the provider, and perform an emergency upgrade and/or migration to clear the queues of SlashPackets that were deemed to be malicious.
+Alternatively, validators would just have to tough it out and wait for the queues to clear, during which all/most validators would be jailed.
+Right after being jailed, validators would have to unjail themselves promptly to ensure safety.
+The coordination required to maintain safety in such a scenario is not ideal.
+
+
As a solution, we can improve the throttling mechanism to instead queue/persist relevant data on each consumer, and have consumers retry slash requests as needed.
Note the consumer already queues up both SlashPackets and VSCMaturedPackets via AppendPendingPacket.
+Those packets are dequeued in every EndBlock in SendPackets and sent to the provider.
+
Instead, we will now introduce the following logic on EndBlock:
+
+
Slash packets will always be sent to the provider once they're at the head of the queue.
+However, once sent, the consumer will not send any subsequent VSCMaturedPackets from the queue until the provider responds with an acknowledgement that the sent SlashPacket has been handled, i.e., validator was jailed.
+That is, SlashPackets block the sending of subsequent VSCMaturedPackets in the consumer queue.
+
If two SlashPackets are at the head of the queue, the consumer will send the first SlashPacket, and then wait for a success acknowledgement from the provider before sending the second SlashPacket.
+This seems like it'd simplify implementation.
+
VSCMaturedPackets at the head of the queue (i.e., NOT following a SlashPacket) can be sent immediately, and do not block any other packets in the queue, since the provider always handles them immediately.
+
+
To prevent the provider from having to keep track of what SlashPackets have been rejected, the consumer will have to retry the sending of SlashPackets over some period of time.
+This can be achieved with an on-chain consumer param, i.e., RetryDelayPeriod.
+To reduce the amount of redundant re-sends, we recommend setting RetryDelayPeriod ~ SlashMeterReplenishmentPeriod, i.e., waiting for the provider slash meter to be replenished before resending the rejected SlashPacket.
+
Note to prevent weird edge case behavior, a retry would not be attempted until either a success or failure acknowledgement has been received from the provider.
+
With the behavior described, we maintain very similar behavior to the previous throttling mechanism regarding the timing that SlashPackets and VSCMaturedPackets are handled on the provider.
+Obviously the queueing and blocking logic is moved, and the two chains would have to send more messages between one another (only in the case the throttling mechanism is triggered).
+
In the normal case, when no or a few SlashPackets are being sent, the VSCMaturedPackets will not be delayed, and hence unbonding will not be delayed.
In addition to the mentioned consumer changes, an optimization will need to be made to the consumer's pending packets storage to properly implement the feature from this ADR.
+
The consumer ccv module previously queued "pending packets" to be sent in each EndBlock in SendPackets.
+These packets are queued in state with a protobuf list of ConsumerPacketData.
+For a single append operation, the entire list is deserialized, then a packet is appended to that list, and the list is serialized again.
+See older version of AppendPendingPacket.
+That is, a single append operation has O(N) complexity, where N is the size of the list.
+
This poor append performance isn't a problem when the pending packets list is small.
+But with this ADR being implemented, the pending packets list could potentially grow to the order of thousands of entries when SlashPackets need to be resent.
+
We can improve the append time for this queue by converting it from a protobuf-esq list, to a queue implemented with sdk-esq code.
+The idea is to persist a uint64 index that will be incremented each time you queue up a packet.
+You can think of this as storing the tail of the queue.
+Then, packet data will be keyed by that index, making the data naturally ordered byte-wise for sdk's iterator.
+The index will also be stored in the packet data value bytes, so that the index can later be used to delete certain packets from the queue.
+
Two things are achieved with this approach:
+
+
More efficient packet append/enqueue times
+
The ability to delete select packets from the queue (previously all packets were deleted at once)
The main change needed for the provider is the removal of queuing logic for SlashPackets and VSCMaturedPackets upon being received.
+
Instead, the provider will consult the slash meter to determine if a SlashPacket can be handled immediately.
+If not, the provider will return an acknowledgement message to the consumer communicating that the SlashPacket could not be handled, and needs to be sent again in the future (retried).
+
VSCMaturedPackets will always be handled immediately upon being received by the provider.
+
Note spec. Specifically the section on VSC Maturity and Slashing Order. Previously the onus was on the provider to maintain this property via queuing packets and handling them FIFO.
+
Now this property will be maintained by the consumer sending packets in the correct order, and blocking the sending of VSCMaturedPackets as needed. Then, the ordered IBC channel will ensure that SlashPackets and VSCMaturedPackets are received in the correct order on the provider.
+
The provider's main responsibility regarding throttling will now be to determine if a received SlashPacket can be handled via slash meter etc., and appropriately acknowledge to the sending consumer.
Why the provider can handle VSCMatured packets immediately
+
A VSCMaturedPacket communicates to the provider that sufficient time passed on the consumer since the corresponding VSCPacket has been applied (on the consumer) such that infractions committed on the consumer could have been submitted.
+
If the consumer is following the queuing/blocking protocol described, then no bad behavior occurs and the VSC Maturity and Slashing Order property is maintained.
+
If a consumer sends VSCMaturedPackets too leniently -- the consumer is malicious and sends duplicate VSCMaturedPackets, or sends the packets sooner than the CCV protocol specifies -- then the provider needs to handle VSCMaturedPackets immediately to prevent DOS, state bloat, or other issues.
+The only possible negative outcome is that the malicious consumer may not be able to jail a validator who should have been jailed.
+The malicious behavior only creates a negative outcome for the consumer chain that is being malicious.
+
If a consumer blocks the sending of VSCMaturedPackets, then unbonding operations on the provider will be delayed, but only until the VSC timeout period has elapsed.
+At that time, the consumer is removed.
+Again the malicious behavior only creates a negative outcome for the consumer chain that is being malicious.
This feature will implement consumer changes in #1024.
+
❗These changes should be deployed to production for all consumers before the provider changes are deployed to production.
+
In other words, the consumer changes in #1024 are compatible with the current ("v1") provider implementation of throttling that's running on the Cosmos Hub as of July 2023.
+
Once all consumers have deployed the changes in #1024, the provider changes from #1321 can be deployed to production, fully enabling v2 throttling.
We no longer have to reason about a "global queue" and a "chain specific queue", and keeping those all in-sync.
+Now SlashPackets and VSCMaturedPackets queuing is handled on each consumer individually.
+
Due to the above, the throttling protocol becomes less complex overall.
+
We no longer have to worry about throttle related DoS attack on the provider, since no queuing exists on the provider.
Some small validators may not have the resources needed to validate all consumer chains. Therefore a need exists to allow the bottom x% of validators to opt-out of validating a consumer chain. Meaning downtime infractions for these validators are dropped without ever reaching the provider.
+
This document specifies a modification to the ccv protocol which allows the bottom x% of the validator set by power to opt out of validating consumer chains without being jailed or otherwise punished for it. The feature is implemented with entirely consumer-side code.
A consumer param exists, known as SoftOptOutThreshold, which is a string decimal in the range of [0, 0.2], that determines the portion of validators which are allowed to opt out of validating that specific consumer.
+
In every consumer beginblocker, a function is ran which determines the so called smallest non opt-out voting power. Validators with voting power greater than or equal to this value must validate the consumer chain, while validators below this value may opt out of validating the consumer chain.
+
The smallest non opt-out voting power is recomputed every beginblocker in UpdateSmallestNonOptOutPower(). In a nutshell, the method obtains the total voting power of the consumer, iterates through the full valset (ordered power ascending) keeping track of a power sum, and when powerSum / totalPower > SoftOptOutThreshold, the SmallestNonOptOutPower is found and persisted.
+
Then, whenever the Slash() interface is executed on the consumer, if the voting power of the relevant validator being slashed is less than SmallestNonOptOutPower for that block, the slash request is dropped and never sent to the provider.
The bottom x% is still part of the total voting power of the consumer chain. This means that if the soft opt-out threshold is set to 10% for example, and every validator in the bottom 10% opts out from validating the consumer, then a 24% downtime of the remaining voting power would halt the chain. This may be especially problematic during consumer upgrades.
+
In nominal scenarios, consumers with soft opt out enabled will be constructing slash packets for small vals, which may be dropped. This is wasted computation, but necessary to keep implementation simple. Note that the sdk's full downtime logic is always executed on the consumer, which can be computationally expensive and slow down certain blocks.
+
In a consumer chain, when a validator that has opted out becomes the proposer, there will naturally be no proposal made and validators would need to move to the next consensus round for the same height to reach a decision. As a result, we would need more time to finalize blocks on a consumer chain.
Validators in the bottom of the valset who don't have to validate, may receive large delegation(s) which suddenly boost the validator to the subset that has to validate. This may catch the validator off guard.
Stride will be the first consumer to "changeover" from a standalone cosmos blockchain, to a consumer chain secured by the Cosmos Hub. This document outlines the changes made to support this changeover process.
Prior to the changeover, the consumer chain will have an existing staking keeper and validator set, these may be referred to as the "standalone staking keeper" and "standalone validator set" respectively.
+
The first step in the changeover process is to submit a ConsumerAdditionProposal. If the proposal passes, the provider will create a new IBC client for the consumer at spawn time, with the provider's validator set. A consumer genesis will also be constructed by the provider for validators to query. Within this consumer genesis contains the initial validator set for the consumer to apply after the changeover.
+
Next, the standalone consumer chain runs an upgrade which adds the CCV module, and is properly setup to execute changeover logic.
+
The consumer upgrade height must be reached after the provider has created the new IBC client. Any Interchain Security validators who will run the consumer, but are not a part of the sovereign validator set, must sync up a full node before the consumer upgrade height is reached. The disk state of said full node will be used to run the consumer chain after the changeover has completed.
+
The meat of the changeover logic is that the consumer chain validator set is updated to that which was specified by the provider via the queried consumer genesis. Validators which were a part of the old set, but not the new set, are given zero voting power. Once these validator updates are given to Comet, the set is committed, and in effect 2 blocks later (see FirstConsumerHeight).
+
A relayer then establishes the new IBC connection between the provider and consumer. The CCV channel handshake is started on top of this connection. Once the CCV channel is established and VSC packets are being relayed, the consumer chain is secured by the provider.
Consumer Genesis state is updated to include a PreCCV boolean. When this boolean is set true in the consumer genesis JSON, special logic is executed on InitGenesis to trigger the changeover process on the consumer's first endblocker after the upgrade which adds the CCV module. Note that InitGenesis is not automatically called during chain upgrades, so the consumer must manually call the consumer's InitGenesis method in an upgrade handler.
+
The ConsumerAdditionProposal type is updated to include a DistributionTransmissionChannel field. This field allows the consumer to use an existing IBC transfer channel to send rewards as a part of the CCV protocol. Consumers that're not changing over from a standalone chain will leave this field blank, indicating that a new transfer channel should be created on top of the same connection as the CCV channel.
+
The CCV consumer keeper is updated to contain an optional reference to the standalone staking keeper. The standalone staking keeper is used to slash for infractions that happened before the changeover was completed. Ie. any infraction from a block height before the changeover, that is submitted after the changeover, will call the standalone staking keeper's slash method. Note that a changeover consumer's standalone staking keeper becomes a democracy module keeper, so it is possible for a governance token to be slashed.
The delineation between different types of consumers in this repo becomes less clear. Ie. there is code in the democracy consumer's app.go that only applies to a previously standalone chain, but that file also serves as the base for a normal democracy consumer launched with RS from genesis.
Testing, QA, and maintenance of interchain-security libraries is an ever-evolving area of software engineering we have to keep incrementally improving. The purpose of the QA process is to catch bugs as early as possible. In an ideal development workflow a bug should never reach production. A bug found in the specification stage is a lot cheaper to resolve than a bug discovered in production (or even in testnet). Ideally, all bugs should be found during the CI execution, and we hope that no bugs will ever even reach the testnet (although nothing can replace actual system stress test under load interacting with users).
+
During development and testnet operation the following types of bugs were the most commonly found:
+
+
improper iterator usage
+
unbounded array access/iteration
+
improper input handling and validation
+
improper cached context usage
+
non-determinism check (improper use of maps in go, relying on random values)
+
KV store management and/or how keys are defined
+
deserialization issues arising from consumer/provider versioning mismatch
+
+
Such bugs can be discovered earlier with better tooling. Some of these bugs can induce increases in block times, chain halts, state corruption, or introduce an attack surface which is difficult to remove if other systems have started depending on that behavior.
Our testing suites consist of multiple parts, each with their own trade-offs and benefits with regards to code coverage, complexity and confidence they provide.
Unit testing is employed mostly for testing single-module functionality. It is the first step in testing and often the most practical. While highly important, unit tests often test a single piece of code and don't test relationships between different moving parts, this makes them less valuable when dealing with multi-module interactions.
+
Unit tests often employ mocks to abstract parts of the system that are not under test. Mocks are not equivalent to actual models and should not be treated as such.
+
Out of all the approaches used, unit testing has the most tools available and the coverage can simply be displayed as % of code lines tested. Although this is a very nice and very easy to understand metric, it does not speak about the quality of the test coverage.
+
Since distributed systems testing is a lot more involved, unit tests are oftentimes not sufficient to cover complex interactions. Unit tests are still necessary and helpful, but in cases where unit tests are not helpful e2e or integration tests should be favored.
With integration testing we test the multi-module interactions while isolating them from the remainder of the system.
+Integration tests can uncover bugs that are often missed by unit tests.
+
It is very difficult to gauge the actual test coverage imparted by integration tests and the available tooling is limited.
+In interchain-security we employ the ibc-go/testing framework to test interactions in-memory.
+
At present, integration testing does not involve the consensus layer - it is only concerned with application level state and logic.
In our context end-to-end testing comprises of tests that use the actual application binaries in an isolated environment (e.g. docker container). During test execution the inputs are meant to simulate actual user interaction, either by submitting transactions/queries using the command line or using gRPC/REST APIs and checking for state changes after an action has been performed. With this testing strategy we also include the consensus layer in all of our runs. This is the closest we can get to testing user interactions without starting a full testnet.
+
End-to-end testing strategies vary between different teams and projects and we strive to unify our approach to the best of our ability (at least for ICS and gaia).
+
The available tooling does not give us significant (or relevant) line of code coverage information since most of the tools are geared towards analyzing unit tests and simple code branch evaluation.
+
We aim to adapt our best practices by learning from other similar systems and projects such as cosmos-sdk, ibc-go and CometBFT.
Oftentimes, specifications are disconnected from the development and QA processes. This gives rise to problems where the specification does not reflect the actual state of the system and vice-versa.
+Usually specifications are just text files that are rarely used and go unmaintained after a while, resulting in consistency issues and misleading instructions/expectations about system behavior.
Specifications written in a dedicated and executable specification language are easier to maintain than the ones written entirely in text.
+Additionally, we can create models based on the specification OR make the model equivalent to a specification.
+
Models do not care about the intricacies of implementation and neither do specifications. Since both models and specifications care about concisely and accurately describing a system (such as a finite state machine), we see a benefit of adding model based tools (such as quint) to our testing and development workflows.
This e2e test suite would execute using a cronjob in our CI (nightly, multiple times a day etc.)
+
Briefly, the same set of traces is run against different maintained versions of the software and the main branch.
+This would allow us to discover potential issues during development instead of in a testnet scenarios.
+
The most valuable issues that can be discovered in this way are state breaking changes, regressions and version incompatibilities.
+
The setup is illustrated by the image below.
+
+
This table explains which versions are tested against each other for the same set of test traces:
CometMock is a mock implementation of the CometBFT consensus engine. It supports most operations performed by CometBFT while also being lightweight and relatively easy to use.
+
CometMock tests allow more nuanced control of test scenarios because CometMock can "fool" the blockchain app into thinking that a certain number of blocks had passed.
+This allows us to test very nuanced scenarios, difficult edge cases and long-running operations (such as unbonding operations).
+
Examples of tests made easier with CometMock are listed below:
+
+
regression tests
+
non-determinism tests
+
upgrade tests
+
state-breaking changes
+
+
With CometMock, the matrix test approach can also be used. The image below illustrates a CometMock setup that can be used to discover non-deterministic behavior and state-breaking changes.
+
+
This table explains which versions are tested against each other for the same set of test traces:
+
+
✅ marks a passing test
+
❌ marks a failing test
+
+
SCENARIO
start chain
add key
delegate
undelegate
redelegate
downtime
equivocation
stop chain
v3 provi + v3 consu
✅
✅
✅
✅
✅
✅
✅
✅
main provi + main consu
✅
✅
✅
✅
✅
✅
✅
✅
commit provi + commit consu
✅
❌
✅
❌
✅
✅
❌
❌
+
Briefly; multiple versions of the application are run against the same CometMock instance and any deviations in app behavior would result in app hash errors (the apps would be in different states after performing the same set of actions).
Model is the part of the system that can emulate the behavior of the system under test.
+Ideally, it is very close to the specification and is written in a specification language such as quint, TLA+ or similar.
+One of the purposes of the model is that it can be used to generate test traces.
The purpose of the driver is to accept test traces (generated by the model or written by hand), process them and provide inputs to the next part of the pipeline.
+
Basically, the driver sits between the model and the actual infrastructure on which the test traces are being executed on.
The procedure outlined in this ADR is not an all-or-nothing approach. Concepts introduced here do not rely on each other, so this ADR may only be applied partially without negative impact on test coverage and code confidence.
The solutions are potentially expensive if we increase usage of the CI pipeline - this is fixed by running "expensive" tests using a cronjob, instead of running them on every commit.
The process of changing development and testing process is not something that can be thought of and delivered quickly. Luckily, the changes can be rolled out incrementally without impacting existing workflows.
I explored the idea of #801 with this spike branch. Here's my conclusions:
+
Splitting this repo to have multiple go.mods is possible. However there are various intricacies involved in decoupling the package hierarchy to have x/ccv/types as the lowest level dep, with x/ccv/consumer and x/ccv/provider being one dep layer above, with high-level tests depending on all three of the mentioned packages. I'd estimate this decoupling would take 2-5 workdays to finish, and require significant review effort.
Let's take a step back and remember the issue we're trying to solve - We need a clean way to decouple semver/releasing for the consumer and provider modules. After more consideration, splitting up go.mods gives us little benefit in achieving this. Reasons:
+
+
The go.mod dependency system is tied to git tags for the entire repo (ex: require github.com/cometbft/cometbft v0.37.2 refers to a historical tag for the entire cometbft repo).
+
It'd be an odd dev experience to allow modules to reference past releases of other modules in the same repo. When would we ever want the consumer module to reference a past release of the types module for example?
+
If we allow for go.mod replace statements to build from local source code, why split up the package deps at all?
+
Splitting go.mods adds a bunch of complexity with go.work files and all that shiz. VSCode does not play well with multiple module repos either.
+
+
Why separate repos is cool but also not the way to go
+
All this considered, the cleanest solution to decoupling semver/releasing for the consumer and provider modules would be to have multiple repos, each with their own go.mod (3-4 repos total including high level tests). With this scheme we could separately tag each repo as changes are merged, they could share some code from types being an external dep, etc.
+
I don't think any of us want to split up the monorepo, that's a lot of work and seems like bikeshedding. There's another solution that's very simple..
A library API breaking change to EITHER the provider or consumer module will result in an increase of the MAJOR version number for BOTH modules (X.y.z-provider AND X.y.z-consumer).
+
A state breaking change (change requiring coordinated upgrade and/or state migration) will result in an increase of the MINOR version number for the AFFECTED module(s) (x.Y.z-provider AND/OR x.Y.z-consumer).
+
Any other changes (including node API breaking changes) will result in an increase of the PATCH version number for the AFFECTED module(s) (x.y.Z-provider AND/OR x.y.Z-consumer).
We upgrade main to use a new version of SDK. This is a major version bump, triggering a new release for both the provider and consumer modules, v5.0.0-provider and v5.0.0-consumer.
+
+
A state breaking change is merged to main for the provider module. We release only a v5.1.0-provider off main.
+
Another state breaking change is merged to main for the provider module. We release only a v5.2.0-provider off main.
+
At this point, the latest consumer version is still v5.0.0-consumer. We now merge a state breaking change for the consumer module to main, and consequently release v5.1.0-consumer. Note that v5.1.0-consumer is tagged off a LATER commit from main than v5.2.0-provider. This is fine, as the consumer module should not be affected by the provider module's state breaking changes.
+
Once either module sees a library API breaking change, we bump the major version for both modules. For example, we merge a library API breaking change to main for the provider module. We release v6.0.0-provider and v6.0.0-consumer off main. Note that most often, a library API breaking change will affect both modules simultaneously (example being bumping sdk version).
Consumer repos have clear communication of what tagged versions are relevant to them. Consumer devs should know to never reference an ICS version that starts with provider, even if it'd technically build.
+
Consumer and provider modules do not deviate as long as we continually release off a shared main branch. Backporting remains relatively unchanged besides being explicit about what module(s) your changes should affect.
+
No code changes, just changes in process. Very simple.
~~Slightly more complexity.~~Considerably more complex to manage the ICS library.
+This is because ICS needs to support multiple versions of SDK (e.g., 0.45, 0.47, 0.50).
+In addition, ICS needs to support a special fork of SDK (with LSM included) for the Cosmos Hub.
+This means that instead of focusing on main the development team needs to manage multiple release
+branches with different dependency trees.
+
This solution does not allow having provider and consumer on separate versions of e.g. the Cosmos SDK.
This ADR presents some approaches on how to slash on the provider chain validators that performed equivocations on consumer chains.
+Currently, the provider chain can receive and verify evidence of equivocation, but it cannot slash the misbehaving validator.
+
In the remainder of this section, we explain how slashing is performed on a single chain and show why slashing on the provider for equivocation on the consumer is challenging.
+
Note that future versions of the Cosmos SDK, CometBFT, and ibc-go could modify the way we slash, etc. Therefore, a future reader of this ADR, should note that when we refer to Cosmos SDK, CometBFT, and ibc-go we specifically refer to their v0.47, v0.37 and v7.3.0 versions respectively.
Slashing is implemented across the slashing
+and staking modules.
+The slashing module's keeper calls the staking module's Slash() method, passing among others, the infractionHeight (i.e., the height when the equivocation occurred), the validator's power at the infraction height, and the slashFactor (currently set to 5% in case of equivocation on the Cosmos Hub).
To slash undelegations, Slash goes through all undelegations and checks whether they started before or after the infraction occurred. If an undelegation started before the infractionHeight, then it is not slashed, otherwise it is slashed by slashFactor.
+
The slashing of redelegations happens in a similar way, meaning that Slash goes through all redelegations and checks whether the redelegations started before or after the infractionHeight.
Besides undelegations and redelegations, the validator's delegations need to also be slashed.
+This is performed by deducting the appropriate amount of tokens from the validator. Note that this deduction is computed based on the voting power the misbehaving validator had at the height of the equivocation. As a result of the tokens deduction,
+the tokens per share
+reduce and hence later on, when delegators undelegate or redelegate, the delegators retrieve back less
+tokens, effectively having their tokens slashed. The rationale behind this slashing mechanism, as mentioned in the Cosmos SDK documentation
+
+
[...] is to simplify the accounting around slashing. Rather than iteratively slashing the tokens of every delegation entry, instead the Validators total bonded tokens can be slashed, effectively reducing the value of each issued delegator share.
+
+
This approach of slashing delegations does not utilize the
+infractionHeight in any way and hence the following scenario could occur:
+
+
a validator V performs an equivocation at a height Hi
+
a new delegator D delegates to V after height Hi
+
evidence of the equivocation by validator V is received
+
the tokens of delegator D are slashed
+
+
In the above scenario, delegator D is slashed, even though D's voting power did not contribute to the infraction.
In the single-chain case, old evidence (e.g., from 3 years ago) is ignored. This is achieved through
+CometBFT that ignores old evidence based on the parameters MaxAgeNumBlocks and MaxAgeDuration (see here).
+Additionally, note that when the evidence is sent by CometBFT to the application, the evidence is rechecked in the evidence module of Cosmos SDK and if it is old, the evidence is ignored.
+In Cosmos Hub, the MaxAgeNumBlocks is set to 1000000 (i.e., ~70 days if we assume we need ~6 sec per block) and MaxAgeDuration is set to 172800000000000 ns (i.e., 2 days). Because of this check, we can easily exclude old evidence.
In the single-chain case, slashing requires both the infractionHeight and the voting power.
+In order to slash on the provider for an equivocation on a consumer, we need to have both the provider's infractionHeight and voting power.
+Note that the infractionHeight on the consumer chain must be mapped to a height on the provider chain.
+Unless we have a way to find the corresponding infractionHeight and power on the provider chain, we cannot slash for equivocation on the consumer in the same way as we would slash in the single-chain case.
+
The challenge of figuring out the corresponding infractionHeight and power values on the provider chain is due to the following trust assumption:
+
+
We trust the consensus layer and validator set of the consumer chains, but we do not trust the application layer.
+
+
As a result, we cannot trust anything that stems from the application state of a consumer chain.
type DuplicateVoteEvidence struct { VoteA *Vote `json:"vote_a"` VoteB *Vote `json:"vote_b"` // abci specific information TotalVotingPower int64 ValidatorPower int64 Timestamp time.Time }
+
The "abci specific information" fields cannot be trusted because they are not signed. Therefore,
+we can use neither ValidatorPower for slashing on the provider chain, nor the Timestamp to check the evidence age. We can get the infractionHeight from the votes, but this infractionHeight corresponds to the infraction height on the consumer and not on the provider chain.
+Similarly, when a relayer or a user sends evidence through a MsgSubmitConsumerMisbehaviour message, the provider gets access to Misbehaviour that we cannot use to extract the infraction height, power, or the time on the provider chain.
As a first iteration, we propose the following approach. At the moment the provider receives evidence of equivocation on a consumer:
+
+
slash all the undelegations and redelegations using slashFactor;
+
slash all delegations using as voting power the sum of the voting power of the misbehaving validator and the power of all the ongoing undelegations and redelegations.
+
+
Evidence expiration: Additionally, because we cannot infer the actual time of the evidence (i.e., the timestamp of the evidence cannot be trusted), we do not consider evidence expiration and hence old evidence is never ignored (e.g., the provider would act on 3 year-old evidence of equivocation on a consumer).
+Additionally, we do not need to store equivocation evidence to avoid slashing a validator more than once, because we do not slash tombstoned validators and we tombstone a validator when slashed.
+
We do not act on evidence that was signed by a validator consensus key that is pruned when we receive the evidence. We prune a validator's consensus key if the validator has assigned a new consumer key (using MsgAssignConsumerKey) and an unbonding period on the consumer chain has elapsed (see key assignment ADR). Note that the provider chain is informed that the unbonding period has elapsed on the consumer when the provider receives a VSCMaturedPacket and because of this, if the consumer delays the sending of a VSCMaturedPacket, we would delay the pruning of the key as well.
undelegationsInTokens := sdk.NewInt(0) for_, v :=range k.stakingKeeper.GetUnbondingDelegationsFromValidator(ctx, validatorAddress){ for_, entry :=range v.Entries { if entry.IsMature(now)&&!entry.OnHold(){ // undelegation no longer eligible for slashing, skip it continue } undelegationsInTokens = undelegationsInTokens.Add(entry.InitialBalance) } } redelegationsInTokens := sdk.NewInt(0) for_, v :=range k.stakingKeeper.GetRedelegationsFromSrcValidator(ctx, validatorAddress){ for_, entry :=range v.Entries { if entry.IsMature(now)&&!entry.OnHold(){ // redelegation no longer eligible for slashing, skip it continue } redelegationsInTokens = redelegationsInTokens.Add(entry.InitialBalance) } } infractionHeight :=0 undelegationsAndRedelegationsInPower = sdk.TokensToConsensusPower(undelegationsInTokens.Add(redelegationsInTokens)) totalPower := validator's voting power + undelegationsAndRedelegationsInPower slashFraction := k.slashingKeeper.SlashFractionDoubleSign(ctx) k.stakingKeeper.Slash(ctx, validatorConsAddress, infractionHeight, totalPower, slashFraction, DoubleSign)
+
Infraction height: We provide a zero infractionHeight to the Slash method in order to slash all ongoing undelegations and redelegations (see checks in Slash, SlashUnbondingDelegation, and SlashRedelegation).
+
Power: We pass the sum of the voting power of the misbehaving validator when the evidence was received (i.e., at evidence height) and the power of all the ongoing undelegations and redelegations.
+If we assume that the slashFactor is 5%, then the voting power we pass is power + totalPower(undelegations) + totalPower(redelegations).
+Hence, when the Slash method slashes all the undelegations and redelegations it would end up with 0.05 * power + 0.05 * totalPower(undelegations) + 0.05 * totalPower(redelegations) - 0.05 * totalPower(undelegations) - 0.05 * totalPower(redelegations) = 0.05 * power and hence it would slash 5% of the validator's power when the evidence is received.
With the proposed approach we can quickly implement slashing functionality on the provider chain for consumer chain equivocations.
+This approach does not need to change the staking module and therefore does not change in any way how slashing is performed today for a single chain.
In every block that the provider valset changes, a VSCPacket must be sent to every consumer and a corresponding VSCMaturedPacket sent back.
+Given that the validator powers may change very often on the provider chain (e.g., the Cosmos Hub), this approach results in a large workload for the relayers.
+Although the validator powers may change very often, these changes are usually small and have an insignificant impact on the chain's security.
+In other words, the valset on the consumers can be slightly outdated without affecting security.
+As a matter of fact, this already happens due to relaying delays.
+
As a solution, this ADR introduces the concept of epochs.
+An epoch consists of multiple blocks.
+The provider sends VSCPackets once per epoch.
+A VSCPacket contains all the validator updates that are needed by a consumer chain.
The implementation of epochs requires the following changes:
+
+
For each consumer chain, we store the consumer validator set that is currently (i.e., in this epoch) validating the
+consumer chain. For each validator in the set we store i) its voting power, and ii) the public key that it is
+using on the consumer chain during the current (i.e., ongoing) epoch.
+The initial consumer validator set for a chain is set during the creation of the consumer genesis.
+
We introduce the BlocksPerEpoch param that sets the number of blocks in an epoch. By default, BlocksPerEpoch is
+set to be 600 which corresponds to 1 hour, assuming 6 seconds per block. This param can be changed through
+a governance proposal. In the provider EndBlock we check BlockHeight() % BlocksPerEpoch() == 0
+to decide when an epoch has ended.
+
At the end of every epoch, if there were validator set changes on the provider, then for every consumer chain, we
+construct a VSCPacket with all the validator updates and add it to the list of PendingVSCPackets. We compute the
+validator updates needed by a consumer chain by comparing the stored list of consumer validators with the current
+bonded validators on the provider, with something similar to this:
+
+
// get the valset that has been validating the consumer chain during this epoch currentValidators :=GetConsumerValSet(consumerChain) // generate the validator updates needed to be sent through a `VSCPacket` by comparing the current validators // in the epoch with the latest bonded validators valUpdates :=DiffValidators(currentValidators, stakingmodule.GetBondedValidators()) // update the current validators set for the upcoming epoch to be the latest bonded validators instead SetConsumerValSet(stakingmodule.GetBondedValidators())
+
Note that a validator can change its consumer public key for a specific consumer chain an arbitrary amount of times during
+a block and during an epoch. Then, when we generate the validator updates in DiffValidators, we have to check whether
+the current consumer public key (retrieved by calling GetValidatorConsumerPubKey) is different from the consumer public
+key the validator was using in the current epoch.
Increase the delay in the propagation of validator set changes (but for reasonable epoch lengths on the order of ~hours or less, this is unlikely to be significant).
Currently, in Replicated Security, the entire validator set of the provider chain is used to secure consumer chains. There are at least three concerns with this approach.
+First, a large number of validators might be forced to validate consumer chains they are not interested in securing.
+Second, it is costly for small validators to secure additional chains. This concern is only partially addressed through soft opt-out that allows small validators to opt out from validating consumer chains.
+Third and for the above reasons, it is challenging for a new consumer chain to join Replicated Security.
+
As a solution, we present Partial Set Security (PSS). As the name suggests, PSS allows for every consumer chain to be secured by only a subset of the provider validator set.
+In what follows we propose the exact steps we need to take to implement PSS. This is a first iteration of PSS, and therefore we present the most minimal solution that make PSS possible.
In Replicated Security, all the provider validators have to secure every consumer chain (with the exception of those validators allowed to opt out through the soft opt-out feature).
+
In PSS, we allow validators to opt in and out of validating any given consumer chain.
+This has one exception: we introduce a parameter N for each consumer chain and require that the validators in top N% of the provider's voting power have to secure the consumer chain.
+Validators outside of the top N% can dynamically opt in if they want to validate on the consumer chain.
+
For example, if a consumer chain has N = 95%, then it ultimately receives the same security it receives today with Replicated Security (with a default SoftOptOutThreshold of 5%).
+On the other hand, if a consumer chain has N = 0%, then no validator is forced to validate the chain, but validators can opt in to do so instead.
+
For the remainder of this ADR, we call a consumer chain Top N if it has joined as a Top N chain with N > 0 and Opt In chain otherwise. An Opt In consumer chain is secured only by the validators that have opted in to secure that chain.
As a simplification and to avoid chain id squatting, a consumer chain can only join PSS through a governance proposal and not in a permissionless way.
+
However, this proposal type will be modified so that it requires a lower quorum percentage than normal proposal, and every validator who voted "YES" on the proposal will form the consumer chain's initial validator set.
+
Consumer chains join PSS the same way chains now join Replicated Security, namely through a ConsumerAdditionProposal proposal.
+We extend ConsumerAdditionProposal with one optional field:
+
uint32 top_N: Corresponds to the percentage of validators that join under the Top N case.
+For example, 53 corresponds to a Top 53% chain, meaning that the top 53% provider validators have to validate the proposed consumer chain.
+top_N can be 0 or include any value in [50, 100]. A chain can join with top_N == 0 as an Opt In, or with top_N ∈ [50, 100] as a Top N chain.
+
In case of a Top N chain, we restrict the possible values of top_N from (0, 100] to [50, 100].
+By having top_N >= 50 we can guarantee that we cannot have a successful attack, assuming that at most 1/3 of provider validators can be malicious.
+This is because, a Top N chain with N >= 50% would have at least 1/3 honest validators, which is sufficient to stop attacks.
+Additionally, by having N >= 50% (and hence N > (VetoThreshold = 33.4%)) we enable the top N validators to Veto any ConsumerAdditionProposal for consumer chains they do not want to validate.
In the code, we distinguish whether a chain is Top N or Opt In by checking whether top_N is zero or not.
+
In a future version of PSS, we intend to introduce a ConsumerModificationProposal so that we can modify the parameters of a consumer chain, e.g, a chain that is Opt In to become Top N, etc.
Then in the keeper we introduce methods as follows:
+
func (k Keeper) SetTopN(ctx sdk.Context, chainID string, topN uint32) func (k Keeper) IsTopN(ctx sdk.Context, chainID string) bool func (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool // returns the N if Top N chain, otherwise an error func (k Keeper) GetTopN(ctx sdk.Context, chainID string) (uint32, error)
+
We also extend the interchain-security-pd query provider list-consumer-chains query to return information on whether a consumer chain is an Opt In or a Top N chain and with what N.
+This way, block explorers can present informative messages such as "This chain is secured by N% of the provider chain" for consumer chains.
A validator can opt in by sending a new type of message that we introduce in tx.proto.
+
messageMsgOptIn{ // the chain id of the consumer chain to opt in to string chainID =1; // the provider address of the validator string providerAddr =2; // (optional) the consensus public key to use on the consumer optionalstring consumerKey =3; }
+
Note that in a Top N consumer chain, the top N% provider validators have to validate the consumer chain.
+Nevertheless, validators in the bottom (100 - N)% can opt in to validate as well.
+Provider validators that belong or enter the top N% validators are automatically opted in to validate a Top N consumer chain.
+This means that if a validator V belongs to the top N% validators but later falls (e.g., due to undelegations) to the bottom (100 - N)%, V is still considered opted in and has to validate unless V sends a MsgOptOut message (see below).
+By automatically opting in validators when they enter the top N% validators and by forcing top N% validators to explicitly opt out in case they fall to the (100 - N)% bottom validators we simplify the design of PSS.
+
Note that a validator can send a MsgOptIn message even if the consumer chain is not yet running. To do this we reuse the IsConsumerProposedOrRegistered. If the chainID does not exist, the MsgOptIn should fail, as well as if the provider address does not exist.
+
Optionally, a validator that opts in can provide a consumerKey so that it assigns a different consumer key (from the provider) to the consumer chain.
+Naturally, a validator can always change the consumer key on a consumer chain by sending a MsgAssignConsumerKey message at a later point in time, as is done in Replicated Security.
For each validator, we store a pair (blockHeight, isOptedIn) that contains the block height the validator opted in and whether the validator is currently opted in or not, under the key:
+
optedInBytePrefix | len(chainID) | chainID | addr
+
By using a prefix iterator on optedInBytePrefix | len(chainID) | chainID we retrieve all the opted in validators.
+
We introduce the following Keeper methods.
+
// returns all the validators that have opted in on chain `chainID` func (k Keeper) GetOptedInValidators(ctx sdk.Context, chainID string) []Validators func (k Keeper) IsValidatorOptedIn(ctx sdk.Context, chainID string, val Validator) bool
One query to retrieve the validators that are opted in and hence the validators that need to validate the consumer chain and one query that given a validator's address returns all the chains this validator has to validate.
As described earlier, validators can manually opt in by sending a MsgOptIn message.
+Additionally, in a Top N chain, a validator is automatically opted in when it moves from the bottom (100 - N)% to the top N% validators.
+
Lastly, validators can also opt in if they vote Yes during the ConsumerAdditionProposal that introduces a consumer chain.
+This simplifies validators operations because they do not have to send an additional message to opt in.
+
Because the Tally method deletes the votes after reading them, we cannot check the votes of the validators after the votes have been tallied.
+To circumvent this, we introduce a hook for AfterProposalVote and keep track of all the votes cast by a validator.
+If a validator casts more than one vote, we only consider the latest vote.
+Finally, we only consider a validator has opted in if it casts a 100% Yes vote in case of a weighted vote.
Validators that have opted in on a chain can opt out by sending the following message:
+
messageMsgOptOut{ // the chain id of the consumer chain to opt out from string chainID =1; // the provider address of the validator string providerAddr =2; }
+
Validators can only opt out after a consumer chain has started and hence the above message returns an error if the chain with chainID is not running.
+Additionally, a validator that belongs to the top N% validators cannot opt out from a Top N chain and hence a MsgOptOut would error in such a case.
We also update the state of the opted-in validators when a validator has opted out by removing the opted-out validator.
+
Note that only opted-in validators can be punished for downtime on a consumer chain.
+For this, we use historical info of all the validators that have opted in; We can examine the blockHeight stored under the key optedInBytePrefix | len(chainID) | chainID | addr to see if a validator was opted in.
+This way we can jail validators for downtime knowing that indeed the validators have opted in at some point in the past.
+Otherwise, we can think of a scenario where a validator V is down for a period of time, but before V gets punished for downtime, validator V opts out, and then we do not know whether V should be punished or not.
A Top N consumer chain always starts at the specified date (spawn_time) if the ConsumerAdditionProposal has passed.
+An Opt In consumer chain only starts if at least one validator has opted in. We check this in BeginBlockInit:
+
func (k Keeper) BeginBlockInit(ctx sdk.Context) { propsToExecute := k.GetConsumerAdditionPropsToExecute(ctx) for _, prop := range propsToExecute { chainID := prop.ChainId if !k.IsTopN(ctx, chainID) && len(k.GetOptedInValidators(ctx, chainID)) == 0 { // drop the proposal ctx.Logger().Info("could not start chain because no validator has opted in") continue } ...
+
How do we send the partial validator sets to the consumer chains?
+
A consumer chain should only be validated by opted in validators.
+We introduce logic to do this when we queue the VSCPackets.
+The logic behind this, is not as straightforward as it seems because CometBFT does not receive the validator set that has to validate a chain, but rather a delta of validator updates.
+For example, to remove an opted-out validator from a consumer chain, we have to send a validator update with a power of 0, similarly to what is done in the assignment of consumer keys.
+We intend to update this ADR at a later stage on how exactly we intend to implement this logic.
In PSS, we distribute rewards only to validators that actually validate the consumer chain.
+To do this, we have a pool associated with each consumer chain and consumers IBC transfer the rewards to this pool.
+We then extract the rewards from each consumer pool and distribute them to the opted in validators.
+
Note that we only distribute rewards to validators that have been opted in for some time (e.g., 10000 blocks) to avoid cases where validators opt in just to receive rewards and then opt out immediately afterward.
In an Opt In chain, a set of validators might attempt to perform an attack. To deter such potential attacks, PSS allows for the use of fraud votes.
+A fraud vote is a governance proposal that enables the slashing of validators that performed an attack.
+Due to their inherent complexity, we intend to introduce fraud votes in a different ADR and at a future iteration of PSS.
We do not change the way slashing for double signing and light client attacks functions.
+If a validator misbehaves on a consumer, then we slash that validator on the provider.
We do not change the way downtime jailing functions.
+If a validator is down on a consumer chain for an adequate amount of time, we jail this validator on the provider but only if the validator was opted in on this consumer chain in the recent past.
Easier for new consumer chains to consume the provider's chain economic security because proposals are more likely to pass if not everyone is forced to validate.
+
+
+
Smaller validators are not forced to validate chains anymore if they do not want to.
A consumer chain does not receive the same economic security as with Replicated Security (assuming the value of SoftOptOutThreshold is 5%), unless it is a Top N chain with N >= 95%.
Security Aggregation enables staking of tokens from external sources such as Ethereum or Bitcoin to Cosmos blockchains. By integrating Security Aggregation, a Cosmos blockchain can be secured by both native tokens and external tokens (e.g. ETH, BTC).
+
Security Aggregation consists of the following parts:
+
+
A mechanism for delegating external tokens to Cosmos validators, such as Babylon or EigenLayer AVS contract.
+
An oracle that tracks how much external stake has been delegated to each Cosmos validator and provides price feeds for external tokens.
+
Power mixing: a mechanism to combine external and native stake to derive the power of each validator.
+
A reward distribution protocol that enables sending back rewards to the external source.
+
+
External staking information is received from an oracle together with price information of related stakes.
+The CosmosLayer derives validator powers based on external and native staking information and initiates rewarding of external depositors.
+
This ADR describes the Cosmos modules of the solution.
As an alternative to sending rewards back to the external chains, stakers could be rewarded on the Cosmos chain.
+This would require a mapping of external addresses to addresses on Cosmos chain for each staker on external source.
+In addition detailed external staking information such as staking addresses, amount of stakes per staker and validator, etc. have to be provided by the oracle.
The Power Mixing feature and Reward Distribution protocol are an integral part of the Security Aggregation solution.
+The Power Mixing module provides the capability of deriving validator power based on stake originated from external sources such as Ethereum/Bitcoin and the native staking module.
+The Reward Distribution manages the process of sending rewards to external stakers.
Power Mixing provides the final validator powers based on staking information of the native chain and the external stakes. The information about external staking and related price feeds are received from an oracle.
+Once the final validator powers are determined the result is submitted to the underlying CometBFT consensus layer by updating the validator set.
+
Requirements:
+
+
validator updates are performed on each EndBlock
+
a validator's power is determined based on its native on-chain stakes and external stakes
+
price information of staked tokens is used to determine a validator’s power, e.g. price ratio (price of native on-chain token / price of external stake)
+
price information of native/external tokens are received from an oracle
+
staking information from external sources received from the oracle
+
native staking information are received from the Cosmos SDK Staking Module
+
set of validator stakes from oracle always have the current price, full set of validators, and current stakes
+
+
The Power Mixing implementation
+
+
queries current validators and their powers from x/staking
+and from oracle (see below).
+
calculates power updates by mixing power values of external and internal sources
+Following pseudocode snippet shows a possible implementation of how power mixing
+feature works.
+
+
// PowerSource is an abstract entity providing validator powers which // are used by the mixer. This can be an oracle, staking module or an // IBC connected bridge. type PowerSource interface { GetValidatorUpdates() []abci.ValidatorUpdate } // MixPowers calculates power updates by mixing validator powers from different sources func (k *Keeper) MixPowers(source ...PowerSource) []abci.ValidatorUpdate { var valUpdate []abci.ValidatorUpdate for _, ps := range source { // mix powers from two sets of validator updates an return set of validator updates // with aggregated powers valUpdate = mixPower(valUpdate, ps.GetValidatorUpdates()) } return valUpdate } func (k *keeper) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { // GetPowerSources (including local staking module) registeredPowerSource := GetPowerSources() return k.MixPowers(registeredPowerSource...) }
The provider module updates the validator set on CometBFT instead of the SDK staking module (x/staking). The provider implementation will intervene in this behavior and ensure that the validator updates are taken from the Power Mixing feature.
+
External power sources are managed by the provider module. Only registered power sources can provide input to the Power Mixing feature.
+Power sources will be assigned a unique identifier which will be used by the oracle, provider module and the power mixing and rewarding feature.
+
Updates with the next validator set are sent to consumer chains on each epoch (see EndBlockVSU()).
+When collecting the validator updates for each consumer chain (see QueueVSCPackets()), the validator powers of the bonded validators will be updated with the validator powers from the external sources using the Power Mixing module.
+These updates are sent as part of the VSC packets to all registered consumer chains.
Consumer chains receive validator updates as part of VSC packets from the provider.
+These packets contain validator powers which were already mixed with external staked powers.
// GetValidatorUpdates returns the power mixed validator results from the provided sources serviceQuery{ rpcGetValidatorUpdates(PowerMixedValUpdateRequest) PowerMixedValUpdateResponse {}; } // PowerMixedValUpdateRequest contains the list of power sources on which the // power mixing should be based on messagePowerMixedValUpdateRequest{ repeatedPowerSource sources; } // PowerMixedValUpdateResponse returns the validator set with the updated powers // from the power mixing feature messagePowerMixedValUpdateResponse{ repeated abci.ValidatorUpdate val_set }
+
The following queries will be provided by the oracle
+
serviceQuery{ rpcGetExtValidators(GetExtValidatorRequest)returns(ExtValidatorsResponse){ option(google.api.http).get ="oracle/v1/get_validators"; }; } messageGetExtValidatorRequest{} // ExtValidatorsResponse is the response from GetExtValidators queries messageExtValidatorsResponse{ repeatedExtValPower powers; } // ExtValPower represents a validator with its staking and token information, // where: // `power_source_identifier` is the identifier of the registered power source // `validator_address` is the address of the validator // `stakes` is the total amount of stakes for a validator // `denom` is the source token of the stake e.g. ETH,BTC // `price_ratio` is the ratio of price of the external token to the price of the 'local' token messageExtValPower{ string power_source_identifier; string validator_address; uint64 stakes; string denom; float price_ratio; } // GetPrice returns a price feed for a given token serviceQuery{ rpcGetPrice(GetPriceRequest)returns(GetPriceResponse){ option(google.api.http).get ="/oracle/v1/get_price"; }; }
+
For security reasons the amount of external stakes needs to be limited. Limitation of external staking could be driven by governance and is not subject of this version of the ADR.
For native staked tokens the Distribution Module of the Cosmos SDK is taking care of sending the rewards to stakers.
+For stakes originated from external chains (Ethereum/Bitcoin) the Reward Handler module sends rewards to EigenLayer/Babylon.
+The transfer of rewards is done using a bridge between the Cosmos chain and the external provider chain.
+
Note: currently there's no support paying rewards on EigenLayer (see here)
Currently, only validators in the active set on the provider can validate on consumer chains, which limits the number of validators that can participate in Interchain Security (ICS).
+Validators outside of the active set might be willing
+to validate on consumer chains, but we might not want to make the provider validator set larger, e.g. to not put more strain on the consensus engine.
+This runs the risk of leaving consumer chains with too few validators.
+
The purpose of this ADR is to allow validators that are not part of the consensus process on the provider chain (because they are inactive)
+to validate on consumer chains.
+
In the context of this ADR, "consensus validator set" is the set of validators participating in the consensus protocol, and "staking validator set" is the set of validators viewed as active by the staking module.
+
Currently, the staking module, provider module, and CometBFT interact in this way:
+
+
The staking module keeps a list of validators. The MaxValidators validators with the largest amount of stake are "active" validators. MaxValidators is a parameter of the staking module. The staking module sends these validators to CometBFT to inform which validators make up the next consensus validators, that is, the set of validators participating in the consensus process. Separately, the provider module reads the list of bonded validators and sends this to the consumer chain, after shaping it according to which validators are opted in and the parameters set by the consumer chain for allowlist, denylist, etc.
The proposed solution to allow validators that are not participating in the consensus process on the provider (inactive validators) is to change 3 main things:
+
a) increase the MaxValidators parameter of the staking module
+
b) do not take the updates for CometBFT directly from the bonded validators in the staking module, by wrapping the staking modules EndBlocker with a dummy EndBlocker that doesn't return any validator updates. Instead, we adjust the provider module to return validator updates on its EndBlocker. These validator updates are obtained by filtering the bonded validators to send only the first MaxProviderConsensusValidators (sorted by largest amount of stake first) many validators to CometBFT
+
c) use the enlarged list of bonded validators from the staking module as basis for the validator set that the provider module sends to consumer chains (again after applying power shaping and filtering out validatiors that are not opted in).
+
In consequence, the provider chain can keep a reasonably-sized consensus validator set, while giving consumer chains a much larger pool of potential validators.
+
+
Some additional considerations:
+
+
Migration: In the migration, the last consensus validator set will be set to the last active validator set from the view of the staking module. Existing consumer chains are migrated to have a validator set size cap (otherwise, they could end up with a huge validator set including all the staking-but-not-consensus-active validators from the provider chain)
+
Slashing: Validators that are not part of the active set on the provider chain can still be jailed for downtime on a consumer chain (via an Interchain Security SlashPacket sent to the provider, who will then jail the validator), but they are not slashed for downtime on the provider chain.
+This is achieved without any additional changes to the slashing module, because the slashing module checks for downtime by looking at the consensus participants reported by CometBFT, and thus with the proposed solution, validators that are not part of the consensus validators on the provider chain are not considered for downtime slashing (see https://github.com/cosmos/cosmos-sdk/blob/v0.47.11/x/slashing/abci.go#L22).
+
Rewards: Validators that are not part of the active set on the provider chain can still receive rewards on the consumer chain, but they do not receive rewards from the provider chain. This change is
+achieved without further changes to staking or reward distributions, because similar to downtime, rewards are based on the consensus validator set (see https://github.com/cosmos/cosmos-sdk/blob/v0.47.11/x/distribution/abci.go#L28)
Introduce the MaxProviderConsensusValidators parameter to the provider module, which is the number of validators that the provider module will send to consumer chains.
+
Store the provider consensus validator set in the provider module state under the LastProviderConsensusValsPrefix key. This is the last set of validators that the provider sent to the consensus engine. This is needed to compute the ValUpdates to send to the consensus engine (by diffing the current set with this last sent set).
+
Increase the MaxValidators parameter of the staking module to the desired size of the potential validator
+set of consumer chains.
To mitigate risks from validators with little stake, we introduce a minimum stake requirement for validators to be able to validate on consumer chains, which can be set by each consumer chain independently, with a default value set by the provider chain.
+
Additionally, we independently allow individual consumer chains to disable this feature, which will disallow validators from outside the provider active set from validating on the consumer chain and revert them to the previous behaviour of only considering validators of the provider that are part of the active consensus validator set.
+
Additional risk mitigations are to increase the active set size slowly, and to monitor the effects on the network closely. For the first iteration, we propose to increase the active set size to 200 validators (while keeping the consensus validators to 180), thus letting the 20 validators with the most stake outside of the active set validate on consumer chains.
Validators outside of the active set can validate on consumer chains without having an impact on the consensus engine of the provider chain
+
Consumer chains can have a much larger validator set than the provider chain if they prefer this e.g. for decentralization reasons
+
Consumer chain teams can, with much less cost than today, start up their own consumer chain node to keep the chain running (in a centralized manner) even if no hub validators have opted in to validate on the chain. This is useful to stop the chain from ending up with an empty validator set and becoming recoverable only with a hardfork
Allowing validators from the inactive set brings with it some additional risks.
+In general, consumer chains will now face some of the problems also faced by standalone chains. It’s reasonable to assume that the validator set on the hub has a minimum amount of operational quality due to being battle tested and decentralized, and consumer chains with validators from outside the hub active set cannot rely on this as much anymore.
With the restricted size of the active set today, it’s clear that the set is at least minimally competitive and it is not trivial to spin up multiple nodes as a validator.
+
When we make the “potential validator set” much larger, we should assume that it becomes much less competitive to be part of that set, and thus trivial for single entities to control many of those validators.
For validators in the active set, we typically assume that if they would misbehave, they pay a large reputational cost. This represents delegators deciding to switch validators (potentially even on chains other than the one the misbehaviour happened on), and loss of credibility in the ecosystem. With the much larger active set, it seems prudent to assume that reputational damage is not a deterrent for many validators. They might only have minimal amounts of delegated stake and control most of it themselves, so they might not be deterred from performing actions that would usually bring reputational damage.
The provider keeper will need to implement the staking keeper interface, and modules need to be wired up to either the staking or provider keeper, depending on whether they need the consensus or staking validator set
+
This will impact how future modules are integrated, since we will need to consider whether those modules should consider the consensus validators or the bonded validators (which other modules might assume to be the same)
We could instead adapt the staking module with a similar change.
+This might be better if it turns out that the staking module active set is used in many other places.
Instead of increasing the active set size, we could allow validators that are unbonded (but still exist on the provider) to validate consumer chains.
+For this, we would need to:
+
+
Modify the VSC updates to consider the set of all validators, even unbonded ones, instead of just active ones
+
Adjust our downtime jailing/equivocation slashing logic to work correctly with unbonded validators. This is very hard, because redelegations are not usually tracked for unbonded validators.
This is unreleased documentation for Interchain Security main version.
For up-to-date documentation, see the latest version (v4.2.0).
Version: main
Overview
+
This is a location to record all high-level architecture decisions in the Interchain Security project.
+
You can read more about the Architecture Decision Record (ADR) concept in this blog post.
+
An ADR should provide:
+
+
Context on the relevant goals and the current state
+
Proposed changes to achieve the goals
+
Summary of pros and cons
+
References
+
Changelog
+
+
Note the distinction between an ADR and a spec. The ADR provides the context, intuition, reasoning, and
+justification for a change in architecture, or for the architecture of something
+new. The spec is much more compressed and streamlined summary of everything as
+it is or should be.
+
If recorded decisions turned out to be lacking, convene a discussion, record the new decisions here, and then modify the code to match.
+
Note the context/background should be written in the present tense.
+
To suggest an ADR, please make use of the ADR template provided.
+
+
\ No newline at end of file
diff --git a/adrs/intro.html.html b/adrs/intro.html.html
new file mode 100644
index 0000000000..ccd2f19f7b
--- /dev/null
+++ b/adrs/intro.html.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/css/styles.7c672362.css b/assets/css/styles.7c672362.css
new file mode 100644
index 0000000000..4b32ac69ed
--- /dev/null
+++ b/assets/css/styles.7c672362.css
@@ -0,0 +1 @@
+.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500);--docsearch-searchbox-shadow:inset 0 0 0 1px var(--docsearch-primary-color)}*,:after,:before{box-sizing:border-box}.antialiased,html{-moz-osx-font-smoothing:grayscale}html .menu__link:hover,html .table-of-contents__link--active,html .table-of-contents__link:hover{text-shadow:.1px .1px 0 var(--ifm-font-color-base),-.1px -.1px 0 var(--ifm-font-color-base),.1px -.1px 0 var(--ifm-font-color-base),-.1px .1px 0 var(--ifm-font-color-base),-.1px 0 0 var(--ifm-font-color-base),.1px 0 0 var(--ifm-font-color-base),0 .1px 0 var(--ifm-font-color-base),0 -.1px 0 var(--ifm-font-color-base)}.markdown,html .markdown{--ifm-heading-vertical-rhythm-bottom:1}.hover\:underline:hover,.underline,html .footer__link-item:hover,html .theme-doc-markdown a{text-decoration-line:underline}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}.clean-list,.containsTaskList_mC6p,.details_lb9f>summary,.dropdown__menu,.menu__list{list-style:none}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}html{-webkit-font-smoothing:antialiased;color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);text-rendering:optimizelegibility}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width);padding:0 var(--ifm-spacing-horizontal);width:100%}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.px-0,.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.items-center,.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width);padding:0 var(--ifm-spacing-horizontal);width:100%}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}html,html .navbar{background-color:var(--ifm-background-color)}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_Gvgb,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);color:var(--ifm-font-color-base);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}.button.button--secondary.button--outline:not(.button--active):not(:hover),.text-docusaurusColorBase,html .DocSearch-Button .DocSearch-Search-Icon,html .DocSearch-Hits mark{color:var(--ifm-font-color-base)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card--full-height{height:100%}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child),.pb-0{padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links,.mb-5{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_BuS1>:last-child,.collapsibleContent_i85q p:last-child,.details_lb9f>summary>p:last-child,.footer__items,html .theme-doc-markdown li:last-child li:last-child{margin-bottom:0}.codeBlockStandalone_MEMb,.p-0,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.navbar-sidebar,.navbar-sidebar__backdrop{opacity:0;top:0;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;bottom:0;left:0;visibility:hidden}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;content:"";filter:var(--ifm-menu-link-sublist-icon-filter)}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.flex,.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.h-full,.navbar__logo img,body,html{height:100%}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand,html .theme-doc-sidebar-container>div:first-child>a{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);position:fixed;transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;position:fixed;right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.hover\:shadow-lg:hover,.shadow,.shadow-none,html .navbar,html .pagination-nav>a:hover,html[data-theme=dark] .navbar-sidebar__brand{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.transform,html .theme-back-to-top-button{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.col-span-2,html .pagination-nav>a{grid-column:span 2/span 2}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto;padding-left:0}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.transition,.transition-all{transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec;--ifm-color-primary:#fff;--ifm-color-primary-dark:#e6e6e6;--ifm-color-primary-darker:#d9d9d9;--ifm-color-primary-darkest:#b3b3b3;--ifm-color-primary-light:#fff;--ifm-color-primary-lighter:#fff;--ifm-color-primary-lightest:#fff;--ifm-background-color:#000;--docusaurus-highlighted-code-line-bg:#00000054;--docsearch-modal-background:#000!important;--docsearch-highlight-color:#ffffff70!important;--docsearch-hit-background:#181818ab!important;--docsearch-key-gradient:linear-gradient(-26.5deg,#5d5d5d,#3c3c3c)!important;--docsearch-key-shadow:inset 0 -2px 0 0 #353535,inset 0 0 1px 1px #7a7a7b,0 2px 2px 0 #2d2d2d4d!important}:root{--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#1a45f0;--ifm-color-primary-dark:#000;--ifm-color-primary-darker:#000;--ifm-color-primary-darkest:#000;--ifm-color-primary-light:#000;--ifm-color-primary-lighter:#000;--ifm-color-primary-lightest:#000;--ifm-code-font-size:95%;--ifm-breadcrumb-item-background-active:#0000;--ifm-breadcrumb-padding-horizontal:0;--ifm-list-paragraph-margin:0;--ifm-spacing-horizontal:2rem;--ifm-blockquote-border-color:#000;--ifm-menu-link-padding-vertical:0.6rem;--ifm-background-color:#fff;--ifm-footer-link-color:var(--ifm-font-color-base);--ifm-menu-link-sublist-icon:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMSAxIDQgNCA0LTQiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9Ii42NjciIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz48L3N2Zz4=);--docsearch-searchbox-background:#f7f7f7;--docsearch-modal-background:#f7f7f7!important;--ifm-navbar-height:5.563rem;--ifm-navbar-sidebar-width:100vw;--docsearch-highlight-color:#181818ab!important;--aa-primary-color-rgb:0,0,0;--ifm-menu-color-background-active:none;--ifm-menu-color-background-hover:none;--docusaurus-highlighted-code-line-bg:#0000001a;--docusaurus-announcement-bar-height:auto;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300);--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}html{font-feature-settings:"kern","liga","calt","zero" 0;-webkit-font-feature-settings:"kern","liga","calt","zero" 0;-webkit-text-size-adjust:100%;text-size-adjust:100%;font-smoothing:antialiased;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-kerning:normal;font-variant-ligatures:contextual common-ligatures;text-rendering:optimizeLegibility}@supports (font-variation-settings:normal){html{font-family:Inter var,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}}*,:after,:before{margin:0}.inline,.tags_jXut,svg{display:inline}::selection{background-color:var(--ifm-color-primary);color:#fff}.text-gray-1000,html #__docusaurus>div[role=banner],html[data-theme=dark] .footer__copyright,html[data-theme=dark] .footer__link-item,html[data-theme=dark] .footer__title,html[data-theme=light] .pagination-nav__sublabel{color:rgb(0 0 0/var(--tw-text-opacity));--tw-text-opacity:1}&[data-theme=dark] ::selection{color:#000}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }@font-face{font-display:swap;font-family:Inter;font-style:normal;font-weight:400;src:url(/interchain-security/assets/fonts/Inter-Regular-c8ba52b05a9ef10f47584d08ece2ec5c.woff2) format("woff2"),url(/interchain-security/assets/fonts/Inter-Regular-8c206db99195777c67691cbba9d64393.woff) format("woff")}@font-face{font-display:swap;font-family:Inter;font-style:normal;font-weight:500;src:url(/interchain-security/assets/fonts/Inter-Medium-293fd13dbca5a3e450ef1ebfb232a299.woff2) format("woff2"),url(/interchain-security/assets/fonts/Inter-Medium-9053572c46aeb4b16caafd643a543b8d.woff) format("woff")}@font-face{font-display:swap;font-family:Inter;font-style:normal;font-weight:700;src:url(/interchain-security/assets/fonts/Inter-Bold-ec64ea577b0349e055ad6646c1d8797a.woff2) format("woff2"),url(/interchain-security/assets/fonts/Inter-Bold-93c1301bd9f486c573b3d9001c6ec0e4.woff) format("woff")}@font-face{font-display:swap;font-family:Inter;font-style:normal;font-weight:900;src:url(/interchain-security/assets/fonts/Inter-Black-15ca31c0a2a68f76d2d12055bdf97bd0.woff2) format("woff2"),url(/interchain-security/assets/fonts/Inter-Black-c6938660eec019fefd684894b6d00900.woff) format("woff")}@font-face{font-display:swap;font-family:Inter var;font-style:oblique 0deg 10deg;font-weight:100 900;src:url(/interchain-security/assets/fonts/Inter.var-c2fe3cb2b7c746f7966a973d869d21c3.woff2) format("woff2")}@font-face{font-family:JetBrains Mono;font-style:normal;font-weight:400;src:url(/interchain-security/assets/fonts/JetBrainsMono-Regular-1e66c47aca088de94ae789a48719cb00.woff2) format("woff2")}.absolute{position:absolute}.relative{position:relative}.-left-\[calc\(theme\(space\.5\)\*1\+theme\(space\.7\)-theme\(space\.3\)\)\],html .theme-doc-sidebar-menu li li li .menu__link--active:not(.menu__link--sublist):before{left:-2.5rem}.-left-\[calc\(theme\(space\.5\)\*2\+theme\(space\.7\)-theme\(space\.3\)\)\],html .theme-doc-sidebar-menu li li li li .menu__link--active:not(.menu__link--sublist):before{left:-3.5rem}.-left-\[calc\(theme\(space\.5\)\*3\+theme\(space\.7\)-theme\(space\.3\)\)\],html .theme-doc-sidebar-menu li li li li li .menu__link--active:not(.menu__link--sublist):before{left:-4.5rem}.-left-\[calc\(theme\(space\.5\)\*4\+theme\(space\.7\)-theme\(space\.3\)\)\],html .theme-doc-sidebar-menu li li li li li li .menu__link--active:not(.menu__link--sublist):before{left:-5.5rem}.-left-\[calc\(theme\(space\.5\)\*5\+theme\(space\.7\)-theme\(space\.3\)\)\],html .theme-doc-sidebar-menu li li li li li li li .menu__link--active:not(.menu__link--sublist):before{left:-6.5rem}.-left-\[calc\(theme\(space\.7\)-theme\(space\.3\)\)\]{left:-1.5rem}.bottom-0{bottom:0}.left-0{left:0}.left-3{left:.5rem}.right-3{right:.5rem}.right-8{right:3rem}.top-0{top:0}.top-\[\.2rem\]{top:.2rem}.order-2{order:2}.order-first{order:-9999}.order-last{order:9999}.my-5,html .theme-doc-markdown li>ol,html .theme-doc-markdown li>ul{margin-bottom:1rem;margin-top:1rem}.mb-3{margin-bottom:.5rem}.mb-3\.5{margin-bottom:.625rem}.mb-4{margin-bottom:.75rem}.ml-0{margin-left:0}.ml-4{margin-left:.75rem}.mt-7{margin-top:2rem}.mt-9{margin-top:4rem}.block,.tocCollapsibleContent_vkbj a{display:block}.grid{display:grid}.hidden,html .DocSearch-Button .DocSearch-Button-Keys,html .breadcrumbs__item:first-child>a>svg{display:none}.h-8{height:3rem}.h-auto,.img_ev3q{height:auto}.h-px{height:1px}.w-8{width:3rem}.w-\[2px\]{width:2px}.w-auto{width:auto}.w-full,html .navbar-sidebar{width:100%}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.justify-start{justify-content:flex-start}.justify-center{justify-content:center}.gap-4{gap:.75rem}.rounded{border-radius:1rem}.rounded-s{border-radius:.5rem}.rounded-sm{border-radius:.625rem}.rounded-s{border-end-start-radius:1rem;border-start-start-radius:1rem}.border{border-width:1px}.border-0{border-width:0}.border-t,html .footer{border-top-width:1px}.border-b,html .navbar{border-bottom-width:1px}.border-r{border-right-width:1px}.border-stone-200{--tw-border-opacity:1;border-color:rgb(231 229 228/var(--tw-border-opacity))}.border-transparent{border-color:#0000}.border-b-docusaurusColorBorder,html .navbar{border-bottom-color:var(--ifm-color-emphasis-200)}.border-t-docusaurusColorBorder{border-top-color:var(--ifm-color-emphasis-200)}.bg-card{--tw-bg-opacity:1;background-color:rgb(247 247 247/var(--tw-bg-opacity))}.bg-fg,html[data-theme=dark] .navbar__toggle,html[data-theme=dark] .theme-doc-toc-mobile{background-color:#181818ab}.bg-gray-1000,html[data-theme=dark] .DocSearch-Footer,html[data-theme=dark] .DocSearch-Modal,html[data-theme=dark] .navbar-sidebar{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-gray-30{background-color:#00000008}.bg-linkHover{--tw-bg-opacity:1;background-color:rgb(85 85 85/var(--tw-bg-opacity))}.p-6{padding:1.5rem}.px-3{padding-left:.5rem;padding-right:.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-5{padding-bottom:1rem;padding-top:1rem}.py-5\.5{padding-bottom:1.25rem;padding-top:1.25rem}.pb-2,html .navbar{padding-bottom:.375rem}.pt-5,.pt-\[calc\(theme\(spacing\.7\)-1rem\)\],html .navbar{padding-top:1rem}.pb-5{padding-bottom:1rem}.pb-5\.5{padding-bottom:1.25rem}.pb-7{padding-bottom:2rem}.pb-8{padding-bottom:3rem}.pb-8\.5{padding-bottom:3.25rem}.pl-0,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pl-6{padding-left:1.5rem}.pl-8{padding-left:3rem}.pt-6{padding-top:1.5rem}.text-center{text-align:center}.font-intervar{font-family:Inter var,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.font-jetbrain,html .theme-code-block{font-family:JetBrains Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-3,.text-\[1rem\],html .theme-doc-markdown blockquote,html .theme-doc-markdown ol,html .theme-doc-markdown p,html .theme-doc-markdown ul{font-size:1rem}.text-4{font-size:1.3125rem}.text-6{font-size:2rem}.text-7{font-size:2.375rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-10{line-height:2.5rem}.leading-6{line-height:1.5rem}.leading-7{line-height:1.75rem}.leading-8{line-height:2rem}.leading-9{line-height:2.25rem}.text-inactive{color:#00000054}.text-inactiveLight{color:#ffffff70}.no-underline,html .theme-doc-markdown .card-section a{text-decoration-line:none}.antialiased{-webkit-font-smoothing:antialiased}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow-none,html .navbar,html .pagination-nav>a:hover,html[data-theme=dark] .navbar-sidebar__brand{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}.grayscale{--tw-grayscale:grayscale(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter}.transition-all{transition-property:all}.duration-200{transition-duration:.2s}html #__docusaurus>div[role=banner]{background-color:#00000008;font-weight:400}html #__docusaurus>div[role=banner] a{font-size:.8125rem;text-decoration-line:none;width:100%}html .navbar{height:auto}html .DocSearch-Button,html .navbar__toggle{background-color:rgb(247 247 247/var(--tw-bg-opacity));height:3rem;width:3rem;--tw-bg-opacity:1}html .navbar__toggle{align-items:center;border-end-start-radius:1rem;border-radius:.5rem;border-start-start-radius:1rem;display:flex;justify-content:center}html .navbar__brand+*{margin-left:auto}html .menu__link,html .navbar__link--active{--tw-text-opacity:1;color:rgb(85 85 85/var(--tw-text-opacity))}html .navbar__items:not(:last-child){justify-content:space-between}html .navbar__items:not(:last-child) button{margin-right:0;order:2}html .navbar__items--right>:last-child{right:3.25rem}html[data-theme=dark] .menu__link,html[data-theme=dark] .navbar__item{color:#ffffffab}html .github-icon:hover{opacity:.5}html .DocSearch-Button{border-radius:.625rem;color:#00000054;justify-content:center;margin-right:.5rem}html .DocSearch-Button .DocSearch-Button-Placeholder{padding-right:6rem}html .DocSearch-Logo path{fill:var(--ifm-font-color-base)}html .navbar-sidebar__brand{height:auto;padding-left:1.5rem;padding-right:1.5rem}html .navbar-sidebar__item{padding-left:1.5rem;padding-right:1.5rem;width:100%}html .navbar-sidebar__back{display:none;padding-left:0;padding-right:0}html .navbar-sidebar__close{--tw-bg-opacity:1;align-items:center;background-color:rgb(0 0 0/var(--tw-bg-opacity));border-end-start-radius:1rem;border-radius:.5rem;border-start-start-radius:1rem;display:flex;height:3rem;justify-content:center;margin-left:0;width:3rem}html .navbar-sidebar__close>svg>g{stroke:#fff}html[data-theme=dark] .navbar-sidebar__brand{position:relative}html[data-theme=dark] .navbar-sidebar__brand:after{--tw-bg-opacity:1;background-color:rgb(85 85 85/var(--tw-bg-opacity));bottom:0;content:"";display:block;height:1px;left:0;margin-left:1.5rem;margin-right:1.5rem;position:absolute;right:.5rem}html[data-theme=dark] .navbar-sidebar__close{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}html[data-theme=dark] .navbar-sidebar__close>svg>g{stroke:#000}html[data-theme=dark] .DocSearch-Button{background-color:#181818ab;color:#ffffff70}html[data-theme=dark] .DocSearch-Button-Key{border-color:#ffffff70;color:#ffffff70}html .breadcrumbs__item:first-child>a:after{content:"Docs"}html .breadcrumbs__item:not(:last-child):after{background-image:none;content:">"}html .theme-doc-toc-mobile{--tw-bg-opacity:1;background-color:rgb(247 247 247/var(--tw-bg-opacity));border-radius:1rem;padding:1.25rem 1.5rem 0}html .theme-doc-toc-mobile>button{display:flex;justify-content:space-between;padding:0 0 1.25rem}html .theme-doc-toc-mobile>button:after{background-image:var(--ifm-menu-link-sublist-icon);background-size:70%;margin-left:1rem;order:9999}html .theme-doc-toc-mobile ul li{margin:1rem 0}html[data-theme=dark] .theme-doc-sidebar-menu .menu__list:before{background-color:#ffffff70}html .theme-doc-sidebar-menu{font-weight:400}html .theme-doc-sidebar-menu .menu__list{padding-left:0;position:relative}html .theme-doc-sidebar-menu .menu__list:before{background-color:#00000012;content:"";display:block;height:100%;left:.5rem;position:absolute;top:0;width:2px}#__docusaurus-base-url-issue-banner-container,.themedComponent_mlkZ,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html .footer__col:first-child .footer__title,html .footer__link-item>svg,html .menu__caret,html .menu__link>svg,html .theme-doc-sidebar-menu .menu__list ul:before,html li li .menu__link--sublist-caret:after,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}html .theme-doc-sidebar-menu .menu__link{padding-left:0;padding-right:1rem}html .theme-doc-sidebar-menu .menu__link--active:not(.menu__link--sublist){color:var(--ifm-font-color-base);font-weight:500}html .theme-doc-sidebar-menu li li{padding-left:2rem}html .theme-doc-sidebar-menu li li .menu__link--active:not(.menu__link--sublist){color:var(--ifm-font-color-base);font-weight:500;position:relative}html .theme-doc-sidebar-menu li li .menu__link--active:not(.menu__link--sublist):before{background-color:var(--ifm-font-color-base);content:"";display:block;height:100%;left:-1.5rem;position:absolute;top:0;width:2px}html .theme-doc-sidebar-menu li li li{padding-left:1rem}html .theme-doc-sidebar-item-link .menu__link[target=_blank]:after{content:"\2197";margin-left:.25rem}html .menu__link:hover{color:var(--ifm-font-color-base)}html .menu__link--sublist-caret{display:flex}html .menu__link--sublist-caret:after{background-repeat:no-repeat;background-size:16px;margin-left:0;margin-right:.75rem;order:-9999}html .menu__list-item--collapsed .menu__caret:before,html .menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(0)}html[data-theme=dark] .pagination-nav>a{--tw-border-opacity:1;background-color:#181818ab;border-color:rgb(41 37 36/var(--tw-border-opacity))}html .pagination-nav{margin-top:4rem;padding-bottom:2rem}html .pagination-nav>a{border-color:#0000;border-radius:1rem;box-shadow:0 0 80px #00000012;padding:1.5rem 1.5rem 3.25rem}html .pagination-nav .pagination-nav__link--next{text-align:left}html .pagination-nav .pagination-nav__sublabel{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity));font-size:1rem;margin-bottom:.625rem}:is([data-theme=dark] html .pagination-nav .pagination-nav__sublabel){color:var(--ifm-font-color-base)}html .pagination-nav .pagination-nav__label{font-size:1.3125rem;font-weight:600}html[data-theme=dark] .pagination-nav__sublabel,html[data-theme=light] .footer__copyright,html[data-theme=light] .footer__link-item,html[data-theme=light] .footer__title{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}html .footer{background-color:var(--ifm-font-color-base);border-top-color:var(--ifm-color-emphasis-200);padding-top:6rem}html .footer__bottom{margin:0 calc(var(--ifm-spacing-horizontal)*-1)}html .footer__copyright{font-size:.8125rem;margin-top:4rem;text-align:center}html .footer__col:not(:first-child){flex-basis:50%}html .theme-back-to-top-button{--tw-rotate:180deg}html .theme-back-to-top-button:after{width:50%}html .theme-code-block{margin-top:.5rem}html .markdown{--ifm-h1-vertical-rhythm-bottom:1}html .theme-doc-markdown{border-bottom-color:#00000012;border-bottom-width:1px;margin-top:2rem;padding-bottom:3rem}.before\:border-current:before,html .theme-doc-markdown ul li li:before{border-color:currentColor;content:var(--tw-content)}html .theme-doc-markdown h1{font-size:2.375rem;font-weight:700;letter-spacing:-.025em;line-height:2.5rem}html .theme-doc-markdown h2{font-size:2rem;font-weight:700;letter-spacing:-.025em;line-height:2.25rem}html .theme-doc-markdown h3{font-size:1.3125rem;font-weight:600;letter-spacing:-.025em;line-height:2rem}html .theme-doc-markdown h4{font-size:1rem;font-weight:600;letter-spacing:-.025em;line-height:1.75rem}html .theme-doc-markdown h5{font-size:1rem;font-weight:600;letter-spacing:.025em;line-height:1.5rem}html .theme-doc-markdown p{line-height:1.625}html .theme-doc-markdown code{border-width:0;padding-left:.5rem;padding-right:.5rem;vertical-align:initial}html .theme-doc-markdown blockquote{margin-bottom:2rem;margin-top:2rem}html .theme-doc-markdown a{color:var(--ifm-color-primary)}html .theme-doc-markdown ol,html .theme-doc-markdown ul{margin-bottom:1.5rem;margin-top:1.5rem}html .theme-doc-markdown ul li{margin-bottom:.75rem;padding-left:1.5rem;position:relative}html .theme-doc-markdown ul li:before{background-color:currentColor;content:var(--tw-content);display:block;height:4px;left:0;position:absolute;top:.5em;width:4px}html .theme-doc-markdown ul li li:before{background-color:initial;border-width:1px}.last\:mb-6:last-child,html .theme-doc-markdown ul li li:last-child{margin-bottom:1.5rem}html .theme-doc-markdown ol{counter-reset:a;list-style-type:none}html .theme-doc-markdown ol>li{margin-bottom:1.25rem;padding-left:3rem;position:relative}html .theme-doc-markdown ol>li:before{content:counters(a,".",decimal-leading-zero) ".";counter-increment:a;display:flex;font-size:1rem;font-weight:600;left:0;letter-spacing:-.025em;position:absolute;top:.2rem}html .theme-doc-markdown ol ol{counter-reset:b}html .theme-doc-markdown ol ol>li:before{content:counters(b,".",decimal-leading-zero) ".";counter-increment:b}html .main-wrapper{min-height:100vh}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:left-0:before{content:var(--tw-content);left:0}.before\:top-\[calc\(1em\/2\)\]:before{content:var(--tw-content);top:.5em}.before\:block:before{content:var(--tw-content);display:block}.before\:h-\[4px\]:before{content:var(--tw-content);height:4px}.before\:w-\[4px\]:before{content:var(--tw-content);width:4px}.before\:border:before{border-width:1px;content:var(--tw-content)}.before\:bg-current:before{background-color:currentColor;content:var(--tw-content)}.hover\:border-stone-300:hover{--tw-border-opacity:1;border-color:rgb(214 211 209/var(--tw-border-opacity))}.hover\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}:is([data-theme=dark] .dark\:border-stone-800){--tw-border-opacity:1;border-color:rgb(41 37 36/var(--tw-border-opacity))}:is([data-theme=dark] .dark\:bg-neutral-900){--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}:is([data-theme=dark] .dark\:text-docusaurusColorBase){color:var(--ifm-font-color-base)}:is([data-theme=dark] .dark\:hover\:border-stone-200:hover){--tw-border-opacity:1;border-color:rgb(231 229 228/var(--tw-border-opacity))}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit;text-decoration:underline}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}[data-theme=dark] .themedComponent--dark_xIcU,[data-theme=light] .themedComponent--light_NVdE,html:not([data-theme]) .themedComponent--light_NVdE{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.dropdownNavbarItemMobile_S0Fm{cursor:pointer}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}@supports selector(:has(*)){.navbarSearchContainer_Bca1:not(:has(>*)){display:none}}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_a6uf{color:red;white-space:pre-wrap}.errorBoundaryFallback_VBag{color:red;padding:.55rem}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none}.hash-link:before{content:"#"}.mainWrapper_z2l0{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:c;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(c);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.admonition_xJq3{margin-bottom:1em}.admonitionHeading_Gvgb{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family)}.admonitionHeading_Gvgb:not(:last-child){margin-bottom:.3rem}.admonitionHeading_Gvgb code{text-transform:none}.admonitionIcon_Rf37{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_Rf37 svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.breadcrumbHomeIcon_YNFT{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_PEFL{display:none;margin:0}.docSidebarContainer_YfHR,.sidebarLogo_isFc{display:none}.docMainContainer_TBSr,.docRoot_UBD9{display:flex;width:100%}.docsWrapper_hBAB{display:flex;flex:1 0 auto}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_TmdG{background-color:var(--docusaurus-collapse-button-bg)}.tocMobile_ITEo,html .navbar__toggle{display:none}html .navbar__items:not(:last-child){justify-content:flex-start;padding-left:.5rem;padding-right:.5rem}html .DocSearch-Button{justify-content:space-between;width:auto}html .theme-doc-breadcrumbs{padding-top:1rem}html .theme-doc-sidebar-container{border-right-color:var(--ifm-color-emphasis-200);border-right-width:1px;margin-left:.75rem}html .pagination-nav>a{grid-column:span 1/span 1}.lastUpdated_vwxv,html .pagination-nav .pagination-nav__link--next{text-align:right}html .footer__col:not(:first-child){flex-basis:0}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.navbarSearchContainer_Bca1{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.docItemCol_VOVn{max-width:75%!important}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_i1dp,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_TmdG:focus,.expandButton_TmdG:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{opacity:0;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_TmdG{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_i1dp{transform:rotate(180deg)}.docSidebarContainer_YfHR{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_DPk8{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_aRkj{height:100%;max-height:100vh;position:sticky;top:0}.docMainContainer_TBSr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_lQrH{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_JWYK{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}}@media (min-width:1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.navbarSearchContainer_Bca1{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_F8PC{padding:0 .3rem}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media screen and (prefers-reduced-motion){:root{transition:none}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}}
\ No newline at end of file
diff --git a/assets/fonts/Inter-Black-15ca31c0a2a68f76d2d12055bdf97bd0.woff2 b/assets/fonts/Inter-Black-15ca31c0a2a68f76d2d12055bdf97bd0.woff2
new file mode 100644
index 0000000000..68f64c9ed9
Binary files /dev/null and b/assets/fonts/Inter-Black-15ca31c0a2a68f76d2d12055bdf97bd0.woff2 differ
diff --git a/assets/fonts/Inter-Black-c6938660eec019fefd684894b6d00900.woff b/assets/fonts/Inter-Black-c6938660eec019fefd684894b6d00900.woff
new file mode 100644
index 0000000000..a18593a096
Binary files /dev/null and b/assets/fonts/Inter-Black-c6938660eec019fefd684894b6d00900.woff differ
diff --git a/assets/fonts/Inter-Bold-93c1301bd9f486c573b3d9001c6ec0e4.woff b/assets/fonts/Inter-Bold-93c1301bd9f486c573b3d9001c6ec0e4.woff
new file mode 100644
index 0000000000..eaf3d4bfd7
Binary files /dev/null and b/assets/fonts/Inter-Bold-93c1301bd9f486c573b3d9001c6ec0e4.woff differ
diff --git a/assets/fonts/Inter-Bold-ec64ea577b0349e055ad6646c1d8797a.woff2 b/assets/fonts/Inter-Bold-ec64ea577b0349e055ad6646c1d8797a.woff2
new file mode 100644
index 0000000000..2846f29cc8
Binary files /dev/null and b/assets/fonts/Inter-Bold-ec64ea577b0349e055ad6646c1d8797a.woff2 differ
diff --git a/assets/fonts/Inter-Medium-293fd13dbca5a3e450ef1ebfb232a299.woff2 b/assets/fonts/Inter-Medium-293fd13dbca5a3e450ef1ebfb232a299.woff2
new file mode 100644
index 0000000000..f92498a2ec
Binary files /dev/null and b/assets/fonts/Inter-Medium-293fd13dbca5a3e450ef1ebfb232a299.woff2 differ
diff --git a/assets/fonts/Inter-Medium-9053572c46aeb4b16caafd643a543b8d.woff b/assets/fonts/Inter-Medium-9053572c46aeb4b16caafd643a543b8d.woff
new file mode 100644
index 0000000000..d546843f28
Binary files /dev/null and b/assets/fonts/Inter-Medium-9053572c46aeb4b16caafd643a543b8d.woff differ
diff --git a/assets/fonts/Inter-Regular-8c206db99195777c67691cbba9d64393.woff b/assets/fonts/Inter-Regular-8c206db99195777c67691cbba9d64393.woff
new file mode 100644
index 0000000000..62d3a61871
Binary files /dev/null and b/assets/fonts/Inter-Regular-8c206db99195777c67691cbba9d64393.woff differ
diff --git a/assets/fonts/Inter-Regular-c8ba52b05a9ef10f47584d08ece2ec5c.woff2 b/assets/fonts/Inter-Regular-c8ba52b05a9ef10f47584d08ece2ec5c.woff2
new file mode 100644
index 0000000000..6c2b6893d5
Binary files /dev/null and b/assets/fonts/Inter-Regular-c8ba52b05a9ef10f47584d08ece2ec5c.woff2 differ
diff --git a/assets/fonts/Inter.var-c2fe3cb2b7c746f7966a973d869d21c3.woff2 b/assets/fonts/Inter.var-c2fe3cb2b7c746f7966a973d869d21c3.woff2
new file mode 100644
index 0000000000..365eedc50c
Binary files /dev/null and b/assets/fonts/Inter.var-c2fe3cb2b7c746f7966a973d869d21c3.woff2 differ
diff --git a/assets/fonts/JetBrainsMono-Regular-1e66c47aca088de94ae789a48719cb00.woff2 b/assets/fonts/JetBrainsMono-Regular-1e66c47aca088de94ae789a48719cb00.woff2
new file mode 100644
index 0000000000..8c862e334d
Binary files /dev/null and b/assets/fonts/JetBrainsMono-Regular-1e66c47aca088de94ae789a48719cb00.woff2 differ
diff --git a/assets/images/cometmock_matrix_test-714f36252aff9df4214823e3145d0ef5.png b/assets/images/cometmock_matrix_test-714f36252aff9df4214823e3145d0ef5.png
new file mode 100644
index 0000000000..740005aed1
Binary files /dev/null and b/assets/images/cometmock_matrix_test-714f36252aff9df4214823e3145d0ef5.png differ
diff --git a/assets/images/hypha-consumer-start-process-2141109f76c584706dd994d7965fd692.svg b/assets/images/hypha-consumer-start-process-2141109f76c584706dd994d7965fd692.svg
new file mode 100644
index 0000000000..1be7b61b7d
--- /dev/null
+++ b/assets/images/hypha-consumer-start-process-2141109f76c584706dd994d7965fd692.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/images/ics_changeover_timeline_stride-9bcad1834fef24a0fea7f2c80c9ccd71.png b/assets/images/ics_changeover_timeline_stride-9bcad1834fef24a0fea7f2c80c9ccd71.png
new file mode 100644
index 0000000000..2cec12a6be
Binary files /dev/null and b/assets/images/ics_changeover_timeline_stride-9bcad1834fef24a0fea7f2c80c9ccd71.png differ
diff --git a/assets/images/inactivevals_after-ac23b4c6474ed6bb2105369cdf8482a0.png b/assets/images/inactivevals_after-ac23b4c6474ed6bb2105369cdf8482a0.png
new file mode 100644
index 0000000000..fb9e862c02
Binary files /dev/null and b/assets/images/inactivevals_after-ac23b4c6474ed6bb2105369cdf8482a0.png differ
diff --git a/assets/images/inactivevals_before-a963b865d2029f6629845f7b1beb215b.png b/assets/images/inactivevals_before-a963b865d2029f6629845f7b1beb215b.png
new file mode 100644
index 0000000000..ffbcd584b8
Binary files /dev/null and b/assets/images/inactivevals_before-a963b865d2029f6629845f7b1beb215b.png differ
diff --git a/assets/images/matrix_e2e_tests-30681305077301daaf3097e1952b54bb.png b/assets/images/matrix_e2e_tests-30681305077301daaf3097e1952b54bb.png
new file mode 100644
index 0000000000..4c94db81a3
Binary files /dev/null and b/assets/images/matrix_e2e_tests-30681305077301daaf3097e1952b54bb.png differ
diff --git a/assets/js/00147ff4.0b3ca866.js b/assets/js/00147ff4.0b3ca866.js
new file mode 100644
index 0000000000..9fb14c102a
--- /dev/null
+++ b/assets/js/00147ff4.0b3ca866.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2110],{9075:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>h,contentTitle:()=>s,default:()=>l,frontMatter:()=>o,metadata:()=>r,toc:()=>c});var a=i(5893),t=i(1151);const o={sidebar_position:5,title:"Frequently Asked Questions",slug:"/faq"},s=void 0,r={id:"frequently-asked-questions",title:"Frequently Asked Questions",description:"What is a consumer chain?",source:"@site/docs/frequently-asked-questions.md",sourceDirName:".",slug:"/faq",permalink:"/interchain-security/faq",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:5,frontMatter:{sidebar_position:5,title:"Frequently Asked Questions",slug:"/faq"},sidebar:"tutorialSidebar",previous:{title:"Partial Set Security",permalink:"/interchain-security/validators/partial-set-security-for-validators"},next:{title:"Overview",permalink:"/interchain-security/adrs/intro"}},h={},c=[{value:"What is a consumer chain?",id:"what-is-a-consumer-chain",level:2},{value:"What happens to consumer if provider is down?",id:"what-happens-to-consumer-if-provider-is-down",level:2},{value:"What happens to provider if consumer is down?",id:"what-happens-to-provider-if-consumer-is-down",level:2},{value:"Can I run the provider and consumer chains on the same machine?",id:"can-i-run-the-provider-and-consumer-chains-on-the-same-machine",level:2},{value:"Can the consumer chain have its own token?",id:"can-the-consumer-chain-have-its-own-token",level:2},{value:"How are Tx fees paid on consumer?",id:"how-are-tx-fees-paid-on-consumer",level:2},{value:"Are there any restrictions the consumer chains need to abide by?",id:"are-there-any-restrictions-the-consumer-chains-need-to-abide-by",level:2},{value:"What's in it for the validators and stakers?",id:"whats-in-it-for-the-validators-and-stakers",level:2},{value:"Can the consumer chain have its own governance?",id:"can-the-consumer-chain-have-its-own-governance",level:2},{value:"Can validators opt out of validating a consumer chain?",id:"can-validators-opt-out-of-validating-a-consumer-chain",level:2},{value:"How does Slashing work?",id:"how-does-slashing-work",level:2},{value:"Can Consumer Chains perform Software Upgrades?",id:"can-consumer-chains-perform-software-upgrades",level:2},{value:"How can I connect to the testnets?",id:"how-can-i-connect-to-the-testnets",level:2},{value:"How do I start using ICS?",id:"how-do-i-start-using-ics",level:2},{value:"Which relayers are supported?",id:"which-relayers-are-supported",level:2},{value:"How does key delegation work in ICS?",id:"how-does-key-delegation-work-in-ics",level:2},{value:"How does Partial Set Security work?",id:"how-does-partial-set-security-work",level:2},{value:"How does a validator know which consumers chains it has to validate?",id:"how-does-a-validator-know-which-consumers-chains-it-has-to-validate",level:2},{value:"How many chains can a validator opt in to?",id:"how-many-chains-can-a-validator-opt-in-to",level:2},{value:"Can validators assign a consensus keys while a consumer-addition proposal is in voting period?",id:"can-validators-assign-a-consensus-keys-while-a-consumer-addition-proposal-is-in-voting-period",level:2},{value:"Can validators assign a consensus key during the voting period for a consumer-addition proposal if they are not in the top N?",id:"can-validators-assign-a-consensus-key-during-the-voting-period-for-a-consumer-addition-proposal-if-they-are-not-in-the-top-n",level:2},{value:"Can validators opt in to an Opt-in or Top N chain after its consumer-addition proposal voting period is over but before the spawn time?",id:"can-validators-opt-in-to-an-opt-in-or-top-n-chain-after-its-consumer-addition-proposal-voting-period-is-over-but-before-the-spawn-time",level:2},{value:"Can validators opt in to an Opt-in chain after the spawn time if nobody else opted in?",id:"can-validators-opt-in-to-an-opt-in-chain-after-the-spawn-time-if-nobody-else-opted-in",level:2},{value:"Can all validators opt out of an Opt-in chain?",id:"can-all-validators-opt-out-of-an-opt-in-chain",level:2},{value:"Can validators set a commission rate for chains they have not opted in to?",id:"can-validators-set-a-commission-rate-for-chains-they-have-not-opted-in-to",level:2},{value:"Can a consumer chain modify its power shaping parameters?",id:"can-a-consumer-chain-modify-its-power-shaping-parameters",level:2},{value:"Can a Top N consumer chain become Opt-In or vice versa?",id:"can-a-top-n-consumer-chain-become-opt-in-or-vice-versa",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"what-is-a-consumer-chain",children:"What is a consumer chain?"}),"\n",(0,a.jsx)(n.p,{children:"Consumer chain is a blockchain operated by (a subset of) the validators of the provider chain. The ICS protocol ensures that the consumer chain gets information about which validators should run it (informs consumer chain about the current state of the validator set and the opted in validators for this consumer chain on the provider)."}),"\n",(0,a.jsx)(n.p,{children:"Consumer chains are run on infrastructure (virtual or physical machines) distinct from the provider, have their own configurations and operating requirements."}),"\n",(0,a.jsx)(n.h2,{id:"what-happens-to-consumer-if-provider-is-down",children:"What happens to consumer if provider is down?"}),"\n",(0,a.jsx)(n.p,{children:"In case the provider chain halts or experiences difficulties the consumer chain will keep operating - the provider chain and consumer chains represent different networks, which only share the validator set."}),"\n",(0,a.jsx)(n.p,{children:"The consumer chain will not halt if the provider halts because they represent distinct networks and distinct infrastructures. Provider chain liveness does not impact consumer chain liveness."}),"\n",(0,a.jsxs)(n.p,{children:["However, if the ",(0,a.jsx)(n.code,{children:"trusting_period"})," (currently 5 days for protocol safety reasons) elapses without receiving any updates from the provider, the consumer chain will essentially transition to a Proof of Authority chain.\nThis means that the validator set on the consumer will be the last validator set of the provider that the consumer knows about."]}),"\n",(0,a.jsx)(n.p,{children:'Steps to recover from this scenario and steps to "release" the validators from their duties will be specified at a later point.\nAt the very least, the consumer chain could replace the validator set, remove the ICS module and perform a genesis restart. The impact of this on the IBC clients and connections is currently under careful consideration.'}),"\n",(0,a.jsx)(n.h2,{id:"what-happens-to-provider-if-consumer-is-down",children:"What happens to provider if consumer is down?"}),"\n",(0,a.jsx)(n.p,{children:"Consumer chains do not impact the provider chain.\nThe ICS protocol is concerned only with validator set management, and the only communication that the provider requires from the consumer is information about validator activity (essentially keeping the provider informed about slash events)."}),"\n",(0,a.jsx)(n.h2,{id:"can-i-run-the-provider-and-consumer-chains-on-the-same-machine",children:"Can I run the provider and consumer chains on the same machine?"}),"\n",(0,a.jsx)(n.p,{children:"Yes, but you should favor running them in separate environments so failure of one machine does not impact your whole operation."}),"\n",(0,a.jsx)(n.h2,{id:"can-the-consumer-chain-have-its-own-token",children:"Can the consumer chain have its own token?"}),"\n",(0,a.jsx)(n.p,{children:"As any other cosmos-sdk chain the consumer chain can issue its own token, manage inflation parameters and use them to pay gas fees."}),"\n",(0,a.jsx)(n.h2,{id:"how-are-tx-fees-paid-on-consumer",children:"How are Tx fees paid on consumer?"}),"\n",(0,a.jsx)(n.p,{children:"The consumer chain operates as any other cosmos-sdk chain. The ICS protocol does not impact the normal chain operations."}),"\n",(0,a.jsx)(n.h2,{id:"are-there-any-restrictions-the-consumer-chains-need-to-abide-by",children:"Are there any restrictions the consumer chains need to abide by?"}),"\n",(0,a.jsx)(n.p,{children:"No. Consumer chains are free to choose how they wish to operate, which modules to include, use CosmWASM in a permissioned or a permissionless way.\nThe only thing that separates consumer chains from standalone chains is that they share their validator set with the provider chain."}),"\n",(0,a.jsx)(n.h2,{id:"whats-in-it-for-the-validators-and-stakers",children:"What's in it for the validators and stakers?"}),"\n",(0,a.jsxs)(n.p,{children:["The consumer chains sends a portion of its fees and inflation as reward to the provider chain as defined by ",(0,a.jsx)(n.code,{children:"ConsumerRedistributionFraction"}),". The rewards are distributed (sent to the provider) every ",(0,a.jsx)(n.code,{children:"BlocksPerDistributionTransmission"}),"."]}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"ConsumerRedistributionFraction"})," and ",(0,a.jsx)(n.code,{children:"BlocksPerDistributionTransmission"})," are parameters defined in the ",(0,a.jsx)(n.code,{children:"ConsumerAdditionProposal"})," used to create the consumer chain. These parameters can be changed via consumer chain governance."]})}),"\n",(0,a.jsx)(n.h2,{id:"can-the-consumer-chain-have-its-own-governance",children:"Can the consumer chain have its own governance?"}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Yes."})}),"\n",(0,a.jsx)(n.p,{children:'In that case the validators are not necessarily part of the governance structure. Instead, their place in governance is replaced by "representatives" (governors). The representatives do not need to run validators, they simply represent the interests of a particular interest group on the consumer chain.'}),"\n",(0,a.jsx)(n.p,{children:"Validators can also be representatives but representatives are not required to run validator nodes."}),"\n",(0,a.jsx)(n.p,{children:"This feature discerns between validator operators (infrastructure) and governance representatives which further democratizes the ecosystem. This also reduces the pressure on validators to be involved in on-chain governance."}),"\n",(0,a.jsx)(n.h2,{id:"can-validators-opt-out-of-validating-a-consumer-chain",children:"Can validators opt out of validating a consumer chain?"}),"\n",(0,a.jsx)(n.p,{children:"A validator can always opt out from an Opt-In consumer chain.\nA validator can only opt out from a Top N chain if the validator does not belong to the top N% validators."}),"\n",(0,a.jsx)(n.h2,{id:"how-does-slashing-work",children:"How does Slashing work?"}),"\n",(0,a.jsxs)(n.p,{children:["Validators that perform an equivocation or a light-client attack on a consumer chain are slashed on the provider chain.\nWe achieve this by submitting the proof of the equivocation or the light-client attack to the provider chain (see ",(0,a.jsx)(n.a,{href:"/interchain-security/features/slashing",children:"slashing"}),")."]}),"\n",(0,a.jsx)(n.h2,{id:"can-consumer-chains-perform-software-upgrades",children:"Can Consumer Chains perform Software Upgrades?"}),"\n",(0,a.jsx)(n.p,{children:"Consumer chains are standalone chains, in the sense that they can run arbitrary logic and use any modules they want (ie CosmWASM)."}),"\n",(0,a.jsx)(n.p,{children:"Consumer chain upgrades are unlikely to impact the provider chain, as long as there are no changes to the ICS module."}),"\n",(0,a.jsx)(n.h2,{id:"how-can-i-connect-to-the-testnets",children:"How can I connect to the testnets?"}),"\n",(0,a.jsxs)(n.p,{children:["Check out the ",(0,a.jsx)(n.a,{href:"/interchain-security/validators/joining-testnet",children:"Joining Interchain Security testnet"})," section."]}),"\n",(0,a.jsx)(n.h2,{id:"how-do-i-start-using-ics",children:"How do I start using ICS?"}),"\n",(0,a.jsxs)(n.p,{children:["To become a consumer chain use this ",(0,a.jsx)(n.a,{href:"/interchain-security/consumer-development/onboarding",children:"checklist"})," and check the ",(0,a.jsx)(n.a,{href:"/interchain-security/consumer-development/app-integration",children:"App integration section"})]}),"\n",(0,a.jsx)(n.h2,{id:"which-relayers-are-supported",children:"Which relayers are supported?"}),"\n",(0,a.jsx)(n.p,{children:"Currently supported versions:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"Hermes 1.8.0"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"how-does-key-delegation-work-in-ics",children:"How does key delegation work in ICS?"}),"\n",(0,a.jsxs)(n.p,{children:["You can check the ",(0,a.jsx)(n.a,{href:"/interchain-security/features/key-assignment",children:"Key Assignment Guide"})," for specific instructions."]}),"\n",(0,a.jsx)(n.h2,{id:"how-does-partial-set-security-work",children:"How does Partial Set Security work?"}),"\n",(0,a.jsx)(n.p,{children:"Partial Set Security allows a provider chain to share only a subset of its validator set with a consumer chain. This subset can be determined by the top N% validators by voting power, or by validators opting in to validate the consumer chain. Partial Set Security allows for flexible tradeoffs between security, decentralization, and the budget a consumer chain spends on rewards to validators."}),"\n",(0,a.jsxs)(n.p,{children:["See the ",(0,a.jsx)(n.a,{href:"/interchain-security/features/partial-set-security",children:"Partial Set Security"})," section for more information."]}),"\n",(0,a.jsx)(n.h2,{id:"how-does-a-validator-know-which-consumers-chains-it-has-to-validate",children:"How does a validator know which consumers chains it has to validate?"}),"\n",(0,a.jsxs)(n.p,{children:["In order for a validator to keep track of all the chains it has to validate, the validator can use the\n",(0,a.jsxs)(n.a,{href:"/interchain-security/validators/partial-set-security-for-validators#which-chains-does-a-validator-have-to-validate",children:[(0,a.jsx)(n.code,{children:"has-to-validate"})," query"]}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"how-many-chains-can-a-validator-opt-in-to",children:"How many chains can a validator opt in to?"}),"\n",(0,a.jsxs)(n.p,{children:["There is ",(0,a.jsx)(n.strong,{children:"no"})," limit in the number of consumers chains a validator can choose to opt in to."]}),"\n",(0,a.jsx)(n.h2,{id:"can-validators-assign-a-consensus-keys-while-a-consumer-addition-proposal-is-in-voting-period",children:"Can validators assign a consensus keys while a consumer-addition proposal is in voting period?"}),"\n",(0,a.jsxs)(n.p,{children:["Yes, see the ",(0,a.jsx)(n.a,{href:"/interchain-security/features/key-assignment",children:"Key Assignment Guide"})," for more information."]}),"\n",(0,a.jsx)(n.h2,{id:"can-validators-assign-a-consensus-key-during-the-voting-period-for-a-consumer-addition-proposal-if-they-are-not-in-the-top-n",children:"Can validators assign a consensus key during the voting period for a consumer-addition proposal if they are not in the top N?"}),"\n",(0,a.jsx)(n.p,{children:"Yes."}),"\n",(0,a.jsx)(n.h2,{id:"can-validators-opt-in-to-an-opt-in-or-top-n-chain-after-its-consumer-addition-proposal-voting-period-is-over-but-before-the-spawn-time",children:"Can validators opt in to an Opt-in or Top N chain after its consumer-addition proposal voting period is over but before the spawn time?"}),"\n",(0,a.jsx)(n.p,{children:"Yes."}),"\n",(0,a.jsx)(n.h2,{id:"can-validators-opt-in-to-an-opt-in-chain-after-the-spawn-time-if-nobody-else-opted-in",children:"Can validators opt in to an Opt-in chain after the spawn time if nobody else opted in?"}),"\n",(0,a.jsx)(n.p,{children:"No, the consumer chain will not be added if nobody opted in by the spawn time. At least one validator, regardless of its voting power, must opt in before the spawn time arrives in order for the chain can start."}),"\n",(0,a.jsx)(n.h2,{id:"can-all-validators-opt-out-of-an-opt-in-chain",children:"Can all validators opt out of an Opt-in chain?"}),"\n",(0,a.jsx)(n.p,{children:"Yes, the consumer chain will halt with an ERR CONSENSUS FAILURE error after the opt-out message for the last validator is received."}),"\n",(0,a.jsx)(n.h2,{id:"can-validators-set-a-commission-rate-for-chains-they-have-not-opted-in-to",children:"Can validators set a commission rate for chains they have not opted in to?"}),"\n",(0,a.jsx)(n.p,{children:"Yes, and this is useful for validators that are not in the top N% of the provider chain, but might move into the top N% in the future.\nBy setting the commission rate ahead of time, they can make sure that they immediately have a commission rate of their choosing as soon as they are in the top N%."}),"\n",(0,a.jsx)(n.h2,{id:"can-a-consumer-chain-modify-its-power-shaping-parameters",children:"Can a consumer chain modify its power shaping parameters?"}),"\n",(0,a.jsxs)(n.p,{children:["Yes, by issuing a ",(0,a.jsx)(n.a,{href:"/interchain-security/features/proposals#consumermodificationproposal",children:(0,a.jsx)(n.code,{children:"ConsumerModificationProposal"})}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"can-a-top-n-consumer-chain-become-opt-in-or-vice-versa",children:"Can a Top N consumer chain become Opt-In or vice versa?"}),"\n",(0,a.jsxs)(n.p,{children:["Yes, by issuing a ",(0,a.jsx)(n.a,{href:"/interchain-security/features/proposals#consumermodificationproposal",children:(0,a.jsx)(n.code,{children:"ConsumerModificationProposal"})}),"."]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>s});var a=i(7294);const t={},o=a.createContext(t);function s(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),a.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/06b45df8.830faa04.js b/assets/js/06b45df8.830faa04.js
new file mode 100644
index 0000000000..9668ae465a
--- /dev/null
+++ b/assets/js/06b45df8.830faa04.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9599],{4562:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v5.0.0","label":"v5.0.0","banner":"unreleased","badge":true,"noIndex":false,"className":"docs-version-v5.0.0","isLast":false,"docsSidebars":{"tutorialSidebar":[{"type":"link","label":"Interchain Security Docs","href":"/interchain-security/v5.0.0/","docId":"index","unlisted":false},{"type":"category","label":"Introduction","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Overview","href":"/interchain-security/v5.0.0/introduction/overview","docId":"introduction/overview","unlisted":false},{"type":"link","label":"Terminology","href":"/interchain-security/v5.0.0/introduction/terminology","docId":"introduction/terminology","unlisted":false},{"type":"link","label":"Interchain Security Parameters","href":"/interchain-security/v5.0.0/introduction/params","docId":"introduction/params","unlisted":false},{"type":"link","label":"Technical Specification","href":"/interchain-security/v5.0.0/introduction/technical-specification","docId":"introduction/technical-specification","unlisted":false}]},{"type":"category","label":"Upgrading","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Upgrading to ICS v5.0.0","href":"/interchain-security/v5.0.0/upgrading/migrate_v4_v5","docId":"upgrading/migrate_v4_v5","unlisted":false}]},{"type":"category","label":"Features","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Key Assignment","href":"/interchain-security/v5.0.0/features/key-assignment","docId":"features/key-assignment","unlisted":false},{"type":"link","label":"Reward Distribution","href":"/interchain-security/v5.0.0/features/reward-distribution","docId":"features/reward-distribution","unlisted":false},{"type":"link","label":"ICS Provider Proposals","href":"/interchain-security/v5.0.0/features/proposals","docId":"features/proposals","unlisted":false},{"type":"link","label":"Consumer Initiated Slashing","href":"/interchain-security/v5.0.0/features/slashing","docId":"features/slashing","unlisted":false}]},{"type":"category","label":"Consumer Guide","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Developing an ICS consumer chain","href":"/interchain-security/v5.0.0/consumer-development/app-integration","docId":"consumer-development/app-integration","unlisted":false},{"type":"link","label":"Consumer Chain Governance","href":"/interchain-security/v5.0.0/consumer-development/consumer-chain-governance","docId":"consumer-development/consumer-chain-governance","unlisted":false},{"type":"link","label":"Onboarding Checklist","href":"/interchain-security/v5.0.0/consumer-development/onboarding","docId":"consumer-development/onboarding","unlisted":false},{"type":"link","label":"Offboarding Checklist","href":"/interchain-security/v5.0.0/consumer-development/offboarding","docId":"consumer-development/offboarding","unlisted":false},{"type":"link","label":"Changeover Procedure","href":"/interchain-security/v5.0.0/consumer-development/changeover-procedure","docId":"consumer-development/changeover-procedure","unlisted":false},{"type":"link","label":"Consumer Genesis Transformation","href":"/interchain-security/v5.0.0/consumer-development/consumer-genesis-transformation","docId":"consumer-development/consumer-genesis-transformation","unlisted":false}]},{"type":"category","label":"Validators Guide","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Overview","href":"/interchain-security/v5.0.0/validators/overview","docId":"validators/overview","unlisted":false},{"type":"link","label":"Joining Interchain Security testnet","href":"/interchain-security/v5.0.0/validators/joining-testnet","docId":"validators/joining-testnet","unlisted":false},{"type":"link","label":"Withdrawing consumer chain validator rewards","href":"/interchain-security/v5.0.0/validators/withdraw_rewards","docId":"validators/withdraw_rewards","unlisted":false},{"type":"link","label":"Validator Instructions for Changeover Procedure","href":"/interchain-security/v5.0.0/validators/changeover-procedure","docId":"validators/changeover-procedure","unlisted":false},{"type":"link","label":"Joining Neutron","href":"/interchain-security/v5.0.0/validators/joining-neutron","docId":"validators/joining-neutron","unlisted":false},{"type":"link","label":"Joining Stride","href":"/interchain-security/v5.0.0/validators/joining-stride","docId":"validators/joining-stride","unlisted":false}]},{"type":"link","label":"Frequently Asked Questions","href":"/interchain-security/v5.0.0/faq","docId":"frequently-asked-questions","unlisted":false},{"type":"category","label":"ADRs","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ADRs","href":"/interchain-security/v5.0.0/adrs/intro","docId":"adrs/intro","unlisted":false},{"type":"link","label":"ADR Template","href":"/interchain-security/v5.0.0/adrs/adr-004-denom-dos-fixes","docId":"adrs/adr-004-denom-dos-fixes","unlisted":false},{"type":"link","label":"ADR Template","href":"/interchain-security/v5.0.0/adrs/adr-007-pause-unbonding-on-eqv-prop","docId":"adrs/adr-007-pause-unbonding-on-eqv-prop","unlisted":false},{"type":"link","label":"ADR Template","href":"/interchain-security/v5.0.0/adrs/adr-template","docId":"adrs/adr-template","unlisted":false},{"type":"link","label":"Key Assignment","href":"/interchain-security/v5.0.0/adrs/adr-001-key-assignment","docId":"adrs/adr-001-key-assignment","unlisted":false},{"type":"link","label":"Jail Throttling","href":"/interchain-security/v5.0.0/adrs/adr-002-throttle","docId":"adrs/adr-002-throttle","unlisted":false},{"type":"link","label":"Equivocation governance proposal","href":"/interchain-security/v5.0.0/adrs/adr-003-equivocation-gov-proposal","docId":"adrs/adr-003-equivocation-gov-proposal","unlisted":false},{"type":"link","label":"Cryptographic verification of equivocation evidence","href":"/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification","docId":"adrs/adr-005-cryptographic-equivocation-verification","unlisted":false},{"type":"link","label":"Throttle with retries","href":"/interchain-security/v5.0.0/adrs/adr-008-throttle-retries","docId":"adrs/adr-008-throttle-retries","unlisted":false},{"type":"link","label":"Soft Opt-Out","href":"/interchain-security/v5.0.0/adrs/adr-009-soft-opt-out","docId":"adrs/adr-009-soft-opt-out","unlisted":false},{"type":"link","label":"Standalone to Consumer Changeover","href":"/interchain-security/v5.0.0/adrs/adr-010-standalone-changeover","docId":"adrs/adr-010-standalone-changeover","unlisted":false},{"type":"link","label":"Improving testing and increasing confidence","href":"/interchain-security/v5.0.0/adrs/adr-011-improving-test-confidence","docId":"adrs/adr-011-improving-test-confidence","unlisted":false},{"type":"link","label":"Separate Releasing","href":"/interchain-security/v5.0.0/adrs/adr-012-separate-releasing","docId":"adrs/adr-012-separate-releasing","unlisted":false},{"type":"link","label":"Slashing on the provider for consumer equivocation","href":"/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing","docId":"adrs/adr-013-equivocation-slashing","unlisted":false},{"type":"link","label":"Epochs","href":"/interchain-security/v5.0.0/adrs/adr-014-epochs","docId":"adrs/adr-014-epochs","unlisted":false},{"type":"link","label":"Partial Set Security","href":"/interchain-security/v5.0.0/adrs/adr-015-partial-set-security","docId":"adrs/adr-015-partial-set-security","unlisted":false}]}]},"docs":{"adrs/adr-001-key-assignment":{"id":"adrs/adr-001-key-assignment","title":"Key Assignment","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-002-throttle":{"id":"adrs/adr-002-throttle","title":"Jail Throttling","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-003-equivocation-gov-proposal":{"id":"adrs/adr-003-equivocation-gov-proposal","title":"Equivocation governance proposal","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-004-denom-dos-fixes":{"id":"adrs/adr-004-denom-dos-fixes","title":"ADR Template","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-005-cryptographic-equivocation-verification":{"id":"adrs/adr-005-cryptographic-equivocation-verification","title":"Cryptographic verification of equivocation evidence","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-007-pause-unbonding-on-eqv-prop":{"id":"adrs/adr-007-pause-unbonding-on-eqv-prop","title":"ADR Template","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-008-throttle-retries":{"id":"adrs/adr-008-throttle-retries","title":"Throttle with retries","description":"ADR 008: Throttle with retries","sidebar":"tutorialSidebar"},"adrs/adr-009-soft-opt-out":{"id":"adrs/adr-009-soft-opt-out","title":"Soft Opt-Out","description":"ADR 009: Soft Opt-Out","sidebar":"tutorialSidebar"},"adrs/adr-010-standalone-changeover":{"id":"adrs/adr-010-standalone-changeover","title":"Standalone to Consumer Changeover","description":"ADR 010: Standalone to Consumer Changeover","sidebar":"tutorialSidebar"},"adrs/adr-011-improving-test-confidence":{"id":"adrs/adr-011-improving-test-confidence","title":"Improving testing and increasing confidence","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-012-separate-releasing":{"id":"adrs/adr-012-separate-releasing","title":"Separate Releasing","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-013-equivocation-slashing":{"id":"adrs/adr-013-equivocation-slashing","title":"Slashing on the provider for consumer equivocation","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-014-epochs":{"id":"adrs/adr-014-epochs","title":"Epochs","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-015-partial-set-security":{"id":"adrs/adr-015-partial-set-security","title":"Partial Set Security","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-template":{"id":"adrs/adr-template","title":"ADR Template","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/intro":{"id":"adrs/intro","title":"ADRs","description":"This is a location to record all high-level architecture decisions in the Interchain Security project.","sidebar":"tutorialSidebar"},"consumer-development/app-integration":{"id":"consumer-development/app-integration","title":"Developing an ICS consumer chain","description":"When developing an ICS consumer chain, besides just focusing on your chain\'s logic you should aim to allocate time to ensure that your chain is compatible with the ICS protocol.","sidebar":"tutorialSidebar"},"consumer-development/changeover-procedure":{"id":"consumer-development/changeover-procedure","title":"Changeover Procedure","description":"Chains that were not initially launched as consumers of replicated security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the changeover procedure and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain.","sidebar":"tutorialSidebar"},"consumer-development/consumer-chain-governance":{"id":"consumer-development/consumer-chain-governance","title":"Consumer Chain Governance","description":"Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We\'ll cover what these are in the \\"Whitelist\\" section below.","sidebar":"tutorialSidebar"},"consumer-development/consumer-genesis-transformation":{"id":"consumer-development/consumer-genesis-transformation","title":"Consumer Genesis Transformation","description":"Preparing a consumer chain for onboarding requires some information explaining how to run your chain. This includes a genesis file with CCV data where the CCV data is exported from the provider chain and added to the consumers genesis file (for more details check the documentation on Onboarding and Changeover).","sidebar":"tutorialSidebar"},"consumer-development/offboarding":{"id":"consumer-development/offboarding","title":"Offboarding Checklist","description":"To offboard a consumer chain simply submit a ConsumerRemovalProposal governance proposal listing a stop_time. After stop time passes, the provider chain will remove the chain from the ICS protocol (it will stop sending validator set updates).","sidebar":"tutorialSidebar"},"consumer-development/onboarding":{"id":"consumer-development/onboarding","title":"Onboarding Checklist","description":"The following checklists will aid in onboarding a new consumer chain to interchain security.","sidebar":"tutorialSidebar"},"features/key-assignment":{"id":"features/key-assignment","title":"Key Assignment","description":"Key Assignment (aka. as key delegation) allows validator operators to use different consensus keys for each consumer chain validator node that they operate.","sidebar":"tutorialSidebar"},"features/proposals":{"id":"features/proposals","title":"ICS Provider Proposals","description":"Interchain security module introduces 3 new proposal types to the provider.","sidebar":"tutorialSidebar"},"features/reward-distribution":{"id":"features/reward-distribution","title":"Reward Distribution","description":"Sending and distributing rewards from consumer chains to the provider chain is handled by the Reward Distribution sub-protocol.","sidebar":"tutorialSidebar"},"features/slashing":{"id":"features/slashing","title":"Consumer Initiated Slashing","description":"A consumer chain is essentially a regular Cosmos-SDK based chain that uses the Interchain Security module to achieve economic security by stake deposited on the provider chain, instead of its own chain.","sidebar":"tutorialSidebar"},"frequently-asked-questions":{"id":"frequently-asked-questions","title":"Frequently Asked Questions","description":"What is the meaning of Validator Set Replication?","sidebar":"tutorialSidebar"},"index":{"id":"index","title":"Interchain Security Docs","description":"Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains.","sidebar":"tutorialSidebar"},"introduction/overview":{"id":"introduction/overview","title":"Overview","description":"Replicated security (aka interchain security V1) is an open sourced IBC application which allows cosmos blockchains to lease their proof-of-stake security to one another.","sidebar":"tutorialSidebar"},"introduction/params":{"id":"introduction/params","title":"Interchain Security Parameters","description":"The parameters necessary for Interchain Security (ICS) are defined in","sidebar":"tutorialSidebar"},"introduction/technical-specification":{"id":"introduction/technical-specification","title":"Technical Specification","description":"For a technical deep dive into the replicated security protocol, see the specification.","sidebar":"tutorialSidebar"},"introduction/terminology":{"id":"introduction/terminology","title":"Terminology","description":"You may have heard of one or multiple buzzwords thrown around in the cosmos and wider crypto ecosystem such shared security, interchain security, replicated security, cross chain validation, and mesh security. These terms will be clarified below, before diving into any introductions.","sidebar":"tutorialSidebar"},"upgrading/migrate_v4_v5":{"id":"upgrading/migrate_v4_v5","title":"Upgrading to ICS v5.0.0","description":"This ICS version uses cosmos-sdk v0.50.x and ibc-go v8.x.","sidebar":"tutorialSidebar"},"validators/changeover-procedure":{"id":"validators/changeover-procedure","title":"Validator Instructions for Changeover Procedure","description":"More details available in Changeover Procedure documentation.","sidebar":"tutorialSidebar"},"validators/joining-neutron":{"id":"validators/joining-neutron","title":"Joining Neutron","description":"Neutron is the first consumer chain to implement ICS.","sidebar":"tutorialSidebar"},"validators/joining-stride":{"id":"validators/joining-stride","title":"Joining Stride","description":"Stride is the first consumer chain to perform the standalone to consumer changeover procedure and transition from a standalone validator set to using cosmoshub-4 validator set.","sidebar":"tutorialSidebar"},"validators/joining-testnet":{"id":"validators/joining-testnet","title":"Joining Interchain Security testnet","description":"Introduction","sidebar":"tutorialSidebar"},"validators/overview":{"id":"validators/overview","title":"Overview","description":"We advise that you join the Replicated Security testnet to gain hands-on experience with running consumer chains.","sidebar":"tutorialSidebar"},"validators/withdraw_rewards":{"id":"validators/withdraw_rewards","title":"Withdrawing consumer chain validator rewards","description":"Here are example steps for withdrawing rewards from consumer chains in the provider chain","sidebar":"tutorialSidebar"}}}')}}]);
\ No newline at end of file
diff --git a/assets/js/07d76e7d.195c3194.js b/assets/js/07d76e7d.195c3194.js
new file mode 100644
index 0000000000..cd279541ad
--- /dev/null
+++ b/assets/js/07d76e7d.195c3194.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2189],{7488:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>l,frontMatter:()=>a,metadata:()=>t,toc:()=>d});var i=s(5893),r=s(1151);const a={sidebar_position:1},o="Key Assignment",t={id:"features/key-assignment",title:"Key Assignment",description:"Key Assignment (aka. as key delegation) allows validator operators to use different consensus keys for each consumer chain validator node that they operate.",source:"@site/docs/features/key-assignment.md",sourceDirName:"features",slug:"/features/key-assignment",permalink:"/interchain-security/features/key-assignment",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Upgrading to ICS v5.0.0",permalink:"/interchain-security/upgrading/migrate_v4_v5"},next:{title:"Reward Distribution",permalink:"/interchain-security/features/reward-distribution"}},c={},d=[{value:"Rules",id:"rules",level:2},{value:"Adding a key",id:"adding-a-key",level:2},{value:"Changing a key",id:"changing-a-key",level:2},{value:"Removing a key",id:"removing-a-key",level:2},{value:"Querying proposed consumer chains",id:"querying-proposed-consumer-chains",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"key-assignment",children:"Key Assignment"}),"\n",(0,i.jsx)(n.p,{children:"Key Assignment (aka. as key delegation) allows validator operators to use different consensus keys for each consumer chain validator node that they operate.\nThere are various reasons to use different consensus keys on different chains, but the main benefit is that validator's provider chain consensus key cannot be compromised if their consumer chain node (or other infrastructure) gets compromised. Interchain security module adds queries and transactions for assigning keys on consumer chains."}),"\n",(0,i.jsxs)(n.p,{children:["The feature is outlined in this ",(0,i.jsx)(n.a,{href:"/interchain-security/adrs/adr-001-key-assignment",children:"ADR-001"})]}),"\n",(0,i.jsxs)(n.p,{children:["By sending an ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," transaction, validators are able to indicate which consensus key they will be using to validate a consumer chain. On receiving the transaction, if the key assignment is valid, the provider will use the assigned consensus key when it sends future voting power updates to the consumer that involve the validator."]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"Key assignment is handled only by the provider chain - the consumer chains are not aware of the fact that different consensus keys represent the same validator entity."})}),"\n",(0,i.jsx)(n.h2,{id:"rules",children:"Rules"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"a key can be assigned as soon as the consumer addition proposal is submitted to the provider"}),"\n",(0,i.jsx)(n.li,{children:"validator A cannot assign consumer key K to consumer chain X if there is already a validator B (B!=A) using K on the provider"}),"\n",(0,i.jsx)(n.li,{children:"validator A cannot assign consumer key K to consumer chain X if there is already a validator B using K on X"}),"\n",(0,i.jsx)(n.li,{children:"a new validator on the provider cannot use a consensus key K if K is already used by any validator on any consumer chain"}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"Validators can use a different key for each consumer chain."})}),"\n",(0,i.jsx)(n.h2,{id:"adding-a-key",children:"Adding a key"}),"\n",(0,i.jsx)(n.p,{children:"First, create a new node on the consumer chain using the equivalent:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"consumerd init \n"})}),"\n",(0,i.jsx)(n.p,{children:"Then query your node for the consensus key."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'consumerd tendermint show-validator # {"@type":"/cosmos.crypto.ed25519.PubKey","key":""}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Then, make an ",(0,i.jsx)(n.code,{children:"assign-consensus-key"})," transaction on the provider chain in order to inform the provider chain about the consensus key you will be using for a specific consumer chain."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad tx provider assign-consensus-key '' --from --home --gas 900000 -b sync -y -o json\n"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"consumer-chain-id"})," is the string identifier of the consumer chain, as assigned on the provider chain"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"consumer-pub-key"})," has the following format ",(0,i.jsx)(n.code,{children:'{"@type":"/cosmos.crypto.ed25519.PubKey","key":""}'})]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Check that the key was assigned correctly by querying the provider:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider validator-consumer-key cosmosvalcons1e....3xsj3ayzf4uv6\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You must use a ",(0,i.jsx)(n.code,{children:"valcons"})," address. You can obtain it by querying your node on the provider ",(0,i.jsx)(n.code,{children:"gaiad tendermint show-address"})]}),"\n",(0,i.jsx)(n.p,{children:"OR"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider validator-provider-key consumervalcons1e....123asdnoaisdao\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You must use a ",(0,i.jsx)(n.code,{children:"valcons"})," address. You can obtain it by querying your node on the consumer ",(0,i.jsx)(n.code,{children:"consumerd tendermint show-address"})]}),"\n",(0,i.jsx)(n.p,{children:"OR"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider all-pairs-valconsensus-address \n"})}),"\n",(0,i.jsxs)(n.p,{children:["You just need to use the ",(0,i.jsx)(n.code,{children:"chainId"})," of consumer to query all pairs valconsensus address with ",(0,i.jsx)(n.code,{children:"consumer-pub-key"})," for each of pair"]}),"\n",(0,i.jsx)(n.h2,{id:"changing-a-key",children:"Changing a key"}),"\n",(0,i.jsx)(n.p,{children:"To change your key, simply repeat all of the steps listed above. Take note that your old key will be remembered for at least the unbonding period of the consumer chain so any slashes can be correctly applied"}),"\n",(0,i.jsx)(n.h2,{id:"removing-a-key",children:"Removing a key"}),"\n",(0,i.jsxs)(n.p,{children:["To remove a key, simply switch it back to the consensus key you have assigned on the provider chain by following steps in the ",(0,i.jsx)(n.code,{children:"Adding a key"})," section and using your provider consensus key."]}),"\n",(0,i.jsx)(n.admonition,{type:"warning",children:(0,i.jsxs)(n.p,{children:["Validators are strongly recommended to assign a separate key for each consumer chain\nand ",(0,i.jsx)(n.strong,{children:"not"})," reuse the provider key across consumer chains for security reasons."]})}),"\n",(0,i.jsx)(n.h2,{id:"querying-proposed-consumer-chains",children:"Querying proposed consumer chains"}),"\n",(0,i.jsx)(n.p,{children:"To query the consumer addition proposals that are in the voting period, you can use the following command on the provider:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider list-proposed-consumer-chains\n"})}),"\n",(0,i.jsx)(n.p,{children:"This query is valuable for staying informed about when keys can be assigned to newly proposed consumer chains."})]})}function l(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>t,a:()=>o});var i=s(7294);const r={},a=i.createContext(r);function o(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/0cb1d302.fabe1b41.js b/assets/js/0cb1d302.fabe1b41.js
new file mode 100644
index 0000000000..47f1f97aa6
--- /dev/null
+++ b/assets/js/0cb1d302.fabe1b41.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1085],{5398:(n,e,t)=>{t.r(e),t.d(e,{assets:()=>a,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>c,toc:()=>u});var i=t(5893),r=t(1151);const o={sidebar_position:5},s="Joining Neutron",c={id:"validators/joining-neutron",title:"Joining Neutron",description:"Neutron is the first consumer chain to implement ICS.",source:"@site/docs/validators/joining-neutron.md",sourceDirName:"validators",slug:"/validators/joining-neutron",permalink:"/interchain-security/validators/joining-neutron",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"tutorialSidebar",previous:{title:"Validator Instructions for Changeover Procedure",permalink:"/interchain-security/validators/changeover-procedure"},next:{title:"Joining Stride",permalink:"/interchain-security/validators/joining-stride"}},a={},u=[{value:"Resources",id:"resources",level:2}];function l(n){const e={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.a)(),...n.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"joining-neutron",children:"Joining Neutron"}),"\n",(0,i.jsx)(e.p,{children:"Neutron is the first consumer chain to implement ICS."}),"\n",(0,i.jsxs)(e.p,{children:["You can find instructions on joining the mainnet ",(0,i.jsx)(e.a,{href:"https://docs.neutron.org/neutron/consumer-chain-launch",children:"here"}),"."]}),"\n",(0,i.jsxs)(e.p,{children:["To join Neutron chain on the interchain security testnet check ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security/pion-1",children:"here"})]}),"\n",(0,i.jsx)(e.h2,{id:"resources",children:"Resources"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://docs.neutron.org",children:"Neutron docs"})}),"\n"]})]})}function d(n={}){const{wrapper:e}={...(0,r.a)(),...n.components};return e?(0,i.jsx)(e,{...n,children:(0,i.jsx)(l,{...n})}):l(n)}},1151:(n,e,t)=>{t.d(e,{Z:()=>c,a:()=>s});var i=t(7294);const r={},o=i.createContext(r);function s(n){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function c(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(r):n.components||r:s(n.components),i.createElement(o.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/1097399d.6cf69a51.js b/assets/js/1097399d.6cf69a51.js
new file mode 100644
index 0000000000..00449f906e
--- /dev/null
+++ b/assets/js/1097399d.6cf69a51.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6548],{5191:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>d,toc:()=>c});var i=t(5893),s=t(1151);const r={sidebar_position:12,title:"Improving testing and increasing confidence"},o="ADR 011: Improving testing and increasing confidence",d={id:"adrs/adr-011-improving-test-confidence",title:"Improving testing and increasing confidence",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-011-improving-test-confidence.md",sourceDirName:"adrs",slug:"/adrs/adr-011-improving-test-confidence",permalink:"/interchain-security/v5.0.0/adrs/adr-011-improving-test-confidence",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:12,frontMatter:{sidebar_position:12,title:"Improving testing and increasing confidence"},sidebar:"tutorialSidebar",previous:{title:"Standalone to Consumer Changeover",permalink:"/interchain-security/v5.0.0/adrs/adr-010-standalone-changeover"},next:{title:"Separate Releasing",permalink:"/interchain-security/v5.0.0/adrs/adr-012-separate-releasing"}},a={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Current state of testing",id:"current-state-of-testing",level:4},{value:"Unit testing",id:"unit-testing",level:3},{value:"Integration testing",id:"integration-testing",level:3},{value:"End-to-end testing",id:"end-to-end-testing",level:3},{value:"Decision",id:"decision",level:2},{value:"1. Connect specifications to code and tooling",id:"1-connect-specifications-to-code-and-tooling",level:3},{value:"Decision context and hypothesis",id:"decision-context-and-hypothesis",level:4},{value:"Main benefit",id:"main-benefit",level:4},{value:"2. Improve e2e tooling",id:"2-improve-e2e-tooling",level:3},{value:"Matrix tests",id:"matrix-tests",level:4},{value:"Introducing e2e regression testing",id:"introducing-e2e-regression-testing",level:4},{value:"Introducing e2e CometMock tests",id:"introducing-e2e-cometmock-tests",level:4},{value:"3. Introduce innovative testing approaches",id:"3-introduce-innovative-testing-approaches",level:3},{value:"Model",id:"model",level:4},{value:"Driver",id:"driver",level:4},{value:"Harness",id:"harness",level:4},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-011-improving-testing-and-increasing-confidence",children:"ADR 011: Improving testing and increasing confidence"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2023-08-11: Proposed, first draft of ADR."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Proposed"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.p,{children:"Testing, QA, and maintenance of interchain-security libraries is an ever-evolving area of software engineering we have to keep incrementally improving. The purpose of the QA process is to catch bugs as early as possible. In an ideal development workflow a bug should never reach production. A bug found in the specification stage is a lot cheaper to resolve than a bug discovered in production (or even in testnet). Ideally, all bugs should be found during the CI execution, and we hope that no bugs will ever even reach the testnet (although nothing can replace actual system stress test under load interacting with users)."}),"\n",(0,i.jsx)(n.p,{children:"During development and testnet operation the following types of bugs were the most commonly found:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"improper iterator usage"}),"\n",(0,i.jsx)(n.li,{children:"unbounded array access/iteration"}),"\n",(0,i.jsx)(n.li,{children:"improper input handling and validation"}),"\n",(0,i.jsx)(n.li,{children:"improper cached context usage"}),"\n",(0,i.jsx)(n.li,{children:"non-determinism check (improper use of maps in go, relying on random values)"}),"\n",(0,i.jsx)(n.li,{children:"KV store management and/or how keys are defined"}),"\n",(0,i.jsx)(n.li,{children:"deserialization issues arising from consumer/provider versioning mismatch"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Such bugs can be discovered earlier with better tooling. Some of these bugs can induce increases in block times, chain halts, state corruption, or introduce an attack surface which is difficult to remove if other systems have started depending on that behavior."}),"\n",(0,i.jsx)(n.h4,{id:"current-state-of-testing",children:"Current state of testing"}),"\n",(0,i.jsx)(n.p,{children:"Our testing suites consist of multiple parts, each with their own trade-offs and benefits with regards to code coverage, complexity and confidence they provide."}),"\n",(0,i.jsx)(n.h3,{id:"unit-testing",children:"Unit testing"}),"\n",(0,i.jsxs)(n.p,{children:["Unit testing is employed mostly for testing single-module functionality. It is the first step in testing and often the most practical. While highly important, unit tests often ",(0,i.jsx)(n.strong,{children:"test a single piece of code"})," and don't test relationships between different moving parts, this makes them less valuable when dealing with multi-module interactions."]}),"\n",(0,i.jsx)(n.p,{children:"Unit tests often employ mocks to abstract parts of the system that are not under test. Mocks are not equivalent to actual models and should not be treated as such."}),"\n",(0,i.jsx)(n.p,{children:"Out of all the approaches used, unit testing has the most tools available and the coverage can simply be displayed as % of code lines tested. Although this is a very nice and very easy to understand metric, it does not speak about the quality of the test coverage."}),"\n",(0,i.jsx)(n.p,{children:"Since distributed systems testing is a lot more involved, unit tests are oftentimes not sufficient to cover complex interactions. Unit tests are still necessary and helpful, but in cases where unit tests are not helpful e2e or integration tests should be favored."}),"\n",(0,i.jsx)(n.h3,{id:"integration-testing",children:"Integration testing"}),"\n",(0,i.jsxs)(n.p,{children:["With integration testing we ",(0,i.jsx)(n.strong,{children:"test the multi-module interactions"})," while isolating them from the remainder of the system.\nIntegration tests can uncover bugs that are often missed by unit tests."]}),"\n",(0,i.jsxs)(n.p,{children:["It is very difficult to gauge the actual test coverage imparted by integration tests and the available tooling is limited.\nIn interchain-security we employ the ",(0,i.jsx)(n.code,{children:"ibc-go/testing"})," framework to test interactions in-memory."]}),"\n",(0,i.jsx)(n.p,{children:"At present, integration testing does not involve the consensus layer - it is only concerned with application level state and logic."}),"\n",(0,i.jsx)(n.h3,{id:"end-to-end-testing",children:"End-to-end testing"}),"\n",(0,i.jsx)(n.p,{children:"In our context end-to-end testing comprises of tests that use the actual application binaries in an isolated environment (e.g. docker container). During test execution the inputs are meant to simulate actual user interaction, either by submitting transactions/queries using the command line or using gRPC/REST APIs and checking for state changes after an action has been performed. With this testing strategy we also include the consensus layer in all of our runs. This is the closest we can get to testing user interactions without starting a full testnet."}),"\n",(0,i.jsx)(n.p,{children:"End-to-end testing strategies vary between different teams and projects and we strive to unify our approach to the best of our ability (at least for ICS and gaia)."}),"\n",(0,i.jsx)(n.p,{children:"The available tooling does not give us significant (or relevant) line of code coverage information since most of the tools are geared towards analyzing unit tests and simple code branch evaluation."}),"\n",(0,i.jsx)(n.p,{children:"We aim to adapt our best practices by learning from other similar systems and projects such as cosmos-sdk, ibc-go and CometBFT."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.h3,{id:"1-connect-specifications-to-code-and-tooling",children:"1. Connect specifications to code and tooling"}),"\n",(0,i.jsx)(n.p,{children:"Oftentimes, specifications are disconnected from the development and QA processes. This gives rise to problems where the specification does not reflect the actual state of the system and vice-versa.\nUsually specifications are just text files that are rarely used and go unmaintained after a while, resulting in consistency issues and misleading instructions/expectations about system behavior."}),"\n",(0,i.jsx)(n.h4,{id:"decision-context-and-hypothesis",children:"Decision context and hypothesis"}),"\n",(0,i.jsx)(n.p,{children:"Specifications written in a dedicated and executable specification language are easier to maintain than the ones written entirely in text.\nAdditionally, we can create models based on the specification OR make the model equivalent to a specification."}),"\n",(0,i.jsxs)(n.p,{children:["Models do not care about the intricacies of implementation and neither do specifications. Since both models and specifications care about concisely and accurately describing a system (such as a finite state machine), we see a benefit of adding model based tools (such as ",(0,i.jsx)(n.a,{href:"https://github.com/informalsystems/quint",children:"quint"}),") to our testing and development workflows."]}),"\n",(0,i.jsx)(n.h4,{id:"main-benefit",children:"Main benefit"}),"\n",(0,i.jsx)(n.p,{children:"MBT tooling can be used to generate test traces that can be executed by multiple different testing setups."}),"\n",(0,i.jsx)(n.h3,{id:"2-improve-e2e-tooling",children:"2. Improve e2e tooling"}),"\n",(0,i.jsx)(n.h4,{id:"matrix-tests",children:"Matrix tests"}),"\n",(0,i.jsxs)(n.p,{children:["Instead of only running tests against current ",(0,i.jsx)(n.code,{children:"main"})," branch we should adopt an approach where we also:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"run regression tests against different released software versions"})," (",(0,i.jsx)(n.code,{children:"ICS v1 vs v2 vs v3"}),")"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.strong,{children:"run non-determinism tests to uncover issues quickly"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Matrix tests can be implemented using ",(0,i.jsx)(n.a,{href:"https://github.com/informalsystems/CometMock",children:"CometMock"})," and refactoring our current e2e CI setup."]}),"\n",(0,i.jsx)(n.h4,{id:"introducing-e2e-regression-testing",children:"Introducing e2e regression testing"}),"\n",(0,i.jsx)(n.p,{children:"This e2e test suite would execute using a cronjob in our CI (nightly, multiple times a day etc.)"}),"\n",(0,i.jsxs)(n.p,{children:["Briefly, the same set of traces is run against different ",(0,i.jsx)(n.strong,{children:"maintained"})," versions of the software and the ",(0,i.jsx)(n.code,{children:"main"})," branch.\nThis would allow us to discover potential issues during development instead of in a testnet scenarios."]}),"\n",(0,i.jsxs)(n.p,{children:["The most valuable issues that can be discovered in this way are ",(0,i.jsx)(n.strong,{children:"state breaking changes"}),", ",(0,i.jsx)(n.strong,{children:"regressions"})," and ",(0,i.jsx)(n.strong,{children:"version incompatibilities"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The setup is illustrated by the image below.\n",(0,i.jsx)(n.img,{alt:"e2e matrix tests",src:t(4023).Z+"",width:"2170",height:"1624"})]}),"\n",(0,i.jsx)(n.p,{children:"This table explains which versions are tested against each other for the same set of test traces:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\u2705 marks a passing test"}),"\n",(0,i.jsx)(n.li,{children:"\u274c marks a failing test"}),"\n"]}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"USES: ICS v1 PROVIDER"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"start chain"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"add key"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"delegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"undelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"redelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"downtime"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"equivocation"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"stop chain"})})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v1 consumer (sdk45,ibc4.3)"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v2 consumer (sdk45, ibc4.4)"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v3 consumer (sdk47, ibc7)"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"main consumer"})}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"neutron"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"stride"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"})]})]})]}),"\n",(0,i.jsx)(n.h4,{id:"introducing-e2e-cometmock-tests",children:"Introducing e2e CometMock tests"}),"\n",(0,i.jsxs)(n.p,{children:["CometMock is a mock implementation of the ",(0,i.jsx)(n.a,{href:"https://github.com/cometbft/cometbft",children:"CometBFT"})," consensus engine. It supports most operations performed by CometBFT while also being lightweight and relatively easy to use."]}),"\n",(0,i.jsxs)(n.p,{children:['CometMock tests allow more nuanced control of test scenarios because CometMock can "fool" the blockchain app into thinking that a certain number of blocks had passed.\n',(0,i.jsx)(n.strong,{children:"This allows us to test very nuanced scenarios, difficult edge cases and long-running operations (such as unbonding operations)."})]}),"\n",(0,i.jsx)(n.p,{children:"Examples of tests made easier with CometMock are listed below:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"regression tests"}),"\n",(0,i.jsx)(n.li,{children:"non-determinism tests"}),"\n",(0,i.jsx)(n.li,{children:"upgrade tests"}),"\n",(0,i.jsx)(n.li,{children:"state-breaking changes"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["With CometMock, the ",(0,i.jsx)(n.strong,{children:"matrix test"})," approach can also be used. The image below illustrates a CometMock setup that can be used to discover non-deterministic behavior and state-breaking changes.\n",(0,i.jsx)(n.img,{alt:"e2e matrix tests",src:t(3146).Z+"",width:"3714",height:"2082"})]}),"\n",(0,i.jsx)(n.p,{children:"This table explains which versions are tested against each other for the same set of test traces:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\u2705 marks a passing test"}),"\n",(0,i.jsx)(n.li,{children:"\u274c marks a failing test"}),"\n"]}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"SCENARIO"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"start chain"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"add key"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"delegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"undelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"redelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"downtime"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"equivocation"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"stop chain"})})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v3 provi + v3 consu"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"main provi + main consu"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"commit provi + commit consu"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"})]})]})]}),"\n",(0,i.jsxs)(n.p,{children:["Briefly; multiple versions of the application are run against the same CometMock instance and any deviations in app behavior would result in ",(0,i.jsx)(n.code,{children:"app hash"})," errors (the apps would be in different states after performing the same set of actions)."]}),"\n",(0,i.jsx)(n.h3,{id:"3-introduce-innovative-testing-approaches",children:"3. Introduce innovative testing approaches"}),"\n",(0,i.jsx)(n.p,{children:"When discussing e2e testing, some very important patterns emerge - especially if test traces are used instead of ad-hoc tests written by hand."}),"\n",(0,i.jsx)(n.p,{children:"We see a unique opportunity to clearly identify concerns and modularize the testing architecture."}),"\n",(0,i.jsxs)(n.p,{children:["The e2e testing frameworks can be split into a ",(0,i.jsx)(n.strong,{children:"pipeline consisting of 3 parts: model, driver and harness"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"model",children:"Model"}),"\n",(0,i.jsx)(n.p,{children:"Model is the part of the system that can emulate the behavior of the system under test.\nIdeally, it is very close to the specification and is written in a specification language such as quint, TLA+ or similar.\nOne of the purposes of the model is that it can be used to generate test traces."}),"\n",(0,i.jsx)(n.h4,{id:"driver",children:"Driver"}),"\n",(0,i.jsx)(n.p,{children:"The purpose of the driver is to accept test traces (generated by the model or written by hand), process them and provide inputs to the next part of the pipeline."}),"\n",(0,i.jsx)(n.p,{children:"Basically, the driver sits between the model and the actual infrastructure on which the test traces are being executed on."}),"\n",(0,i.jsx)(n.h4,{id:"harness",children:"Harness"}),"\n",(0,i.jsx)(n.p,{children:"Harness is the infrastructure layer of the pipeline that accepts inputs from the driver."}),"\n",(0,i.jsx)(n.p,{children:"There can be multiple harnesses as long as they can perform four things:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"bootstrap a test execution environment (local, docker, k8s\u2026)"}),"\n",(0,i.jsx)(n.li,{children:"accept inputs from drivers"}),"\n",(0,i.jsx)(n.li,{children:"perform the action specified by the driver"}),"\n",(0,i.jsx)(n.li,{children:"report results after performing actions"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.p,{children:"The procedure outlined in this ADR is not an all-or-nothing approach. Concepts introduced here do not rely on each other, so this ADR may only be applied partially without negative impact on test coverage and code confidence."}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"introduction of maintainable MBT solutions"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:'improvement over the current "difftest" setup that relies on an opinionated typescript model and go driver'}),"\n"]}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsx)(n.li,{children:"increased code coverage and confidence"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"using CometMock allows us to run more tests in less time"}),"\n",(0,i.jsx)(n.li,{children:"adding matrix e2e tests allows us to quickly pinpoint differences between code versions"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsx)(n.p,{children:"It might be easier to forgo the MBT tooling and instead focus on pure property based testing"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/667",children:"PBT proof of concept"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/flyingmutant/rapid",children:"property based testing in go"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:'The solutions are potentially expensive if we increase usage of the CI pipeline - this is fixed by running "expensive" tests using a cronjob, instead of running them on every commit.'}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsx)(n.p,{children:"The process of changing development and testing process is not something that can be thought of and delivered quickly. Luckily, the changes can be rolled out incrementally without impacting existing workflows."}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/gaia/issues/2427",children:"https://github.com/cosmos/gaia/issues/2427"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/gaia/issues/2420",children:"https://github.com/cosmos/gaia/issues/2420"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc-go/tree/main/e2e",children:"ibc-go e2e tests"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},3146:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/cometmock_matrix_test-714f36252aff9df4214823e3145d0ef5.png"},4023:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/matrix_e2e_tests-30681305077301daaf3097e1952b54bb.png"},1151:(e,n,t)=>{t.d(n,{Z:()=>d,a:()=>o});var i=t(7294);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/16d4e57d.c5b611b1.js b/assets/js/16d4e57d.c5b611b1.js
new file mode 100644
index 0000000000..77ee6995a4
--- /dev/null
+++ b/assets/js/16d4e57d.c5b611b1.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5387],{1258:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>l});var n=t(5893),r=t(1151);const o={sidebar_position:2},a="Terminology",s={id:"introduction/terminology",title:"Terminology",description:"You may have heard of one or multiple buzzwords thrown around in the cosmos and wider crypto ecosystem such shared security, interchain security, replicated security, cross chain validation, and mesh security. These terms will be clarified below, before diving into any introductions.",source:"@site/versioned_docs/version-v5.0.0/introduction/terminology.md",sourceDirName:"introduction",slug:"/introduction/terminology",permalink:"/interchain-security/v5.0.0/introduction/terminology",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Overview",permalink:"/interchain-security/v5.0.0/introduction/overview"},next:{title:"Interchain Security Parameters",permalink:"/interchain-security/v5.0.0/introduction/params"}},c={},l=[{value:"Shared Security",id:"shared-security",level:2},{value:"Interchain Security",id:"interchain-security",level:2},{value:"Replicated Security",id:"replicated-security",level:2},{value:"Mesh security",id:"mesh-security",level:2},{value:"Consumer Chain",id:"consumer-chain",level:2},{value:"Standalone Chain",id:"standalone-chain",level:2},{value:"Changeover Procedure",id:"changeover-procedure",level:2}];function h(e){const i={a:"a",h1:"h1",h2:"h2",p:"p",strong:"strong",...(0,r.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"terminology",children:"Terminology"}),"\n",(0,n.jsx)(i.p,{children:"You may have heard of one or multiple buzzwords thrown around in the cosmos and wider crypto ecosystem such shared security, interchain security, replicated security, cross chain validation, and mesh security. These terms will be clarified below, before diving into any introductions."}),"\n",(0,n.jsx)(i.h2,{id:"shared-security",children:"Shared Security"}),"\n",(0,n.jsx)(i.p,{children:"Shared security is a family of technologies that include optimistic rollups, zk-rollups, sharding and Interchain Security. Ie. any protocol or technology that can allow one blockchain to lend/share its proof-of-stake security with another blockchain or off-chain process."}),"\n",(0,n.jsx)(i.h2,{id:"interchain-security",children:"Interchain Security"}),"\n",(0,n.jsx)(i.p,{children:"Interchain Security is the Cosmos-specific category of Shared Security that uses IBC (Inter-Blockchain Communication), i.e. any shared security protocol built with IBC."}),"\n",(0,n.jsx)(i.h2,{id:"replicated-security",children:"Replicated Security"}),"\n",(0,n.jsx)(i.p,{children:'A particular protocol/implementation of Interchain Security that fully replicates the security and decentralization of a validator set across multiple blockchains. Replicated security has also been referred to as "Cross Chain Validation" or "Interchain Security V1", a legacy term for the same protocol. That is, a "provider chain" such as the Cosmos Hub can share its exact validator set with multiple consumer chains by communicating changes in its validator set over IBC. Note this documentation is focused on explaining the concepts from replicated security.'}),"\n",(0,n.jsx)(i.h2,{id:"mesh-security",children:"Mesh security"}),"\n",(0,n.jsxs)(i.p,{children:["A protocol built on IBC that allows delegators on a cosmos chain to re-delegate their stake to validators in another chain's own validator set, using the original chain's token (which remains bonded on the original chain). For a deeper exploration of mesh security, see ",(0,n.jsx)(i.a,{href:"https://informal.systems/blog/replicated-vs-mesh-security",children:"Replicated vs. Mesh Security on the Informal Blog"}),"."]}),"\n",(0,n.jsx)(i.h2,{id:"consumer-chain",children:"Consumer Chain"}),"\n",(0,n.jsx)(i.p,{children:"Chain that is secured by the validator set of the provider, instead of its own.\nReplicated security allows the provider chain validator set to validate blocks on the consumer chain."}),"\n",(0,n.jsx)(i.h2,{id:"standalone-chain",children:"Standalone Chain"}),"\n",(0,n.jsx)(i.p,{children:"Chain that is secured by its own validator set. This chain does not participate in replicated security."}),"\n",(0,n.jsx)(i.p,{children:'Standalone chains may sometimes be called "sovereign" - the terms are synonymous.'}),"\n",(0,n.jsx)(i.h2,{id:"changeover-procedure",children:"Changeover Procedure"}),"\n",(0,n.jsxs)(i.p,{children:["Chains that were not initially launched as consumers of replicated security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the ",(0,n.jsx)(i.strong,{children:"changeover procedure"})," and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain."]})]})}function d(e={}){const{wrapper:i}={...(0,r.a)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},1151:(e,i,t)=>{t.d(i,{Z:()=>s,a:()=>a});var n=t(7294);const r={},o=n.createContext(r);function a(e){const i=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function s(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),n.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/1772.531d94c5.js b/assets/js/1772.531d94c5.js
new file mode 100644
index 0000000000..9ce56dc605
--- /dev/null
+++ b/assets/js/1772.531d94c5.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1772],{5658:(e,t,i)=>{i.d(t,{Z:()=>a});i(7294);var n=i(512),s=i(5999),o=i(2503),r=i(5893);function a(e){let{className:t}=e;return(0,r.jsx)("main",{className:(0,n.Z)("container margin-vert--xl",t),children:(0,r.jsx)("div",{className:"row",children:(0,r.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,r.jsx)(o.Z,{as:"h1",className:"hero__title",children:(0,r.jsx)(s.Z,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,r.jsx)("p",{children:(0,r.jsx)(s.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,r.jsx)("p",{children:(0,r.jsx)(s.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}},1772:(e,t,i)=>{i.r(t),i.d(t,{default:()=>l});i(7294);var n=i(5999),s=i(1944),o=i(6040),r=i(5658),a=i(5893);function l(){const e=(0,n.I)({id:"theme.NotFound.title",message:"Page Not Found"});return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(s.d,{title:e}),(0,a.jsx)(o.Z,{children:(0,a.jsx)(r.Z,{})})]})}}}]);
\ No newline at end of file
diff --git a/assets/js/17896441.407f320a.js b/assets/js/17896441.407f320a.js
new file mode 100644
index 0000000000..2ff97b6850
--- /dev/null
+++ b/assets/js/17896441.407f320a.js
@@ -0,0 +1 @@
+(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7918],{7951:function(e,t,n){"use strict";var s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});const a=s(n(7294)),o=s(n(5971)),i=s(n(9286));e.exports=(i.default,e=>e.reference?a.default.createElement(o.default,{...e}):a.default.createElement(i.default,{...e}))},5971:function(e,t,n){"use strict";var s=this&&this.__createBinding||(Object.create?function(e,t,n,s){void 0===s&&(s=n),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,s){void 0===s&&(s=n),e[s]=t[n]}),a=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&s(t,e,n);return a(t,e),t},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.codeReducer=t.parseReference=void 0;const l=o(n(7294)),r=i(n(9286)),c={code:"loading...",error:null,loading:null},d={fontSize:".9em",fontWeight:600,color:"#0E75DD",textAlign:"center",paddingBottom:"13px",textDecoration:"underline"};function u(e){const t=e.slice(e.indexOf("https"),-1),[n,s]=t.split("#"),a=globalThis||{};a.URL||(a.URL=URL);const[o,i,l,r,...c]=new a.URL(n).pathname.split("/").slice(1),[d,u]=s?s.split("-").map((e=>parseInt(e.slice(1),10)-1)):[0,1/0];return{url:`https://raw.githubusercontent.com/${o}/${i}/${r}/${c.join("/")}`,fromLine:d,toLine:u,title:c.join("/")}}function m(e,{type:t,value:n}){switch(t){case"reset":return c;case"loading":return{...e,loading:!0};case"loaded":return{...e,code:n,loading:!1};case"error":return{...e,error:n,loading:!1};default:return e}}t.parseReference=u,t.codeReducer=m,t.default=function(e){var t,n,s;const[a,o]=l.useReducer(m,c),i=u(e.children);!1!==a.loading&&async function({url:e,fromLine:t,toLine:n},s){let a;try{a=await fetch(e)}catch(l){return s({type:"error",value:l})}if(200!==a.status)return s({type:"error",value:await a.text()});const o=(await a.text()).split("\n").slice(t,(n||t)+1),i=o.reduce(((e,t)=>{if(0===t.length)return e;const n=t.match(/^\s+/);return n?Math.min(e,n[0].length):0}),1/0);s({type:"loaded",value:o.map((e=>e.slice(i))).join("\n")})}(i,o);const h=null===(t=e.metastring)||void 0===t?void 0:t.match(/title="(?.*)"/),p={...e,metastring:(null===(n=null==h?void 0:h.groups)||void 0===n?void 0:n.title)?` title="${null===(s=null==h?void 0:h.groups)||void 0===s?void 0:s.title}"`:` title="${i.title}"`,children:c.code};return l.default.createElement("div",null,l.default.createElement(r.default,{...p},a.code),l.default.createElement("div",{style:d},l.default.createElement("a",{href:e.children,target:"_blank"},"See full example on GitHub")))}},9286:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>U});var s=n(7294),a=n(2389),o=n(512),i=n(2949),l=n(6668);function r(){const{prism:e}=(0,l.L)(),{colorMode:t}=(0,i.I)(),n=e.theme,s=e.darkTheme||n;return"dark"===t?s:n}var c=n(5281),d=n(7594),u=n.n(d);const m=/title=(?["'])(?.*?)\1/,h=/\{(?[\d,-]+)\}/,p={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"},lua:{start:"--",end:""},wasm:{start:"\\;\\;",end:""},tex:{start:"%",end:""}};function f(e,t){const n=e.map((e=>{const{start:n,end:s}=p[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${s})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function x(e,t){let n=e.replace(/\n$/,"");const{language:s,magicComments:a,metastring:o}=t;if(o&&h.test(o)){const e=o.match(h).groups.range;if(0===a.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${o}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=a[0].className,s=u()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(s),code:n}}if(void 0===s)return{lineClassNames:{},code:n};const i=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return f(["js","jsBlock"],t);case"jsx":case"tsx":return f(["js","jsBlock","jsx"],t);case"html":return f(["js","jsBlock","html"],t);case"python":case"py":case"bash":return f(["bash"],t);case"markdown":case"md":return f(["html","jsx","bash"],t);case"tex":case"latex":case"matlab":return f(["tex"],t);case"lua":case"haskell":case"sql":return f(["lua"],t);case"wasm":return f(["wasm"],t);default:return f(Object.keys(p).filter((e=>!["lua","wasm","tex","latex","matlab"].includes(e))),t)}}(s,a),l=n.split("\n"),r=Object.fromEntries(a.map((e=>[e.className,{start:0,range:""}]))),c=Object.fromEntries(a.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),d=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),m=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let u=0;uvoid 0!==e));c[t]?r[c[t]].range+=`${u},`:d[t]?r[d[t]].start=u:m[t]&&(r[m[t]].range+=`${r[m[t]].start}-${u-1},`),l.splice(u,1)}n=l.join("\n");const x={};return Object.entries(r).forEach((e=>{let[t,{range:n}]=e;u()(n).forEach((e=>{x[e]??=[],x[e].push(t)}))})),{lineClassNames:x,code:n}}const g={codeBlockContainer:"codeBlockContainer_Ckt0"};var b=n(5893);function v(e){let{as:t,...n}=e;const s=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[s,a]=e;const o=t[s];o&&"string"==typeof a&&(n[o]=a)})),n}(r());return(0,b.jsx)(t,{...n,style:s,className:(0,o.Z)(n.className,g.codeBlockContainer,c.k.common.codeBlock)})}const j={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function N(e){let{children:t,className:n}=e;return(0,b.jsx)(v,{as:"pre",tabIndex:0,className:(0,o.Z)(j.codeBlockStandalone,"thin-scrollbar",n),children:(0,b.jsx)("code",{className:j.codeBlockLines,children:t})})}var C=n(902);const k={attributes:!0,characterData:!0,childList:!0,subtree:!0};function L(e,t){const[n,a]=(0,s.useState)(),o=(0,s.useCallback)((()=>{a(e.current?.closest("[role=tabpanel][hidden]"))}),[e,a]);(0,s.useEffect)((()=>{o()}),[o]),function(e,t,n){void 0===n&&(n=k);const a=(0,C.zX)(t),o=(0,C.Ql)(n);(0,s.useEffect)((()=>{const t=new MutationObserver(a);return e&&t.observe(e,o),()=>t.disconnect()}),[e,a,o])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),o())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}var y=n(2573);const _={codeLine:"codeLine_lJS_",codeLineNumber:"codeLineNumber_Tfdd",codeLineContent:"codeLineContent_feaV"};function w(e){let{line:t,classNames:n,showLineNumbers:s,getLineProps:a,getTokenProps:i}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const l=a({line:t,className:(0,o.Z)(n,s&&_.codeLine)}),r=t.map(((e,t)=>(0,b.jsx)("span",{...i({token:e,key:t})},t)));return(0,b.jsxs)("span",{...l,children:[s?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("span",{className:_.codeLineNumber}),(0,b.jsx)("span",{className:_.codeLineContent,children:r})]}):r,(0,b.jsx)("br",{})]})}var B=n(5999);function Z(e){return(0,b.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,b.jsx)("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})})}function T(e){return(0,b.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,b.jsx)("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"})})}const E={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function H(e){let{code:t,className:n}=e;const[a,i]=(0,s.useState)(!1),l=(0,s.useRef)(void 0),r=(0,s.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;if("string"!=typeof e)throw new TypeError(`Expected parameter \`text\` to be a \`string\`, got \`${typeof e}\`.`);const s=document.createElement("textarea"),a=document.activeElement;s.value=e,s.setAttribute("readonly",""),s.style.contain="strict",s.style.position="absolute",s.style.left="-9999px",s.style.fontSize="12pt";const o=document.getSelection(),i=o.rangeCount>0&&o.getRangeAt(0);n.append(s),s.select(),s.selectionStart=0,s.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch{}s.remove(),i&&(o.removeAllRanges(),o.addRange(i)),a&&a.focus()}(t),i(!0),l.current=window.setTimeout((()=>{i(!1)}),1e3)}),[t]);return(0,s.useEffect)((()=>()=>window.clearTimeout(l.current)),[]),(0,b.jsx)("button",{type:"button","aria-label":a?(0,B.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,B.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,B.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,o.Z)("clean-btn",n,E.copyButton,a&&E.copyButtonCopied),onClick:r,children:(0,b.jsxs)("span",{className:E.copyButtonIcons,"aria-hidden":"true",children:[(0,b.jsx)(Z,{className:E.copyButtonIcon}),(0,b.jsx)(T,{className:E.copyButtonSuccessIcon})]})})}function M(e){return(0,b.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,b.jsx)("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})})}const A={wordWrapButtonIcon:"wordWrapButtonIcon_Bwma",wordWrapButtonEnabled:"wordWrapButtonEnabled_EoeP"};function I(e){let{className:t,onClick:n,isEnabled:s}=e;const a=(0,B.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return(0,b.jsx)("button",{type:"button",onClick:n,className:(0,o.Z)("clean-btn",t,s&&A.wordWrapButtonEnabled),"aria-label":a,title:a,children:(0,b.jsx)(M,{className:A.wordWrapButtonIcon,"aria-hidden":"true"})})}function S(e){let{children:t,className:n="",metastring:a,title:i,showLineNumbers:c,language:d}=e;const{prism:{defaultLanguage:u,magicComments:h}}=(0,l.L)(),p=function(e){return e?.toLowerCase()}(d??function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return t?.replace(/language-/,"")}(n)??u),f=r(),g=function(){const[e,t]=(0,s.useState)(!1),[n,a]=(0,s.useState)(!1),o=(0,s.useRef)(null),i=(0,s.useCallback)((()=>{const n=o.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[o,e]),l=(0,s.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=o.current,n=e>t||o.current.querySelector("code").hasAttribute("style");a(n)}),[o]);return L(o,l),(0,s.useEffect)((()=>{l()}),[e,l]),(0,s.useEffect)((()=>(window.addEventListener("resize",l,{passive:!0}),()=>{window.removeEventListener("resize",l)})),[l]),{codeBlockRef:o,isEnabled:e,isCodeScrollable:n,toggle:i}}(),N=function(e){return e?.match(m)?.groups.title??""}(a)||i,{lineClassNames:C,code:k}=x(t,{metastring:a,language:p,magicComments:h}),_=c??function(e){return Boolean(e?.includes("showLineNumbers"))}(a);return(0,b.jsxs)(v,{as:"div",className:(0,o.Z)(n,p&&!n.includes(`language-${p}`)&&`language-${p}`),children:[N&&(0,b.jsx)("div",{className:j.codeBlockTitle,children:N}),(0,b.jsxs)("div",{className:j.codeBlockContent,children:[(0,b.jsx)(y.y$,{theme:f,code:k,language:p??"text",children:e=>{let{className:t,style:n,tokens:s,getLineProps:a,getTokenProps:i}=e;return(0,b.jsx)("pre",{tabIndex:0,ref:g.codeBlockRef,className:(0,o.Z)(t,j.codeBlock,"thin-scrollbar"),style:n,children:(0,b.jsx)("code",{className:(0,o.Z)(j.codeBlockLines,_&&j.codeBlockLinesWithNumbering),children:s.map(((e,t)=>(0,b.jsx)(w,{line:e,getLineProps:a,getTokenProps:i,classNames:C[t],showLineNumbers:_},t)))})})}}),(0,b.jsxs)("div",{className:j.buttonGroup,children:[(g.isEnabled||g.isCodeScrollable)&&(0,b.jsx)(I,{className:j.codeButton,onClick:()=>g.toggle(),isEnabled:g.isEnabled}),(0,b.jsx)(H,{className:j.codeButton,code:k})]})]})]})}function U(e){let{children:t,...n}=e;const o=(0,a.Z)(),i=function(e){return s.Children.toArray(e).some((e=>(0,s.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),l="string"==typeof i?S:N;return(0,b.jsx)(l,{...n,children:i},String(o))}},7078:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>bt});var s=n(7294),a=n(1944),o=n(902),i=n(5893);const l=s.createContext(null);function r(e){let{children:t,content:n}=e;const a=function(e){return(0,s.useMemo)((()=>({metadata:e.metadata,frontMatter:e.frontMatter,assets:e.assets,contentTitle:e.contentTitle,toc:e.toc})),[e])}(n);return(0,i.jsx)(l.Provider,{value:a,children:t})}function c(){const e=(0,s.useContext)(l);if(null===e)throw new o.i6("DocProvider");return e}function d(){const{metadata:e,frontMatter:t,assets:n}=c();return(0,i.jsx)(a.d,{title:e.title,description:e.description,keywords:t.keywords,image:n.image??t.image})}var u=n(512),m=n(7524),h=n(5999),p=n(9960);function f(e){const{permalink:t,title:n,subLabel:s,isNext:a}=e;return(0,i.jsxs)(p.Z,{className:(0,u.Z)("pagination-nav__link",a?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t,children:[s&&(0,i.jsx)("div",{className:"pagination-nav__sublabel",children:s}),(0,i.jsx)("div",{className:"pagination-nav__label",children:n})]})}function x(e){const{previous:t,next:n}=e;return(0,i.jsxs)("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,h.I)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages",description:"The ARIA label for the docs pagination"}),children:[t&&(0,i.jsx)(f,{...t,subLabel:(0,i.jsx)(h.Z,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc",children:"Previous"})}),n&&(0,i.jsx)(f,{...n,subLabel:(0,i.jsx)(h.Z,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc",children:"Next"}),isNext:!0})]})}function g(){const{metadata:e}=c();return(0,i.jsx)(x,{previous:e.previous,next:e.next})}var b=n(2263),v=n(143),j=n(5281),N=n(373),C=n(4477);const k={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,i.jsx)(h.Z,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:(0,i.jsx)("b",{children:n.label})},children:"This is unreleased documentation for {siteTitle} {versionLabel} version."})},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,i.jsx)(h.Z,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:(0,i.jsx)("b",{children:n.label})},children:"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained."})}};function L(e){const t=k[e.versionMetadata.banner];return(0,i.jsx)(t,{...e})}function y(e){let{versionLabel:t,to:n,onClick:s}=e;return(0,i.jsx)(h.Z,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:(0,i.jsx)("b",{children:(0,i.jsx)(p.Z,{to:n,onClick:s,children:(0,i.jsx)(h.Z,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label",children:"latest version"})})})},children:"For up-to-date documentation, see the {latestVersionLink} ({versionLabel})."})}function _(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:s}}=(0,b.Z)(),{pluginId:a}=(0,v.gA)({failfast:!0}),{savePreferredVersionName:o}=(0,N.J)(a),{latestDocSuggestion:l,latestVersionSuggestion:r}=(0,v.Jo)(a),c=l??(d=r).docs.find((e=>e.id===d.mainDocId));var d;return(0,i.jsxs)("div",{className:(0,u.Z)(t,j.k.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert",children:[(0,i.jsx)("div",{children:(0,i.jsx)(L,{siteTitle:s,versionMetadata:n})}),(0,i.jsx)("div",{className:"margin-top--md",children:(0,i.jsx)(y,{versionLabel:r.label,to:c.path,onClick:()=>o(r.name)})})]})}function w(e){let{className:t}=e;const n=(0,C.E)();return n.banner?(0,i.jsx)(_,{className:t,versionMetadata:n}):null}function B(e){let{className:t}=e;const n=(0,C.E)();return n.badge?(0,i.jsx)("span",{className:(0,u.Z)(t,j.k.docs.docVersionBadge,"badge badge--secondary"),children:(0,i.jsx)(h.Z,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label},children:"Version: {versionLabel}"})}):null}function Z(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n}=e;return(0,i.jsx)(h.Z,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:(0,i.jsx)("b",{children:(0,i.jsx)("time",{dateTime:new Date(1e3*t).toISOString(),children:n})})},children:" on {date}"})}function T(e){let{lastUpdatedBy:t}=e;return(0,i.jsx)(h.Z,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:(0,i.jsx)("b",{children:t})},children:" by {user}"})}function E(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n,lastUpdatedBy:s}=e;return(0,i.jsxs)("span",{className:j.k.common.lastUpdated,children:[(0,i.jsx)(h.Z,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t&&n?(0,i.jsx)(Z,{lastUpdatedAt:t,formattedLastUpdatedAt:n}):"",byUser:s?(0,i.jsx)(T,{lastUpdatedBy:s}):""},children:"Last updated{atDate}{byUser}"}),!1]})}const H={iconEdit:"iconEdit_Z9Sw"};function M(e){let{className:t,...n}=e;return(0,i.jsx)("svg",{fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,u.Z)(H.iconEdit,t),"aria-hidden":"true",...n,children:(0,i.jsx)("g",{children:(0,i.jsx)("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})})})}function A(e){let{editUrl:t}=e;return(0,i.jsxs)(p.Z,{to:t,className:j.k.common.editThisPage,children:[(0,i.jsx)(M,{}),(0,i.jsx)(h.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page",children:"Edit this page"})]})}const I={tag:"tag_zVej",tagRegular:"tagRegular_sFm0",tagWithCount:"tagWithCount_h2kH"};function S(e){let{permalink:t,label:n,count:s}=e;return(0,i.jsxs)(p.Z,{href:t,className:(0,u.Z)(I.tag,s?I.tagWithCount:I.tagRegular),children:[n,s&&(0,i.jsx)("span",{children:s})]})}const U={tags:"tags_jXut",tag:"tag_QGVx"};function R(e){let{tags:t}=e;return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("b",{children:(0,i.jsx)(h.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list",children:"Tags:"})}),(0,i.jsx)("ul",{className:(0,u.Z)(U.tags,"padding--none","margin-left--sm"),children:t.map((e=>{let{label:t,permalink:n}=e;return(0,i.jsx)("li",{className:U.tag,children:(0,i.jsx)(S,{label:t,permalink:n})},n)}))})]})}const z={lastUpdated:"lastUpdated_vwxv"};function O(e){return(0,i.jsx)("div",{className:(0,u.Z)(j.k.docs.docFooterTagsRow,"row margin-bottom--sm"),children:(0,i.jsx)("div",{className:"col",children:(0,i.jsx)(R,{...e})})})}function V(e){let{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:s,formattedLastUpdatedAt:a}=e;return(0,i.jsxs)("div",{className:(0,u.Z)(j.k.docs.docFooterEditMetaRow,"row"),children:[(0,i.jsx)("div",{className:"col",children:t&&(0,i.jsx)(A,{editUrl:t})}),(0,i.jsx)("div",{className:(0,u.Z)("col",z.lastUpdated),children:(n||s)&&(0,i.jsx)(E,{lastUpdatedAt:n,formattedLastUpdatedAt:a,lastUpdatedBy:s})})]})}function P(){const{metadata:e}=c(),{editUrl:t,lastUpdatedAt:n,formattedLastUpdatedAt:s,lastUpdatedBy:a,tags:o}=e,l=o.length>0,r=!!(t||n||a);return l||r?(0,i.jsxs)("footer",{className:(0,u.Z)(j.k.docs.docFooter,"docusaurus-mt-lg"),children:[l&&(0,i.jsx)(O,{tags:o}),r&&(0,i.jsx)(V,{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:a,formattedLastUpdatedAt:s})]}):null}var $=n(6043),D=n(6668);function W(e){const t=e.map((e=>({...e,parentIndex:-1,children:[]}))),n=Array(7).fill(-1);t.forEach(((e,t)=>{const s=n.slice(2,e.level);e.parentIndex=Math.max(...s),n[e.level]=t}));const s=[];return t.forEach((e=>{const{parentIndex:n,...a}=e;n>=0?t[n].children.push(a):s.push(a)})),s}function F(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:s}=e;return t.flatMap((e=>{const t=F({toc:e.children,minHeadingLevel:n,maxHeadingLevel:s});return function(e){return e.level>=n&&e.level<=s}(e)?[{...e,children:t}]:t}))}function q(e){const t=e.getBoundingClientRect();return t.top===t.bottom?q(e.parentNode):t}function G(e,t){let{anchorTopOffset:n}=t;const s=e.find((e=>q(e).top>=n));if(s){return function(e){return e.top>0&&e.bottom{e.current=t?0:document.querySelector(".navbar").clientHeight}),[t]),e}function Y(e){const t=(0,s.useRef)(void 0),n=J();(0,s.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:s,linkActiveClassName:a,minHeadingLevel:o,maxHeadingLevel:i}=e;function l(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(s),l=function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e;const s=[];for(let a=t;a<=n;a+=1)s.push(`h${a}.anchor`);return Array.from(document.querySelectorAll(s.join()))}({minHeadingLevel:o,maxHeadingLevel:i}),r=G(l,{anchorTopOffset:n.current}),c=e.find((e=>r&&r.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,n){n?(t.current&&t.current!==e&&t.current.classList.remove(a),e.classList.add(a),t.current=e):e.classList.remove(a)}(e,e===c)}))}return document.addEventListener("scroll",l),document.addEventListener("resize",l),l(),()=>{document.removeEventListener("scroll",l),document.removeEventListener("resize",l)}}),[e,n])}function Q(e){let{toc:t,className:n,linkClassName:s,isChild:a}=e;return t.length?(0,i.jsx)("ul",{className:a?void 0:n,children:t.map((e=>(0,i.jsxs)("li",{children:[(0,i.jsx)(p.Z,{to:`#${e.id}`,className:s??void 0,dangerouslySetInnerHTML:{__html:e.value}}),(0,i.jsx)(Q,{isChild:!0,toc:e.children,className:n,linkClassName:s})]},e.id)))}):null}const X=s.memo(Q);function K(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:a="table-of-contents__link",linkActiveClassName:o,minHeadingLevel:l,maxHeadingLevel:r,...c}=e;const d=(0,D.L)(),u=l??d.tableOfContents.minHeadingLevel,m=r??d.tableOfContents.maxHeadingLevel,h=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return(0,s.useMemo)((()=>F({toc:W(t),minHeadingLevel:n,maxHeadingLevel:a})),[t,n,a])}({toc:t,minHeadingLevel:u,maxHeadingLevel:m});return Y((0,s.useMemo)((()=>{if(a&&o)return{linkClassName:a,linkActiveClassName:o,minHeadingLevel:u,maxHeadingLevel:m}}),[a,o,u,m])),(0,i.jsx)(X,{toc:h,className:n,linkClassName:a,...c})}const ee={tocCollapsibleButton:"tocCollapsibleButton_TO0P",tocCollapsibleButtonExpanded:"tocCollapsibleButtonExpanded_MG3E"};function te(e){let{collapsed:t,...n}=e;return(0,i.jsx)("button",{type:"button",...n,className:(0,u.Z)("clean-btn",ee.tocCollapsibleButton,!t&&ee.tocCollapsibleButtonExpanded,n.className),children:(0,i.jsx)(h.Z,{id:"theme.TOCCollapsible.toggleButtonLabel",description:"The label used by the button on the collapsible TOC component",children:"On this page"})})}const ne={tocCollapsible:"tocCollapsible_ETCw",tocCollapsibleContent:"tocCollapsibleContent_vkbj",tocCollapsibleExpanded:"tocCollapsibleExpanded_sAul"};function se(e){let{toc:t,className:n,minHeadingLevel:s,maxHeadingLevel:a}=e;const{collapsed:o,toggleCollapsed:l}=(0,$.u)({initialState:!0});return(0,i.jsxs)("div",{className:(0,u.Z)(ne.tocCollapsible,!o&&ne.tocCollapsibleExpanded,n),children:[(0,i.jsx)(te,{collapsed:o,onClick:l}),(0,i.jsx)($.z,{lazy:!0,className:ne.tocCollapsibleContent,collapsed:o,children:(0,i.jsx)(K,{toc:t,minHeadingLevel:s,maxHeadingLevel:a})})]})}const ae={tocMobile:"tocMobile_ITEo"};function oe(){const{toc:e,frontMatter:t}=c();return(0,i.jsx)(se,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:(0,u.Z)(j.k.docs.docTocMobile,ae.tocMobile)})}const ie={tableOfContents:"tableOfContents_bqdL",docItemContainer:"docItemContainer_F8PC"},le="table-of-contents__link toc-highlight",re="table-of-contents__link--active";function ce(e){let{className:t,...n}=e;return(0,i.jsx)("div",{className:(0,u.Z)(ie.tableOfContents,"thin-scrollbar",t),children:(0,i.jsx)(K,{...n,linkClassName:le,linkActiveClassName:re})})}function de(){const{toc:e,frontMatter:t}=c();return(0,i.jsx)(ce,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:j.k.docs.docTocDesktop})}var ue=n(2503),me=n(1151),he=n(5742),pe=n(7951),fe=n.n(pe);var xe=n(2389);const ge={details:"details_lb9f",isBrowser:"isBrowser_bmU9",collapsibleContent:"collapsibleContent_i85q"};function be(e){return!!e&&("SUMMARY"===e.tagName||be(e.parentElement))}function ve(e,t){return!!e&&(e===t||ve(e.parentElement,t))}function je(e){let{summary:t,children:n,...a}=e;const o=(0,xe.Z)(),l=(0,s.useRef)(null),{collapsed:r,setCollapsed:c}=(0,$.u)({initialState:!a.open}),[d,m]=(0,s.useState)(a.open),h=s.isValidElement(t)?t:(0,i.jsx)("summary",{children:t??"Details"});return(0,i.jsxs)("details",{...a,ref:l,open:d,"data-collapsed":r,className:(0,u.Z)(ge.details,o&&ge.isBrowser,a.className),onMouseDown:e=>{be(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;be(t)&&ve(t,l.current)&&(e.preventDefault(),r?(c(!1),m(!0)):c(!0))},children:[h,(0,i.jsx)($.z,{lazy:!1,collapsed:r,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{c(e),m(!e)},children:(0,i.jsx)("div",{className:ge.collapsibleContent,children:n})})]})}const Ne={details:"details_b_Ee"},Ce="alert alert--info";function ke(e){let{...t}=e;return(0,i.jsx)(je,{...t,className:(0,u.Z)(Ce,Ne.details,t.className)})}function Le(e){const t=s.Children.toArray(e.children),n=t.find((e=>s.isValidElement(e)&&"summary"===e.type)),a=(0,i.jsx)(i.Fragment,{children:t.filter((e=>e!==n))});return(0,i.jsx)(ke,{...e,summary:n,children:a})}function ye(e){return(0,i.jsx)(ue.Z,{...e})}const _e={containsTaskList:"containsTaskList_mC6p"};function we(e){if(void 0!==e)return(0,u.Z)(e,e?.includes("contains-task-list")&&_e.containsTaskList)}const Be={img:"img_ev3q"};function Ze(e){const{mdxAdmonitionTitle:t,rest:n}=function(e){const t=s.Children.toArray(e),n=t.find((e=>s.isValidElement(e)&&"mdxAdmonitionTitle"===e.type)),a=t.filter((e=>e!==n)),o=n?.props.children;return{mdxAdmonitionTitle:o,rest:a.length>0?(0,i.jsx)(i.Fragment,{children:a}):null}}(e.children),a=e.title??t;return{...e,...a&&{title:a},children:n}}const Te={admonition:"admonition_xJq3",admonitionHeading:"admonitionHeading_Gvgb",admonitionIcon:"admonitionIcon_Rf37",admonitionContent:"admonitionContent_BuS1"};function Ee(e){let{type:t,className:n,children:s}=e;return(0,i.jsx)("div",{className:(0,u.Z)(j.k.common.admonition,j.k.common.admonitionType(t),Te.admonition,n),children:s})}function He(e){let{icon:t,title:n}=e;return(0,i.jsxs)("div",{className:Te.admonitionHeading,children:[(0,i.jsx)("span",{className:Te.admonitionIcon,children:t}),n]})}function Me(e){let{children:t}=e;return t?(0,i.jsx)("div",{className:Te.admonitionContent,children:t}):null}function Ae(e){const{type:t,icon:n,title:s,children:a,className:o}=e;return(0,i.jsxs)(Ee,{type:t,className:o,children:[(0,i.jsx)(He,{title:s,icon:n}),(0,i.jsx)(Me,{children:a})]})}function Ie(e){return(0,i.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"})})}const Se={icon:(0,i.jsx)(Ie,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)",children:"note"})};function Ue(e){return(0,i.jsx)(Ae,{...Se,...e,className:(0,u.Z)("alert alert--secondary",e.className),children:e.children})}function Re(e){return(0,i.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"})})}const ze={icon:(0,i.jsx)(Re,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)",children:"tip"})};function Oe(e){return(0,i.jsx)(Ae,{...ze,...e,className:(0,u.Z)("alert alert--success",e.className),children:e.children})}function Ve(e){return(0,i.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"})})}const Pe={icon:(0,i.jsx)(Ve,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)",children:"info"})};function $e(e){return(0,i.jsx)(Ae,{...Pe,...e,className:(0,u.Z)("alert alert--info",e.className),children:e.children})}function De(e){return(0,i.jsx)("svg",{viewBox:"0 0 16 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"})})}const We={icon:(0,i.jsx)(De,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.warning",description:"The default label used for the Warning admonition (:::warning)",children:"warning"})};function Fe(e){return(0,i.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"})})}const qe={icon:(0,i.jsx)(Fe,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)",children:"danger"})};const Ge={icon:(0,i.jsx)(De,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)",children:"caution"})};const Je={...{note:Ue,tip:Oe,info:$e,warning:function(e){return(0,i.jsx)(Ae,{...We,...e,className:(0,u.Z)("alert alert--warning",e.className),children:e.children})},danger:function(e){return(0,i.jsx)(Ae,{...qe,...e,className:(0,u.Z)("alert alert--danger",e.className),children:e.children})}},...{secondary:e=>(0,i.jsx)(Ue,{title:"secondary",...e}),important:e=>(0,i.jsx)($e,{title:"important",...e}),success:e=>(0,i.jsx)(Oe,{title:"success",...e}),caution:function(e){return(0,i.jsx)(Ae,{...Ge,...e,className:(0,u.Z)("alert alert--warning",e.className),children:e.children})}}};function Ye(e){const t=Ze(e),n=(s=t.type,Je[s]||(console.warn(`No admonition component found for admonition type "${s}". Using Info as fallback.`),Je.info));var s;return(0,i.jsx)(n,{...t})}var Qe=n(1875);const Xe={Head:he.Z,details:Le,Details:Le,code:function(e){return s.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")))?(0,i.jsx)("code",{...e}):(0,i.jsx)(fe(),{...e})},a:function(e){return(0,i.jsx)(p.Z,{...e})},pre:function(e){return(0,i.jsx)(i.Fragment,{children:e.children})},ul:function(e){return(0,i.jsx)("ul",{...e,className:we(e.className)})},img:function(e){return(0,i.jsx)("img",{loading:"lazy",...e,className:(t=e.className,(0,u.Z)(t,Be.img))});var t},h1:e=>(0,i.jsx)(ye,{as:"h1",...e}),h2:e=>(0,i.jsx)(ye,{as:"h2",...e}),h3:e=>(0,i.jsx)(ye,{as:"h3",...e}),h4:e=>(0,i.jsx)(ye,{as:"h4",...e}),h5:e=>(0,i.jsx)(ye,{as:"h5",...e}),h6:e=>(0,i.jsx)(ye,{as:"h6",...e}),admonition:Ye,mermaid:Qe.Z};function Ke(e){let{children:t}=e;return(0,i.jsx)(me.Z,{components:Xe,children:t})}function et(e){let{children:t}=e;const n=function(){const{metadata:e,frontMatter:t,contentTitle:n}=c();return t.hide_title||void 0!==n?null:e.title}();return(0,i.jsxs)("div",{className:(0,u.Z)(j.k.docs.docMarkdown,"markdown"),children:[n&&(0,i.jsx)("header",{children:(0,i.jsx)(ue.Z,{as:"h1",children:n})}),(0,i.jsx)(Ke,{children:t})]})}var tt=n(2802),nt=n(8596),st=n(4996);function at(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"})})}const ot={breadcrumbHomeIcon:"breadcrumbHomeIcon_YNFT"};function it(){const e=(0,st.Z)("/");return(0,i.jsx)("li",{className:"breadcrumbs__item",children:(0,i.jsx)(p.Z,{"aria-label":(0,h.I)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:"breadcrumbs__link",href:e,children:(0,i.jsx)(at,{className:ot.breadcrumbHomeIcon})})})}const lt={breadcrumbsContainer:"breadcrumbsContainer_Z_bl"};function rt(e){let{children:t,href:n,isLast:s}=e;const a="breadcrumbs__link";return s?(0,i.jsx)("span",{className:a,itemProp:"name",children:t}):n?(0,i.jsx)(p.Z,{className:a,href:n,itemProp:"item",children:(0,i.jsx)("span",{itemProp:"name",children:t})}):(0,i.jsx)("span",{className:a,children:t})}function ct(e){let{children:t,active:n,index:s,addMicrodata:a}=e;return(0,i.jsxs)("li",{...a&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},className:(0,u.Z)("breadcrumbs__item",{"breadcrumbs__item--active":n}),children:[t,(0,i.jsx)("meta",{itemProp:"position",content:String(s+1)})]})}function dt(){const e=(0,tt.s1)(),t=(0,nt.Ns)();return e?(0,i.jsx)("nav",{className:(0,u.Z)(j.k.docs.docBreadcrumbs,lt.breadcrumbsContainer),"aria-label":(0,h.I)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"}),children:(0,i.jsxs)("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList",children:[t&&(0,i.jsx)(it,{}),e.map(((t,n)=>{const s=n===e.length-1,a="category"===t.type&&t.linkUnlisted?void 0:t.href;return(0,i.jsx)(ct,{active:s,index:n,addMicrodata:!!a,children:(0,i.jsx)(rt,{href:a,isLast:s,children:t.label})},n)}))]})}):null}function ut(){return(0,i.jsx)(h.Z,{id:"theme.unlistedContent.title",description:"The unlisted content banner title",children:"Unlisted page"})}function mt(){return(0,i.jsx)(h.Z,{id:"theme.unlistedContent.message",description:"The unlisted content banner message",children:"This page is unlisted. Search engines will not index it, and only users having a direct link can access it."})}function ht(){return(0,i.jsx)(he.Z,{children:(0,i.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})}function pt(e){let{className:t}=e;return(0,i.jsx)(Ye,{type:"caution",title:(0,i.jsx)(ut,{}),className:(0,u.Z)(t,j.k.common.unlistedBanner),children:(0,i.jsx)(mt,{})})}function ft(e){return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(ht,{}),(0,i.jsx)(pt,{...e})]})}const xt={docItemContainer:"docItemContainer_Djhp",docItemCol:"docItemCol_VOVn"};function gt(e){let{children:t}=e;const n=function(){const{frontMatter:e,toc:t}=c(),n=(0,m.i)(),s=e.hide_table_of_contents,a=!s&&t.length>0;return{hidden:s,mobile:a?(0,i.jsx)(oe,{}):void 0,desktop:!a||"desktop"!==n&&"ssr"!==n?void 0:(0,i.jsx)(de,{})}}(),{metadata:{unlisted:s}}=c();return(0,i.jsxs)("div",{className:"row",children:[(0,i.jsxs)("div",{className:(0,u.Z)("col",!n.hidden&&xt.docItemCol),children:[s&&(0,i.jsx)(ft,{}),(0,i.jsx)(w,{}),(0,i.jsxs)("div",{className:xt.docItemContainer,children:[(0,i.jsxs)("article",{children:[(0,i.jsx)(dt,{}),(0,i.jsx)(B,{}),n.mobile,(0,i.jsx)(et,{children:t}),(0,i.jsx)(P,{})]}),(0,i.jsx)(g,{})]})]}),n.desktop&&(0,i.jsx)("div",{className:"col col--3",children:n.desktop})]})}function bt(e){const t=`docs-doc-id-${e.content.metadata.id}`,n=e.content;return(0,i.jsx)(r,{content:e.content,children:(0,i.jsxs)(a.FG,{className:t,children:[(0,i.jsx)(d,{}),(0,i.jsx)(gt,{children:(0,i.jsx)(n,{})})]})})}},7594:(e,t)=>{function n(e){let t,n=[];for(let s of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(s))n.push(parseInt(s,10));else if(t=s.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,s,a,o]=t;if(s&&o){s=parseInt(s),o=parseInt(o);const e=s{"use strict";n.d(t,{Z:()=>l,a:()=>i});var s=n(7294);const a={},o=s.createContext(a);function i(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/1ae81764.482af898.js b/assets/js/1ae81764.482af898.js
new file mode 100644
index 0000000000..7dd47bd6ad
--- /dev/null
+++ b/assets/js/1ae81764.482af898.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2262],{9436:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>c,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>l});var n=t(5893),r=t(1151);const a={sidebar_position:2},o="Terminology",s={id:"introduction/terminology",title:"Terminology",description:"You may have heard of one or multiple buzzwords thrown around in the cosmos and wider crypto ecosystem such shared security, interchain security, replicated security, cross chain validation, and mesh security. These terms will be clarified below, before diving into any introductions.",source:"@site/versioned_docs/version-v4.2.0-docs/introduction/terminology.md",sourceDirName:"introduction",slug:"/introduction/terminology",permalink:"/interchain-security/v4.2.0/introduction/terminology",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Overview",permalink:"/interchain-security/v4.2.0/introduction/overview"},next:{title:"Interchain Security Parameters",permalink:"/interchain-security/v4.2.0/introduction/params"}},c={},l=[{value:"Shared Security",id:"shared-security",level:2},{value:"Interchain Security",id:"interchain-security",level:2},{value:"Replicated Security",id:"replicated-security",level:2},{value:"Partial Set Security",id:"partial-set-security",level:2},{value:"Mesh security",id:"mesh-security",level:2},{value:"Consumer Chain",id:"consumer-chain",level:2},{value:"Standalone Chain",id:"standalone-chain",level:2},{value:"Changeover Procedure",id:"changeover-procedure",level:2}];function h(e){const i={a:"a",h1:"h1",h2:"h2",p:"p",strong:"strong",...(0,r.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"terminology",children:"Terminology"}),"\n",(0,n.jsx)(i.p,{children:"You may have heard of one or multiple buzzwords thrown around in the cosmos and wider crypto ecosystem such shared security, interchain security, replicated security, cross chain validation, and mesh security. These terms will be clarified below, before diving into any introductions."}),"\n",(0,n.jsx)(i.h2,{id:"shared-security",children:"Shared Security"}),"\n",(0,n.jsx)(i.p,{children:"Shared security is a family of technologies that include optimistic rollups, zk-rollups, sharding and Interchain Security. Ie. any protocol or technology that can allow one blockchain to lend/share its proof-of-stake security with another blockchain or off-chain process."}),"\n",(0,n.jsx)(i.h2,{id:"interchain-security",children:"Interchain Security"}),"\n",(0,n.jsx)(i.p,{children:"Interchain Security is the Cosmos-specific category of Shared Security that uses IBC (Inter-Blockchain Communication), i.e. any shared security protocol built with IBC."}),"\n",(0,n.jsx)(i.h2,{id:"replicated-security",children:"Replicated Security"}),"\n",(0,n.jsx)(i.p,{children:'A particular protocol/implementation of Interchain Security that fully replicates the security and decentralization of a validator set across multiple blockchains. Replicated security has also been referred to as "Cross Chain Validation" or "Interchain Security V1", a legacy term for the same protocol. That is, a "provider chain" such as the Cosmos Hub can share its exact validator set with multiple consumer chains by communicating changes in its validator set over IBC.'}),"\n",(0,n.jsx)(i.h2,{id:"partial-set-security",children:"Partial Set Security"}),"\n",(0,n.jsx)(i.p,{children:'A major iteration of Interchain Security, also known as "Interchain Security V2". Partial Set Security allows a provider chain to share only a subset of its validator set with a consumer chain. This subset can be determined by the top N% validators by voting power, or by validators opting in to validate the consumer chain. Partial Set Security allows for more flexible security tradeoffs than Replicated Security.'}),"\n",(0,n.jsx)(i.h2,{id:"mesh-security",children:"Mesh security"}),"\n",(0,n.jsxs)(i.p,{children:["A protocol built on IBC that allows delegators on a cosmos chain to re-delegate their stake to validators in another chain's own validator set, using the original chain's token (which remains bonded on the original chain). For a deeper exploration of mesh security, see ",(0,n.jsx)(i.a,{href:"https://informal.systems/blog/replicated-vs-mesh-security",children:"Replicated vs. Mesh Security on the Informal Blog"}),"."]}),"\n",(0,n.jsx)(i.h2,{id:"consumer-chain",children:"Consumer Chain"}),"\n",(0,n.jsx)(i.p,{children:"Chain that is secured by the validator set of the provider, instead of its own.\nReplicated security allows the provider chain validator set to validate blocks on the consumer chain."}),"\n",(0,n.jsx)(i.h2,{id:"standalone-chain",children:"Standalone Chain"}),"\n",(0,n.jsx)(i.p,{children:"Chain that is secured by its own validator set. This chain does not participate in replicated security."}),"\n",(0,n.jsx)(i.p,{children:'Standalone chains may sometimes be called "sovereign" - the terms are synonymous.'}),"\n",(0,n.jsx)(i.h2,{id:"changeover-procedure",children:"Changeover Procedure"}),"\n",(0,n.jsxs)(i.p,{children:["Chains that were not initially launched as consumers of replicated security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the ",(0,n.jsx)(i.strong,{children:"changeover procedure"})," and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain."]})]})}function d(e={}){const{wrapper:i}={...(0,r.a)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},1151:(e,i,t)=>{t.d(i,{Z:()=>s,a:()=>o});var n=t(7294);const r={},a=n.createContext(r);function o(e){const i=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function s(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),n.createElement(a.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/1ca82e41.07ae1c1e.js b/assets/js/1ca82e41.07ae1c1e.js
new file mode 100644
index 0000000000..6d7f944d81
--- /dev/null
+++ b/assets/js/1ca82e41.07ae1c1e.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7617],{1343:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>l,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=r(5893),t=r(1151);const o={sidebar_position:6},s="Consumer Genesis Transformation",a={id:"consumer-development/consumer-genesis-transformation",title:"Consumer Genesis Transformation",description:"Preparing a consumer chain for onboarding requires some information explaining how to run your chain. This includes a genesis file with CCV data where the CCV data is exported from the provider chain and added to the consumers genesis file (for more details check the documentation on Onboarding and Changeover).",source:"@site/versioned_docs/version-v5.0.0/consumer-development/consumer-genesis-transformation.md",sourceDirName:"consumer-development",slug:"/consumer-development/consumer-genesis-transformation",permalink:"/interchain-security/v5.0.0/consumer-development/consumer-genesis-transformation",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Changeover Procedure",permalink:"/interchain-security/v5.0.0/consumer-development/changeover-procedure"},next:{title:"Overview",permalink:"/interchain-security/v5.0.0/validators/overview"}},c={},d=[{value:"1. Prerequisite",id:"1-prerequisite",level:2},{value:"2. Export the CCV data",id:"2-export-the-ccv-data",level:2},{value:"3. Transform CCV data",id:"3-transform-ccv-data",level:2}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"consumer-genesis-transformation",children:"Consumer Genesis Transformation"}),"\n",(0,i.jsxs)(n.p,{children:["Preparing a consumer chain for onboarding requires some information explaining how to run your chain. This includes a genesis file with CCV data where the CCV data is exported from the provider chain and added to the consumers genesis file (for more details check the documentation on ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/onboarding",children:"Onboarding"})," and ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/changeover-procedure",children:"Changeover"}),").\nIn case that the provider chain is running an older version of the InterChainSecurity (ICS) module than the consumer chain - or vice versa - the exported CCV data might need to be transformed to the format supported by the ICS implementation run on the consumer chain. This is the case if the consumer chain runs version 4 of ICS or later and the provider is running version 3 or older of the ICS module."]}),"\n",(0,i.jsxs)(n.p,{children:["Check the ",(0,i.jsx)(n.a,{href:"../../../RELEASES.md#backwards-compatibility",children:"compatibility notes"})," for known incompatibilities between provider and consumer versions and indications if a consumer genesis transformation is required."]}),"\n",(0,i.jsx)(n.p,{children:"To transform such CCV data follow the instructions below"}),"\n",(0,i.jsx)(n.h2,{id:"1-prerequisite",children:"1. Prerequisite"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["used provider and consumer versions require transformation step as indicated in in the ",(0,i.jsx)(n.a,{href:"../../../RELEASES.md#backwards-compatibility",children:"compatibility notes"})]}),"\n",(0,i.jsx)(n.li,{children:"interchain-security-cd application supports the versions used by the consumer and provider"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"2-export-the-ccv-data",children:"2. Export the CCV data"}),"\n",(0,i.jsxs)(n.p,{children:["Export the CCV data from the provider chain as described in the ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/onboarding",children:"Onboarding"})," and ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/changeover-procedure",children:"Changeover"})," your following.\nAs a result the CCV data will be stored in a file in JSON format."]}),"\n",(0,i.jsx)(n.h2,{id:"3-transform-ccv-data",children:"3. Transform CCV data"}),"\n",(0,i.jsx)(n.p,{children:"To transform the CCV data"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["to the format supported by the current version of the consumer run the following command:","\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"interchain-security-cd genesis transform [genesis-file]\n"})}),"\n","where 'genesis-file' is the path to the file containing the CCV data exported in ",(0,i.jsx)(n.a,{href:"#2-export-the-ccv-data",children:"step 2"}),".\nAs a result the CCV data in the new format will be written to standard output."]}),"\n",(0,i.jsxs)(n.li,{children:["a specific target version of a consumer run the following command:","\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"interchain-security-cd genesis transform --to [genesis-file]\n\n"})}),"\n","where ",(0,i.jsx)(n.code,{children:"{r.d(n,{Z:()=>a,a:()=>s});var i=r(7294);const t={},o=i.createContext(t);function s(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/21cfc626.8729733a.js b/assets/js/21cfc626.8729733a.js
new file mode 100644
index 0000000000..a47c80dbae
--- /dev/null
+++ b/assets/js/21cfc626.8729733a.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[52],{964:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>u,contentTitle:()=>c,default:()=>m,frontMatter:()=>o,metadata:()=>d,toc:()=>h});var t=n(5893),i=n(1151),s=n(2307),a=n(8758);const o={sidebar_position:1},c="Interchain Security Docs",d={id:"index",title:"Interchain Security Docs",description:"Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains.",source:"@site/versioned_docs/version-v5.0.0/index.mdx",sourceDirName:".",slug:"/",permalink:"/interchain-security/v5.0.0/",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",next:{title:"Overview",permalink:"/interchain-security/v5.0.0/introduction/overview"}},u={},h=[];function l(e){const r={h1:"h1",p:"p",...(0,i.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h1,{id:"interchain-security-docs",children:"Interchain Security Docs"}),"\n",(0,t.jsx)(r.p,{children:"Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains."}),"\n",(0,t.jsx)(r.p,{children:"Here you can find information about replicated security, consumer chain development and instructions for validator onboarding."}),"\n",(0,t.jsx)(s.Z,{cards:a.Z})]})}function m(e={}){const{wrapper:r}={...(0,i.a)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},2307:(e,r,n)=>{n.d(r,{Z:()=>s});n(7294);var t=n(5893);const i=function(e){return(0,t.jsx)("a",{href:e.href,className:"border shadow rounded-sm border-stone-200 dark:border-stone-800 dark:bg-neutral-900 hover:border-stone-300 hover:shadow-lg dark:hover:border-stone-200 transition-all duration-200 no-underline",children:(0,t.jsxs)("div",{className:"p-6",children:[(0,t.jsx)("h2",{className:"",children:e.header}),(0,t.jsx)("p",{className:"",children:e.summary})]})})};const s=function(e){return(0,t.jsx)("div",{className:"card-section grid grid-cols-1 lg:grid-cols-2 gap-4 no-underline",children:e.cards.map(((e,r)=>(0,t.jsx)(i,{href:e.href,header:e.header,summary:e.summary},r)))})}},8758:(e,r,n)=>{n.d(r,{Z:()=>t});const t=[{href:"/interchain-security/introduction/overview",header:"Basic concepts",summary:"Get started with the basic concepts and ideas."},{href:"/interchain-security/consumer-development/app-integration",header:"Start building",summary:"Click here to start building with Interchain security"},{href:"/interchain-security/features/key-assignment",header:"Feature: Key Assignment",summary:"Learn about the key assignment feature"},{href:"/interchain-security/features/reward-distribution",header:"Feature: Reward Distribution",summary:"Learn about consumer chain rewards distribution"},{href:"/interchain-security/consumer-development/onboarding",header:"Onboarding Checklist",summary:"Checklist to help you integrate Interchain Security, get support and onboard validators"},{href:"/interchain-security/faq",header:"FAQ",summary:"Frequently asked questions about the protocol and its implications"}]},1151:(e,r,n)=>{n.d(r,{Z:()=>o,a:()=>a});var t=n(7294);const i={},s=t.createContext(i);function a(e){const r=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function o(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),t.createElement(s.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/21dfdb60.4f19dea1.js b/assets/js/21dfdb60.4f19dea1.js
new file mode 100644
index 0000000000..a65701ba7c
--- /dev/null
+++ b/assets/js/21dfdb60.4f19dea1.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5932],{2702:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>c});var s=t(5893),i=t(1151);const o={sidebar_position:2,title:"ADR Template"},r="ADR [ADR-NUMBER]: [TITLE]",a={id:"adrs/adr-template",title:"ADR Template",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-template.md",sourceDirName:"adrs",slug:"/adrs/adr-template",permalink:"/interchain-security/v5.0.0/adrs/adr-template",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"ADR Template"},sidebar:"tutorialSidebar",previous:{title:"ADR Template",permalink:"/interchain-security/v5.0.0/adrs/adr-007-pause-unbonding-on-eqv-prop"},next:{title:"Key Assignment",permalink:"/interchain-security/v5.0.0/adrs/adr-001-key-assignment"}},l={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function d(e){const n={blockquote:"blockquote",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"adr-adr-number-title",children:"ADR [ADR-NUMBER]: [TITLE]"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:'A decision may be "proposed" if it hasn\'t been agreed upon yet, or "accepted" once it is agreed upon. If a later ADR changes or reverses a decision, it may be marked as "deprecated" or "superseded" with a reference to its replacement.'}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"[Deprecated|Proposed|Accepted]"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"This section contains all the context one needs to understand the current state, and why there is a problem. It should be as succinct as possible and introduce the high level idea behind the solution."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"This section explains all of the details of the proposed solution, including implementation details.\nIt should also describe affects / corollary items that may need to be changed as a part of this.\nIf the proposed change will be large, please also indicate a way to do the change to maximize ease of review.\n(e.g. the optimal split of things to do between separate PR's)"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:'This section describes the consequences, after applying the decision. All consequences should be summarized here, not just the "positive" ones.'}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!"}),"\n"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"[references]"}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>r});var s=t(7294);const i={},o=s.createContext(i);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/2510f7b4.823faae0.js b/assets/js/2510f7b4.823faae0.js
new file mode 100644
index 0000000000..26384470de
--- /dev/null
+++ b/assets/js/2510f7b4.823faae0.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2558],{6250:(n,e,t)=>{t.r(e),t.d(e,{assets:()=>a,contentTitle:()=>s,default:()=>l,frontMatter:()=>o,metadata:()=>c,toc:()=>u});var i=t(5893),r=t(1151);const o={sidebar_position:5},s="Joining Neutron",c={id:"validators/joining-neutron",title:"Joining Neutron",description:"Neutron is the first consumer chain to implement ICS.",source:"@site/versioned_docs/version-v4.2.0-docs/validators/joining-neutron.md",sourceDirName:"validators",slug:"/validators/joining-neutron",permalink:"/interchain-security/v4.2.0/validators/joining-neutron",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"tutorialSidebar",previous:{title:"Validator Instructions for Changeover Procedure",permalink:"/interchain-security/v4.2.0/validators/changeover-procedure"},next:{title:"Joining Stride",permalink:"/interchain-security/v4.2.0/validators/joining-stride"}},a={},u=[{value:"Resources",id:"resources",level:2}];function d(n){const e={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.a)(),...n.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"joining-neutron",children:"Joining Neutron"}),"\n",(0,i.jsx)(e.p,{children:"Neutron is the first consumer chain to implement ICS."}),"\n",(0,i.jsxs)(e.p,{children:["You can find instructions on joining the mainnet ",(0,i.jsx)(e.a,{href:"https://docs.neutron.org/neutron/consumer-chain-launch",children:"here"}),"."]}),"\n",(0,i.jsxs)(e.p,{children:["To join Neutron chain on the interchain security testnet check ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security/pion-1",children:"here"})]}),"\n",(0,i.jsx)(e.h2,{id:"resources",children:"Resources"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://docs.neutron.org",children:"Neutron docs"})}),"\n"]})]})}function l(n={}){const{wrapper:e}={...(0,r.a)(),...n.components};return e?(0,i.jsx)(e,{...n,children:(0,i.jsx)(d,{...n})}):d(n)}},1151:(n,e,t)=>{t.d(e,{Z:()=>c,a:()=>s});var i=t(7294);const r={},o=i.createContext(r);function s(n){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function c(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(r):n.components||r:s(n.components),i.createElement(o.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/26981f24.3de9a95d.js b/assets/js/26981f24.3de9a95d.js
new file mode 100644
index 0000000000..fcd7347c29
--- /dev/null
+++ b/assets/js/26981f24.3de9a95d.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1483],{5183:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>d});var s=i(5893),t=i(1151);const o={sidebar_position:5},a="Changeover Procedure",r={id:"consumer-development/changeover-procedure",title:"Changeover Procedure",description:"Chains that were not initially launched as consumers of replicated security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the changeover procedure and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain.",source:"@site/versioned_docs/version-v5.0.0/consumer-development/changeover-procedure.md",sourceDirName:"consumer-development",slug:"/consumer-development/changeover-procedure",permalink:"/interchain-security/v5.0.0/consumer-development/changeover-procedure",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"tutorialSidebar",previous:{title:"Offboarding Checklist",permalink:"/interchain-security/v5.0.0/consumer-development/offboarding"},next:{title:"Consumer Genesis Transformation",permalink:"/interchain-security/v5.0.0/consumer-development/consumer-genesis-transformation"}},c={},d=[{value:"Overview",id:"overview",level:2},{value:"1. ConsumerAddition proposal submitted to the provider chain",id:"1-consumeraddition-proposal-submitted-to-the-provider-chain",level:3},{value:"2. upgrade proposal on standalone chain",id:"2-upgrade-proposal-on-standalone-chain",level:3},{value:"3. spawn time is reached",id:"3-spawn-time-is-reached",level:3},{value:"4. standalone chain upgrade",id:"4-standalone-chain-upgrade",level:3},{value:"Notes",id:"notes",level:4},{value:"Onboarding Checklist",id:"onboarding-checklist",level:2},{value:"1. Complete testing & integration",id:"1-complete-testing--integration",level:2},{value:"2. Create an Onboarding Repository",id:"2-create-an-onboarding-repository",level:2},{value:"3. Submit a ConsumerChainAddition Governance Proposal to the provider",id:"3-submit-a-consumerchainaddition-governance-proposal-to-the-provider",level:2},{value:"3. Submit an Upgrade Proposal & Prepare for Changeover",id:"3-submit-an-upgrade-proposal--prepare-for-changeover",level:2},{value:"4. Upgrade time \ud83d\ude80",id:"4-upgrade-time-",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",input:"input",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"changeover-procedure",children:"Changeover Procedure"}),"\n",(0,s.jsxs)(n.p,{children:["Chains that were not initially launched as consumers of replicated security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the ",(0,s.jsx)(n.strong,{children:"changeover procedure"})," and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain."]}),"\n",(0,s.jsx)(n.p,{children:"The relevant protocol specifications are available below:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/overview_and_basic_concepts.md#channel-initialization-existing-chains",children:"ICS-28 with existing chains"}),"."]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-010-standalone-changeover",children:"ADR in ICS repo"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(n.p,{children:"Standalone to consumer changeover procedure can roughly be separated into 4 parts:"}),"\n",(0,s.jsxs)(n.h3,{id:"1-consumeraddition-proposal-submitted-to-the-provider-chain",children:["1. ConsumerAddition proposal submitted to the ",(0,s.jsx)(n.code,{children:"provider"})," chain"]}),"\n",(0,s.jsx)(n.p,{children:'The proposal is equivalent to the "normal" ConsumerAddition proposal submitted by new consumer chains.'}),"\n",(0,s.jsx)(n.p,{children:"However, here are the most important notes and differences between a new consumer chain and a standalone chain performing a changeover:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"chain_id"})," must be equal to the standalone chain id"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"initial_height"})," field has additional rules to abide by:"]}),"\n"]}),"\n",(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'{\n...\n "initial_height" : {\n // must correspond to current revision number of standalone chain\n // e.g. stride-1 => "revision_number": 1\n "revision_number": 1,\n\n // must correspond to a height that is at least 1 block after the upgrade\n // that will add the `consumer` module to the standalone chain\n // e.g. "upgrade_height": 100 => "revision_height": 101\n "revision_height": 1,\n },\n...\n}\n'})}),(0,s.jsx)(n.p,{children:"RevisionNumber: 0, RevisionHeight: 111"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"genesis_hash"})," can be safely ignored because the chain is already running. A hash of the standalone chain's initial genesis may be used"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"binary_hash"})," may not be available ahead of time. All chains performing the changeover go through rigorous testing - if bugs are caught and fixed the hash listed in the proposal may not be the most recent one."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"spawn_time"})," listed in the proposal MUST be before the ",(0,s.jsx)(n.code,{children:"upgrade_height"})," listed in the upgrade proposal on the standalone chain."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"spawn_time"})," must occur before the ",(0,s.jsx)(n.code,{children:"upgrade_height"})," on the standalone chain is reached because the ",(0,s.jsx)(n.code,{children:"provider"})," chain must generate the ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," that contains the ",(0,s.jsx)(n.strong,{children:"validator set"})," that will be used after the changeover."]})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"unbonding_period"})," must correspond to the value used on the standalone chain. Otherwise, the clients used for the ccv protocol may be incorrectly initialized."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"distribution_transmission_channel"})," ",(0,s.jsx)(n.strong,{children:"should be set"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.admonition,{type:"note",children:[(0,s.jsxs)(n.p,{children:["Populating ",(0,s.jsx)(n.code,{children:"distribution_transmission_channel"})," will enable the standalone chain to reuse one of the existing channels to the provider for consumer chain rewards distribution. This will preserve the ",(0,s.jsx)(n.code,{children:"ibc denom"})," that may already be in use."]}),(0,s.jsx)(n.p,{children:"If the parameter is not set, a new channel will be created."})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"ccv_timeout_period"})," has no important notes"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"transfer_timeout_period"})," has no important notes"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"consumer_redistribution_fraction"})," has no important notes"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"blocks_per_distribution_transmission"})," has no important notes"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"historical_entries"})," has no important notes"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"2-upgrade-proposal-on-standalone-chain",children:"2. upgrade proposal on standalone chain"}),"\n",(0,s.jsxs)(n.p,{children:["The standalone chain creates an upgrade proposal to include the ",(0,s.jsx)(n.code,{children:"interchain-security/x/ccv/consumer"})," module."]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["The upgrade height in the proposal should correspond to a height that is after the ",(0,s.jsx)(n.code,{children:"spawn_time"})," in the consumer addition proposal submitted to the ",(0,s.jsx)(n.code,{children:"provider"})," chain."]})}),"\n",(0,s.jsx)(n.p,{children:"Otherwise, the upgrade is indistinguishable from a regular on-chain upgrade proposal."}),"\n",(0,s.jsx)(n.h3,{id:"3-spawn-time-is-reached",children:"3. spawn time is reached"}),"\n",(0,s.jsxs)(n.p,{children:["When the ",(0,s.jsx)(n.code,{children:"spawn_time"})," is reached on the ",(0,s.jsx)(n.code,{children:"provider"})," it will generate a ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," that contains the validator set that will supersede the ",(0,s.jsx)(n.code,{children:"standalone"})," validator set."]}),"\n",(0,s.jsxs)(n.p,{children:["This ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," must be available on the standalone chain during the on-chain upgrade."]}),"\n",(0,s.jsx)(n.h3,{id:"4-standalone-chain-upgrade",children:"4. standalone chain upgrade"}),"\n",(0,s.jsxs)(n.p,{children:["Performing the on-chain upgrade on the standalone chain will add the ",(0,s.jsx)(n.code,{children:"ccv/consumer"})," module and allow the chain to become a ",(0,s.jsx)(n.code,{children:"consumer"})," of replicated security."]}),"\n",(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," must be exported to a file and placed in the correct folder on the standalone chain before the upgrade."]}),(0,s.jsx)(n.p,{children:"The file must be placed at the exact specified location, otherwise the upgrade will not be executed correctly."}),(0,s.jsxs)(n.p,{children:["Usually the file is placed in ",(0,s.jsx)(n.code,{children:"$NODE_HOME/config"}),", but the file name and the exact directory is dictated by the upgrade code on the ",(0,s.jsx)(n.code,{children:"standalone"})," chain."]}),(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["please check exact instructions provided by the ",(0,s.jsx)(n.code,{children:"standalone"})," chain team"]}),"\n"]})]}),"\n",(0,s.jsxs)(n.p,{children:["After the ",(0,s.jsx)(n.code,{children:"genesis.json"})," file has been made available, the process is equivalent to a normal on-chain upgrade. The standalone validator set will sign the next couple of blocks before transferring control to ",(0,s.jsx)(n.code,{children:"provider"})," validator set."]}),"\n",(0,s.jsxs)(n.p,{children:["The standalone validator set can still be slashed for any infractions if evidence is submitted within the ",(0,s.jsx)(n.code,{children:"unboding_period"}),"."]}),"\n",(0,s.jsx)(n.h4,{id:"notes",children:"Notes"}),"\n",(0,s.jsx)(n.p,{children:"The changeover procedure may be updated in the future to create a seamless way of providing the validator set information to the standalone chain."}),"\n",(0,s.jsx)(n.h2,{id:"onboarding-checklist",children:"Onboarding Checklist"}),"\n",(0,s.jsxs)(n.p,{children:["This onboarding checklist is slightly different from the one under ",(0,s.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/onboarding",children:"Onboarding"})]}),"\n",(0,s.jsxs)(n.p,{children:["Additionally, you can check the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md",children:"testnet repo"})," for a comprehensive guide on preparing and launching consumer chains."]}),"\n",(0,s.jsx)(n.h2,{id:"1-complete-testing--integration",children:"1. Complete testing & integration"}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test integration with gaia"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test your protocol with supported relayer versions (minimum hermes 1.4.1)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test the changeover procedure"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","reach out to the ICS team if you are facing issues"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"2-create-an-onboarding-repository",children:"2. Create an Onboarding Repository"}),"\n",(0,s.jsx)(n.p,{children:"To help validators and other node runners onboard onto your chain, please prepare a repository with information on how to run your chain."}),"\n",(0,s.jsx)(n.p,{children:"This should include (at minimum):"}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json with CCV data (after spawn time passes). Check if CCV data needs to be transformed (see ",(0,s.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/consumer-genesis-transformation",children:"Transform Consumer Genesis"}),")"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","information about relevant seed/peer nodes you are running"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","relayer information (compatible versions)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","copy of your governance proposal (as JSON)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","a script showing how to start your chain and connect to peers (optional)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take feedback from other developers, validators and community regarding your onboarding repo and make improvements where applicable"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Example of such a repository can be found ",(0,s.jsx)(n.a,{href:"https://github.com/hyphacoop/ics-testnets/tree/main/game-of-chains-2022/sputnik",children:"here"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"3-submit-a-consumerchainaddition-governance-proposal-to-the-provider",children:"3. Submit a ConsumerChainAddition Governance Proposal to the provider"}),"\n",(0,s.jsxs)(n.p,{children:["Before you submit a ",(0,s.jsx)(n.code,{children:"ConsumerChainAddition"})," proposal, please provide a ",(0,s.jsx)(n.code,{children:"spawn_time"})," that is ",(0,s.jsx)(n.strong,{children:"before"})," the ",(0,s.jsx)(n.code,{children:"upgrade_height"})," of the upgrade that will introduce the ",(0,s.jsx)(n.code,{children:"ccv module"})," to your chain."]}),"\n",(0,s.jsx)(n.admonition,{type:"danger",children:(0,s.jsxs)(n.p,{children:["If the ",(0,s.jsx)(n.code,{children:"spawn_time"})," happens after your ",(0,s.jsx)(n.code,{children:"upgrade_height"})," the provider will not be able to communicate the new validator set to be used after the changeover."]})}),"\n",(0,s.jsxs)(n.p,{children:["Additionally, reach out to the community via the ",(0,s.jsx)(n.a,{href:"https://forum.cosmos.network/",children:"forum"})," to formalize your intention to become an ICS consumer, gather community support and accept feedback from the community, validators and developers."]}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine your chain's spawn time"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine consumer chain parameters to be put in the proposal"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take note to include a link to your onboarding repository"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Example of a consumer chain addition proposal."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:'// ConsumerAdditionProposal is a governance proposal on the provider chain to spawn a new consumer chain or add a standalone chain.\n// If it passes, then all validators on the provider chain are expected to validate the consumer chain at spawn time.\n// It is recommended that spawn time occurs after the proposal end time and that it is scheduled to happen before the standalone chain upgrade\n// that sill introduce the ccv module.\n{\n // Title of the proposal\n "title": "Changeover Standalone chain",\n // Description of the proposal\n // format the text as a .md file and include the file in your onboarding repository\n "description": ".md description of your chain and all other relevant information",\n // Proposed chain-id of the new consumer chain.\n // Must be unique from all other consumer chain ids of the executing provider chain.\n "chain_id": "standalone-1",\n // Initial height of new consumer chain.\n // For a completely new chain, this will be {0,1}.\n "initial_height" : {\n // must correspond to current revision number of standalone chain\n // e.g. standalone-1 => "revision_number": 1\n "revision_number": 1,\n\n // must correspond to a height that is at least 1 block after the upgrade\n // that will add the `consumer` module to the standalone chain\n // e.g. "upgrade_height": 100 => "revision_height": 101\n "revision_number": 1,\n },\n // Hash of the consumer chain genesis state without the consumer CCV module genesis params.\n // => not relevant for changeover procedure\n "genesis_hash": "d86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0",\n // Hash of the consumer chain binary that should be run by validators on standalone chain upgrade\n // => not relevant for changeover procedure as it may become stale\n "binary_hash": "376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1",\n // Time on the provider chain at which the consumer chain genesis is finalized and all validators\n // will be responsible for starting their consumer chain validator node.\n "spawn_time": "2023-02-28T20:40:00.000000Z",\n // Unbonding period for the consumer chain.\n // It should should be smaller than that of the provider.\n "unbonding_period": 86400000000000,\n // Timeout period for CCV related IBC packets.\n // Packets are considered timed-out after this interval elapses.\n "ccv_timeout_period": 259200000000000,\n // IBC transfer packets will timeout after this interval elapses.\n "transfer_timeout_period": 1800000000000,\n // The fraction of tokens allocated to the consumer redistribution address during distribution events.\n // The fraction is a string representing a decimal number. For example "0.75" would represent 75%.\n // The reward amount distributed to the provider is calculated as: 1 - consumer_redistribution_fraction.\n "consumer_redistribution_fraction": "0.75",\n // BlocksPerDistributionTransmission is the number of blocks between IBC token transfers from the consumer chain to the provider chain.\n // eg. send rewards to the provider every 1000 blocks\n "blocks_per_distribution_transmission": 1000,\n // The number of historical info entries to persist in store.\n // This param is a part of the cosmos sdk staking module. In the case of\n // a ccv enabled consumer chain, the ccv module acts as the staking module.\n "historical_entries": 10000,\n // The ID of a token transfer channel used for the Reward Distribution\n\t// sub-protocol. If DistributionTransmissionChannel == "", a new transfer\n\t// channel is created on top of the same connection as the CCV channel.\n\t// Note that transfer_channel_id is the ID of the channel end on the consumer chain.\n // it is most relevant for chains performing a standalone to consumer changeover\n // in order to maintain the existing ibc transfer channel\n "distribution_transmission_channel": "channel-123" // NOTE: use existing transfer channel if available\n}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"3-submit-an-upgrade-proposal--prepare-for-changeover",children:"3. Submit an Upgrade Proposal & Prepare for Changeover"}),"\n",(0,s.jsxs)(n.p,{children:["This proposal should add the ccv ",(0,s.jsx)(n.code,{children:"consumer"})," module to your chain."]}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","proposal ",(0,s.jsx)(n.code,{children:"upgrade_height"})," must happen after ",(0,s.jsx)(n.code,{children:"spawn_time"})," in the ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","advise validators about the exact procedure for your chain and point them to your onboarding repository"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"4-upgrade-time-",children:"4. Upgrade time \ud83d\ude80"}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","after ",(0,s.jsx)(n.code,{children:"spawn_time"}),", request ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," from the ",(0,s.jsx)(n.code,{children:"provider"})," and place it in ",(0,s.jsx)(n.code,{children:"/.sovereign/config/genesis.json"})]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","upgrade the binary to the one listed in your ",(0,s.jsx)(n.code,{children:"UpgradeProposal"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:['The chain starts after at least 66.67% of standalone voting power comes online. The consumer chain is considered interchain secured once the "old" validator set signs a couple of blocks and transfers control to the ',(0,s.jsx)(n.code,{children:"provider"})," validator set."]}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","provide a repo with onboarding instructions for validators (it should already be listed in the proposal)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json after ",(0,s.jsx)(n.code,{children:"spawn_time"})," obtained from ",(0,s.jsx)(n.code,{children:"provider"})," (MUST contain the initial validator set)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","maintenance & emergency contact info (relevant discord, telegram, slack or other communication channels)"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>a});var s=i(7294);const t={},o=s.createContext(t);function a(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/287de311.83f8008b.js b/assets/js/287de311.83f8008b.js
new file mode 100644
index 0000000000..2ae7caafa1
--- /dev/null
+++ b/assets/js/287de311.83f8008b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7184],{3879:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>a,metadata:()=>o,toc:()=>h});var s=i(5893),t=i(1151);const a={sidebar_position:1},r="Overview",o={id:"validators/overview",title:"Overview",description:"We advise that you join the Replicated Security testnet to gain hands-on experience with running consumer chains.",source:"@site/versioned_docs/version-v4.2.0-docs/validators/overview.md",sourceDirName:"validators",slug:"/validators/overview",permalink:"/interchain-security/v4.2.0/validators/overview",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Consumer Genesis Transformation",permalink:"/interchain-security/v4.2.0/consumer-development/consumer-genesis-transformation"},next:{title:"Joining Interchain Security testnet",permalink:"/interchain-security/v4.2.0/validators/joining-testnet"}},c={},h=[{value:"Startup sequence overview",id:"startup-sequence-overview",level:2},{value:"1. Consumer Chain init + 2. Genesis generation",id:"1-consumer-chain-init--2-genesis-generation",level:3},{value:"3. Submit Proposal",id:"3-submit-proposal",level:3},{value:"4. CCV Genesis state generation",id:"4-ccv-genesis-state-generation",level:3},{value:"5. Updating the genesis file",id:"5-updating-the-genesis-file",level:3},{value:"6. Chain start",id:"6-chain-start",level:3},{value:"7. Creating IBC connections",id:"7-creating-ibc-connections",level:3},{value:"Downtime Infractions",id:"downtime-infractions",level:2},{value:"Double-signing Infractions",id:"double-signing-infractions",level:2},{value:"Key assignment",id:"key-assignment",level:2},{value:"References:",id:"references",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["We advise that you join the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security",children:"Replicated Security testnet"})," to gain hands-on experience with running consumer chains."]})}),"\n",(0,s.jsx)(n.p,{children:"At present, replicated security requires all validators of the provider chain (ie. Cosmos Hub) to run validator nodes for all governance-approved consumer chains."}),"\n",(0,s.jsxs)(n.p,{children:["Once a ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})," passes, validators need to prepare to run the consumer chain binaries (these will be linked in their proposals) and set up validator nodes on governance-approved consumer chains."]}),"\n",(0,s.jsx)(n.p,{children:"Provider chain and consumer chains represent standalone chains that only share the validator set ie. the same validator operators are tasked with running all chains."}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"To validate a consumer chain and be eligible for rewards validators are required to be in the active set of the provider chain (first 180 validators for Cosmos Hub)."})}),"\n",(0,s.jsx)(n.h2,{id:"startup-sequence-overview",children:"Startup sequence overview"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer chains cannot start and be secured by the validator set of the provider unless a ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})," is passed.\nEach proposal contains defines a ",(0,s.jsx)(n.code,{children:"spawn_time"})," - the timestamp when the consumer chain genesis is finalized and the consumer chain clients get initialized on the provider."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["Validators are required to run consumer chain binaries only after ",(0,s.jsx)(n.code,{children:"spawn_time"})," has passed."]})}),"\n",(0,s.jsx)(n.p,{children:"Please note that any additional instructions pertaining to specific consumer chain launches will be available before spawn time. The chain start will be stewarded by the Cosmos Hub team and the teams developing their respective consumer chains."}),"\n",(0,s.jsxs)(n.p,{children:["The image below illustrates the startup sequence\n",(0,s.jsx)(n.img,{alt:"startup",src:i(9558).Z+"",width:"942",height:"632"})]}),"\n",(0,s.jsx)(n.h3,{id:"1-consumer-chain-init--2-genesis-generation",children:"1. Consumer Chain init + 2. Genesis generation"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer chain team initializes the chain genesis.json and prepares binaries which will be listed in the ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})]}),"\n",(0,s.jsx)(n.h3,{id:"3-submit-proposal",children:"3. Submit Proposal"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer chain team (or their advocates) submits a ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"}),".\nThe most important parameters for validators are:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"spawn_time"})," - the time after which the consumer chain must be started"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"genesis_hash"})," - hash of the pre-ccv genesis.json; the file does not contain any validator info -> the information is available only after the proposal is passed and ",(0,s.jsx)(n.code,{children:"spawn_time"})," is reached"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"binary_hash"})," - hash of the consumer chain binary used to validate the software builds"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"4-ccv-genesis-state-generation",children:"4. CCV Genesis state generation"}),"\n",(0,s.jsxs)(n.p,{children:["After reaching ",(0,s.jsx)(n.code,{children:"spawn_time"})," the provider chain will automatically create the CCV validator states that will be used to populate the corresponding fields in the consumer chain ",(0,s.jsx)(n.code,{children:"genesis.json"}),". The CCV validator set consists of the validator set on the provider at ",(0,s.jsx)(n.code,{children:"spawn_time"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"The state can be queried on the provider chain (in this case the Cosmos Hub):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:" gaiad query provider consumer-genesis -o json > ccvconsumer_genesis.json\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This is used by the launch coordinator to create the final ",(0,s.jsx)(n.code,{children:"genesis.json"})," that will be distributed to validators in step 5."]}),"\n",(0,s.jsx)(n.h3,{id:"5-updating-the-genesis-file",children:"5. Updating the genesis file"}),"\n",(0,s.jsxs)(n.p,{children:["Upon reaching the ",(0,s.jsx)(n.code,{children:"spawn_time"})," the initial validator set state will become available on the provider chain. The initial validator set is included in the ",(0,s.jsx)(n.strong,{children:"final genesis.json"})," of the consumer chain."]}),"\n",(0,s.jsx)(n.h3,{id:"6-chain-start",children:"6. Chain start"}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"The consumer chain will start producing blocks as soon as 66.67% of the provider chain's voting power comes online (on the consumer chain). The relayer should be started after block production commences."})}),"\n",(0,s.jsxs)(n.p,{children:["The new ",(0,s.jsx)(n.code,{children:"genesis.json"})," containing the initial validator set will be distributed to validators by the consumer chain team (launch coordinator). Each validator should use the provided ",(0,s.jsx)(n.code,{children:"genesis.json"})," to start their consumer chain node."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["Please pay attention to any onboarding repositories provided by the consumer chain teams.\nRecommendations are available in ",(0,s.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/onboarding",children:"Consumer Onboarding Checklist"}),".\nAnother comprehensive guide is available in the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md",children:"Interchain Security testnet repo"}),"."]})}),"\n",(0,s.jsx)(n.h3,{id:"7-creating-ibc-connections",children:"7. Creating IBC connections"}),"\n",(0,s.jsx)(n.p,{children:"Finally, to fully establish interchain security an IBC relayer is used to establish connections and create the required channels."}),"\n",(0,s.jsx)(n.admonition,{type:"warning",children:(0,s.jsx)(n.p,{children:"The relayer can establish the connection only after the consumer chain starts producing blocks."})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"hermes create connection --a-chain --a-client 07-tendermint-0 --b-client \nhermes create channel --a-chain --a-port consumer --b-port provider --order ordered --a-connection connection-0 --channel-version 1\nhermes start\n"})}),"\n",(0,s.jsx)(n.h2,{id:"downtime-infractions",children:"Downtime Infractions"}),"\n",(0,s.jsxs)(n.p,{children:["At present, the consumer chain can report evidence about downtime infractions to the provider chain. The ",(0,s.jsx)(n.code,{children:"min_signed_per_window"})," and ",(0,s.jsx)(n.code,{children:"signed_blocks_window"})," can be different on each consumer chain and are subject to changes via consumer chain governance."]}),"\n",(0,s.jsxs)(n.admonition,{type:"info",children:[(0,s.jsx)(n.p,{children:"Causing a downtime infraction on any consumer chain will not incur a slash penalty. Instead, the offending validator will be jailed on the provider chain and consequently on all consumer chains."}),(0,s.jsxs)(n.p,{children:["To unjail, the validator must wait for the jailing period to elapse on the provider chain and ",(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup#unjail-validator",children:"submit an unjail transaction"})," on the provider chain. After unjailing on the provider, the validator will be unjailed on all consumer chains."]}),(0,s.jsxs)(n.p,{children:["More information is available in ",(0,s.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/slashing#downtime-infractions",children:"Downtime Slashing documentation"})]})]}),"\n",(0,s.jsx)(n.h2,{id:"double-signing-infractions",children:"Double-signing Infractions"}),"\n",(0,s.jsxs)(n.p,{children:["To learn more about equivocation handling in interchain security check out the ",(0,s.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/slashing",children:"Slashing"})," documentation section."]}),"\n",(0,s.jsx)(n.h2,{id:"key-assignment",children:"Key assignment"}),"\n",(0,s.jsx)(n.p,{children:"Validators can use different consensus keys on the provider and each of the consumer chains. The consumer chain consensus key must be registered on the provider before use."}),"\n",(0,s.jsxs)(n.p,{children:["For more information check out the ",(0,s.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/key-assignment",children:"Key assignment overview and guide"})]}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-faq",children:"Cosmos Hub Validators FAQ"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup",children:"Cosmos Hub Running a validator"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md#chain-launch",children:"Startup Sequence"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup#unjail-validator",children:"Submit Unjailing Transaction"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},9558:(e,n,i)=>{i.d(n,{Z:()=>s});const s=i.p+"assets/images/hypha-consumer-start-process-2141109f76c584706dd994d7965fd692.svg"},1151:(e,n,i)=>{i.d(n,{Z:()=>o,a:()=>r});var s=i(7294);const t={},a=s.createContext(t);function r(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/2a9fa04d.fa9a65c7.js b/assets/js/2a9fa04d.fa9a65c7.js
new file mode 100644
index 0000000000..d88af73ae4
--- /dev/null
+++ b/assets/js/2a9fa04d.fa9a65c7.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3670],{8328:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var i=n(5893),s=n(1151);const r={sidebar_position:7,title:"Throttle with retries"},a=void 0,o={id:"adrs/adr-008-throttle-retries",title:"Throttle with retries",description:"ADR 008: Throttle with retries",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-008-throttle-retries.md",sourceDirName:"adrs",slug:"/adrs/adr-008-throttle-retries",permalink:"/interchain-security/v4.2.0/adrs/adr-008-throttle-retries",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:7,frontMatter:{sidebar_position:7,title:"Throttle with retries"},sidebar:"tutorialSidebar",previous:{title:"Cryptographic verification of equivocation evidence",permalink:"/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification"},next:{title:"Soft Opt-Out",permalink:"/interchain-security/v4.2.0/adrs/adr-009-soft-opt-out"}},d={},c=[{value:"ADR 008: Throttle with retries",id:"adr-008-throttle-with-retries",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consumer changes",id:"consumer-changes",level:3},{value:"Consumer pending packets storage optimization",id:"consumer-pending-packets-storage-optimization",level:4},{value:"Provider changes",id:"provider-changes",level:3},{value:"Handling VSCMaturedPackets immediately",id:"handling-vscmaturedpackets-immediately",level:4},{value:"Why the provider can handle VSCMatured packets immediately",id:"why-the-provider-can-handle-vscmatured-packets-immediately",level:4},{value:"Splitting of PRs and Upgrade Order",id:"splitting-of-prs-and-upgrade-order",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"adr-008-throttle-with-retries",children:"ADR 008: Throttle with retries"}),"\n",(0,i.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"6/9/23: Initial draft"}),"\n",(0,i.jsx)(t.li,{children:"6/22/23: added note on consumer pending packets storage optimization"}),"\n",(0,i.jsx)(t.li,{children:"7/14/23: Added note on upgrade order"}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(t.p,{children:"Accepted"}),"\n",(0,i.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,i.jsxs)(t.p,{children:["For context on why the throttling mechanism exists, see ",(0,i.jsx)(t.a,{href:"/interchain-security/v4.2.0/adrs/adr-002-throttle",children:"ADR 002"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Note the terms slash throttling and jail throttling are synonymous, since in replicated security a ",(0,i.jsx)(t.code,{children:"SlashPacket"})," simply jails a validator for downtime infractions."]}),"\n",(0,i.jsxs)(t.p,{children:["Currently the throttling mechanism is designed so that provider logic (slash meter, etc.) dictates how many ",(0,i.jsx)(t.code,{children:"SlashPackets"})," can be handled over time.\nThrottled ",(0,i.jsx)(t.code,{children:"SlashPackets"})," are persisted on the provider, leading to multiple possible issues. Namely:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["If ",(0,i.jsx)(t.code,{children:"SlashPackets"})," or ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," are actually throttled/queued on the provider, state can grow and potentially lead to a DoS attack.\nWe have short term solutions around this, but overall they come with their own weaknesses.\nSee ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/594",children:"#594"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:["If a jailing attack described in ",(0,i.jsx)(t.a,{href:"/interchain-security/v4.2.0/adrs/adr-002-throttle",children:"ADR 002"})," were actually to be carried out with the current throttling design, we'd likely have to halt the provider, and perform an emergency upgrade and/or migration to clear the queues of ",(0,i.jsx)(t.code,{children:"SlashPackets"})," that were deemed to be malicious.\nAlternatively, validators would just have to ",(0,i.jsx)(t.em,{children:"tough it out"})," and wait for the queues to clear, during which all/most validators would be jailed.\nRight after being jailed, validators would have to unjail themselves promptly to ensure safety.\nThe coordination required to maintain safety in such a scenario is not ideal."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"As a solution, we can improve the throttling mechanism to instead queue/persist relevant data on each consumer, and have consumers retry slash requests as needed."}),"\n",(0,i.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(t.h3,{id:"consumer-changes",children:"Consumer changes"}),"\n",(0,i.jsxs)(t.p,{children:["Note the consumer already queues up both ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," via ",(0,i.jsx)(t.code,{children:"AppendPendingPacket"}),".\nThose packets are dequeued in every ",(0,i.jsx)(t.code,{children:"EndBlock"})," in ",(0,i.jsx)(t.code,{children:"SendPackets"})," and sent to the provider."]}),"\n",(0,i.jsxs)(t.p,{children:["Instead, we will now introduce the following logic on ",(0,i.jsx)(t.code,{children:"EndBlock"}),":"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Slash packets will always be sent to the provider once they're at the head of the queue.\nHowever, once sent, the consumer will not send any subsequent ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," from the queue until the provider responds with an acknowledgement that the sent ",(0,i.jsx)(t.code,{children:"SlashPacket"})," has been handled, i.e., validator was jailed.\nThat is, ",(0,i.jsx)(t.code,{children:"SlashPackets"})," block the sending of subsequent ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," in the consumer queue."]}),"\n",(0,i.jsxs)(t.li,{children:["If two ",(0,i.jsx)(t.code,{children:"SlashPackets"})," are at the head of the queue, the consumer will send the first ",(0,i.jsx)(t.code,{children:"SlashPacket"}),", and then wait for a success acknowledgement from the provider before sending the second ",(0,i.jsx)(t.code,{children:"SlashPacket"}),".\nThis seems like it'd simplify implementation."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," at the head of the queue (i.e., NOT following a ",(0,i.jsx)(t.code,{children:"SlashPacket"}),") can be sent immediately, and do not block any other packets in the queue, since the provider always handles them immediately."]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["To prevent the provider from having to keep track of what ",(0,i.jsx)(t.code,{children:"SlashPackets"})," have been rejected, the consumer will have to retry the sending of ",(0,i.jsx)(t.code,{children:"SlashPackets"})," over some period of time.\nThis can be achieved with an on-chain consumer param, i.e., ",(0,i.jsx)(t.code,{children:"RetryDelayPeriod"}),".\nTo reduce the amount of redundant re-sends, we recommend setting ",(0,i.jsx)(t.code,{children:"RetryDelayPeriod ~ SlashMeterReplenishmentPeriod"}),", i.e., waiting for the provider slash meter to be replenished before resending the rejected ",(0,i.jsx)(t.code,{children:"SlashPacket"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"Note to prevent weird edge case behavior, a retry would not be attempted until either a success or failure acknowledgement has been received from the provider."}),"\n",(0,i.jsxs)(t.p,{children:["With the behavior described, we maintain very similar behavior to the previous throttling mechanism regarding the timing that ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," are handled on the provider.\nObviously the queueing and blocking logic is moved, and the two chains would have to send more messages between one another (only in the case the throttling mechanism is triggered)."]}),"\n",(0,i.jsxs)(t.p,{children:["In the normal case, when no or a few ",(0,i.jsx)(t.code,{children:"SlashPackets"})," are being sent, the ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," will not be delayed, and hence unbonding will not be delayed."]}),"\n",(0,i.jsxs)(t.p,{children:["For the implementation of this design, see ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/fec3eccad59416cbdb6844e279f59e3f81242888/x/ccv/consumer/keeper/throttle_retry.go",children:"throttle_retry.go"}),"."]}),"\n",(0,i.jsx)(t.h4,{id:"consumer-pending-packets-storage-optimization",children:"Consumer pending packets storage optimization"}),"\n",(0,i.jsx)(t.p,{children:"In addition to the mentioned consumer changes, an optimization will need to be made to the consumer's pending packets storage to properly implement the feature from this ADR."}),"\n",(0,i.jsxs)(t.p,{children:['The consumer ccv module previously queued "pending packets" to be sent in each ',(0,i.jsx)(t.code,{children:"EndBlock"})," in ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/3bc4e7135066d848aac60b0787364c07157fd36d/x/ccv/consumer/keeper/relay.go#L178",children:"SendPackets"}),".\nThese packets are queued in state with a protobuf list of ",(0,i.jsx)(t.code,{children:"ConsumerPacketData"}),".\nFor a single append operation, the entire list is deserialized, then a packet is appended to that list, and the list is serialized again.\nSee older version of ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/05c2dae7c6372b1252b9e97215d07c6aa7618f33/x/ccv/consumer/keeper/keeper.go#L606",children:"AppendPendingPacket"}),".\nThat is, a single append operation has O(N) complexity, where N is the size of the list."]}),"\n",(0,i.jsxs)(t.p,{children:["This poor append performance isn't a problem when the pending packets list is small.\nBut with this ADR being implemented, the pending packets list could potentially grow to the order of thousands of entries when ",(0,i.jsx)(t.code,{children:"SlashPackets"})," need to be resent."]}),"\n",(0,i.jsx)(t.p,{children:"We can improve the append time for this queue by converting it from a protobuf-esq list, to a queue implemented with sdk-esq code.\nThe idea is to persist a uint64 index that will be incremented each time you queue up a packet.\nYou can think of this as storing the tail of the queue.\nThen, packet data will be keyed by that index, making the data naturally ordered byte-wise for sdk's iterator.\nThe index will also be stored in the packet data value bytes, so that the index can later be used to delete certain packets from the queue."}),"\n",(0,i.jsx)(t.p,{children:"Two things are achieved with this approach:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"More efficient packet append/enqueue times"}),"\n",(0,i.jsx)(t.li,{children:"The ability to delete select packets from the queue (previously all packets were deleted at once)"}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"provider-changes",children:"Provider changes"}),"\n",(0,i.jsxs)(t.p,{children:["The main change needed for the provider is the removal of queuing logic for ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," upon being received."]}),"\n",(0,i.jsxs)(t.p,{children:["Instead, the provider will consult the slash meter to determine if a ",(0,i.jsx)(t.code,{children:"SlashPacket"})," can be handled immediately.\nIf not, the provider will return an acknowledgement message to the consumer communicating that the ",(0,i.jsx)(t.code,{children:"SlashPacket"})," could not be handled, and needs to be sent again in the future (retried)."]}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," will always be handled immediately upon being received by the provider."]}),"\n",(0,i.jsxs)(t.p,{children:["Note ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#consumer-initiated-slashing",children:"spec"}),". Specifically the section on ",(0,i.jsx)(t.em,{children:"VSC Maturity and Slashing Order"}),". Previously the onus was on the provider to maintain this property via queuing packets and handling them FIFO."]}),"\n",(0,i.jsxs)(t.p,{children:["Now this property will be maintained by the consumer sending packets in the correct order, and blocking the sending of ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," as needed. Then, the ordered IBC channel will ensure that ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," are received in the correct order on the provider."]}),"\n",(0,i.jsxs)(t.p,{children:["The provider's main responsibility regarding throttling will now be to determine if a received ",(0,i.jsx)(t.code,{children:"SlashPacket"})," can be handled via slash meter etc., and appropriately acknowledge to the sending consumer."]}),"\n",(0,i.jsxs)(t.h4,{id:"handling-vscmaturedpackets-immediately",children:["Handling ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," immediately"]}),"\n",(0,i.jsx)(t.h4,{id:"why-the-provider-can-handle-vscmatured-packets-immediately",children:"Why the provider can handle VSCMatured packets immediately"}),"\n",(0,i.jsxs)(t.p,{children:["A ",(0,i.jsx)(t.code,{children:"VSCMaturedPacket"})," communicates to the provider that sufficient time passed on the consumer since the corresponding ",(0,i.jsx)(t.code,{children:"VSCPacket"})," has been applied (on the consumer) such that infractions committed on the consumer could have been submitted."]}),"\n",(0,i.jsxs)(t.p,{children:["If the consumer is following the queuing/blocking protocol described, then no bad behavior occurs and the ",(0,i.jsx)(t.em,{children:"VSC Maturity and Slashing Order"})," property is maintained."]}),"\n",(0,i.jsxs)(t.p,{children:["If a consumer sends ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," too leniently -- the consumer is malicious and sends duplicate ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"}),", or sends the packets sooner than the CCV protocol specifies -- then the provider needs to handle ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," immediately to prevent DOS, state bloat, or other issues.\nThe only possible negative outcome is that the malicious consumer may not be able to jail a validator who should have been jailed.\nThe malicious behavior only creates a negative outcome for the consumer chain that is being malicious."]}),"\n",(0,i.jsxs)(t.p,{children:["If a consumer blocks the sending of ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"}),", then unbonding operations on the provider will be delayed, but only until the VSC timeout period has elapsed.\nAt that time, the consumer is removed.\nAgain the malicious behavior only creates a negative outcome for the consumer chain that is being malicious."]}),"\n",(0,i.jsx)(t.h3,{id:"splitting-of-prs-and-upgrade-order",children:"Splitting of PRs and Upgrade Order"}),"\n",(0,i.jsxs)(t.p,{children:["This feature will implement consumer changes in ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1024",children:"#1024"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["\u2757",(0,i.jsx)(t.em,{children:(0,i.jsx)(t.strong,{children:"These changes should be deployed to production for all consumers before the provider changes are deployed to production."})})]}),"\n",(0,i.jsxs)(t.p,{children:["In other words, the consumer changes in ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1024",children:"#1024"}),' are compatible with the current ("v1") provider implementation of throttling that\'s running on the Cosmos Hub as of July 2023.']}),"\n",(0,i.jsxs)(t.p,{children:["Once all consumers have deployed the changes in #1024, the provider changes from ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1321",children:"#1321"})," can be deployed to production, fully enabling v2 throttling."]}),"\n",(0,i.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Consumers will now have to manage their own queues, and retry logic."}),"\n",(0,i.jsx)(t.li,{children:"Consumers still aren't trustless, but the provider is now less susceptible to mismanaged or malicious consumers."}),"\n",(0,i.jsx)(t.li,{children:'Recovering from the "jailing attack" is more elegant.'}),"\n",(0,i.jsxs)(t.li,{children:["Some issues like ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/1001",children:"#1001"})," will now be handled implicitly by the improved throttling mechanism."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," can be handled immediately once received by the provider if the slash meter allows."]}),"\n",(0,i.jsxs)(t.li,{children:["In general, we reduce the amount of computation that happens in the provider ",(0,i.jsx)(t.code,{children:"EndBlock"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:['We no longer have to reason about a "global queue" and a "chain specific queue", and keeping those all in-sync.\nNow ',(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," queuing is handled on each consumer individually."]}),"\n",(0,i.jsx)(t.li,{children:"Due to the above, the throttling protocol becomes less complex overall."}),"\n",(0,i.jsx)(t.li,{children:"We no longer have to worry about throttle related DoS attack on the provider, since no queuing exists on the provider."}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Increased number of IBC packets being relayed anytime throttling logic is triggered."}),"\n",(0,i.jsx)(t.li,{children:"Consumer complexity increases, since consumers now have manage queuing themselves, and implement packet retry logic."}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Core throttling logic on the provider remains unchanged, i.e., slash meter, replenishment cycles, etc."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/713",children:"EPIC"})," tracking the changes proposed by this ADR"]}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/interchain-security/v4.2.0/adrs/adr-002-throttle",children:"ADR 002: Jail Throttling"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/594",children:"#594"})}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>o,a:()=>a});var i=n(7294);const s={},r=i.createContext(s);function a(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/2c92eef1.232084f8.js b/assets/js/2c92eef1.232084f8.js
new file mode 100644
index 0000000000..2380e41429
--- /dev/null
+++ b/assets/js/2c92eef1.232084f8.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3158],{6386:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>s,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>p});var n=t(5893),c=t(1151);const o={sidebar_position:4},r="Technical Specification",a={id:"introduction/technical-specification",title:"Technical Specification",description:"For a technical deep dive into the replicated security protocol, see the specification.",source:"@site/versioned_docs/version-v5.0.0/introduction/technical-specification.md",sourceDirName:"introduction",slug:"/introduction/technical-specification",permalink:"/interchain-security/v5.0.0/introduction/technical-specification",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"Interchain Security Parameters",permalink:"/interchain-security/v5.0.0/introduction/params"},next:{title:"Upgrading to ICS v5.0.0",permalink:"/interchain-security/v5.0.0/upgrading/migrate_v4_v5"}},s={},p=[];function d(e){const i={a:"a",h1:"h1",p:"p",...(0,c.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"technical-specification",children:"Technical Specification"}),"\n",(0,n.jsxs)(i.p,{children:["For a technical deep dive into the replicated security protocol, see the ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/README.md",children:"specification"}),"."]})]})}function u(e={}){const{wrapper:i}={...(0,c.a)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},1151:(e,i,t)=>{t.d(i,{Z:()=>a,a:()=>r});var n=t(7294);const c={},o=n.createContext(c);function r(e){const i=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function a(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:r(e.components),n.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/2ed06975.0d9c3801.js b/assets/js/2ed06975.0d9c3801.js
new file mode 100644
index 0000000000..018f0b9a2f
--- /dev/null
+++ b/assets/js/2ed06975.0d9c3801.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1038],{439:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var r=i(5893),t=i(1151);const s={sidebar_position:1,title:"ADRs"},c="Architecture Decision Records (ADR)",a={id:"adrs/intro",title:"ADRs",description:"This is a location to record all high-level architecture decisions in the Interchain Security project.",source:"@site/versioned_docs/version-v5.0.0/adrs/intro.md",sourceDirName:"adrs",slug:"/adrs/intro",permalink:"/interchain-security/v5.0.0/adrs/intro",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:1,frontMatter:{sidebar_position:1,title:"ADRs"},sidebar:"tutorialSidebar",previous:{title:"Frequently Asked Questions",permalink:"/interchain-security/v5.0.0/faq"},next:{title:"ADR Template",permalink:"/interchain-security/v5.0.0/adrs/adr-004-denom-dos-fixes"}},o={},d=[{value:"Table of Contents",id:"table-of-contents",level:2},{value:"Accepted",id:"accepted",level:3},{value:"Proposed",id:"proposed",level:3},{value:"Rejected",id:"rejected",level:3},{value:"Deprecated",id:"deprecated",level:3}];function h(e){const n={a:"a",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,t.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"architecture-decision-records-adr",children:"Architecture Decision Records (ADR)"}),"\n",(0,r.jsx)(n.p,{children:"This is a location to record all high-level architecture decisions in the Interchain Security project."}),"\n",(0,r.jsxs)(n.p,{children:["You can read more about the ADR concept in this ",(0,r.jsx)(n.a,{href:"https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0#.78xhdix6t",children:"blog post"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"An ADR should provide:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Context on the relevant goals and the current state"}),"\n",(0,r.jsx)(n.li,{children:"Proposed changes to achieve the goals"}),"\n",(0,r.jsx)(n.li,{children:"Summary of pros and cons"}),"\n",(0,r.jsx)(n.li,{children:"References"}),"\n",(0,r.jsx)(n.li,{children:"Changelog"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Note the distinction between an ADR and a spec. The ADR provides the context, intuition, reasoning, and\njustification for a change in architecture, or for the architecture of something\nnew. The spec is much more compressed and streamlined summary of everything as\nit is or should be."}),"\n",(0,r.jsx)(n.p,{children:"If recorded decisions turned out to be lacking, convene a discussion, record the new decisions here, and then modify the code to match."}),"\n",(0,r.jsx)(n.p,{children:"Note the context/background should be written in the present tense."}),"\n",(0,r.jsxs)(n.p,{children:["To suggest an ADR, please make use of the ",(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-template",children:"ADR template"})," provided."]}),"\n",(0,r.jsx)(n.h2,{id:"table-of-contents",children:"Table of Contents"}),"\n",(0,r.jsx)(n.h3,{id:"accepted",children:"Accepted"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-001-key-assignment",children:"ADR 001: Key Assignment"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-002-throttle",children:"ADR 002: Jail Throttling"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-004-denom-dos-fixes",children:"ADR 004: Denom DOS fixes"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR 005: Cryptographic verification of equivocation evidence"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-008-throttle-retries",children:"ADR 008: Throttle with retries"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-009-soft-opt-out",children:"ADR 009: Soft Opt-Out"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-010-standalone-changeover",children:"ADR 010: Standalone to Consumer Changeover"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing",children:"ADR 013: Slashing on the provider for consumer equivocation"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"proposed",children:"Proposed"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-011-improving-test-confidence",children:"ADR 011: Improving testing and increasing confidence"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-014-epochs",children:"ADR 014: Epochs"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-015-partial-set-security",children:"ADR 015: Partial Set Security"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"rejected",children:"Rejected"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-007-pause-unbonding-on-eqv-prop",children:"ADR 007: Pause validator unbonding during equivocation proposal"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-012-separate-releasing",children:"ADR 012: Separate Releasing"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"deprecated",children:"Deprecated"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-003-equivocation-gov-proposal",children:"ADR 003: Equivocation governance proposal"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>a,a:()=>c});var r=i(7294);const t={},s=r.createContext(t);function c(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:c(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/3672b5b7.7d4ba869.js b/assets/js/3672b5b7.7d4ba869.js
new file mode 100644
index 0000000000..f504805255
--- /dev/null
+++ b/assets/js/3672b5b7.7d4ba869.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[320],{9873:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>t,default:()=>h,frontMatter:()=>o,metadata:()=>d,toc:()=>a});var r=n(5893),s=n(1151);const o={sidebar_position:3},t="Interchain Security Parameters",d={id:"introduction/params",title:"Interchain Security Parameters",description:"The parameters necessary for Interchain Security (ICS) are defined in",source:"@site/docs/introduction/params.md",sourceDirName:"introduction",slug:"/introduction/params",permalink:"/interchain-security/introduction/params",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"tutorialSidebar",previous:{title:"Terminology",permalink:"/interchain-security/introduction/terminology"},next:{title:"Technical Specification",permalink:"/interchain-security/introduction/technical-specification"}},c={},a=[{value:"Time-Based Parameters",id:"time-based-parameters",level:2},{value:"ProviderUnbondingPeriod",id:"providerunbondingperiod",level:3},{value:"ConsumerUnbondingPeriod",id:"consumerunbondingperiod",level:3},{value:"TrustingPeriodFraction",id:"trustingperiodfraction",level:3},{value:"CCVTimeoutPeriod",id:"ccvtimeoutperiod",level:3},{value:"InitTimeoutPeriod",id:"inittimeoutperiod",level:3},{value:"VscTimeoutPeriod",id:"vsctimeoutperiod",level:3},{value:"BlocksPerDistributionTransmission",id:"blocksperdistributiontransmission",level:3},{value:"TransferPeriodTimeout",id:"transferperiodtimeout",level:3},{value:"Reward Distribution Parameters",id:"reward-distribution-parameters",level:2},{value:"ConsumerRedistributionFraction",id:"consumerredistributionfraction",level:3},{value:"BlocksPerDistributionTransmission",id:"blocksperdistributiontransmission-1",level:3},{value:"TransferTimeoutPeriod",id:"transfertimeoutperiod",level:3},{value:"DistributionTransmissionChannel",id:"distributiontransmissionchannel",level:3},{value:"ProviderFeePoolAddrStr",id:"providerfeepooladdrstr",level:3},{value:"Slash Throttle Parameters",id:"slash-throttle-parameters",level:2},{value:"SlashMeterReplenishPeriod",id:"slashmeterreplenishperiod",level:3},{value:"SlashMeterReplenishFraction",id:"slashmeterreplenishfraction",level:3},{value:"MaxThrottledPackets",id:"maxthrottledpackets",level:3},{value:"RetryDelayPeriod",id:"retrydelayperiod",level:3},{value:"Epoch Parameters",id:"epoch-parameters",level:2},{value:"BlocksPerEpoch",id:"blocksperepoch",level:3}];function l(e){const i={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.h1,{id:"interchain-security-parameters",children:"Interchain Security Parameters"}),"\n",(0,r.jsx)(i.p,{children:"The parameters necessary for Interchain Security (ICS) are defined in"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["the ",(0,r.jsx)(i.code,{children:"Params"})," structure in ",(0,r.jsx)(i.code,{children:"proto/interchain_security/ccv/provider/v1/provider.proto"})," for the provider;"]}),"\n",(0,r.jsxs)(i.li,{children:["the ",(0,r.jsx)(i.code,{children:"Params"})," structure in ",(0,r.jsx)(i.code,{children:"proto/interchain_security/ccv/consumer/v1/consumer.proto"})," for the consumer."]}),"\n"]}),"\n",(0,r.jsx)(i.h2,{id:"time-based-parameters",children:"Time-Based Parameters"}),"\n",(0,r.jsx)(i.p,{children:"ICS relies on the following time-based parameters."}),"\n",(0,r.jsx)(i.h3,{id:"providerunbondingperiod",children:"ProviderUnbondingPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ProviderUnbondingPeriod"})," is the unbonding period on the provider chain as configured during chain genesis. This parameter can later be changed via governance."]}),"\n",(0,r.jsx)(i.h3,{id:"consumerunbondingperiod",children:"ConsumerUnbondingPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"})," is the unbonding period on the consumer chain."]}),"\n",(0,r.jsxs)(i.admonition,{type:"info",children:[(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"})," is set via the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})," governance proposal to add a new consumer chain.\nIt is recommended that every consumer chain set and unbonding period shorter than ",(0,r.jsx)(i.code,{children:"ProviderUnbondingPeriod"})]}),(0,r.jsx)("br",{}),(0,r.jsx)(i.p,{children:"Example:"}),(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod = ProviderUnbondingPeriod - one day\n"})})]}),"\n",(0,r.jsx)(i.p,{children:"Unbonding operations (such as undelegations) are completed on the provider only after the unbonding period elapses on every consumer."}),"\n",(0,r.jsx)(i.h3,{id:"trustingperiodfraction",children:"TrustingPeriodFraction"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TrustingPeriodFraction"})," is used to calculate the ",(0,r.jsx)(i.code,{children:"TrustingPeriod"})," of created IBC clients on both provider and consumer chains."]}),"\n",(0,r.jsxs)(i.p,{children:["Setting ",(0,r.jsx)(i.code,{children:"TrustingPeriodFraction"})," to ",(0,r.jsx)(i.code,{children:"0.5"})," would result in the following:"]}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{children:"TrustingPeriodFraction = 0.5\nProviderClientOnConsumerTrustingPeriod = ProviderUnbondingPeriod * 0.5\nConsumerClientOnProviderTrustingPeriod = ConsumerUnbondingPeriod * 0.5\n"})}),"\n",(0,r.jsxs)(i.p,{children:["Note that a light clients must be updated within the ",(0,r.jsx)(i.code,{children:"TrustingPeriod"})," in order to avoid being frozen."]}),"\n",(0,r.jsxs)(i.p,{children:["For more details, see the ",(0,r.jsx)(i.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/client/ics-007-tendermint-client/README.md",children:"IBC specification of Tendermint clients"}),"."]}),"\n",(0,r.jsx)(i.h3,{id:"ccvtimeoutperiod",children:"CCVTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"CCVTimeoutPeriod"})," is the period used to compute the timeout timestamp when sending IBC packets."]}),"\n",(0,r.jsxs)(i.p,{children:["For more details, see the ",(0,r.jsx)(i.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/core/ics-004-channel-and-packet-semantics/README.md#sending-packets",children:"IBC specification of Channel & Packet Semantics"}),"."]}),"\n",(0,r.jsx)(i.admonition,{type:"warning",children:(0,r.jsx)(i.p,{children:"If a sent packet is not relayed within this period, then the packet times out. The CCV channel used by the interchain security protocol is closed, and the corresponding consumer is removed."})}),"\n",(0,r.jsx)(i.p,{children:"CCVTimeoutPeriod may have different values on the provider and consumer chains."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"CCVTimeoutPeriod"})," on the provider ",(0,r.jsx)(i.strong,{children:"must"})," be larger than ",(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"})]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"CCVTimeoutPeriod"})," on the consumer is initial set via the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})]}),"\n"]}),"\n",(0,r.jsx)(i.h3,{id:"inittimeoutperiod",children:"InitTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"InitTimeoutPeriod"})," is the maximum allowed duration for CCV channel initialization to execute."]}),"\n",(0,r.jsxs)(i.p,{children:["For any consumer chain, if the CCV channel is not established within ",(0,r.jsx)(i.code,{children:"InitTimeoutPeriod"})," then the consumer chain will be removed and therefore will not be secured by the provider chain."]}),"\n",(0,r.jsxs)(i.p,{children:["The countdown starts when the ",(0,r.jsx)(i.code,{children:"spawn_time"})," specified in the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})," is reached."]}),"\n",(0,r.jsx)(i.h3,{id:"vsctimeoutperiod",children:"VscTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"VscTimeoutPeriod"})," is the provider-side param that enables the provider to timeout VSC packets even when a consumer chain is not live.\nIf the ",(0,r.jsx)(i.code,{children:"VscTimeoutPeriod"})," is ever reached for a consumer chain that chain will be considered not live and removed from interchain security."]}),"\n",(0,r.jsx)(i.admonition,{type:"tip",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"VscTimeoutPeriod"})," MUST be larger than the ",(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"}),"."]})}),"\n",(0,r.jsx)(i.h3,{id:"blocksperdistributiontransmission",children:"BlocksPerDistributionTransmission"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," is the number of blocks between rewards transfers from the consumer to the provider."]}),"\n",(0,r.jsx)(i.h3,{id:"transferperiodtimeout",children:"TransferPeriodTimeout"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TransferPeriodTimeout"})," is the period used to compute the timeout timestamp when sending IBC transfer packets from a consumer to the provider."]}),"\n",(0,r.jsxs)(i.p,{children:["If this timeout expires, then the transfer is attempted again after ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," blocks."]}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"TransferPeriodTimeout"})," on the consumer is initial set via the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})," gov proposal to add the consumer"]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"TransferPeriodTimeout"})," should be smaller than ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission x avg_block_time"})]}),"\n"]}),"\n",(0,r.jsx)(i.h2,{id:"reward-distribution-parameters",children:"Reward Distribution Parameters"}),"\n",(0,r.jsx)(i.admonition,{type:"tip",children:(0,r.jsxs)(i.p,{children:["The following chain parameters dictate consumer chain distribution amount and frequency.\nThey are set at consumer genesis and ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"}),", ",(0,r.jsx)(i.code,{children:"ConsumerRedistributionFraction"}),"\n",(0,r.jsx)(i.code,{children:"TransferTimeoutPeriod"})," must be provided in every ",(0,r.jsx)(i.code,{children:"ConsumerChainAddition"})," proposal."]})}),"\n",(0,r.jsx)(i.h3,{id:"consumerredistributionfraction",children:"ConsumerRedistributionFraction"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ConsumerRedistributionFraction"})," is the fraction of tokens allocated to the consumer redistribution address during distribution events. The fraction is a string representing a decimal number. For example ",(0,r.jsx)(i.code,{children:'"0.75"'})," would represent ",(0,r.jsx)(i.code,{children:"75%"}),"."]}),"\n",(0,r.jsxs)(i.admonition,{type:"tip",children:[(0,r.jsx)(i.p,{children:"Example:"}),(0,r.jsxs)(i.p,{children:["With ",(0,r.jsx)(i.code,{children:"ConsumerRedistributionFraction"})," set to ",(0,r.jsx)(i.code,{children:'"0.75"'})," the consumer chain would send ",(0,r.jsx)(i.code,{children:"75%"})," of its block rewards and accumulated fees to the consumer redistribution address, and the remaining ",(0,r.jsx)(i.code,{children:"25%"})," to the provider chain every ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," blocks."]})]}),"\n",(0,r.jsx)(i.h3,{id:"blocksperdistributiontransmission-1",children:"BlocksPerDistributionTransmission"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," is the number of blocks between IBC token transfers from the consumer chain to the provider chain."]}),"\n",(0,r.jsx)(i.h3,{id:"transfertimeoutperiod",children:"TransferTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TransferTimeoutPeriod"})," is the timeout period for consumer chain reward distribution IBC packets."]}),"\n",(0,r.jsx)(i.h3,{id:"distributiontransmissionchannel",children:"DistributionTransmissionChannel"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"DistributionTransmissionChannel"})," is the provider chain IBC channel used for receiving consumer chain reward distribution token transfers. This is automatically set during the consumer-provider handshake procedure."]}),"\n",(0,r.jsx)(i.h3,{id:"providerfeepooladdrstr",children:"ProviderFeePoolAddrStr"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ProviderFeePoolAddrStr"})," is the provider chain fee pool address used for receiving consumer chain reward distribution token transfers. This is automatically set during the consumer-provider handshake procedure."]}),"\n",(0,r.jsx)(i.h2,{id:"slash-throttle-parameters",children:"Slash Throttle Parameters"}),"\n",(0,r.jsx)(i.h3,{id:"slashmeterreplenishperiod",children:"SlashMeterReplenishPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"SlashMeterReplenishPeriod"})," exists on the provider such that once the slash meter becomes not-full, the slash meter is replenished after this period has elapsed."]}),"\n",(0,r.jsxs)(i.p,{children:["The meter is replenished to an amount equal to the slash meter allowance for that block, or ",(0,r.jsx)(i.code,{children:"SlashMeterReplenishFraction * CurrentTotalVotingPower"}),"."]}),"\n",(0,r.jsx)(i.h3,{id:"slashmeterreplenishfraction",children:"SlashMeterReplenishFraction"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"SlashMeterReplenishFraction"})," exists on the provider as the portion (in range [0, 1]) of total voting power that is replenished to the slash meter when a replenishment occurs."]}),"\n",(0,r.jsxs)(i.p,{children:["This param also serves as a maximum fraction of total voting power that the slash meter can hold. The param is set/persisted as a string, and converted to a ",(0,r.jsx)(i.code,{children:"sdk.Dec"})," when used."]}),"\n",(0,r.jsx)(i.h3,{id:"maxthrottledpackets",children:"MaxThrottledPackets"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"MaxThrottledPackets"})," exists on the provider as the maximum amount of throttled slash or vsc matured packets that can be queued from a single consumer before the provider chain halts, it should be set to a large value."]}),"\n",(0,r.jsx)(i.p,{children:"This param would allow provider binaries to panic deterministically in the event that packet throttling results in a large amount of state-bloat. In such a scenario, packet throttling could prevent a violation of safety caused by a malicious consumer, at the cost of provider liveness."}),"\n",(0,r.jsx)(i.admonition,{type:"info",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"MaxThrottledPackets"})," was deprecated in ICS versions >= v3.2.0 due to the implementation of ",(0,r.jsx)(i.a,{href:"/interchain-security/adrs/adr-008-throttle-retries",children:"ADR-008"}),"."]})}),"\n",(0,r.jsx)(i.h3,{id:"retrydelayperiod",children:"RetryDelayPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"RetryDelayPeriod"})," exists on the consumer for ",(0,r.jsx)(i.strong,{children:"ICS versions >= v3.2.0"})," (introduced by the implementation of ",(0,r.jsx)(i.a,{href:"/interchain-security/adrs/adr-008-throttle-retries",children:"ADR-008"}),") and is the period at which the consumer retries to send a ",(0,r.jsx)(i.code,{children:"SlashPacket"})," that was rejected by the provider."]}),"\n",(0,r.jsx)(i.h2,{id:"epoch-parameters",children:"Epoch Parameters"}),"\n",(0,r.jsx)(i.h3,{id:"blocksperepoch",children:"BlocksPerEpoch"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"BlocksPerEpoch"})," exists on the provider for ",(0,r.jsx)(i.strong,{children:"ICS versions >= 3.3.0"})," (introduced by the implementation of ",(0,r.jsx)(i.a,{href:"/interchain-security/adrs/adr-014-epochs",children:"ADR-014"}),")\nand corresponds to the number of blocks that constitute an epoch. This param is set to 600 by default. Assuming we need 6 seconds to\ncommit a block, the duration of an epoch corresponds to 1 hour. This means that a ",(0,r.jsx)(i.code,{children:"VSCPacket"})," would be sent to a consumer\nchain once at the end of every epoch, so once every 600 blocks. This parameter can be adjusted via a governance proposal,\nhowever careful consideration is needed so that ",(0,r.jsx)(i.code,{children:"BlocksPerEpoch"})," is not too large. A large ",(0,r.jsx)(i.code,{children:"BlocksPerEpoch"})," could lead to a delay\nof ",(0,r.jsx)(i.code,{children:"VSCPacket"}),"s and hence potentially lead to ",(0,r.jsx)(i.a,{href:"https://informal.systems/blog/learning-to-live-with-unbonding-pausing",children:"unbonding pausing"}),".\nFor setting ",(0,r.jsx)(i.code,{children:"BlocksPerEpoch"}),", we also need to consider potential slow chain upgrades that could delay the sending of a\n",(0,r.jsx)(i.code,{children:"VSCPacket"}),", as well as potential increases in the time it takes to commit a block (e.g., from 6 seconds to 30 seconds)."]})]})}function h(e={}){const{wrapper:i}={...(0,s.a)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},1151:(e,i,n)=>{n.d(i,{Z:()=>d,a:()=>t});var r=n(7294);const s={},o=r.createContext(s);function t(e){const i=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function d(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:t(e.components),r.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/3ec9db48.3a34695e.js b/assets/js/3ec9db48.3a34695e.js
new file mode 100644
index 0000000000..98be93d4ad
--- /dev/null
+++ b/assets/js/3ec9db48.3a34695e.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8233],{4554:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>l,frontMatter:()=>t,metadata:()=>a,toc:()=>c});var i=r(5893),s=r(1151);const t={sidebar_position:2},o="Reward Distribution",a={id:"features/reward-distribution",title:"Reward Distribution",description:"Sending and distributing rewards from consumer chains to the provider chain is handled by the Reward Distribution sub-protocol.",source:"@site/versioned_docs/version-v4.2.0-docs/features/reward-distribution.md",sourceDirName:"features",slug:"/features/reward-distribution",permalink:"/interchain-security/v4.2.0/features/reward-distribution",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Key Assignment",permalink:"/interchain-security/v4.2.0/features/key-assignment"},next:{title:"ICS Provider Proposals",permalink:"/interchain-security/v4.2.0/features/proposals"}},d={},c=[{value:"Whitelisting Reward Denoms",id:"whitelisting-reward-denoms",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"reward-distribution",children:"Reward Distribution"}),"\n",(0,i.jsxs)(n.p,{children:["Sending and distributing rewards from consumer chains to the provider chain is handled by the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/overview_and_basic_concepts.md#reward-distribution",children:"Reward Distribution sub-protocol"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Consumer chains have the option of sharing (a portion of) their block rewards (inflation tokens and fees) with the provider chain validators and delegators.\nIn replicated security, block rewards are periodically sent from the consumer to the provider according to consumer chain parameters using an IBC transfer channel.\nThis channel is created during consumer chain initialization, unless it is provided via the ",(0,i.jsx)(n.code,{children:"ConsumerAdditionProposal"})," when adding a new consumer chain.\nFor more details, see the ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/introduction/params#reward-distribution-parameters",children:"reward distribution parameters"}),"."]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Providing an IBC transfer channel (see ",(0,i.jsx)(n.code,{children:"DistributionTransmissionChannel"}),") enables a consumer chain to re-use one of the existing channels to the provider for consumer chain rewards distribution. This will preserve the ",(0,i.jsx)(n.code,{children:"ibc denom"})," that may already be in use.\nThis is especially important for standalone chains transitioning to become consumer chains.\nFor more details, see the ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/changeover-procedure",children:"changeover procedure"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Reward distribution on the provider is handled by the distribution module."}),"\n",(0,i.jsx)(n.h2,{id:"whitelisting-reward-denoms",children:"Whitelisting Reward Denoms"}),"\n",(0,i.jsxs)(n.p,{children:["The ICS distribution system works by allowing consumer chains to send rewards to a module address on the provider called the ",(0,i.jsx)(n.code,{children:"ConsumerRewardsPool"}),".\nTo avoid spam, the provider must whitelist denoms before accepting them as ICS rewards.\nOnly whitelisted denoms are transferred from the ",(0,i.jsx)(n.code,{children:"ConsumerRewardsPool"})," to the ",(0,i.jsx)(n.code,{children:"FeePoolAddress"}),", to be distributed to delegators and validators.\nThe whitelisted denoms can be adjusted through governance by sending a ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/proposals#changerewarddenomproposal",children:(0,i.jsx)(n.code,{children:"ChangeRewardDenomProposal"})}),"."]}),"\n",(0,i.jsx)(n.p,{children:"To query the list of whitelisted reward denoms on the Cosmos Hub, use the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"> gaiad q provider registered-consumer-reward-denoms\ndenoms:\n- ibc/0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5\n- ibc/6B8A3F5C2AD51CD6171FA41A7E8C35AD594AB69226438DB94450436EA57B3A89\n- uatom\n"})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsxs)(n.p,{children:["Use the following command to get a human readable denom from the ",(0,i.jsx)(n.code,{children:"ibc/*"})," denom trace format:"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"> gaiad query ibc-transfer denom-trace ibc/0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5\ndenom_trace:\n base_denom: untrn\n path: transfer/channel-569\n"})})]})]})}function l(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>o});var i=r(7294);const s={},t=i.createContext(s);function o(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/3f3637cb.463b9af5.js b/assets/js/3f3637cb.463b9af5.js
new file mode 100644
index 0000000000..b7f2620595
--- /dev/null
+++ b/assets/js/3f3637cb.463b9af5.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3596],{9529:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>r,metadata:()=>s,toc:()=>h});var i=o(5893),t=o(1151);const r={sidebar_position:1},a="Overview",s={id:"introduction/overview",title:"Overview",description:"Interchain Security is an open sourced IBC application which allows cosmos blockchains to lease their proof-of-stake security to one another.",source:"@site/versioned_docs/version-v4.2.0-docs/introduction/overview.md",sourceDirName:"introduction",slug:"/introduction/overview",permalink:"/interchain-security/v4.2.0/introduction/overview",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Interchain Security Docs",permalink:"/interchain-security/v4.2.0/"},next:{title:"Terminology",permalink:"/interchain-security/v4.2.0/introduction/terminology"}},c={},h=[{value:"Why Interchain Security?",id:"why-interchain-security",level:2},{value:"Core protocol",id:"core-protocol",level:2},{value:"Downtime Slashing",id:"downtime-slashing",level:3},{value:"Tokenomics and Rewards",id:"tokenomics-and-rewards",level:3}];function l(e){const n={a:"a",admonition:"admonition",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"overview",children:"Overview"}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsx)(n.p,{children:"Interchain Security is an open sourced IBC application which allows cosmos blockchains to lease their proof-of-stake security to one another."}),(0,i.jsx)("br",{}),(0,i.jsx)(n.p,{children:'Interchain Security allows anyone to launch a "consumer" blockchain using a subset, or even the entire, validator set from the "provider" blockchain by creating a governance proposal. If the proposal is accepted, provider chain validators start validating the consumer chain as well. Consumer chains will therefore inherit security and decentralization from the provider.'})]}),"\n",(0,i.jsx)(n.h2,{id:"why-interchain-security",children:"Why Interchain Security?"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"The right amount of security for each application. Consumer chains can choose to inherit the whole validator set from the provider, or they can launch as an opt in chain where only a subset of the provider validators validate the consumer chain. This allows for a wide range of security tradeoffs."}),"\n",(0,i.jsx)(n.li,{children:"Independent block-space. Transactions on consumer chains do not compete with any other applications. This means that there will be no unexpected congestion, and performance will generally be much better than on a shared smart contract platform such as Ethereum."}),"\n",(0,i.jsx)(n.li,{children:"Projects keep majority of gas fees. Depending on configuration, these fees either go to the project\u2019s community DAO, or can be used in the protocol in other ways."}),"\n",(0,i.jsx)(n.li,{children:"No validator search. Consumer chains do not have their own validator sets, and so do not need to find validators one by one. Validators from the provider chain validate on the consumer chain with their stake on the provider chain, earning additional rewards. For the consumer chain, this comes with the benefit of exposing their chain to the wider audience of the provider chain."}),"\n",(0,i.jsx)(n.li,{children:"Instant sovereignty. Consumers can run arbitrary app logic similar to standalone chains. At any time in the future, a consumer chain can elect to become a completely standalone chain, with its own validator set."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"core-protocol",children:"Core protocol"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Protocol specification is available as ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/overview_and_basic_concepts.md",children:"ICS-028"})," in the IBC repository."]})}),"\n",(0,i.jsx)(n.p,{children:"Once an IBC connection and proper channel is established between a provider and consumer chain, the provider will continually send validator set updates to the consumer over IBC. The consumer uses these validator set updates to update its own validator set in Comet. Thus, the provider validator set is effectively replicated on the consumer."}),"\n",(0,i.jsx)(n.p,{children:"To ensure the security of the consumer chain, provider delegators cannot unbond their tokens until the unbonding periods of each consumer chain has passed. In practice this will not be noticeable to the provider delegators, since consumer chains will be configured to have a slightly shorter unbonding period than the provider."}),"\n",(0,i.jsx)(n.h3,{id:"downtime-slashing",children:"Downtime Slashing"}),"\n",(0,i.jsx)(n.p,{children:"If downtime is initiated by a validator on a consumer chain, a downtime packet will be relayed to the provider to jail that validator for a set amount of time. The validator who committed downtime will then miss out on staking rewards for the configured jailing period."}),"\n",(0,i.jsx)(n.h3,{id:"tokenomics-and-rewards",children:"Tokenomics and Rewards"}),"\n",(0,i.jsx)(n.p,{children:"Consumer chains are free to create their own native token which can be used for fees, and can be created on the consumer chain in the form of inflationary rewards. These rewards can be used to incentivize user behavior, for example, LPing or staking. A portion of these fees and rewards will be sent to provider chain stakers, but that proportion is completely customizable by the developers, and subject to governance."})]})}function d(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>s,a:()=>a});var i=o(7294);const t={},r=i.createContext(t);function a(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/3f869ff5.5e0f39e2.js b/assets/js/3f869ff5.5e0f39e2.js
new file mode 100644
index 0000000000..7423c370d9
--- /dev/null
+++ b/assets/js/3f869ff5.5e0f39e2.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4470],{4522:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>r,toc:()=>h});var n=i(5893),a=i(1151);const o={},s="Power Shaping",r={id:"features/power-shaping",title:"Power Shaping",description:"To give consumer chains more flexibility in choosing their validator set, Interchain Security offers",source:"@site/versioned_docs/version-v4.2.0-docs/features/power-shaping.md",sourceDirName:"features",slug:"/features/power-shaping",permalink:"/interchain-security/v4.2.0/features/power-shaping",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Partial Set Security",permalink:"/interchain-security/v4.2.0/features/partial-set-security"},next:{title:"Developing an ICS consumer chain",permalink:"/interchain-security/v4.2.0/consumer-development/app-integration"}},l={},h=[{value:"Guidelines for setting power shaping parameters",id:"guidelines-for-setting-power-shaping-parameters",level:2}];function c(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"power-shaping",children:"Power Shaping"}),"\n",(0,n.jsx)(t.p,{children:'To give consumer chains more flexibility in choosing their validator set, Interchain Security offers\nseveral "power shaping" mechanisms for consumer chains.'}),"\n",(0,n.jsx)(t.p,{children:"These are:"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Capping the size of the validator set"}),": The consumer chain can specify a maximum number of validators it\nwants to have in its validator set. This can be used to limit the number of validators in the set, which can\nbe useful for chains that want to have a smaller validator set for faster blocks or lower overhead."]}),"\n"]}),"\n",(0,n.jsx)(t.admonition,{type:"info",children:(0,n.jsx)(t.p,{children:"This is only applicable to Opt In chains (chains with Top N = 0)."})}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Capping the fraction of power any single validator can have"}),": The consumer chain can specify a maximum fraction\nof the total voting power that any single validator in its validator set should have.\nThis is a security measure with the intention of making it harder for a single large validator to take over a consumer chain. This mitigates the risk of an Opt In chain with only a few validators being dominated by a validator with a large amount of stake opting in.\nFor example, setting this fraction to e.g. 33% would mean that no single validator can have more than 33% of the total voting power,\nand thus there is no single validator who would stop the chain by going offline."]}),"\n"]}),"\n",(0,n.jsx)(t.admonition,{type:"info",children:(0,n.jsx)(t.p,{children:"This is a soft cap, and the actual power of a validator can exceed this fraction if the validator set is small (e.g. there are only 3 validators and the cap is 20%)."})}),"\n",(0,n.jsx)(t.admonition,{type:"info",children:(0,n.jsx)(t.p,{children:"Rewards are distributed proportionally to validators with respect to their capped voting power on the consumer,\nnot their total voting power on the provider."})}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Allowlist and denylist"}),": The consumer chain can specify a list of validators that are allowed or disallowed from participating in the validator set. If an allowlist is set, all validators not on the allowlist cannot validate the consumer chain. If a validator is on both lists, the denylist takes precedence, that is, they cannot validate the consumer chain. If neither list is set, all validators are able to validate the consumer chain."]}),"\n"]}),"\n",(0,n.jsx)(t.admonition,{type:"warning",children:(0,n.jsxs)(t.p,{children:["Note that if denylisting is used in a Top N consumer chain, then the chain might not be secured by N% of the total provider's\npower. For example, consider that the top validator ",(0,n.jsx)(t.code,{children:"V"})," on the provider chain has 10% of the voting power, and we have a Top 50% consumer chain,\nthen if ",(0,n.jsx)(t.code,{children:"V"})," is denylisted, the consumer chain would only be secured by at least 40% of the provider's power."]})}),"\n",(0,n.jsxs)(t.p,{children:["All these mechanisms are set by the consumer chain in the ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"}),". They operate ",(0,n.jsx)(t.em,{children:"solely on the provider chain"}),", meaning the consumer chain simply receives the validator set after these rules have been applied and does not have any knowledge about whether they are applied."]}),"\n",(0,n.jsxs)(t.p,{children:["Each of these mechanisms is ",(0,n.jsx)(t.em,{children:"set during the consumer addition proposal"})," (see ",(0,n.jsx)(t.a,{href:"/interchain-security/v4.2.0/consumer-development/onboarding#3-submit-a-governance-proposal",children:"Onboarding"}),"), and is currently ",(0,n.jsx)(t.em,{children:"immutable"})," after the chain has been added."]}),"\n",(0,n.jsx)(t.p,{children:"The values can be seen by querying the list of consumer chains:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"interchain-security-pd query provider list-consumer-chains\n"})}),"\n",(0,n.jsx)(t.h2,{id:"guidelines-for-setting-power-shaping-parameters",children:"Guidelines for setting power shaping parameters"}),"\n",(0,n.jsx)(t.p,{children:"When setting power shaping parameters, please consider the following guidelines:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Do not cap the validator set size too low: Notice that this number is the *",(0,n.jsx)(t.em,{children:"maximum"})," number of validators that will ever validate the consumer chain. If this number is too low, the chain will be very limited in the\namount of stake that secures it. The validator set size cap should only be used if there are strong reasons to prefer fewer validators. Consider that setting the cap will mean that\neven if the whole validator set of the provider wants to validate on the chain, some validators will simply not be able to."]}),"\n",(0,n.jsx)(t.li,{children:"Capping the fraction of power any single validator can have is a decent security measure, but it's good to be aware of the interactions with the size of the validator set.\nFor example, if there are only 3 validators, and the cap is 20%, this will not be possible (since even splitting the power fairly would mean that each validator has 33% of the power, so is above the cap).\nHowever, the cap can be a good measure to prevent a single large validator from essentially taking over the chain.\nIn general, values under 33% make sense (since a validator that has 33% of the chains power would halt the chain if they go offline).\nNotice that the smaller this value is, the more the original voting power gets distorted, which could discourage large validators from deciding to opt in to the chain."}),"\n",(0,n.jsxs)(t.li,{children:["If the allowlist is ",(0,n.jsx)(t.em,{children:"empty"}),", all validators can validate the chain. If it is ",(0,n.jsx)(t.em,{children:"non empty"}),", then ",(0,n.jsx)(t.em,{children:"only"})," validators on the allowlist can validate the chain.\nThus, an allowlist containing too few validators is a security risk. In particular, consider that if the validators on the allowlist lose a lot of stake or stop being validators,\nan allowlist that is too short can very quickly become outdated and leave too few validators, or validators with too little stake, to secure the chain in a decentralized way."]}),"\n",(0,n.jsx)(t.li,{children:"If the denylist is too full, this can likewise be problematic. If too many large validators are denylisted, the chain might not be secured by a large enough fraction of the provider's power, in particular when\nthe power distribution on the provider shifts and the denylisted validators gain more power."}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"In general, when setting these parameters, consider that the voting power distribution in the future might be very different from the one right now,\nand that the chain should be secure even if the power distribution changes significantly."})]})}function d(e={}){const{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},1151:(e,t,i)=>{i.d(t,{Z:()=>r,a:()=>s});var n=i(7294);const a={},o=n.createContext(a);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/405e8773.a6ffe47d.js b/assets/js/405e8773.a6ffe47d.js
new file mode 100644
index 0000000000..7dca915361
--- /dev/null
+++ b/assets/js/405e8773.a6ffe47d.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5180],{1912:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var i=s(5893),t=s(1151);const r={sidebar_position:2,title:"Joining Interchain Security testnet"},o=void 0,a={id:"validators/joining-testnet",title:"Joining Interchain Security testnet",description:"Introduction",source:"@site/versioned_docs/version-v4.2.0-docs/validators/joining-testnet.md",sourceDirName:"validators",slug:"/validators/joining-testnet",permalink:"/interchain-security/v4.2.0/validators/joining-testnet",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"Joining Interchain Security testnet"},sidebar:"tutorialSidebar",previous:{title:"Overview",permalink:"/interchain-security/v4.2.0/validators/overview"},next:{title:"Withdrawing consumer chain validator rewards",permalink:"/interchain-security/v4.2.0/validators/withdraw_rewards"}},c={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Joining the provider chain",id:"joining-the-provider-chain",level:2},{value:"Initialization",id:"initialization",level:2},{value:"Joining consumer chains",id:"joining-consumer-chains",level:2},{value:"Re-using consensus key",id:"re-using-consensus-key",level:2},{value:"Assigning consensus keys",id:"assigning-consensus-keys",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(n.p,{children:["This short guide will teach you how to join the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security",children:"Interchain Security testnet"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The experience gained in the testnet will prepare you for validating interchain secured chains."}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"Provider and consumer chain represent distinct networks and infrastructures operated by the same validator set."}),(0,i.jsxs)(n.p,{children:["For general information about running cosmos-sdk based chains check out the ",(0,i.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup",children:"validator basics"})," and ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/main/run-node/run-node",children:"Running a Node section"})," of Cosmos SDK docs"]})]}),"\n",(0,i.jsx)(n.h2,{id:"joining-the-provider-chain",children:"Joining the provider chain"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"At present, all validators of the provider chain must also validate all governance approved consumer chains. The consumer chains cannot have a validator set different than the provider, which means they cannot introduce validators that are not also validating the provider chain."})}),"\n",(0,i.jsxs)(n.p,{children:["A comprehensive guide is available ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security/provider",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"initialization",children:"Initialization"}),"\n",(0,i.jsxs)(n.p,{children:["First, initialize your ",(0,i.jsx)(n.code,{children:"$NODE_HOME"})," using the ",(0,i.jsx)(n.code,{children:"provider"})," chain binary."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"NODE_MONIKER=\nCHAIN_ID=provider\nNODE_HOME=\n\ngaiad init $NODE_MONIKER --chain-id $CHAIN_ID --home $NODE_HOME\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Add your key to the keyring - more details available ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/main/run-node/keyring",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["In this example we will use the ",(0,i.jsx)(n.code,{children:"test"})," keyring-backend. This option is not safe to use in production."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad keys add --keyring-backend test\n\n# save the address as variable for later use\nMY_VALIDATOR_ADDRESS=$(gaiad keys show my_validator -a --keyring-backend test)\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Before issuing any transactions, use the ",(0,i.jsx)(n.code,{children:"provider"})," testnet faucet to add funds to your address."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'curl https://faucet.rs-testnet.polypore.xyz/request?address=$MY_VALIDATOR_ADDRESS&chain=provider\n\n# example output:\n{\n "address": "cosmos17p3erf5gv2436fd4vyjwmudakts563a497syuz",\n "amount": "10000000uatom",\n "chain": "provider",\n "hash": "10BFEC53C80C9B649B66549FD88A0B6BCF09E8FCE468A73B4C4243422E724985",\n "status": "success"\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Then, use the account associated with the keyring to issue a ",(0,i.jsx)(n.code,{children:"create-validator"})," transaction which will register your validator on chain."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'gaiad tx staking create-validator \\\n --amount=1000000uatom \\\n --pubkey=$(gaiad tendermint show-validator) \\\n --moniker="choose a moniker" \\\n --chain-id=$CHAIN_ID" \\\n --commission-rate="0.10" \\\n --commission-max-rate="0.20" \\\n --commission-max-change-rate="0.01" \\\n --min-self-delegation="1000000" \\\n --gas="auto" \\\n --gas-prices="0.0025uatom" \\\n --from=\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Check this ",(0,i.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup#edit-validator-description",children:"guide"})," to edit your validator."]})}),"\n",(0,i.jsxs)(n.p,{children:["After this step, your validator is created and you can start your node and catch up to the rest of the network. It is recommended that you use ",(0,i.jsx)(n.code,{children:"statesync"})," to catch up to the rest of the network."]}),"\n",(0,i.jsxs)(n.p,{children:["You can use this script to modify your ",(0,i.jsx)(n.code,{children:"config.toml"})," with the required statesync parameters."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# create the statesync script\n$: cd $NODE_HOME\n$: touch statesync.sh\n$ chmod 700 statesync.sh # make executable\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Paste the following instructions into the ",(0,i.jsx)(n.code,{children:"statesync.sh"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'#!/bin/bash\n\nSNAP_RPC="https://rpc.provider-state-sync-01.rs-testnet.polypore.xyz:443"\n\nLATEST_HEIGHT=$(curl -s $SNAP_RPC/block | jq -r .result.block.header.height); \\\nBLOCK_HEIGHT=$((LATEST_HEIGHT - 2000)); \\\nTRUST_HASH=$(curl -s "$SNAP_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash)\n\nsed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\\1true| ; \\\ns|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\\1\\"$SNAP_RPC,$SNAP_RPC\\"| ; \\\ns|^(trust_height[[:space:]]+=[[:space:]]+).*$|\\1$BLOCK_HEIGHT| ; \\\ns|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\\1\\"$TRUST_HASH\\"|" $NODE_HOME/config/config.toml\n'})}),"\n",(0,i.jsx)(n.p,{children:"Then, you can execute the script:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"$: ./statesync.sh # setup config.toml for statesync\n"})}),"\n",(0,i.jsx)(n.p,{children:"Finally, copy the provider genesis and start your node:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'$: GENESIS_URL=https://github.com/cosmos/testnets/raw/master/interchain-security/provider/provider-genesis.json\n$: wget $GENESIS_URL -O genesis.json\n$: genesis.json $NODE_HOME/config/genesis.json\n# start the service\n$: gaiad start --x-crisis-skip-assert-invariants --home $NODE_HOME --p2p.seeds="08ec17e86dac67b9da70deb20177655495a55407@provider-seed-01.rs-testnet.polypore.xyz:26656,4ea6e56300a2f37b90e58de5ee27d1c9065cf871@provider-seed-02.rs-testnet.polypore.xyz:26656"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Additional scripts to setup your nodes are available ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/provider/join-ics-provider.sh",children:"here"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/provider/join-ics-provider-cv.sh",children:"here"}),". The scripts will configure your node and create the required services - the scripts only work in linux environments."]}),"\n",(0,i.jsx)(n.h2,{id:"joining-consumer-chains",children:"Joining consumer chains"}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"Once you reach the active set on the provider chain, you will be required to validate all available consumer chains."}),(0,i.jsxs)(n.p,{children:["We strongly recommend that you assign a separate key for each consumer chain.\nCheck out this ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/key-assignment",children:"guide"})," to learn more about key assignment in interchain security."]})]}),"\n",(0,i.jsx)(n.p,{children:"To join consumer chains, simply replicate the steps above for each consumer using the correct consumer chain binaries."}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["When running the provider chain and consumers on the same machine please update the ",(0,i.jsx)(n.code,{children:"PORT"})," numbers for each of them and make sure they do not overlap (otherwise the binaries will not start)."]}),(0,i.jsx)(n.p,{children:"Important ports to re-configure:"}),(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--rpc.laddr"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--p2p.laddr"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--api.address"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--grpc.address"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--grpc-web.address"})}),"\n"]})]}),"\n",(0,i.jsx)(n.h2,{id:"re-using-consensus-key",children:"Re-using consensus key"}),"\n",(0,i.jsxs)(n.p,{children:["To reuse the key on the provider and consumer chains, simply initialize your consumer chain and place the ",(0,i.jsx)(n.code,{children:"priv_validator_key.json"})," into the home directory of your consumer chain (",(0,i.jsx)(n.code,{children:"/config/priv_validator_key.json"}),")."]}),"\n",(0,i.jsx)(n.p,{children:"When you start the chain, the consensus key will be the same on the provider and the consumer chain."}),"\n",(0,i.jsx)(n.h2,{id:"assigning-consensus-keys",children:"Assigning consensus keys"}),"\n",(0,i.jsx)(n.p,{children:"Whenever you initialize a new node, it will be configured with a consensus key you can use."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'# machine running consumer chain\nconsumerd init --home --chain-id consumer-1\n\n# use the output of this command to get the consumer chain consensus key\nconsumerd tendermint show-validator\n# output: {"@type":"/cosmos.crypto.ed25519.PubKey","key":""}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Then, let the provider know which key you will be using for the consumer chain:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# machine running the provider chain\ngaiad tx provider assign-consensus-key consumer-1 '' --from --home $NODE_HOME --gas 900000 -b sync -y -o json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["After this step, you are ready to copy the consumer genesis into your nodes's ",(0,i.jsx)(n.code,{children:"/config"})," folder, start your consumer chain node and catch up to the network."]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>a,a:()=>o});var i=s(7294);const t={},r=i.createContext(t);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/4106f1c5.c90c0bfb.js b/assets/js/4106f1c5.c90c0bfb.js
new file mode 100644
index 0000000000..2711d898c1
--- /dev/null
+++ b/assets/js/4106f1c5.c90c0bfb.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[842],{7049:(n,e,i)=>{i.r(e),i.d(e,{assets:()=>d,contentTitle:()=>t,default:()=>p,frontMatter:()=>s,metadata:()=>a,toc:()=>h});var r=i(5893),o=i(1151);const s={sidebar_position:4},t="Consumer Initiated Slashing",a={id:"features/slashing",title:"Consumer Initiated Slashing",description:"A consumer chain is essentially a regular Cosmos-SDK based chain that uses the Interchain Security module to achieve economic security by stake deposited on the provider chain, instead of its own chain.",source:"@site/docs/features/slashing.md",sourceDirName:"features",slug:"/features/slashing",permalink:"/interchain-security/features/slashing",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"ICS Provider Proposals",permalink:"/interchain-security/features/proposals"},next:{title:"Democracy modules",permalink:"/interchain-security/features/democracy-modules"}},d={},h=[{value:"Downtime Infractions",id:"downtime-infractions",level:2},{value:"Equivocation Infractions",id:"equivocation-infractions",level:2},{value:"Report equivocation infractions through CLI",id:"report-equivocation-infractions-through-cli",level:3},{value:"Report equivocation infractions with Hermes",id:"report-equivocation-infractions-with-hermes",level:3}];function c(n){const e={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,o.a)(),...n.components},{Details:i}=e;return i||function(n,e){throw new Error("Expected "+(e?"component":"object")+" `"+n+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(e.h1,{id:"consumer-initiated-slashing",children:"Consumer Initiated Slashing"}),"\n",(0,r.jsx)(e.p,{children:"A consumer chain is essentially a regular Cosmos-SDK based chain that uses the Interchain Security module to achieve economic security by stake deposited on the provider chain, instead of its own chain.\nIn essence, provider chain and consumer chains are different networks (different infrastructures) that are bound together by the provider's validator set. By being bound to the provider's validator set, a consumer chain inherits the economic security guarantees of the provider chain (in terms of total stake)."}),"\n",(0,r.jsx)(e.p,{children:"To maintain the proof of stake model, the consumer chain is able to send evidence of infractions (double signing and downtime) to the provider chain so the offending validators can be penalized.\nAny infraction committed on any of the consumer chains is reflected on the provider and all other consumer chains."}),"\n",(0,r.jsx)(e.p,{children:"In the current implementation there are two important changes brought by the Interchain Security module."}),"\n",(0,r.jsx)(e.h2,{id:"downtime-infractions",children:"Downtime Infractions"}),"\n",(0,r.jsx)(e.p,{children:"Downtime infractions are reported by consumer chains and are acted upon on the provider as soon as the provider receives the infraction evidence."}),"\n",(0,r.jsx)(e.p,{children:"Instead of slashing, the provider will only jail offending validator for the duration of time established by the chain parameters."}),"\n",(0,r.jsx)(e.admonition,{type:"info",children:(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.a,{href:"/interchain-security/adrs/adr-002-throttle",children:"Slash throttling"})," (sometimes called jail throttling) mechanism ensures that only a fraction of the validator set can be jailed at any one time to prevent malicious consumer chains from harming the provider."]})}),"\n",(0,r.jsx)(e.p,{children:"Note that validators are only jailed for downtime on consumer chains that they opted-in to validate on,\nor in the case of Top N chains, where they are automatically opted in by being in the Top N% of the validator set on the provider."}),"\n",(0,r.jsx)(e.h2,{id:"equivocation-infractions",children:"Equivocation Infractions"}),"\n",(0,r.jsxs)(e.p,{children:["Equivocation infractions are reported by external agents (e.g., relayers) that can submit to the provider evidence of light client or double signing attacks observed on a consumer chain.\nThe evidence is submitted by sending ",(0,r.jsx)(e.code,{children:"MsgSubmitConsumerMisbehaviour"})," or ",(0,r.jsx)(e.code,{children:"MsgSubmitConsumerDoubleVoting"})," transactions to the provider.\nWhen valid evidence is received, the malicious validators are slashed, jailed, and tombstoned on the provider.\nThis is enabled through the ",(0,r.jsx)(e.em,{children:"cryptographic verification of equivocation"})," feature.\nFor more details, see ",(0,r.jsx)(e.a,{href:"/interchain-security/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR-005"})," and ",(0,r.jsx)(e.a,{href:"/interchain-security/adrs/adr-013-equivocation-slashing",children:"ADR-013"}),"."]}),"\n",(0,r.jsx)(e.h3,{id:"report-equivocation-infractions-through-cli",children:"Report equivocation infractions through CLI"}),"\n",(0,r.jsx)(e.p,{children:"The ICS provider module offers two commands for submitting evidence of misbehavior originating from a consumer chain.\nBelow are two examples illustrating the process on Cosmos Hub."}),"\n",(0,r.jsx)(e.p,{children:"Use the following command to submit evidence of double signing attacks:"}),"\n",(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-bash",children:"gaiad tx provider submit-consumer-double-voting [path/to/evidence.json] [path/to/infraction_header.json] --from node0 --home ../node0 --chain-id $CID \n"})}),"\n",(0,r.jsxs)(i,{children:[(0,r.jsxs)("summary",{children:["Example of ",(0,r.jsx)(e.code,{children:"evidence.json"})]}),(0,r.jsx)("div",{children:(0,r.jsx)("div",{children:(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-json",children:'{\n "vote_a": {\n "type": 1,\n "height": 25,\n "round": 0,\n "block_id": {\n "hash": "tBBWTqjECl31S/clZGoxLdDqs93kTvy3qhpPqET/laY=",\n "part_set_header": {\n "total": 1,\n "hash": "ai2qCLgVZAFph4FJ4Cqw5QW1GZKR4zjOv0bI/Um5AIc="\n }\n },\n "timestamp": "2023-11-20T12:57:54.565207Z",\n "validator_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "signature": "y9yILm9hmv45BZwAaaq9mS1FpH7QeAIJ5Jkcc3U2/k5uks9cuqr4NTIwaIrqMSMKwxVyqiR56xmCT59a6AngAA=="\n },\n "vote_b": {\n "type": 1,\n "height": 25,\n "round": 0,\n "block_id": {\n "hash": "3P06pszgPatuIdLTP5fDWiase4SYHIq9YXGSbRk9/50=",\n "part_set_header": {\n "total": 1,\n "hash": "S+SbOMxFRzfeNNpX9/jyFMz94VwBKk7Dpx6ZyvSYyNU="\n }\n },\n "timestamp": "2023-11-20T12:57:54.599273Z",\n "validator_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "validator_index": 0,\n "signature": "DGFcn4Um1t2kXW60+JhMk5cj7ZFdE5goKVOGiZkLwnNv43+6aGmOWjoq0SHYVzM4MwSwOwbhgZNbkWX+EHGUBw=="\n },\n "total_voting_power": 300,\n "validator_power": 100,\n "timestamp": "2023-11-20T12:57:51.267308Z"\n}\n'})})})})]}),"\n",(0,r.jsxs)(i,{children:[(0,r.jsxs)("summary",{children:["Example of ",(0,r.jsx)(e.code,{children:"infraction_header.json"})]}),(0,r.jsx)("div",{children:(0,r.jsx)("div",{children:(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-json",children:'{\n "signed_header": {\n "header": {\n "version": {\n "block": 11,\n "app": 2\n },\n "chain_id": "consumer",\n "height": 22,\n "time": "2023-11-20T12:57:40.479686Z",\n "last_block_id": {\n "hash": "L63hyLJ+y9+fpb7WYKdmmBhPHwbfEGQEuKmvGzyBPiY=",\n "part_set_header": {\n "total": 18,\n "hash": "euzRQjN7MjGtM6skXM4B8wOgAldWGfZSJRA9JRlO42s="\n }\n },\n "last_commit_hash": "qdDJwVziW3pPqmf8QDGZG+5HVd3OF7fCVh2Z8KQqNVU=",\n "data_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",\n "validators_hash": "pVc+gSYkGesaP3OkK4ig3DBi4o9/GCdXGtO/PQ6i/Ik=",\n "next_validators_hash": "pVc+gSYkGesaP3OkK4ig3DBi4o9/GCdXGtO/PQ6i/Ik=",\n "consensus_hash": "BICRvH3cKD93v7+R1zxE2ljD34qcvIZ0Bdi389qtoi8=",\n "app_hash": "Yu3HX62w7orbbY/pm2QEK7yIwR+AlNdjSSqiK1kmuJM=",\n "last_results_hash": "Yu3HX62w7orbbY/pm2QEK7yIwR+AlNdjSSqiK1kmuJM=",\n "evidence_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",\n "proposer_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA="\n },\n "commit": {\n "height": 22,\n "round": 1,\n "block_id": {\n "hash": "PKrS32IEZoFY2q2S3iQ68HQL751ieBhf5Eu/Y5Z/QPg=",\n "part_set_header": {\n "total": 1,\n "hash": "8UuA7Oqw5AH/KOacpmHVSMOIDe4l2eC8VmdH2mzcpiM="\n }\n },\n "signatures": [\n {\n "block_id_flag": 2,\n "validator_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "timestamp": "2023-11-20T12:57:44.076538Z",\n "signature": "bSOH4+Vg2I37zeJphOguGOD0GK3JzM1ghSgJd0UlW/DHn1u9Hvv4EekHuCu6qwRLZcuS/ZxNlmr9qYNfxX3bDA=="\n },\n {\n "block_id_flag": 2,\n "validator_address": "i/A830FM7cfmA8yTn9n3xBg5XpU=",\n "timestamp": "2020-01-02T00:07:00Z",\n "signature": "7bXSDtlOwGK/gLEsFpTWOzm2TFoaARrWQUpbgWEwKtLlUs7iE06TOvJ3yPPfTfqqN/qYnvxxgjl0M0EhUWu5Bg=="\n },\n {\n "block_id_flag": 2,\n "validator_address": "lrQDkJ2fk7UAgNzRZfcwMKSYa2E=",\n "timestamp": "2023-11-20T12:57:44.076519Z",\n "signature": "Pb6G4bCg4wafmV89WNnzXxbSCknZUHnSQfSCE5QMFxPtSUIN4A7SK5m7yltqMJF5zkyenlFiEI4J3OZ4KCjCAw=="\n },\n {\n "block_id_flag": 2,\n "validator_address": "+R94nXSeM1Z49e/CXpyHT3M+h3k=",\n "timestamp": "2023-11-20T12:57:44.057451Z",\n "signature": "j3EasIHNYA6MxW/PiWyruzHsjVsBV9t11W6Qx800WMm/+P+CkfR+UZAp7MPTvKZEZFuh3GUsBtyfb/vA+jJWCw=="\n }\n ]\n }\n },\n "validator_set": {\n "validators": [\n {\n "address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "pub_key": {\n "ed25519": "dtn+SfD+4QLo0+t0hAoP6Q2sGjh0XEI3LWVG+doh3u0="\n },\n "voting_power": 100,\n "proposer_priority": -200\n },\n {\n "address": "lrQDkJ2fk7UAgNzRZfcwMKSYa2E=",\n "pub_key": {\n "ed25519": "UgN2JsjPy2WLh7dzJRBkUQtdgNoT4/uGj7kbIVqqHT8="\n },\n "voting_power": 100,\n "proposer_priority": 100\n },\n {\n "address": "+R94nXSeM1Z49e/CXpyHT3M+h3k=",\n "pub_key": {\n "ed25519": "5svW8261x+cZosp2xIhqzgt2tyuawrSDyHlpbgS3BC4="\n },\n "voting_power": 100,\n "proposer_priority": 100\n },\n {\n "address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "pub_key": {\n "ed25519": "dtn+SfD+4QLo0+t0hAoP6Q2sGjh0XEI3LWVG+doh3u0="\n },\n "voting_power": 100,\n "proposer_priority": -200\n }\n ],\n "proposer": {\n "address": "VUz+QceJ8Nu7GbJuVItwsfVjybA=",\n "pub_key": {\n "ed25519": "0s8KDTgEcwmOBrHWvV7mtBlItJ3upgM1FJsciwREdy4="\n },\n "voting_power": 1,\n "proposer_priority": -3\n }\n },\n "trusted_height": {\n "revision_height": 18\n },\n "trusted_validators": {\n "validators": [\n {\n "address": "VUz+QceJ8Nu7GbJuVItwsfVjybA=",\n "pub_key": {\n "ed25519": "0s8KDTgEcwmOBrHWvV7mtBlItJ3upgM1FJsciwREdy4="\n },\n "voting_power": 1,\n "proposer_priority": -3\n },\n {\n "address": "i/A830FM7cfmA8yTn9n3xBg5XpU=",\n "pub_key": {\n "ed25519": "FCmIw7hSuiAoWk/2f4LuGQ+3zx5101xiqU8DoC5wGkg="\n },\n "voting_power": 1,\n "proposer_priority": 1\n },\n {\n "address": "2DrZF0roNnnvEy4NS2aY811ncKg=",\n "pub_key": {\n "ed25519": "MI9c6sphsWlx0RAHCYOjMRXMFkTUaEYwOiOKG/0tsMs="\n },\n "voting_power": 1,\n "proposer_priority": 1\n },\n {\n "address": "73aN0uOc5b/Zfq2Xcjl0kH2r+tw=",\n "pub_key": {\n "ed25519": "gWNcDup4mdnsuqET4QeFRzVb+FnSP4Vz3iNMj5wvWXk="\n },\n "voting_power": 1,\n "proposer_priority": 1\n }\n ],\n "proposer": {\n "address": "VUz+QceJ8Nu7GbJuVItwsfVjybA=",\n "pub_key": {\n "ed25519": "0s8KDTgEcwmOBrHWvV7mtBlItJ3upgM1FJsciwREdy4="\n },\n "voting_power": 1,\n "proposer_priority": -3\n }\n }\n}\n'})})})})]}),"\n",(0,r.jsx)(e.p,{children:"Use the following command to submit evidence of light client attacks:"}),"\n",(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-bash",children:"gaiad tx provider submit-consumer-misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0 --chain-id $CID\n"})}),"\n",(0,r.jsxs)(i,{children:[(0,r.jsxs)("summary",{children:["Example of ",(0,r.jsx)(e.code,{children:"misbehaviour.json"})]}),(0,r.jsx)("div",{children:(0,r.jsx)("div",{children:(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-json",children:'{\n "client_id": "07-tendermint-0",\n "header_1": {\n "signed_header": {\n "header": {\n "version": {\n "block": "11",\n "app": "2"\n },\n "chain_id": "testchain2",\n "height": "19",\n "time": "2020-01-02T00:08:10Z",\n "last_block_id": {\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "part_set_header": {\n "total": 10000,\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n }\n },\n "last_commit_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "data_hash": "bW4ouLmLUycELqUKV91G5syFHHLlKL3qpu/e7v5moLg=",\n "validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "next_validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "consensus_hash": "5eVmxB7Vfj/4zBDxhBeHiLj6pgKwfPH0JSF72BefHyQ=",\n "app_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "last_results_hash": "CS4FhjAkftYAmGOhLu4RfSbNnQi1rcqrN/KrNdtHWjc=",\n "evidence_hash": "c4ZdsI9J1YQokF04mrTKS5bkWjIGx6adQ6Xcc3LmBxQ=",\n "proposer_address": "CbKqPquy50bcrY7JRdW7zXybSuA="\n },\n "commit": {\n "height": "19",\n "round": 1,\n "block_id": {\n "hash": "W2xVqzPw03ZQ1kAMpcpht9WohwMzsGnyKKNjPYKDF6U=",\n "part_set_header": {\n "total": 3,\n "hash": "hwgKOc/jNqZj6lwNm97vSTq9wYt8Pj4MjmYTVMGDFDI="\n }\n },\n "signatures": [\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "PGTquCtnTNFFY5HfEFz9f9pA7PYqjtQfBwHq6cxF/Ux8OI6nVqyadD9a84Xm7fSm6mqdW+T6YVfqIKmIoRjJDQ=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "0e39yoBorwORAH/K9qJ7D1N1Yr7CutMiQJ+oiIK39eMhuoK3UWzQyMGRLzDOIDupf8yD99mvGVVAlNIODlV3Dg=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "lhc2tkwydag9D1iLQhdDCE8GgrHP94M1LbHFYMoL9tExaEq6RiFW/k71TQH5x96XQ9XYOznMIHKC2BDh4GlnAQ=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "8xeSBf0nSFs/X/rQ9CZLzwkJJhQBLA2jKdPGP3MlULxm992XxrOsIYq47u1daxvSsn6ql5OVYjzBNU0qbPpvCA=="\n }\n ]\n }\n },\n "validator_set": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n },\n "trusted_height": {\n "revision_number": "0",\n "revision_height": "18"\n },\n "trusted_validators": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n }\n },\n "header_2": {\n "signed_header": {\n "header": {\n "version": {\n "block": "11",\n "app": "2"\n },\n "chain_id": "testchain2",\n "height": "19",\n "time": "2020-01-02T00:08:20Z",\n "last_block_id": {\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "part_set_header": {\n "total": 10000,\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n }\n },\n "last_commit_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "data_hash": "bW4ouLmLUycELqUKV91G5syFHHLlKL3qpu/e7v5moLg=",\n "validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "next_validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "consensus_hash": "5eVmxB7Vfj/4zBDxhBeHiLj6pgKwfPH0JSF72BefHyQ=",\n "app_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "last_results_hash": "CS4FhjAkftYAmGOhLu4RfSbNnQi1rcqrN/KrNdtHWjc=",\n "evidence_hash": "c4ZdsI9J1YQokF04mrTKS5bkWjIGx6adQ6Xcc3LmBxQ=",\n "proposer_address": "CbKqPquy50bcrY7JRdW7zXybSuA="\n },\n "commit": {\n "height": "19",\n "round": 1,\n "block_id": {\n "hash": "IZM8NKS+8FHB7CBmgB8Nz7BRVVXiiyqMQDvHFUvgzxo=",\n "part_set_header": {\n "total": 3,\n "hash": "hwgKOc/jNqZj6lwNm97vSTq9wYt8Pj4MjmYTVMGDFDI="\n }\n },\n "signatures": [\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "pLIEZ4WSAtnMsgryujheHSq4+YG3RqTfMn2ZxgEymr0wyi+BNlQAKRtRfesm0vfYxvjzc/jhGqtUqHtSIaCwCQ=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "XG7iTe/spWyTUkT7XDzfLMpYqrdyqizE4/X4wl/W+1eaQp0WsCHYnvPU3x9NAnYfZzaKdonZiDWs7wacbZTcDg=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "TqegK7ORuICSy++wVdPHt8fL2WfPlYsMPv1XW79wUdcjnQkezOM50OSqYaP4ua5frIZsn+sWteDrlqFTdkl3BA=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "dhvp3XlIaCxx5MFDs0TCkAPHSm0PS2EtJzYAx2c/7MWdLwUJFZrAUTeimQE2c9i9ro91cjZn/vI0/oFRXab6Aw=="\n }\n ]\n }\n },\n "validator_set": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n },\n "trusted_height": {\n "revision_number": "0",\n "revision_height": "18"\n },\n "trusted_validators": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n }\n }\n}\n'})})})})]}),"\n",(0,r.jsx)(e.h3,{id:"report-equivocation-infractions-with-hermes",children:"Report equivocation infractions with Hermes"}),"\n",(0,r.jsxs)(e.p,{children:["Ensure you have a well-configured Hermes ",(0,r.jsx)(e.code,{children:"v1.7.3+"})," relayer effectively relaying packets between a consumer chain and a provider chain.\nThe following command demonstrates how to run a Hermes instance in ",(0,r.jsx)(e.em,{children:"evidence mode"})," to detect misbehaviors on a consumer chain and automatically submit the evidence to the provider chain."]}),"\n",(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-bash",children:"hermes evidence --chain \n"})}),"\n",(0,r.jsx)(e.admonition,{type:"tip",children:(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.code,{children:"hermes evidence"})," takes a ",(0,r.jsx)(e.code,{children:"--check-past-blocks"})," option giving the possibility to look for older evidence (default is 100)."]})})]})}function p(n={}){const{wrapper:e}={...(0,o.a)(),...n.components};return e?(0,r.jsx)(e,{...n,children:(0,r.jsx)(c,{...n})}):c(n)}},1151:(n,e,i)=>{i.d(e,{Z:()=>a,a:()=>t});var r=i(7294);const o={},s=r.createContext(o);function t(n){const e=r.useContext(s);return r.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function a(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(o):n.components||o:t(n.components),r.createElement(s.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/4179ee03.b3fced4f.js b/assets/js/4179ee03.b3fced4f.js
new file mode 100644
index 0000000000..3c0f4154d4
--- /dev/null
+++ b/assets/js/4179ee03.b3fced4f.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6073],{2069:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>p,frontMatter:()=>o,metadata:()=>t,toc:()=>c});var s=r(5893),i=r(1151);const o={sidebar_position:1},a="Upgrading to ICS v5.0.0",t={id:"upgrading/migrate_v4_v5",title:"Upgrading to ICS v5.0.0",description:"This ICS version uses cosmos-sdk v0.50.x and ibc-go v8.x.",source:"@site/docs/upgrading/migrate_v4_v5.md",sourceDirName:"upgrading",slug:"/upgrading/migrate_v4_v5",permalink:"/interchain-security/upgrading/migrate_v4_v5",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Technical Specification",permalink:"/interchain-security/introduction/technical-specification"},next:{title:"Key Assignment",permalink:"/interchain-security/features/key-assignment"}},d={},c=[{value:"Provider",id:"provider",level:2},{value:"Keeper initialization",id:"keeper-initialization",level:3},{value:"Protocol changes",id:"protocol-changes",level:3},{value:"Revert AfterUnbondingInitiated",id:"revert-afterunbondinginitiated",level:4},{value:"Migration (v4 -> v5)",id:"migration-v4---v5",level:3},{value:"Additions",id:"additions",level:3},{value:"MsgUpdateParams transaction",id:"msgupdateparams-transaction",level:3},{value:"Governance proposals",id:"governance-proposals",level:3},{value:"Consumer",id:"consumer",level:2},{value:"Keeper initialization",id:"keeper-initialization-1",level:3},{value:"Additions",id:"additions-1",level:3},{value:"MsgUpdateParams transaction",id:"msgupdateparams-transaction-1",level:4},{value:"Params Query",id:"params-query",level:4},{value:"Migration (v2 -> v3)",id:"migration-v2---v3",level:3},{value:"Interface method changes",id:"interface-method-changes",level:3},{value:"Democracy",id:"democracy",level:2},{value:"Note:",id:"note",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"upgrading-to-ics-v500",children:"Upgrading to ICS v5.0.0"}),"\n",(0,s.jsx)(n.p,{children:"This ICS version uses cosmos-sdk v0.50.x and ibc-go v8.x."}),"\n",(0,s.jsxs)(n.p,{children:["To migrate you application to cosmos-sdk v0.50.x please use this ",(0,s.jsx)(n.a,{href:"https://docs.cosmos.network/v0.50/build/migrations/upgrading",children:"guide"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"To migrate your application to ibc-go v8.x.y please use the following guides:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://ibc.cosmos.network/main/migrations/v7-to-v8",children:"migrate ibc-go to v8.0.0"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://ibc.cosmos.network/main/migrations/v8-to-v8_1",children:"migrate ibc-go to v8.1.0"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"ICS specific changes are outlined below."}),"\n",(0,s.jsxs)(n.p,{children:["Pre-requisite version for this upgrade: ",(0,s.jsx)(n.code,{children:"v4.x"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"provider",children:"Provider"}),"\n",(0,s.jsx)(n.h3,{id:"keeper-initialization",children:"Keeper initialization"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-diff",children:"// app.go\n\napp.ProviderKeeper = ibcproviderkeeper.NewKeeper(\n appCodec,\n keys[providertypes.StoreKey],\n app.GetSubspace(providertypes.ModuleName),\n scopedIBCProviderKeeper,\n app.IBCKeeper.ChannelKeeper,\n- app.IBCKeeper.PortKeeper\n+ app.IBCKeeper.PortKeeper,\n app.IBCKeeper.ConnectionKeeper,\n app.IBCKeeper.ClientKeeper,\n app.StakingKeeper,\n app.SlashingKeeper,\n app.AccountKeeper,\n app.DistrKeeper,\n app.BankKeeper,\n *app.GovKeeper,\n+ authtypes.NewModuleAddress(govtypes.ModuleName).String(),\n+ authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),\n+ authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),\n authtypes.FeeCollectorName,\n)\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"authority"})," was added - requirement for executing ",(0,s.jsx)(n.code,{children:"MsgUpdateParams"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["uses ",(0,s.jsx)(n.code,{children:"x/gov"})," module address by default"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"validatorAddressCodec"})," & ",(0,s.jsx)(n.code,{children:"consensusAddressCodec"})," were added - they must match the bech32 address codec used by ",(0,s.jsx)(n.code,{children:"x/auth"}),", ",(0,s.jsx)(n.code,{children:"x/bank"}),", ",(0,s.jsx)(n.code,{children:"x/staking"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"protocol-changes",children:"Protocol changes"}),"\n",(0,s.jsxs)(n.h4,{id:"revert-afterunbondinginitiated",children:["Revert ",(0,s.jsx)(n.code,{children:"AfterUnbondingInitiated"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"AfterUnbondingInitiated"})," behavior was reverted to ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/v1.2.0-multiden/x/ccv/provider/keeper/hooks.go#L53",children:"ICS@v1.2.0-multiden"})]}),"\n",(0,s.jsx)(n.p,{children:"The revert re-introduces an additional state check."}),"\n",(0,s.jsxs)(n.p,{children:["See this ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/1045",children:"issue"})," for more context and the actions taken."]}),"\n",(0,s.jsx)(n.h3,{id:"migration-v4---v5",children:"Migration (v4 -> v5)"}),"\n",(0,s.jsxs)(n.p,{children:["ConensusVersion was bumped to ",(0,s.jsx)(n.code,{children:"5"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The migration allows storing the provider module params in the ",(0,s.jsx)(n.code,{children:"x/ccv/provider"})," module store instead of relying on legacy ",(0,s.jsx)(n.code,{children:"x/param"})," store."]}),"\n",(0,s.jsx)(n.p,{children:"There are no special requirements for executing this migration."}),"\n",(0,s.jsx)(n.h3,{id:"additions",children:"Additions"}),"\n",(0,s.jsx)(n.h3,{id:"msgupdateparams-transaction",children:"MsgUpdateParams transaction"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"x/gov"})," module account is selected as the default ",(0,s.jsx)(n.code,{children:"authority"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["It is available when using ",(0,s.jsx)(n.code,{children:"gov"})," CLI commands:"]}),"\n",(0,s.jsx)(n.p,{children:"Drafting a proposal:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:'interchain-security-pd tx gov draft-proposal\n# select "other"\n# find and select "/interchain_security.ccv.provider.v1.MsgUpdateParams"\n'})}),"\n",(0,s.jsx)(n.p,{children:"Submitting a proposal:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd tx gov submit-proposal \n"})}),"\n",(0,s.jsxs)(n.p,{children:["Example ",(0,s.jsx)(n.code,{children:"proposal-message.json"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "messages": [\n {\n "@type": "/interchain_security.ccv.provider.v1.MsgUpdateParams",\n "authority": "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn",\n "params": {\n "trusting_period_fraction": "0.66",\n "ccv_timeout_period": "2419200s",\n "init_timeout_period": "604800s",\n "vsc_timeout_period": "3024000s",\n "slash_meter_replenish_period": "3s",\n "slash_meter_replenish_fraction": "1.0",\n "consumer_reward_denom_registration_fee": {\n "denom": "stake",\n "amount": "10000000"\n },\n "blocks_per_epoch": "600"\n }\n }\n ],\n "metadata": "ipfs://CID",\n "deposit": "10000stake",\n "title": "Update Provider params",\n "summary": "Update Provider params",\n "expedited": false\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:""}),"\n",(0,s.jsxs)(n.p,{children:["When updating parameters ",(0,s.jsx)(n.strong,{children:"all"})," parameters fields must be specified. Make sure you are only changing parameters that you are interested in."]}),"\n",(0,s.jsx)(n.p,{children:"To avoid accidentally changing parameters you can first check the current on-chain provider params using:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:'interchain-security-pd q provider params -o json\n\n{\n "template_client": {...},\n "trusting_period_fraction": "0.66",\n "ccv_timeout_period": "2419200s",\n "init_timeout_period": "604800s",\n "vsc_timeout_period": "3024000s",\n "slash_meter_replenish_period": "3s",\n "slash_meter_replenish_fraction": "1.0",\n "consumer_reward_denom_registration_fee": {\n "denom": "stake",\n "amount": "10000000"\n },\n "blocks_per_epoch": "600"\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"governance-proposals",children:"Governance proposals"}),"\n",(0,s.jsx)(n.p,{children:"Submitting the following legacy proposals is still supported:"}),"\n",(0,s.jsx)(n.h1,{id:"consumer-addition-proposal",children:"Consumer addition proposal"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd tx gov submit-legacy-proposal consumer-addition \n"})}),"\n",(0,s.jsx)(n.h1,{id:"consumer-removal-proposal",children:"Consumer removal proposal"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd tx gov submit-legacy-proposal consumer-removal \n"})}),"\n",(0,s.jsx)(n.h1,{id:"consumer-addition-proposal-1",children:"Consumer addition proposal"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd tx gov submit-legacy-proposal change-reward-denoms \n"})}),"\n",(0,s.jsxs)(n.p,{children:["You may also submit proposal messages above using ",(0,s.jsx)(n.code,{children:"submit-proposal"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"consumer",children:"Consumer"}),"\n",(0,s.jsx)(n.h3,{id:"keeper-initialization-1",children:"Keeper initialization"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-diff",children:"// pre-initialize ConsumerKeeper to satsfy ibckeeper.NewKeeper\napp.ConsumerKeeper = ibcconsumerkeeper.NewNonZeroKeeper(\n appCodec,\n keys[ibcconsumertypes.StoreKey],\n app.GetSubspace(ibcconsumertypes.ModuleName),\n)\n\napp.IBCKeeper = ibckeeper.NewKeeper(\n appCodec,\n keys[ibchost.StoreKey],\n app.GetSubspace(ibchost.ModuleName),\n app.ConsumerKeeper,\n app.UpgradeKeeper,\n scopedIBCKeeper,\n authtypes.NewModuleAddress(govtypes.ModuleName).String(),\n)\n\n// initialize the actual consumer keeper\napp.ConsumerKeeper = ibcconsumerkeeper.NewKeeper(\n appCodec,\n keys[ibcconsumertypes.StoreKey],\n app.GetSubspace(ibcconsumertypes.ModuleName),\n scopedIBCConsumerKeeper,\n app.IBCKeeper.ChannelKeeper,\n- &app.IBCKeeper.PortKeeper,\n+ app.IBCKeeper.PortKeeper,\n app.IBCKeeper.ConnectionKeeper,\n app.IBCKeeper.ClientKeeper,\n app.SlashingKeeper,\n app.BankKeeper,\n app.AccountKeeper,\n &app.TransferKeeper,\n app.IBCKeeper,\n authtypes.FeeCollectorName,\n\n // make sure the authority address makes sense for your chain\n // the exact module account may differ depending on your setup (x/gov, x/admin or custom module)\n // for x/ccv/democracy using the x/gov module address is correct\n // if you don't have a way of updating consumer params you may still use the line below as it will have no affect\n+ authtypes.NewModuleAddress(govtypes.ModuleName).String(),\n \n // add address codecs \n+ authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),\n+ authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),\n)\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"authority"})," was added - requirement for executing ",(0,s.jsx)(n.code,{children:"MsgUpdateParams"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"make sure the authority address makes sense for your chain"}),"\n",(0,s.jsxs)(n.li,{children:["the exact module account may differ depending on your setup (",(0,s.jsx)(n.code,{children:"x/gov"}),", ",(0,s.jsx)(n.code,{children:"x/admin"})," or custom module)"]}),"\n",(0,s.jsxs)(n.li,{children:["for ",(0,s.jsx)(n.code,{children:"x/ccv/democracy"})," using the ",(0,s.jsx)(n.code,{children:"x/gov"})," module address is correct"]}),"\n",(0,s.jsxs)(n.li,{children:["if you don't have a way of updating consumer params you may use ",(0,s.jsx)(n.code,{children:"authtypes.NewModuleAddress(govtypes.ModuleName).String()"})," (has no effect on functionality)"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"validatorAddressCodec"})," & ",(0,s.jsx)(n.code,{children:"consensusAddressCodec"})," were added - they must match the bech32 address codec used by ",(0,s.jsx)(n.code,{children:"x/auth"}),", ",(0,s.jsx)(n.code,{children:"x/bank"}),", ",(0,s.jsx)(n.code,{children:"x/staking"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"additions-1",children:"Additions"}),"\n",(0,s.jsxs)(n.h4,{id:"msgupdateparams-transaction-1",children:[(0,s.jsx)(n.code,{children:"MsgUpdateParams"})," transaction"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["This functionality is not supported on ",(0,s.jsx)(n.code,{children:"x/ccv/consumer"})," without additional configuration."]})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["if you are using ",(0,s.jsx)(n.code,{children:"x/ccv/democracy"})," the feature is supported out of the box"]}),"\n",(0,s.jsxs)(n.li,{children:["if you are using custom logic for changing consumer params, please update your code by providing the appropriate ",(0,s.jsx)(n.code,{children:"authority"})," module account during ",(0,s.jsx)(n.code,{children:"ConsumerKeeper"})," initialization in ",(0,s.jsx)(n.code,{children:"app.go"}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["You must add ",(0,s.jsx)(n.code,{children:'"/interchain_security.ccv.consumer.v1.MsgUpdateParams"'})," to your parameters whitelist to be able to change ",(0,s.jsx)(n.code,{children:"ccvconsumer"})," parameters via governance."]})}),"\n",(0,s.jsxs)(n.p,{children:["It is available when using ",(0,s.jsx)(n.code,{children:"gov"})," CLI commands:"]}),"\n",(0,s.jsx)(n.p,{children:"Drafting a proposal:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:'interchain-security-cd tx gov draft-proposal\n# select "other"\n# find and select "/interchain_security.ccv.consumer.v1.MsgUpdateParams"\n'})}),"\n",(0,s.jsx)(n.p,{children:"Submitting a proposal:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsxs)(n.strong,{children:["this proposal cannot be executed on chains without access to ",(0,s.jsx)(n.code,{children:"x/gov"})," or other modules for managing governance"]})}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"\ninterchain-security-cdd tx gov submit-proposal \n\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Example ",(0,s.jsx)(n.code,{children:"proposal-message.json"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "messages": [\n {\n "@type": "/interchain_security.ccv.consumer.v1.MsgUpdateParams",\n "authority": "consumer10d07y265gmmuvt4z0w9aw880jnsr700jlh7295",\n "params": {\n "enabled": true,\n "blocks_per_distribution_transmission": "20",\n "distribution_transmission_channel": "channel-1",\n "provider_fee_pool_addr_str": "",\n "ccv_timeout_period": "2419200s",\n "transfer_timeout_period": "3000s",\n "consumer_redistribution_fraction": "0.75",\n "historical_entries": "10000",\n "unbonding_period": "1209600s",\n "soft_opt_out_threshold": "0.05",\n "reward_denoms": [],\n "provider_reward_denoms": [],\n "retry_delay_period": "3000s"\n }\n }\n ],\n "metadata": "ipfs://CID",\n "deposit": "1000uatom",\n "title": "Update Consumer Params -- change transfer_timeout_period to 3000s",\n "summary": "Test Update Consumer Params",\n "expedited": false\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["When updating parameters ",(0,s.jsx)(n.strong,{children:"all"})," parameters fields must be specified. Make sure you are only changing parameters that you are interested in."]}),"\n",(0,s.jsx)(n.p,{children:"To avoid accidentally changing parameters you can first check the current on-chain consumer params using:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd q ccvconsumer params -o json\n"})}),"\n",(0,s.jsx)(n.h4,{id:"params-query",children:"Params Query"}),"\n",(0,s.jsx)(n.p,{children:"Consumer params query was added:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:'interchain-security-cd q ccvconsumer params -o json\n\n{\n "params": {\n "enabled": true,\n "blocks_per_distribution_transmission": "1000",\n "distribution_transmission_channel": "",\n "provider_fee_pool_addr_str": "",\n "ccv_timeout_period": "2419200s",\n "transfer_timeout_period": "3600s",\n "consumer_redistribution_fraction": "0.75",\n "historical_entries": "10000",\n "unbonding_period": "1209600s",\n "soft_opt_out_threshold": "0.05",\n "reward_denoms": [],\n "provider_reward_denoms": [],\n "retry_delay_period": "3600s"\n }\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"migration-v2---v3",children:"Migration (v2 -> v3)"}),"\n",(0,s.jsxs)(n.p,{children:["ConensusVersion was bumped to ",(0,s.jsx)(n.code,{children:"3"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The migration allows storing the consumer module params in the ",(0,s.jsx)(n.code,{children:"x/ccv/consumer"})," module store instead of relying on legacy ",(0,s.jsx)(n.code,{children:"x/param"})," store."]}),"\n",(0,s.jsx)(n.p,{children:"There are no special requirements for executing this migration."}),"\n",(0,s.jsx)(n.h3,{id:"interface-method-changes",children:"Interface method changes"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer methods were changed to match the cosmos-sdk ",(0,s.jsx)(n.code,{children:"StakingKeeper"})," interface.\nYou will not need to change your code, unless you are using the ",(0,s.jsx)(n.code,{children:"ConsumerKeeper"})," inside custom tests or you have developed custom app functionality that relies on ",(0,s.jsx)(n.code,{children:"ConsumerKeeper"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Please check the list below if you are using any of the consumer methods:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-go",children:"type StakingKeeper interface {\n UnbondingTime(ctx context.Context) (time.Duration, error)\n GetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) (stakingtypes.Validator, error)\n GetLastValidatorPower(ctx context.Context, operator sdk.ValAddress) (int64, error)\n Jail(context.Context, sdk.ConsAddress) error // jail a validator\n Slash(ctx context.Context, consAddr sdk.ConsAddress, infractionHeight, power int64, slashFactor math.LegacyDec) (math.Int, error)\n SlashWithInfractionReason(ctx context.Context, consAddr sdk.ConsAddress, infractionHeight, power int64, slashFactor math.LegacyDec, infraction stakingtypes.Infraction) (math.Int, error)\n Unjail(ctx context.Context, addr sdk.ConsAddress) error\n GetValidator(ctx context.Context, addr sdk.ValAddress) (stakingtypes.Validator, error)\n IterateLastValidatorPowers(ctx context.Context, cb func(addr sdk.ValAddress, power int64) (stop bool)) error\n IterateValidators(ctx context.Context, f func(index int64, validator stakingtypes.ValidatorI) (stop bool)) error\n Validator(ctx context.Context, addr sdk.ValAddress) (stakingtypes.ValidatorI, error)\n IsValidatorJailed(ctx context.Context, addr sdk.ConsAddress) (bool, error)\n ValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) (stakingtypes.ValidatorI, error)\n Delegation(ctx context.Context, addr sdk.AccAddress, valAddr sdk.ValAddress) (stakingtypes.DelegationI, error)\n MaxValidators(ctx context.Context) (uint32, error)\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The consumer implements the ",(0,s.jsx)(n.code,{children:"StakingKeeper"})," interface shown above."]}),"\n",(0,s.jsx)(n.h2,{id:"democracy",children:"Democracy"}),"\n",(0,s.jsxs)(n.p,{children:["Changes in ",(0,s.jsx)(n.code,{children:"Consumer"})," also apply to ",(0,s.jsx)(n.code,{children:"Democracy"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Democracy ",(0,s.jsx)(n.code,{children:"x/staking"}),", ",(0,s.jsx)(n.code,{children:"x/distribution"})," and ",(0,s.jsx)(n.code,{children:"x/gov"})," were updated to reflect changes in ",(0,s.jsx)(n.code,{children:"cosmos-sdk v0.50.x"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["There were no notable changes arising to the module functionality aside from conforming to ",(0,s.jsx)(n.code,{children:"cosmos-sdk v0.50.x"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"note",children:"Note:"}),"\n",(0,s.jsxs)(n.p,{children:["You must add ",(0,s.jsx)(n.code,{children:'"/interchain_security.ccv.consumer.v1.MsgUpdateParams"'})," to your parameters whitelist to be able to change ",(0,s.jsx)(n.code,{children:"consumer"})," parameters via governance."]})]})}function p(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>t,a:()=>a});var s=r(7294);const i={},o=s.createContext(i);function a(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/425bba28.90680342.js b/assets/js/425bba28.90680342.js
new file mode 100644
index 0000000000..03fe5f3e83
--- /dev/null
+++ b/assets/js/425bba28.90680342.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1118],{737:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>l,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=r(5893),t=r(1151);const o={sidebar_position:6},s="Consumer Genesis Transformation",a={id:"consumer-development/consumer-genesis-transformation",title:"Consumer Genesis Transformation",description:"Preparing a consumer chain for onboarding requires some information explaining how to run your chain. This includes a genesis file with CCV data where the CCV data is exported from the provider chain and added to the consumers genesis file (for more details check the documentation on Onboarding and Changeover).",source:"@site/docs/consumer-development/consumer-genesis-transformation.md",sourceDirName:"consumer-development",slug:"/consumer-development/consumer-genesis-transformation",permalink:"/interchain-security/consumer-development/consumer-genesis-transformation",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Changeover Procedure",permalink:"/interchain-security/consumer-development/changeover-procedure"},next:{title:"Overview",permalink:"/interchain-security/validators/overview"}},c={},d=[{value:"1. Prerequisite",id:"1-prerequisite",level:2},{value:"2. Export the CCV data",id:"2-export-the-ccv-data",level:2},{value:"3. Transform CCV data",id:"3-transform-ccv-data",level:2}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"consumer-genesis-transformation",children:"Consumer Genesis Transformation"}),"\n",(0,i.jsxs)(n.p,{children:["Preparing a consumer chain for onboarding requires some information explaining how to run your chain. This includes a genesis file with CCV data where the CCV data is exported from the provider chain and added to the consumers genesis file (for more details check the documentation on ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/onboarding",children:"Onboarding"})," and ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/changeover-procedure",children:"Changeover"}),").\nIn case that the provider chain is running an older version of the InterChainSecurity (ICS) module than the consumer chain - or vice versa - the exported CCV data might need to be transformed to the format supported by the ICS implementation run on the consumer chain. This is the case if the consumer chain runs version 4 of ICS or later and the provider is running version 3 or older of the ICS module."]}),"\n",(0,i.jsxs)(n.p,{children:["Check the ",(0,i.jsx)(n.a,{href:"../../../RELEASES.md#backwards-compatibility",children:"compatibility notes"})," for known incompatibilities between provider and consumer versions and indications if a consumer genesis transformation is required."]}),"\n",(0,i.jsx)(n.p,{children:"To transform such CCV data follow the instructions below"}),"\n",(0,i.jsx)(n.h2,{id:"1-prerequisite",children:"1. Prerequisite"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["used provider and consumer versions require transformation step as indicated in in the ",(0,i.jsx)(n.a,{href:"../../../RELEASES.md#backwards-compatibility",children:"compatibility notes"})]}),"\n",(0,i.jsx)(n.li,{children:"interchain-security-cd application supports the versions used by the consumer and provider"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"2-export-the-ccv-data",children:"2. Export the CCV data"}),"\n",(0,i.jsxs)(n.p,{children:["Export the CCV data from the provider chain as described in the ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/onboarding",children:"Onboarding"})," and ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/changeover-procedure",children:"Changeover"})," your following.\nAs a result the CCV data will be stored in a file in JSON format."]}),"\n",(0,i.jsx)(n.h2,{id:"3-transform-ccv-data",children:"3. Transform CCV data"}),"\n",(0,i.jsx)(n.p,{children:"To transform the CCV data"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["to the format supported by the current version of the consumer run the following command:","\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"interchain-security-cd genesis transform [genesis-file]\n"})}),"\n","where 'genesis-file' is the path to the file containing the CCV data exported in ",(0,i.jsx)(n.a,{href:"#2-export-the-ccv-data",children:"step 2"}),".\nAs a result the CCV data in the new format will be written to standard output."]}),"\n",(0,i.jsxs)(n.li,{children:["a specific target version of a consumer run the following command:","\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"interchain-security-cd genesis transform --to [genesis-file]\n\n"})}),"\n","where ",(0,i.jsx)(n.code,{children:"{r.d(n,{Z:()=>a,a:()=>s});var i=r(7294);const t={},o=i.createContext(t);function s(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/434502c4.8d5a5d14.js b/assets/js/434502c4.8d5a5d14.js
new file mode 100644
index 0000000000..c83f6410a1
--- /dev/null
+++ b/assets/js/434502c4.8d5a5d14.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[411],{854:(n,e,i)=>{i.r(e),i.d(e,{assets:()=>d,contentTitle:()=>t,default:()=>p,frontMatter:()=>o,metadata:()=>a,toc:()=>h});var r=i(5893),s=i(1151);const o={sidebar_position:4},t="Consumer Initiated Slashing",a={id:"features/slashing",title:"Consumer Initiated Slashing",description:"A consumer chain is essentially a regular Cosmos-SDK based chain that uses the Interchain Security module to achieve economic security by stake deposited on the provider chain, instead of its own chain.",source:"@site/versioned_docs/version-v5.0.0/features/slashing.md",sourceDirName:"features",slug:"/features/slashing",permalink:"/interchain-security/v5.0.0/features/slashing",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"ICS Provider Proposals",permalink:"/interchain-security/v5.0.0/features/proposals"},next:{title:"Developing an ICS consumer chain",permalink:"/interchain-security/v5.0.0/consumer-development/app-integration"}},d={},h=[{value:"Downtime Infractions",id:"downtime-infractions",level:2},{value:"Equivocation Infractions",id:"equivocation-infractions",level:2},{value:"Report equivocation infractions through CLI",id:"report-equivocation-infractions-through-cli",level:3},{value:"Report equivocation infractions with Hermes",id:"report-equivocation-infractions-with-hermes",level:3}];function c(n){const e={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,s.a)(),...n.components},{Details:i}=e;return i||function(n,e){throw new Error("Expected "+(e?"component":"object")+" `"+n+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(e.h1,{id:"consumer-initiated-slashing",children:"Consumer Initiated Slashing"}),"\n",(0,r.jsx)(e.p,{children:"A consumer chain is essentially a regular Cosmos-SDK based chain that uses the Interchain Security module to achieve economic security by stake deposited on the provider chain, instead of its own chain.\nIn essence, provider chain and consumer chains are different networks (different infrastructures) that are bound together by the provider's validator set. By being bound to the provider's validator set, a consumer chain inherits the economic security guarantees of the provider chain (in terms of total stake)."}),"\n",(0,r.jsx)(e.p,{children:"To maintain the proof of stake model, the consumer chain is able to send evidence of infractions (double signing and downtime) to the provider chain so the offending validators can be penalized.\nAny infraction committed on any of the consumer chains is reflected on the provider and all other consumer chains."}),"\n",(0,r.jsx)(e.p,{children:"In the current implementation there are two important changes brought by the Interchain Security module."}),"\n",(0,r.jsx)(e.h2,{id:"downtime-infractions",children:"Downtime Infractions"}),"\n",(0,r.jsx)(e.p,{children:"Downtime infractions are reported by consumer chains and are acted upon on the provider as soon as the provider receives the infraction evidence."}),"\n",(0,r.jsx)(e.p,{children:"Instead of slashing, the provider will only jail offending validator for the duration of time established by the chain parameters."}),"\n",(0,r.jsx)(e.admonition,{type:"info",children:(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.a,{href:"/interchain-security/v5.0.0/adrs/adr-002-throttle",children:"Slash throttling"})," (sometimes called jail throttling) mechanism ensures that only a fraction of the validator set can be jailed at any one time to prevent malicious consumer chains from harming the provider."]})}),"\n",(0,r.jsx)(e.h2,{id:"equivocation-infractions",children:"Equivocation Infractions"}),"\n",(0,r.jsxs)(e.p,{children:["Equivocation infractions are reported by external agents (e.g., relayers) that can submit to the provider evidence of light client or double signing attacks observed on a consumer chain.\nThe evidence is submitted by sending ",(0,r.jsx)(e.code,{children:"MsgSubmitConsumerMisbehaviour"})," or ",(0,r.jsx)(e.code,{children:"MsgSubmitConsumerDoubleVoting"})," transactions to the provider.\nWhen valid evidence is received, the malicious validators are slashed, jailed, and tombstoned on the provider.\nThis is enabled through the ",(0,r.jsx)(e.em,{children:"cryptographic verification of equivocation"})," feature.\nFor more details, see ",(0,r.jsx)(e.a,{href:"/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR-005"})," and ",(0,r.jsx)(e.a,{href:"/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing",children:"ADR-013"}),"."]}),"\n",(0,r.jsx)(e.h3,{id:"report-equivocation-infractions-through-cli",children:"Report equivocation infractions through CLI"}),"\n",(0,r.jsx)(e.p,{children:"The ICS provider module offers two commands for submitting evidence of misbehavior originating from a consumer chain.\nBelow are two examples illustrating the process on Cosmos Hub."}),"\n",(0,r.jsx)(e.p,{children:"Use the following command to submit evidence of double signing attacks:"}),"\n",(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-bash",children:"gaiad tx provider submit-consumer-double-voting [path/to/evidence.json] [path/to/infraction_header.json] --from node0 --home ../node0 --chain-id $CID \n"})}),"\n",(0,r.jsxs)(i,{children:[(0,r.jsxs)("summary",{children:["Example of ",(0,r.jsx)(e.code,{children:"evidence.json"})]}),(0,r.jsx)("div",{children:(0,r.jsx)("div",{children:(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-json",children:'{\n "vote_a": {\n "type": 1,\n "height": 25,\n "round": 0,\n "block_id": {\n "hash": "tBBWTqjECl31S/clZGoxLdDqs93kTvy3qhpPqET/laY=",\n "part_set_header": {\n "total": 1,\n "hash": "ai2qCLgVZAFph4FJ4Cqw5QW1GZKR4zjOv0bI/Um5AIc="\n }\n },\n "timestamp": "2023-11-20T12:57:54.565207Z",\n "validator_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "signature": "y9yILm9hmv45BZwAaaq9mS1FpH7QeAIJ5Jkcc3U2/k5uks9cuqr4NTIwaIrqMSMKwxVyqiR56xmCT59a6AngAA=="\n },\n "vote_b": {\n "type": 1,\n "height": 25,\n "round": 0,\n "block_id": {\n "hash": "3P06pszgPatuIdLTP5fDWiase4SYHIq9YXGSbRk9/50=",\n "part_set_header": {\n "total": 1,\n "hash": "S+SbOMxFRzfeNNpX9/jyFMz94VwBKk7Dpx6ZyvSYyNU="\n }\n },\n "timestamp": "2023-11-20T12:57:54.599273Z",\n "validator_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "validator_index": 0,\n "signature": "DGFcn4Um1t2kXW60+JhMk5cj7ZFdE5goKVOGiZkLwnNv43+6aGmOWjoq0SHYVzM4MwSwOwbhgZNbkWX+EHGUBw=="\n },\n "total_voting_power": 300,\n "validator_power": 100,\n "timestamp": "2023-11-20T12:57:51.267308Z"\n}\n'})})})})]}),"\n",(0,r.jsxs)(i,{children:[(0,r.jsxs)("summary",{children:["Example of ",(0,r.jsx)(e.code,{children:"infraction_header.json"})]}),(0,r.jsx)("div",{children:(0,r.jsx)("div",{children:(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-json",children:'{\n "signed_header": {\n "header": {\n "version": {\n "block": 11,\n "app": 2\n },\n "chain_id": "consumer",\n "height": 22,\n "time": "2023-11-20T12:57:40.479686Z",\n "last_block_id": {\n "hash": "L63hyLJ+y9+fpb7WYKdmmBhPHwbfEGQEuKmvGzyBPiY=",\n "part_set_header": {\n "total": 18,\n "hash": "euzRQjN7MjGtM6skXM4B8wOgAldWGfZSJRA9JRlO42s="\n }\n },\n "last_commit_hash": "qdDJwVziW3pPqmf8QDGZG+5HVd3OF7fCVh2Z8KQqNVU=",\n "data_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",\n "validators_hash": "pVc+gSYkGesaP3OkK4ig3DBi4o9/GCdXGtO/PQ6i/Ik=",\n "next_validators_hash": "pVc+gSYkGesaP3OkK4ig3DBi4o9/GCdXGtO/PQ6i/Ik=",\n "consensus_hash": "BICRvH3cKD93v7+R1zxE2ljD34qcvIZ0Bdi389qtoi8=",\n "app_hash": "Yu3HX62w7orbbY/pm2QEK7yIwR+AlNdjSSqiK1kmuJM=",\n "last_results_hash": "Yu3HX62w7orbbY/pm2QEK7yIwR+AlNdjSSqiK1kmuJM=",\n "evidence_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",\n "proposer_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA="\n },\n "commit": {\n "height": 22,\n "round": 1,\n "block_id": {\n "hash": "PKrS32IEZoFY2q2S3iQ68HQL751ieBhf5Eu/Y5Z/QPg=",\n "part_set_header": {\n "total": 1,\n "hash": "8UuA7Oqw5AH/KOacpmHVSMOIDe4l2eC8VmdH2mzcpiM="\n }\n },\n "signatures": [\n {\n "block_id_flag": 2,\n "validator_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "timestamp": "2023-11-20T12:57:44.076538Z",\n "signature": "bSOH4+Vg2I37zeJphOguGOD0GK3JzM1ghSgJd0UlW/DHn1u9Hvv4EekHuCu6qwRLZcuS/ZxNlmr9qYNfxX3bDA=="\n },\n {\n "block_id_flag": 2,\n "validator_address": "i/A830FM7cfmA8yTn9n3xBg5XpU=",\n "timestamp": "2020-01-02T00:07:00Z",\n "signature": "7bXSDtlOwGK/gLEsFpTWOzm2TFoaARrWQUpbgWEwKtLlUs7iE06TOvJ3yPPfTfqqN/qYnvxxgjl0M0EhUWu5Bg=="\n },\n {\n "block_id_flag": 2,\n "validator_address": "lrQDkJ2fk7UAgNzRZfcwMKSYa2E=",\n "timestamp": "2023-11-20T12:57:44.076519Z",\n "signature": "Pb6G4bCg4wafmV89WNnzXxbSCknZUHnSQfSCE5QMFxPtSUIN4A7SK5m7yltqMJF5zkyenlFiEI4J3OZ4KCjCAw=="\n },\n {\n "block_id_flag": 2,\n "validator_address": "+R94nXSeM1Z49e/CXpyHT3M+h3k=",\n "timestamp": "2023-11-20T12:57:44.057451Z",\n "signature": "j3EasIHNYA6MxW/PiWyruzHsjVsBV9t11W6Qx800WMm/+P+CkfR+UZAp7MPTvKZEZFuh3GUsBtyfb/vA+jJWCw=="\n }\n ]\n }\n },\n "validator_set": {\n "validators": [\n {\n "address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "pub_key": {\n "ed25519": "dtn+SfD+4QLo0+t0hAoP6Q2sGjh0XEI3LWVG+doh3u0="\n },\n "voting_power": 100,\n "proposer_priority": -200\n },\n {\n "address": "lrQDkJ2fk7UAgNzRZfcwMKSYa2E=",\n "pub_key": {\n "ed25519": "UgN2JsjPy2WLh7dzJRBkUQtdgNoT4/uGj7kbIVqqHT8="\n },\n "voting_power": 100,\n "proposer_priority": 100\n },\n {\n "address": "+R94nXSeM1Z49e/CXpyHT3M+h3k=",\n "pub_key": {\n "ed25519": "5svW8261x+cZosp2xIhqzgt2tyuawrSDyHlpbgS3BC4="\n },\n "voting_power": 100,\n "proposer_priority": 100\n },\n {\n "address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "pub_key": {\n "ed25519": "dtn+SfD+4QLo0+t0hAoP6Q2sGjh0XEI3LWVG+doh3u0="\n },\n "voting_power": 100,\n "proposer_priority": -200\n }\n ],\n "proposer": {\n "address": "VUz+QceJ8Nu7GbJuVItwsfVjybA=",\n "pub_key": {\n "ed25519": "0s8KDTgEcwmOBrHWvV7mtBlItJ3upgM1FJsciwREdy4="\n },\n "voting_power": 1,\n "proposer_priority": -3\n }\n },\n "trusted_height": {\n "revision_height": 18\n },\n "trusted_validators": {\n "validators": [\n {\n "address": "VUz+QceJ8Nu7GbJuVItwsfVjybA=",\n "pub_key": {\n "ed25519": "0s8KDTgEcwmOBrHWvV7mtBlItJ3upgM1FJsciwREdy4="\n },\n "voting_power": 1,\n "proposer_priority": -3\n },\n {\n "address": "i/A830FM7cfmA8yTn9n3xBg5XpU=",\n "pub_key": {\n "ed25519": "FCmIw7hSuiAoWk/2f4LuGQ+3zx5101xiqU8DoC5wGkg="\n },\n "voting_power": 1,\n "proposer_priority": 1\n },\n {\n "address": "2DrZF0roNnnvEy4NS2aY811ncKg=",\n "pub_key": {\n "ed25519": "MI9c6sphsWlx0RAHCYOjMRXMFkTUaEYwOiOKG/0tsMs="\n },\n "voting_power": 1,\n "proposer_priority": 1\n },\n {\n "address": "73aN0uOc5b/Zfq2Xcjl0kH2r+tw=",\n "pub_key": {\n "ed25519": "gWNcDup4mdnsuqET4QeFRzVb+FnSP4Vz3iNMj5wvWXk="\n },\n "voting_power": 1,\n "proposer_priority": 1\n }\n ],\n "proposer": {\n "address": "VUz+QceJ8Nu7GbJuVItwsfVjybA=",\n "pub_key": {\n "ed25519": "0s8KDTgEcwmOBrHWvV7mtBlItJ3upgM1FJsciwREdy4="\n },\n "voting_power": 1,\n "proposer_priority": -3\n }\n }\n}\n'})})})})]}),"\n",(0,r.jsx)(e.p,{children:"Use the following command to submit evidence of light client attacks:"}),"\n",(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-bash",children:"gaiad tx provider submit-consumer-misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0 --chain-id $CID\n"})}),"\n",(0,r.jsxs)(i,{children:[(0,r.jsxs)("summary",{children:["Example of ",(0,r.jsx)(e.code,{children:"misbehaviour.json"})]}),(0,r.jsx)("div",{children:(0,r.jsx)("div",{children:(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-json",children:'{\n "client_id": "07-tendermint-0",\n "header_1": {\n "signed_header": {\n "header": {\n "version": {\n "block": "11",\n "app": "2"\n },\n "chain_id": "testchain2",\n "height": "19",\n "time": "2020-01-02T00:08:10Z",\n "last_block_id": {\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "part_set_header": {\n "total": 10000,\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n }\n },\n "last_commit_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "data_hash": "bW4ouLmLUycELqUKV91G5syFHHLlKL3qpu/e7v5moLg=",\n "validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "next_validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "consensus_hash": "5eVmxB7Vfj/4zBDxhBeHiLj6pgKwfPH0JSF72BefHyQ=",\n "app_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "last_results_hash": "CS4FhjAkftYAmGOhLu4RfSbNnQi1rcqrN/KrNdtHWjc=",\n "evidence_hash": "c4ZdsI9J1YQokF04mrTKS5bkWjIGx6adQ6Xcc3LmBxQ=",\n "proposer_address": "CbKqPquy50bcrY7JRdW7zXybSuA="\n },\n "commit": {\n "height": "19",\n "round": 1,\n "block_id": {\n "hash": "W2xVqzPw03ZQ1kAMpcpht9WohwMzsGnyKKNjPYKDF6U=",\n "part_set_header": {\n "total": 3,\n "hash": "hwgKOc/jNqZj6lwNm97vSTq9wYt8Pj4MjmYTVMGDFDI="\n }\n },\n "signatures": [\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "PGTquCtnTNFFY5HfEFz9f9pA7PYqjtQfBwHq6cxF/Ux8OI6nVqyadD9a84Xm7fSm6mqdW+T6YVfqIKmIoRjJDQ=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "0e39yoBorwORAH/K9qJ7D1N1Yr7CutMiQJ+oiIK39eMhuoK3UWzQyMGRLzDOIDupf8yD99mvGVVAlNIODlV3Dg=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "lhc2tkwydag9D1iLQhdDCE8GgrHP94M1LbHFYMoL9tExaEq6RiFW/k71TQH5x96XQ9XYOznMIHKC2BDh4GlnAQ=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "8xeSBf0nSFs/X/rQ9CZLzwkJJhQBLA2jKdPGP3MlULxm992XxrOsIYq47u1daxvSsn6ql5OVYjzBNU0qbPpvCA=="\n }\n ]\n }\n },\n "validator_set": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n },\n "trusted_height": {\n "revision_number": "0",\n "revision_height": "18"\n },\n "trusted_validators": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n }\n },\n "header_2": {\n "signed_header": {\n "header": {\n "version": {\n "block": "11",\n "app": "2"\n },\n "chain_id": "testchain2",\n "height": "19",\n "time": "2020-01-02T00:08:20Z",\n "last_block_id": {\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "part_set_header": {\n "total": 10000,\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n }\n },\n "last_commit_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "data_hash": "bW4ouLmLUycELqUKV91G5syFHHLlKL3qpu/e7v5moLg=",\n "validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "next_validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "consensus_hash": "5eVmxB7Vfj/4zBDxhBeHiLj6pgKwfPH0JSF72BefHyQ=",\n "app_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "last_results_hash": "CS4FhjAkftYAmGOhLu4RfSbNnQi1rcqrN/KrNdtHWjc=",\n "evidence_hash": "c4ZdsI9J1YQokF04mrTKS5bkWjIGx6adQ6Xcc3LmBxQ=",\n "proposer_address": "CbKqPquy50bcrY7JRdW7zXybSuA="\n },\n "commit": {\n "height": "19",\n "round": 1,\n "block_id": {\n "hash": "IZM8NKS+8FHB7CBmgB8Nz7BRVVXiiyqMQDvHFUvgzxo=",\n "part_set_header": {\n "total": 3,\n "hash": "hwgKOc/jNqZj6lwNm97vSTq9wYt8Pj4MjmYTVMGDFDI="\n }\n },\n "signatures": [\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "pLIEZ4WSAtnMsgryujheHSq4+YG3RqTfMn2ZxgEymr0wyi+BNlQAKRtRfesm0vfYxvjzc/jhGqtUqHtSIaCwCQ=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "XG7iTe/spWyTUkT7XDzfLMpYqrdyqizE4/X4wl/W+1eaQp0WsCHYnvPU3x9NAnYfZzaKdonZiDWs7wacbZTcDg=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "TqegK7ORuICSy++wVdPHt8fL2WfPlYsMPv1XW79wUdcjnQkezOM50OSqYaP4ua5frIZsn+sWteDrlqFTdkl3BA=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "dhvp3XlIaCxx5MFDs0TCkAPHSm0PS2EtJzYAx2c/7MWdLwUJFZrAUTeimQE2c9i9ro91cjZn/vI0/oFRXab6Aw=="\n }\n ]\n }\n },\n "validator_set": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n },\n "trusted_height": {\n "revision_number": "0",\n "revision_height": "18"\n },\n "trusted_validators": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n }\n }\n}\n'})})})})]}),"\n",(0,r.jsx)(e.h3,{id:"report-equivocation-infractions-with-hermes",children:"Report equivocation infractions with Hermes"}),"\n",(0,r.jsxs)(e.p,{children:["Ensure you have a well-configured Hermes ",(0,r.jsx)(e.code,{children:"v1.7.3+"})," relayer effectively relaying packets between a consumer chain and a provider chain.\nThe following command demonstrates how to run a Hermes instance in ",(0,r.jsx)(e.em,{children:"evidence mode"})," to detect misbehaviors on a consumer chain and automatically submit the evidence to the provider chain."]}),"\n",(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-bash",children:"hermes evidence --chain \n"})}),"\n",(0,r.jsx)(e.admonition,{type:"tip",children:(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.code,{children:"hermes evidence"})," takes a ",(0,r.jsx)(e.code,{children:"--check-past-blocks"})," option giving the possibility to look for older evidence (default is 100)."]})})]})}function p(n={}){const{wrapper:e}={...(0,s.a)(),...n.components};return e?(0,r.jsx)(e,{...n,children:(0,r.jsx)(c,{...n})}):c(n)}},1151:(n,e,i)=>{i.d(e,{Z:()=>a,a:()=>t});var r=i(7294);const s={},o=r.createContext(s);function t(n){const e=r.useContext(o);return r.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function a(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(s):n.components||s:t(n.components),r.createElement(o.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/46057b98.17b22c1f.js b/assets/js/46057b98.17b22c1f.js
new file mode 100644
index 0000000000..9e0c1af100
--- /dev/null
+++ b/assets/js/46057b98.17b22c1f.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3159],{8812:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>d});var o=i(5893),s=i(1151);const t={sidebar_position:4,title:"Equivocation governance proposal"},a="ADR 003: Equivocation governance proposal",r={id:"adrs/adr-003-equivocation-gov-proposal",title:"Equivocation governance proposal",description:"Changelog",source:"@site/docs/adrs/adr-003-equivocation-gov-proposal.md",sourceDirName:"adrs",slug:"/adrs/adr-003-equivocation-gov-proposal",permalink:"/interchain-security/adrs/adr-003-equivocation-gov-proposal",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Equivocation governance proposal"},sidebar:"tutorialSidebar",previous:{title:"Jail Throttling",permalink:"/interchain-security/adrs/adr-002-throttle"},next:{title:"Cryptographic verification of equivocation evidence",permalink:"/interchain-security/adrs/adr-005-cryptographic-equivocation-verification"}},c={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"adr-003-equivocation-governance-proposal",children:"ADR 003: Equivocation governance proposal"}),"\n",(0,o.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"2023-02-06: Initial draft"}),"\n",(0,o.jsx)(n.li,{children:"2023-11-30: Change status to deprecated"}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,o.jsx)(n.p,{children:"Deprecated"}),"\n",(0,o.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Note:"})," ADR deprecated as the equivocation proposal was removed by the\ncryptographic verification of equivocation feature\n(see ",(0,o.jsx)(n.a,{href:"/interchain-security/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR-005"})," and\n",(0,o.jsx)(n.a,{href:"/interchain-security/adrs/adr-013-equivocation-slashing",children:"ADR-013"}),")."]}),"\n",(0,o.jsx)(n.p,{children:"We want to limit the possibilities of a consumer chain to execute actions on the provider chain to maintain and ensure optimum security of the provider chain."}),"\n",(0,o.jsx)(n.p,{children:"For instance, a malicious consumer consumer chain can send slash packet to the provider chain, which will slash a validator without the need of providing an evidence."}),"\n",(0,o.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,o.jsx)(n.p,{children:"To protect against a malicious consumer chain, slash packets unrelated to downtime are ignored by the provider chain. Thus, an other mechanism is required to punish validators that have committed a double-sign on a consumer chain."}),"\n",(0,o.jsxs)(n.p,{children:["A new kind of governance proposal is added to the ",(0,o.jsx)(n.code,{children:"provider"})," module, allowing to slash and tombstone a validator for double-signing in case of any harmful action on the consumer chain."]}),"\n",(0,o.jsxs)(n.p,{children:["If such proposal passes, the proposal handler delegates to the ",(0,o.jsx)(n.code,{children:"evidence"})," module to process the equivocation. This module ensures the evidence isn\u2019t too old, or else ignores it (see ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/21021b837882d1d40f1d79bcbc4fad2e79a3fefe/x/evidence/keeper/infraction.go#L54-L62",children:"code"}),"). ",(0,o.jsx)(n.em,{children:"Too old"})," is determined by 2 consensus params :"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"evidence.max_age_duration"})," number of nanoseconds before an evidence is considered too old"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"evidence.max_age_numblocks"})," number of blocks before an evidence is considered too old."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"On the hub, those parameters are equals to"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'// From https://cosmos-rpc.polkachu.com/consensus_params?height=13909682\n(...)\n"evidence": {\n\t"max_age_num_blocks": "1000000",\n\t"max_age_duration": "172800000000000",\n (...)\n},\n(...)\n'})}),"\n",(0,o.jsxs)(n.p,{children:["A governance proposal takes 14 days, so those parameters must be big enough so the evidence provided in the proposal is not ignored by the ",(0,o.jsx)(n.code,{children:"evidence"})," module when the proposal passes and is handled by the hub."]}),"\n",(0,o.jsxs)(n.p,{children:["For ",(0,o.jsx)(n.code,{children:"max_age_num_blocks=1M"}),", the parameter is big enough if we consider the hub produces 12k blocks per day (",(0,o.jsx)(n.code,{children:"blocks_per_year/365 = 436,0000/365"}),"). The evidence can be up to 83 days old (",(0,o.jsx)(n.code,{children:"1,000,000/12,000"}),") and not be ignored."]}),"\n",(0,o.jsxs)(n.p,{children:["For ",(0,o.jsx)(n.code,{children:"max_age_duration=172,800,000,000,000"}),", the parameter is too low, because the value is in nanoseconds so it\u2019s 2 days. Fortunately the condition that checks those 2 parameters uses a ",(0,o.jsx)(n.strong,{children:"AND"}),", so if ",(0,o.jsx)(n.code,{children:"max_age_num_blocks"})," condition passes, the evidence won\u2019t be ignored."]}),"\n",(0,o.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,o.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Remove the possibility from a malicious consumer chain to \u201cattack\u201d the provider chain by slashing/jailing validators."}),"\n",(0,o.jsx)(n.li,{children:"Provide a more acceptable implementation for the validator community."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Punishment action of double-signing isn\u2019t \u201cautomated\u201d, a governance proposal is required which takes more time."}),"\n",(0,o.jsx)(n.li,{children:"You need to pay 250ATOM to submit an equivocation evidence."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,o.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["PR that ignores non downtime slash packet : ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/692",children:"https://github.com/cosmos/interchain-security/pull/692"})]}),"\n",(0,o.jsxs)(n.li,{children:["PR that adds the governance slash proposal: ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/703",children:"https://github.com/cosmos/interchain-security/pull/703"})]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>a});var o=i(7294);const s={},t=o.createContext(s);function a(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/491e9485.2134357d.js b/assets/js/491e9485.2134357d.js
new file mode 100644
index 0000000000..caa944dcf4
--- /dev/null
+++ b/assets/js/491e9485.2134357d.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6784],{953:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var i=n(5893),s=n(1151);const r={sidebar_position:7,title:"Throttle with retries"},a=void 0,o={id:"adrs/adr-008-throttle-retries",title:"Throttle with retries",description:"ADR 008: Throttle with retries",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-008-throttle-retries.md",sourceDirName:"adrs",slug:"/adrs/adr-008-throttle-retries",permalink:"/interchain-security/v5.0.0/adrs/adr-008-throttle-retries",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:7,frontMatter:{sidebar_position:7,title:"Throttle with retries"},sidebar:"tutorialSidebar",previous:{title:"Cryptographic verification of equivocation evidence",permalink:"/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification"},next:{title:"Soft Opt-Out",permalink:"/interchain-security/v5.0.0/adrs/adr-009-soft-opt-out"}},d={},c=[{value:"ADR 008: Throttle with retries",id:"adr-008-throttle-with-retries",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consumer changes",id:"consumer-changes",level:3},{value:"Consumer pending packets storage optimization",id:"consumer-pending-packets-storage-optimization",level:4},{value:"Provider changes",id:"provider-changes",level:3},{value:"Handling VSCMaturedPackets immediately",id:"handling-vscmaturedpackets-immediately",level:4},{value:"Why the provider can handle VSCMatured packets immediately",id:"why-the-provider-can-handle-vscmatured-packets-immediately",level:4},{value:"Splitting of PRs and Upgrade Order",id:"splitting-of-prs-and-upgrade-order",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"adr-008-throttle-with-retries",children:"ADR 008: Throttle with retries"}),"\n",(0,i.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"6/9/23: Initial draft"}),"\n",(0,i.jsx)(t.li,{children:"6/22/23: added note on consumer pending packets storage optimization"}),"\n",(0,i.jsx)(t.li,{children:"7/14/23: Added note on upgrade order"}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(t.p,{children:"Accepted"}),"\n",(0,i.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,i.jsxs)(t.p,{children:["For context on why the throttling mechanism exists, see ",(0,i.jsx)(t.a,{href:"/interchain-security/v5.0.0/adrs/adr-002-throttle",children:"ADR 002"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Note the terms slash throttling and jail throttling are synonymous, since in replicated security a ",(0,i.jsx)(t.code,{children:"SlashPacket"})," simply jails a validator for downtime infractions."]}),"\n",(0,i.jsxs)(t.p,{children:["Currently the throttling mechanism is designed so that provider logic (slash meter, etc.) dictates how many ",(0,i.jsx)(t.code,{children:"SlashPackets"})," can be handled over time.\nThrottled ",(0,i.jsx)(t.code,{children:"SlashPackets"})," are persisted on the provider, leading to multiple possible issues. Namely:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["If ",(0,i.jsx)(t.code,{children:"SlashPackets"})," or ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," are actually throttled/queued on the provider, state can grow and potentially lead to a DoS attack.\nWe have short term solutions around this, but overall they come with their own weaknesses.\nSee ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/594",children:"#594"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:["If a jailing attack described in ",(0,i.jsx)(t.a,{href:"/interchain-security/v5.0.0/adrs/adr-002-throttle",children:"ADR 002"})," were actually to be carried out with the current throttling design, we'd likely have to halt the provider, and perform an emergency upgrade and/or migration to clear the queues of ",(0,i.jsx)(t.code,{children:"SlashPackets"})," that were deemed to be malicious.\nAlternatively, validators would just have to ",(0,i.jsx)(t.em,{children:"tough it out"})," and wait for the queues to clear, during which all/most validators would be jailed.\nRight after being jailed, validators would have to unjail themselves promptly to ensure safety.\nThe coordination required to maintain safety in such a scenario is not ideal."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"As a solution, we can improve the throttling mechanism to instead queue/persist relevant data on each consumer, and have consumers retry slash requests as needed."}),"\n",(0,i.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(t.h3,{id:"consumer-changes",children:"Consumer changes"}),"\n",(0,i.jsxs)(t.p,{children:["Note the consumer already queues up both ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," via ",(0,i.jsx)(t.code,{children:"AppendPendingPacket"}),".\nThose packets are dequeued in every ",(0,i.jsx)(t.code,{children:"EndBlock"})," in ",(0,i.jsx)(t.code,{children:"SendPackets"})," and sent to the provider."]}),"\n",(0,i.jsxs)(t.p,{children:["Instead, we will now introduce the following logic on ",(0,i.jsx)(t.code,{children:"EndBlock"}),":"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Slash packets will always be sent to the provider once they're at the head of the queue.\nHowever, once sent, the consumer will not send any subsequent ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," from the queue until the provider responds with an acknowledgement that the sent ",(0,i.jsx)(t.code,{children:"SlashPacket"})," has been handled, i.e., validator was jailed.\nThat is, ",(0,i.jsx)(t.code,{children:"SlashPackets"})," block the sending of subsequent ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," in the consumer queue."]}),"\n",(0,i.jsxs)(t.li,{children:["If two ",(0,i.jsx)(t.code,{children:"SlashPackets"})," are at the head of the queue, the consumer will send the first ",(0,i.jsx)(t.code,{children:"SlashPacket"}),", and then wait for a success acknowledgement from the provider before sending the second ",(0,i.jsx)(t.code,{children:"SlashPacket"}),".\nThis seems like it'd simplify implementation."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," at the head of the queue (i.e., NOT following a ",(0,i.jsx)(t.code,{children:"SlashPacket"}),") can be sent immediately, and do not block any other packets in the queue, since the provider always handles them immediately."]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["To prevent the provider from having to keep track of what ",(0,i.jsx)(t.code,{children:"SlashPackets"})," have been rejected, the consumer will have to retry the sending of ",(0,i.jsx)(t.code,{children:"SlashPackets"})," over some period of time.\nThis can be achieved with an on-chain consumer param, i.e., ",(0,i.jsx)(t.code,{children:"RetryDelayPeriod"}),".\nTo reduce the amount of redundant re-sends, we recommend setting ",(0,i.jsx)(t.code,{children:"RetryDelayPeriod ~ SlashMeterReplenishmentPeriod"}),", i.e., waiting for the provider slash meter to be replenished before resending the rejected ",(0,i.jsx)(t.code,{children:"SlashPacket"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"Note to prevent weird edge case behavior, a retry would not be attempted until either a success or failure acknowledgement has been received from the provider."}),"\n",(0,i.jsxs)(t.p,{children:["With the behavior described, we maintain very similar behavior to the previous throttling mechanism regarding the timing that ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," are handled on the provider.\nObviously the queueing and blocking logic is moved, and the two chains would have to send more messages between one another (only in the case the throttling mechanism is triggered)."]}),"\n",(0,i.jsxs)(t.p,{children:["In the normal case, when no or a few ",(0,i.jsx)(t.code,{children:"SlashPackets"})," are being sent, the ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," will not be delayed, and hence unbonding will not be delayed."]}),"\n",(0,i.jsxs)(t.p,{children:["For the implementation of this design, see ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/fec3eccad59416cbdb6844e279f59e3f81242888/x/ccv/consumer/keeper/throttle_retry.go",children:"throttle_retry.go"}),"."]}),"\n",(0,i.jsx)(t.h4,{id:"consumer-pending-packets-storage-optimization",children:"Consumer pending packets storage optimization"}),"\n",(0,i.jsx)(t.p,{children:"In addition to the mentioned consumer changes, an optimization will need to be made to the consumer's pending packets storage to properly implement the feature from this ADR."}),"\n",(0,i.jsxs)(t.p,{children:['The consumer ccv module previously queued "pending packets" to be sent in each ',(0,i.jsx)(t.code,{children:"EndBlock"})," in ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/3bc4e7135066d848aac60b0787364c07157fd36d/x/ccv/consumer/keeper/relay.go#L178",children:"SendPackets"}),".\nThese packets are queued in state with a protobuf list of ",(0,i.jsx)(t.code,{children:"ConsumerPacketData"}),".\nFor a single append operation, the entire list is deserialized, then a packet is appended to that list, and the list is serialized again.\nSee older version of ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/05c2dae7c6372b1252b9e97215d07c6aa7618f33/x/ccv/consumer/keeper/keeper.go#L606",children:"AppendPendingPacket"}),".\nThat is, a single append operation has O(N) complexity, where N is the size of the list."]}),"\n",(0,i.jsxs)(t.p,{children:["This poor append performance isn't a problem when the pending packets list is small.\nBut with this ADR being implemented, the pending packets list could potentially grow to the order of thousands of entries when ",(0,i.jsx)(t.code,{children:"SlashPackets"})," need to be resent."]}),"\n",(0,i.jsx)(t.p,{children:"We can improve the append time for this queue by converting it from a protobuf-esq list, to a queue implemented with sdk-esq code.\nThe idea is to persist a uint64 index that will be incremented each time you queue up a packet.\nYou can think of this as storing the tail of the queue.\nThen, packet data will be keyed by that index, making the data naturally ordered byte-wise for sdk's iterator.\nThe index will also be stored in the packet data value bytes, so that the index can later be used to delete certain packets from the queue."}),"\n",(0,i.jsx)(t.p,{children:"Two things are achieved with this approach:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"More efficient packet append/enqueue times"}),"\n",(0,i.jsx)(t.li,{children:"The ability to delete select packets from the queue (previously all packets were deleted at once)"}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"provider-changes",children:"Provider changes"}),"\n",(0,i.jsxs)(t.p,{children:["The main change needed for the provider is the removal of queuing logic for ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," upon being received."]}),"\n",(0,i.jsxs)(t.p,{children:["Instead, the provider will consult the slash meter to determine if a ",(0,i.jsx)(t.code,{children:"SlashPacket"})," can be handled immediately.\nIf not, the provider will return an acknowledgement message to the consumer communicating that the ",(0,i.jsx)(t.code,{children:"SlashPacket"})," could not be handled, and needs to be sent again in the future (retried)."]}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," will always be handled immediately upon being received by the provider."]}),"\n",(0,i.jsxs)(t.p,{children:["Note ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#consumer-initiated-slashing",children:"spec"}),". Specifically the section on ",(0,i.jsx)(t.em,{children:"VSC Maturity and Slashing Order"}),". Previously the onus was on the provider to maintain this property via queuing packets and handling them FIFO."]}),"\n",(0,i.jsxs)(t.p,{children:["Now this property will be maintained by the consumer sending packets in the correct order, and blocking the sending of ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," as needed. Then, the ordered IBC channel will ensure that ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," are received in the correct order on the provider."]}),"\n",(0,i.jsxs)(t.p,{children:["The provider's main responsibility regarding throttling will now be to determine if a received ",(0,i.jsx)(t.code,{children:"SlashPacket"})," can be handled via slash meter etc., and appropriately acknowledge to the sending consumer."]}),"\n",(0,i.jsxs)(t.h4,{id:"handling-vscmaturedpackets-immediately",children:["Handling ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," immediately"]}),"\n",(0,i.jsx)(t.h4,{id:"why-the-provider-can-handle-vscmatured-packets-immediately",children:"Why the provider can handle VSCMatured packets immediately"}),"\n",(0,i.jsxs)(t.p,{children:["A ",(0,i.jsx)(t.code,{children:"VSCMaturedPacket"})," communicates to the provider that sufficient time passed on the consumer since the corresponding ",(0,i.jsx)(t.code,{children:"VSCPacket"})," has been applied (on the consumer) such that infractions committed on the consumer could have been submitted."]}),"\n",(0,i.jsxs)(t.p,{children:["If the consumer is following the queuing/blocking protocol described, then no bad behavior occurs and the ",(0,i.jsx)(t.em,{children:"VSC Maturity and Slashing Order"})," property is maintained."]}),"\n",(0,i.jsxs)(t.p,{children:["If a consumer sends ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," too leniently -- the consumer is malicious and sends duplicate ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"}),", or sends the packets sooner than the CCV protocol specifies -- then the provider needs to handle ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," immediately to prevent DOS, state bloat, or other issues.\nThe only possible negative outcome is that the malicious consumer may not be able to jail a validator who should have been jailed.\nThe malicious behavior only creates a negative outcome for the consumer chain that is being malicious."]}),"\n",(0,i.jsxs)(t.p,{children:["If a consumer blocks the sending of ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"}),", then unbonding operations on the provider will be delayed, but only until the VSC timeout period has elapsed.\nAt that time, the consumer is removed.\nAgain the malicious behavior only creates a negative outcome for the consumer chain that is being malicious."]}),"\n",(0,i.jsx)(t.h3,{id:"splitting-of-prs-and-upgrade-order",children:"Splitting of PRs and Upgrade Order"}),"\n",(0,i.jsxs)(t.p,{children:["This feature will implement consumer changes in ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1024",children:"#1024"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["\u2757",(0,i.jsx)(t.em,{children:(0,i.jsx)(t.strong,{children:"These changes should be deployed to production for all consumers before the provider changes are deployed to production."})})]}),"\n",(0,i.jsxs)(t.p,{children:["In other words, the consumer changes in ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1024",children:"#1024"}),' are compatible with the current ("v1") provider implementation of throttling that\'s running on the Cosmos Hub as of July 2023.']}),"\n",(0,i.jsxs)(t.p,{children:["Once all consumers have deployed the changes in #1024, the provider changes from ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1321",children:"#1321"})," can be deployed to production, fully enabling v2 throttling."]}),"\n",(0,i.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Consumers will now have to manage their own queues, and retry logic."}),"\n",(0,i.jsx)(t.li,{children:"Consumers still aren't trustless, but the provider is now less susceptible to mismanaged or malicious consumers."}),"\n",(0,i.jsx)(t.li,{children:'Recovering from the "jailing attack" is more elegant.'}),"\n",(0,i.jsxs)(t.li,{children:["Some issues like ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/1001",children:"#1001"})," will now be handled implicitly by the improved throttling mechanism."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," can be handled immediately once received by the provider if the slash meter allows."]}),"\n",(0,i.jsxs)(t.li,{children:["In general, we reduce the amount of computation that happens in the provider ",(0,i.jsx)(t.code,{children:"EndBlock"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:['We no longer have to reason about a "global queue" and a "chain specific queue", and keeping those all in-sync.\nNow ',(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," queuing is handled on each consumer individually."]}),"\n",(0,i.jsx)(t.li,{children:"Due to the above, the throttling protocol becomes less complex overall."}),"\n",(0,i.jsx)(t.li,{children:"We no longer have to worry about throttle related DoS attack on the provider, since no queuing exists on the provider."}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Increased number of IBC packets being relayed anytime throttling logic is triggered."}),"\n",(0,i.jsx)(t.li,{children:"Consumer complexity increases, since consumers now have manage queuing themselves, and implement packet retry logic."}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Core throttling logic on the provider remains unchanged, i.e., slash meter, replenishment cycles, etc."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/713",children:"EPIC"})," tracking the changes proposed by this ADR"]}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/interchain-security/v5.0.0/adrs/adr-002-throttle",children:"ADR 002: Jail Throttling"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/594",children:"#594"})}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>o,a:()=>a});var i=n(7294);const s={},r=i.createContext(s);function a(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/4c7d82ee.1a561975.js b/assets/js/4c7d82ee.1a561975.js
new file mode 100644
index 0000000000..eaa82e436c
--- /dev/null
+++ b/assets/js/4c7d82ee.1a561975.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7649],{1915:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>r,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>c,toc:()=>h});var n=t(5893),s=t(1151);const o={sidebar_position:4,title:"Cryptographic verification of equivocation evidence"},a="ADR 005: Cryptographic verification of equivocation evidence",c={id:"adrs/adr-005-cryptographic-equivocation-verification",title:"Cryptographic verification of equivocation evidence",description:"Changelog",source:"@site/docs/adrs/adr-005-cryptographic-equivocation-verification.md",sourceDirName:"adrs",slug:"/adrs/adr-005-cryptographic-equivocation-verification",permalink:"/interchain-security/adrs/adr-005-cryptographic-equivocation-verification",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Cryptographic verification of equivocation evidence"},sidebar:"tutorialSidebar",previous:{title:"Equivocation governance proposal",permalink:"/interchain-security/adrs/adr-003-equivocation-gov-proposal"},next:{title:"Throttle with retries",permalink:"/interchain-security/adrs/adr-008-throttle-retries"}},r={},h=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Light Client Attack",id:"light-client-attack",level:3},{value:"Double Signing Attack",id:"double-signing-attack",level:3},{value:"Decision",id:"decision",level:2},{value:"Light Client Attack",id:"light-client-attack-1",level:3},{value:"Double Signing Attack",id:"double-signing-attack-1",level:3},{value:"Current limitations:",id:"current-limitations",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function l(e){const i={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,s.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"adr-005-cryptographic-verification-of-equivocation-evidence",children:"ADR 005: Cryptographic verification of equivocation evidence"}),"\n",(0,n.jsx)(i.h2,{id:"changelog",children:"Changelog"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"5/1/2023: First draft"}),"\n",(0,n.jsx)(i.li,{children:"7/23/2023: Add light client attacks handling"}),"\n",(0,n.jsx)(i.li,{children:"9/6/2023: Add double signing attacks handling"}),"\n",(0,n.jsx)(i.li,{children:"11/3/2023: Update limitations to clarify amnesia attacks are ignored"}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"status",children:"Status"}),"\n",(0,n.jsx)(i.p,{children:"Accepted"}),"\n",(0,n.jsx)(i.h2,{id:"context",children:"Context"}),"\n",(0,n.jsx)(i.p,{children:"Currently, we use a governance proposal to slash validators for equivocation (double signing and light client attacks).\nEvery proposal needs to go through a (two weeks) voting period before it can be approved.\nGiven a three-week unbonding period, this means that an equivocation proposal needs to be submitted within one week since the infraction occurred."}),"\n",(0,n.jsx)(i.p,{children:"This ADR proposes a system to slash validators automatically for equivocation, immediately upon the provider chain's receipt of the evidence. Another thing to note is that we intend to introduce this system in stages, since even the partial ability to slash and/or tombstone is a strict improvement in security.\nThe feature is implemented in two parts, each with its dedicated endpoint. One endpoint handles light client attacks, while the other handles double signing attacks."}),"\n",(0,n.jsx)(i.h3,{id:"light-client-attack",children:"Light Client Attack"}),"\n",(0,n.jsx)(i.p,{children:"In a nutshell, the light client is a process that solely verifies a specific state machine's\nconsensus without executing the transactions. The light clients get new headers by querying\nmultiple nodes, called primary and witness nodes."}),"\n",(0,n.jsxs)(i.p,{children:["Light clients download new headers committed on chain from a primary. Headers can be verified in two ways: sequentially,\nwhere the block height of headers is serial, or using skipping. This second verification method allows light clients to download headers\nwith nonconsecutive block height, where some intermediate headers are skipped (see ",(0,n.jsx)(i.a,{href:"https://arxiv.org/pdf/2010.07031",children:"Tendermint Light Client, Figure 1 and Figure 3"}),").\nAdditionally, light clients are cross-checking new headers obtained from a primary with witnesses to ensure all nodes share the same state."]}),"\n",(0,n.jsxs)(i.p,{children:["A light client attack occurs when a Byzantine validator sends invalid headers to a light client.\nAs the light client doesn't execute transactions, it can be deceived into trusting corrupted application state transitions.\nFor instance, if a light client receives header ",(0,n.jsx)(i.code,{children:"A"})," from the primary and header ",(0,n.jsx)(i.code,{children:"B"})," from a witness for the same block height ",(0,n.jsx)(i.code,{children:"H"}),",\nand both headers are successfully verified, it indicates a light client attack.\nNote that in this case, either the primary or the witness or both are malicious."]}),"\n",(0,n.jsxs)(i.p,{children:["The types of light client attacks are defined by analyzing the differences between the conflicting headers.\nThere are three types of light client attacks: lunatic attack, equivocation attack, and amnesia attack.\nFor details, see the ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/main/spec/light-client/attacks/notes-on-evidence-handling.md#evidence-handling",children:"CometBFT specification"}),"."]}),"\n",(0,n.jsxs)(i.p,{children:["When a light client agent detects two conflicting headers, it will initially verify their traces (see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/light/detector.go#L28",children:"cometBFT detector"}),") using its primary and witness nodes.\nIf these headers pass successful verification, the Byzantine validators will be identified based on the header's commit signatures\nand the type of light client attack. The agent will then transmit this information to its nodes using a ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#light-client-attacks",children:(0,n.jsx)(i.code,{children:"LightClientAttackEvidence"})})," evidence to be eventually voted on and added to a block.\nNote that from a light client agent perspective, it is not possible to establish whether a primary or a witness node, or both, are malicious.\nTherefore, it will create and send two evidences: one against the primary (sent to the witness), and one against the witness (sent to the primary).\nBoth nodes will then verify it before broadcasting it and adding it to the ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/evidence/pool.go#L28",children:"evidence pool"}),".\nIf an evidence is finally committed to a block, the chain's evidence module will execute it, resulting in the jailing and the slashing of the validators responsible for the light client attack."]}),"\n",(0,n.jsxs)(i.p,{children:["Light clients are a core component of IBC. In the event of a light client attack, IBC relayers notify the affected chains by submitting an ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/ibc-go/blob/v4.4.2/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L79",children:"IBC misbehavior message"}),".\nA misbehavior message includes the conflicting headers that constitute a light client attack evidence. Upon receiving such a message,\na chain will first verify whether these headers would have convinced its light client. This verification is achieved by checking\nthe header states against the light client consensus states (see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/ibc-go/blob/v4.4.2/modules/light-clients/07-tendermint/types/misbehaviour_handle.go#L24",children:"IBC misbehaviour handler"}),'). If the misbehaviour is successfully verified, the chain will then "freeze" the\nlight client, halting any further trust in or updating of its states.']}),"\n",(0,n.jsx)(i.h3,{id:"double-signing-attack",children:"Double Signing Attack"}),"\n",(0,n.jsxs)(i.p,{children:["A double signing attack, also known as equivocation,\noccurs when a validator votes for two different blocks in the same round of the CometBFT consensus.\nThis consensus mechanism operates with multiple voting rounds at each block height,\nand it strictly prohibits sending two votes of the same type during a round\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/consensus.md#state-machine-overview",children:"CometBFT State Machine Overview"}),")."]}),"\n",(0,n.jsxs)(i.p,{children:["When a node observes two votes from the same peer, it will use these two votes to create\na ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/types/evidence.go#L35",children:(0,n.jsx)(i.code,{children:"DuplicateVoteEvidence"})}),"\nevidence and gossip it to the other nodes in the network\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#detection",children:"CometBFT equivocation detection"}),").\nEach node will then verify the evidence according to the CometBFT rules that define a valid double signing infraction, and based on this verification, they will decide whether to add the evidence to a block.\nDuring the evidence verification process, the signatures of the conflicting votes must be verified successfully.\nNote that this is achieved using the public key of the misbehaving validator, along with the chain ID of the chain where the infraction occurred (see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#verification",children:"CometBFT equivocation verification"}),")."]}),"\n",(0,n.jsxs)(i.p,{children:["Once a double signing evidence is committed to a block, the consensus layer will report the equivocation to the evidence module of the Cosmos SDK application layer.\nThe application will, in turn, punish the malicious validator through jailing, tombstoning and slashing\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.45.16-ics-lsm/x/evidence/keeper/infraction.go#L263",children:"handleEquivocationEvidence"}),")."]}),"\n",(0,n.jsx)(i.h2,{id:"decision",children:"Decision"}),"\n",(0,n.jsx)(i.h3,{id:"light-client-attack-1",children:"Light Client Attack"}),"\n",(0,n.jsxs)(i.p,{children:["In the first part of the feature, we introduce a new endpoint: ",(0,n.jsx)(i.code,{children:"HandleConsumerMisbehaviour(ctx sdk.Context, misbehaviour ibctmtypes.Misbehaviour)"}),".\nThe main idea is to leverage the current IBC misbehaviour handling and update it to solely jail and slash the validators that\nperformed a light client attack. Note that in this context, we assume that chains connected via a light client\nshare a subset of the validator set of the provider."]}),"\n",(0,n.jsx)(i.p,{children:"This endpoint reuses the IBC client libraries to verify that the misbehaviour headers would have fooled the light client.\nAdditionally, it\u2019s crucial that the endpoint logic results in the slashing and jailing of validators under the same conditions\nas a light client agent detector. Therefore, the endpoint ensures that the two conditions are met:\nthe headers in the misbehaviour message have the same block height, and\nthe light client isn\u2019t expired."}),"\n",(0,n.jsx)(i.p,{children:"After having successfully verified a misbehaviour, the endpoint executes the jailing and slashing of the malicious validators similarly as in the evidence module."}),"\n",(0,n.jsx)(i.h3,{id:"double-signing-attack-1",children:"Double Signing Attack"}),"\n",(0,n.jsxs)(i.p,{children:["In the second part of the feature, we introduce a new endpoint ",(0,n.jsx)(i.code,{children:"HandleConsumerDoubleVoting( ctx sdk.Context, evidence *tmtypes.DuplicateVoteEvidence, chainID string, pubkey cryptotypes.PubKey)"}),".\nSimply put, the handling logic verifies a double signing evidence against a provided\npublic key and chain ID and, if successful, executes the jailing of the malicious validator who double voted."]}),"\n",(0,n.jsxs)(i.p,{children:["We define a new\n",(0,n.jsx)(i.code,{children:"MsgSubmitConsumerDoubleVoting"})," message to report a double voting evidence observed\non a consumer chain to the endpoint of the provider chain. This message contains two fields:\na double signing evidence\n",(0,n.jsx)(i.code,{children:"duplicate_vote_evidence"})," and a light client header for the infraction block height,\nreferred to as ",(0,n.jsx)(i.code,{children:"infraction_block_header"}),".\nThe latter provides the malicious validator's public key and the chain ID required to verify the signature of the votes contained in the evidence."]}),"\n",(0,n.jsxs)(i.p,{children:["Note that double signing evidence is not verified using the same conditions as in the implementation CometBFT (see\n",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/evidence/verify.go#L19",children:(0,n.jsx)(i.code,{children:"verify(evidence types.Evidence)"})})," method). Specifically, we do not check that the evidence hasn't expired.\nMore details can be found in the ",(0,n.jsx)(i.a,{href:"#current-limitations",children:'"Current limitations"'})," section below."]}),"\n",(0,n.jsxs)(i.p,{children:["Upon a successful equivocation verification, the misbehaving validator is jailed for the maximum time\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.45.16-ics-lsm/x/evidence/types/params.go#L11",children:"DoubleSignJailEndTime"}),"\nin the SDK evidence module)."]}),"\n",(0,n.jsx)(i.h3,{id:"current-limitations",children:"Current limitations:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"We cannot derive an infraction height from the evidence, so it is only possible to jail validators, not actually slash them.\nTo explain the technical reasons behind this limitation, let's recap the initial consumer initiated slashing logic.\nIn a nutshell, consumer heights are mapped to provider heights through VSCPackets, namely through the so called vscIDs.\nWhen an infraction occurs on the consumer, a SlashPacket containing the vscID obtained from mapping the consumer infraction height\nis sent to the provider. Upon receiving the packet, the provider maps the consumer infraction height to a local infraction height,\nwhich is used to slash the misbehaving validator. In the context of untrusted consumer chains, all their states, including vscIDs,\ncould be corrupted and therefore cannot be used for slashing purposes."}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"For the same reasons explained above, the age of a consumer double signing evidence can't be verified,\neither using its infraction height or its unsigned timestamp. Note that changes the jailing behaviour, potentially leading to a validator's jailing based on some \"old\" evidence from a consumer, which wouldn't occur if the consumer were a standalone chain."}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsxs)(i.p,{children:["In the first stage of this feature, validators are jailed indefinitely without being tombstoned.\nThe underlying reason is that a malicious validator could take advantage of getting tombstoned\nto avoid being slashed on the provider (",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/1232#issuecomment-1693127641",children:"see comment"}),")."]}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsxs)(i.p,{children:["Currently, the endpoint can only handle ",(0,n.jsx)(i.em,{children:"equivocation"})," light client attacks. This is because the ",(0,n.jsx)(i.em,{children:"lunatic"})," attacks require the endpoint to possess the ability to dissociate which header is conflicted or trusted upon receiving a misbehavior message. Without this information, it's not possible to extract the Byzantine validators from the conflicting headers (see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/826#discussion_r1268668684",children:"comment"}),'). In addition, "amnesia" attacks are ignored, similar to CometBFT (see ',(0,n.jsx)(i.a,{href:"https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-047-handling-evidence-from-light-client.md#negative",children:"ADR-056"}),")."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"consequences",children:"Consequences"}),"\n",(0,n.jsx)(i.h3,{id:"positive",children:"Positive"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"It is now possible for the provider chain to jail validators who committed\nlight client or double signing attacks on a consumer chain."}),"\n"]}),"\n",(0,n.jsx)(i.h3,{id:"negative",children:"Negative"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"N/A"}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/826",children:"ICS misbehaviour handling PR"})}),"\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"Consumer double voting handler PR"})}),"\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://docs.google.com/document/d/1fe1uSJl1ZIYWXoME3Yf4Aodvz7V597Ric875JH-rigM/edit#heading=h.rv4t8i6d6jfn",children:"Architectural diagrams"})}),"\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-013-equivocation-slashing.md",children:"ADR on equivocation slashing"})}),"\n"]})]})}function d(e={}){const{wrapper:i}={...(0,s.a)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},1151:(e,i,t)=>{t.d(i,{Z:()=>c,a:()=>a});var n=t(7294);const s={},o=n.createContext(s);function a(e){const i=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/4edc808e.176093f8.js b/assets/js/4edc808e.176093f8.js
new file mode 100644
index 0000000000..b896846bdd
--- /dev/null
+++ b/assets/js/4edc808e.176093f8.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4173],{7559:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>u,contentTitle:()=>c,default:()=>m,frontMatter:()=>o,metadata:()=>d,toc:()=>h});var t=n(5893),i=n(1151),s=n(2307),a=n(8758);const o={sidebar_position:1},c="Interchain Security Docs",d={id:"index",title:"Interchain Security Docs",description:"Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains.",source:"@site/docs/index.mdx",sourceDirName:".",slug:"/",permalink:"/interchain-security/",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",next:{title:"Overview",permalink:"/interchain-security/introduction/overview"}},u={},h=[];function l(e){const r={h1:"h1",p:"p",...(0,i.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h1,{id:"interchain-security-docs",children:"Interchain Security Docs"}),"\n",(0,t.jsx)(r.p,{children:"Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains."}),"\n",(0,t.jsx)(r.p,{children:"Here you can find information about Interchain Security, consumer chain development and instructions for validator onboarding."}),"\n",(0,t.jsx)(s.Z,{cards:a.Z})]})}function m(e={}){const{wrapper:r}={...(0,i.a)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},2307:(e,r,n)=>{n.d(r,{Z:()=>s});n(7294);var t=n(5893);const i=function(e){return(0,t.jsx)("a",{href:e.href,className:"border shadow rounded-sm border-stone-200 dark:border-stone-800 dark:bg-neutral-900 hover:border-stone-300 hover:shadow-lg dark:hover:border-stone-200 transition-all duration-200 no-underline",children:(0,t.jsxs)("div",{className:"p-6",children:[(0,t.jsx)("h2",{className:"",children:e.header}),(0,t.jsx)("p",{className:"",children:e.summary})]})})};const s=function(e){return(0,t.jsx)("div",{className:"card-section grid grid-cols-1 lg:grid-cols-2 gap-4 no-underline",children:e.cards.map(((e,r)=>(0,t.jsx)(i,{href:e.href,header:e.header,summary:e.summary},r)))})}},8758:(e,r,n)=>{n.d(r,{Z:()=>t});const t=[{href:"/interchain-security/introduction/overview",header:"Basic concepts",summary:"Get started with the basic concepts and ideas."},{href:"/interchain-security/consumer-development/app-integration",header:"Start building",summary:"Click here to start building with Interchain security"},{href:"/interchain-security/features/key-assignment",header:"Feature: Key Assignment",summary:"Learn about the key assignment feature"},{href:"/interchain-security/features/reward-distribution",header:"Feature: Reward Distribution",summary:"Learn about consumer chain rewards distribution"},{href:"/interchain-security/consumer-development/onboarding",header:"Onboarding Checklist",summary:"Checklist to help you integrate Interchain Security, get support and onboard validators"},{href:"/interchain-security/faq",header:"FAQ",summary:"Frequently asked questions about the protocol and its implications"}]},1151:(e,r,n)=>{n.d(r,{Z:()=>o,a:()=>a});var t=n(7294);const i={},s=t.createContext(i);function a(e){const r=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function o(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),t.createElement(s.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/4edefe03.b3451047.js b/assets/js/4edefe03.b3451047.js
new file mode 100644
index 0000000000..68bb0ca108
--- /dev/null
+++ b/assets/js/4edefe03.b3451047.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[918],{7168:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>r,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>c,toc:()=>h});var n=t(5893),s=t(1151);const o={sidebar_position:4,title:"Cryptographic verification of equivocation evidence"},a="ADR 005: Cryptographic verification of equivocation evidence",c={id:"adrs/adr-005-cryptographic-equivocation-verification",title:"Cryptographic verification of equivocation evidence",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-005-cryptographic-equivocation-verification.md",sourceDirName:"adrs",slug:"/adrs/adr-005-cryptographic-equivocation-verification",permalink:"/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Cryptographic verification of equivocation evidence"},sidebar:"tutorialSidebar",previous:{title:"Equivocation governance proposal",permalink:"/interchain-security/v5.0.0/adrs/adr-003-equivocation-gov-proposal"},next:{title:"Throttle with retries",permalink:"/interchain-security/v5.0.0/adrs/adr-008-throttle-retries"}},r={},h=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Light Client Attack",id:"light-client-attack",level:3},{value:"Double Signing Attack",id:"double-signing-attack",level:3},{value:"Decision",id:"decision",level:2},{value:"Light Client Attack",id:"light-client-attack-1",level:3},{value:"Double Signing Attack",id:"double-signing-attack-1",level:3},{value:"Current limitations:",id:"current-limitations",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function l(e){const i={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,s.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"adr-005-cryptographic-verification-of-equivocation-evidence",children:"ADR 005: Cryptographic verification of equivocation evidence"}),"\n",(0,n.jsx)(i.h2,{id:"changelog",children:"Changelog"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"5/1/2023: First draft"}),"\n",(0,n.jsx)(i.li,{children:"7/23/2023: Add light client attacks handling"}),"\n",(0,n.jsx)(i.li,{children:"9/6/2023: Add double signing attacks handling"}),"\n",(0,n.jsx)(i.li,{children:"11/3/2023: Update limitations to clarify amnesia attacks are ignored"}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"status",children:"Status"}),"\n",(0,n.jsx)(i.p,{children:"Accepted"}),"\n",(0,n.jsx)(i.h2,{id:"context",children:"Context"}),"\n",(0,n.jsx)(i.p,{children:"Currently, we use a governance proposal to slash validators for equivocation (double signing and light client attacks).\nEvery proposal needs to go through a (two weeks) voting period before it can be approved.\nGiven a three-week unbonding period, this means that an equivocation proposal needs to be submitted within one week since the infraction occurred."}),"\n",(0,n.jsx)(i.p,{children:"This ADR proposes a system to slash validators automatically for equivocation, immediately upon the provider chain's receipt of the evidence. Another thing to note is that we intend to introduce this system in stages, since even the partial ability to slash and/or tombstone is a strict improvement in security.\nThe feature is implemented in two parts, each with its dedicated endpoint. One endpoint handles light client attacks, while the other handles double signing attacks."}),"\n",(0,n.jsx)(i.h3,{id:"light-client-attack",children:"Light Client Attack"}),"\n",(0,n.jsx)(i.p,{children:"In a nutshell, the light client is a process that solely verifies a specific state machine's\nconsensus without executing the transactions. The light clients get new headers by querying\nmultiple nodes, called primary and witness nodes."}),"\n",(0,n.jsxs)(i.p,{children:["Light clients download new headers committed on chain from a primary. Headers can be verified in two ways: sequentially,\nwhere the block height of headers is serial, or using skipping. This second verification method allows light clients to download headers\nwith nonconsecutive block height, where some intermediate headers are skipped (see ",(0,n.jsx)(i.a,{href:"https://arxiv.org/pdf/2010.07031.pdf",children:"Tendermint Light Client, Figure 1 and Figure 3"}),").\nAdditionally, light clients are cross-checking new headers obtained from a primary with witnesses to ensure all nodes share the same state."]}),"\n",(0,n.jsxs)(i.p,{children:["A light client attack occurs when a Byzantine validator sends invalid headers to a light client.\nAs the light client doesn't execute transactions, it can be deceived into trusting corrupted application state transitions.\nFor instance, if a light client receives header ",(0,n.jsx)(i.code,{children:"A"})," from the primary and header ",(0,n.jsx)(i.code,{children:"B"})," from a witness for the same block height ",(0,n.jsx)(i.code,{children:"H"}),",\nand both headers are successfully verified, it indicates a light client attack.\nNote that in this case, either the primary or the witness or both are malicious."]}),"\n",(0,n.jsxs)(i.p,{children:["The types of light client attacks are defined by analyzing the differences between the conflicting headers.\nThere are three types of light client attacks: lunatic attack, equivocation attack, and amnesia attack.\nFor details, see the ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/main/spec/light-client/attacks/notes-on-evidence-handling.md#evidence-handling",children:"CometBFT specification"}),"."]}),"\n",(0,n.jsxs)(i.p,{children:["When a light client agent detects two conflicting headers, it will initially verify their traces (see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/light/detector.go#L28",children:"cometBFT detector"}),") using its primary and witness nodes.\nIf these headers pass successful verification, the Byzantine validators will be identified based on the header's commit signatures\nand the type of light client attack. The agent will then transmit this information to its nodes using a ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#light-client-attacks",children:(0,n.jsx)(i.code,{children:"LightClientAttackEvidence"})})," evidence to be eventually voted on and added to a block.\nNote that from a light client agent perspective, it is not possible to establish whether a primary or a witness node, or both, are malicious.\nTherefore, it will create and send two evidences: one against the primary (sent to the witness), and one against the witness (sent to the primary).\nBoth nodes will then verify it before broadcasting it and adding it to the ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/evidence/pool.go#L28",children:"evidence pool"}),".\nIf an evidence is finally committed to a block, the chain's evidence module will execute it, resulting in the jailing and the slashing of the validators responsible for the light client attack."]}),"\n",(0,n.jsxs)(i.p,{children:["Light clients are a core component of IBC. In the event of a light client attack, IBC relayers notify the affected chains by submitting an ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/ibc-go/blob/v4.4.2/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L79",children:"IBC misbehavior message"}),".\nA misbehavior message includes the conflicting headers that constitute a light client attack evidence. Upon receiving such a message,\na chain will first verify whether these headers would have convinced its light client. This verification is achieved by checking\nthe header states against the light client consensus states (see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/ibc-go/blob/v4.4.2/modules/light-clients/07-tendermint/types/misbehaviour_handle.go#L24",children:"IBC misbehaviour handler"}),'). If the misbehaviour is successfully verified, the chain will then "freeze" the\nlight client, halting any further trust in or updating of its states.']}),"\n",(0,n.jsx)(i.h3,{id:"double-signing-attack",children:"Double Signing Attack"}),"\n",(0,n.jsxs)(i.p,{children:["A double signing attack, also known as equivocation,\noccurs when a validator votes for two different blocks in the same round of the CometBFT consensus.\nThis consensus mechanism operates with multiple voting rounds at each block height,\nand it strictly prohibits sending two votes of the same type during a round\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/consensus.md#state-machine-overview",children:"CometBFT State Machine Overview"}),")."]}),"\n",(0,n.jsxs)(i.p,{children:["When a node observes two votes from the same peer, it will use these two votes to create\na ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/types/evidence.go#L35",children:(0,n.jsx)(i.code,{children:"DuplicateVoteEvidence"})}),"\nevidence and gossip it to the other nodes in the network\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#detection",children:"CometBFT equivocation detection"}),").\nEach node will then verify the evidence according to the CometBFT rules that define a valid double signing infraction, and based on this verification, they will decide whether to add the evidence to a block.\nDuring the evidence verification process, the signatures of the conflicting votes must be verified successfully.\nNote that this is achieved using the public key of the misbehaving validator, along with the chain ID of the chain where the infraction occurred (see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#verification",children:"CometBFT equivocation verification"}),")."]}),"\n",(0,n.jsxs)(i.p,{children:["Once a double signing evidence is committed to a block, the consensus layer will report the equivocation to the evidence module of the Cosmos SDK application layer.\nThe application will, in turn, punish the malicious validator through jailing, tombstoning and slashing\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.45.16-ics-lsm/x/evidence/keeper/infraction.go#L263",children:"handleEquivocationEvidence"}),")."]}),"\n",(0,n.jsx)(i.h2,{id:"decision",children:"Decision"}),"\n",(0,n.jsx)(i.h3,{id:"light-client-attack-1",children:"Light Client Attack"}),"\n",(0,n.jsxs)(i.p,{children:["In the first part of the feature, we introduce a new endpoint: ",(0,n.jsx)(i.code,{children:"HandleConsumerMisbehaviour(ctx sdk.Context, misbehaviour ibctmtypes.Misbehaviour)"}),".\nThe main idea is to leverage the current IBC misbehaviour handling and update it to solely jail and slash the validators that\nperformed a light client attack. Note that in this context, we assume that chains connected via a light client\nshare the same validator set, as is the case with Replicated Security."]}),"\n",(0,n.jsx)(i.p,{children:"This endpoint reuses the IBC client libraries to verify that the misbehaviour headers would have fooled the light client.\nAdditionally, it\u2019s crucial that the endpoint logic results in the slashing and jailing of validators under the same conditions\nas a light client agent detector. Therefore, the endpoint ensures that the two conditions are met:\nthe headers in the misbehaviour message have the same block height, and\nthe light client isn\u2019t expired."}),"\n",(0,n.jsx)(i.p,{children:"After having successfully verified a misbehaviour, the endpoint executes the jailing and slashing of the malicious validators similarly as in the evidence module."}),"\n",(0,n.jsx)(i.h3,{id:"double-signing-attack-1",children:"Double Signing Attack"}),"\n",(0,n.jsxs)(i.p,{children:["In the second part of the feature, we introduce a new endpoint ",(0,n.jsx)(i.code,{children:"HandleConsumerDoubleVoting( ctx sdk.Context, evidence *tmtypes.DuplicateVoteEvidence, chainID string, pubkey cryptotypes.PubKey)"}),".\nSimply put, the handling logic verifies a double signing evidence against a provided\npublic key and chain ID and, if successful, executes the jailing of the malicious validator who double voted."]}),"\n",(0,n.jsxs)(i.p,{children:["We define a new\n",(0,n.jsx)(i.code,{children:"MsgSubmitConsumerDoubleVoting"})," message to report a double voting evidence observed\non a consumer chain to the endpoint of the provider chain. This message contains two fields:\na double signing evidence\n",(0,n.jsx)(i.code,{children:"duplicate_vote_evidence"})," and a light client header for the infraction block height,\nreferred to as ",(0,n.jsx)(i.code,{children:"infraction_block_header"}),".\nThe latter provides the malicious validator's public key and the chain ID required to verify the signature of the votes contained in the evidence."]}),"\n",(0,n.jsxs)(i.p,{children:["Note that double signing evidence is not verified using the same conditions as in the implementation CometBFT (see\n",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/evidence/verify.go#L19",children:(0,n.jsx)(i.code,{children:"verify(evidence types.Evidence)"})})," method). Specifically, we do not check that the evidence hasn't expired.\nMore details can be found in the ",(0,n.jsx)(i.a,{href:"#current-limitations",children:'"Current limitations"'})," section below."]}),"\n",(0,n.jsxs)(i.p,{children:["Upon a successful equivocation verification, the misbehaving validator is jailed for the maximum time\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.45.16-ics-lsm/x/evidence/types/params.go#L11",children:"DoubleSignJailEndTime"}),"\nin the SDK evidence module)."]}),"\n",(0,n.jsx)(i.h3,{id:"current-limitations",children:"Current limitations:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"We cannot derive an infraction height from the evidence, so it is only possible to jail validators, not actually slash them.\nTo explain the technical reasons behind this limitation, let's recap the initial consumer initiated slashing logic.\nIn a nutshell, consumer heights are mapped to provider heights through VSCPackets, namely through the so called vscIDs.\nWhen an infraction occurs on the consumer, a SlashPacket containing the vscID obtained from mapping the consumer infraction height\nis sent to the provider. Upon receiving the packet, the provider maps the consumer infraction height to a local infraction height,\nwhich is used to slash the misbehaving validator. In the context of untrusted consumer chains, all their states, including vscIDs,\ncould be corrupted and therefore cannot be used for slashing purposes."}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"For the same reasons explained above, the age of a consumer double signing evidence can't be verified,\neither using its infraction height or its unsigned timestamp. Note that changes the jailing behaviour, potentially leading to a validator's jailing based on some \"old\" evidence from a consumer, which wouldn't occur if the consumer were a standalone chain."}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsxs)(i.p,{children:["In the first stage of this feature, validators are jailed indefinitely without being tombstoned.\nThe underlying reason is that a malicious validator could take advantage of getting tombstoned\nto avoid being slashed on the provider (",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/1232#issuecomment-1693127641",children:"see comment"}),")."]}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsxs)(i.p,{children:["Currently, the endpoint can only handle ",(0,n.jsx)(i.em,{children:"equivocation"})," light client attacks. This is because the ",(0,n.jsx)(i.em,{children:"lunatic"})," attacks require the endpoint to possess the ability to dissociate which header is conflicted or trusted upon receiving a misbehavior message. Without this information, it's not possible to extract the Byzantine validators from the conflicting headers (see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/826#discussion_r1268668684",children:"comment"}),'). In addition, "amnesia" attacks are ignored, similar to CometBFT (see ',(0,n.jsx)(i.a,{href:"https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-047-handling-evidence-from-light-client.md#negative",children:"ADR-056"}),")."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"consequences",children:"Consequences"}),"\n",(0,n.jsx)(i.h3,{id:"positive",children:"Positive"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"It is now possible for the provider chain to jail validators who committed\nlight client or double signing attacks on a consumer chain."}),"\n"]}),"\n",(0,n.jsx)(i.h3,{id:"negative",children:"Negative"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"N/A"}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/826",children:"ICS misbehaviour handling PR"})}),"\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"Consumer double voting handler PR"})}),"\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://docs.google.com/document/d/1fe1uSJl1ZIYWXoME3Yf4Aodvz7V597Ric875JH-rigM/edit#heading=h.rv4t8i6d6jfn",children:"Architectural diagrams"})}),"\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-013-equivocation-slashing.md",children:"ADR on equivocation slashing"})}),"\n"]})]})}function d(e={}){const{wrapper:i}={...(0,s.a)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},1151:(e,i,t)=>{t.d(i,{Z:()=>c,a:()=>a});var n=t(7294);const s={},o=n.createContext(s);function a(e){const i=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/4f50acdf.f5850848.js b/assets/js/4f50acdf.f5850848.js
new file mode 100644
index 0000000000..1e4da13a7e
--- /dev/null
+++ b/assets/js/4f50acdf.f5850848.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9815],{7125:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var i=s(5893),t=s(1151);const r={sidebar_position:2,title:"Joining Interchain Security testnet"},o=void 0,a={id:"validators/joining-testnet",title:"Joining Interchain Security testnet",description:"Introduction",source:"@site/docs/validators/joining-testnet.md",sourceDirName:"validators",slug:"/validators/joining-testnet",permalink:"/interchain-security/validators/joining-testnet",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"Joining Interchain Security testnet"},sidebar:"tutorialSidebar",previous:{title:"Overview",permalink:"/interchain-security/validators/overview"},next:{title:"Consumer chain validator rewards",permalink:"/interchain-security/validators/withdraw_rewards"}},c={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Joining the provider chain",id:"joining-the-provider-chain",level:2},{value:"Initialization",id:"initialization",level:2},{value:"Joining consumer chains",id:"joining-consumer-chains",level:2},{value:"Re-using consensus key",id:"re-using-consensus-key",level:2},{value:"Assigning consensus keys",id:"assigning-consensus-keys",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(n.p,{children:["This short guide will teach you how to join the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security",children:"Interchain Security testnet"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The experience gained in the testnet will prepare you for validating interchain secured chains."}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"Provider and consumer chain represent distinct networks and infrastructures operated by the same validator set."}),(0,i.jsxs)(n.p,{children:["For general information about running cosmos-sdk based chains check out the ",(0,i.jsx)(n.a,{href:"https://hub.cosmos.network/main/validators/validator-setup",children:"validator basics"})," and ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/main/run-node/run-node",children:"Running a Node section"})," of Cosmos SDK docs"]})]}),"\n",(0,i.jsx)(n.h2,{id:"joining-the-provider-chain",children:"Joining the provider chain"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"At present, all validators of the provider chain must also validate all governance approved consumer chains. The consumer chains cannot have a validator set different than the provider, which means they cannot introduce validators that are not also validating the provider chain."})}),"\n",(0,i.jsxs)(n.p,{children:["A comprehensive guide is available ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security/provider",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"initialization",children:"Initialization"}),"\n",(0,i.jsxs)(n.p,{children:["First, initialize your ",(0,i.jsx)(n.code,{children:"$NODE_HOME"})," using the ",(0,i.jsx)(n.code,{children:"provider"})," chain binary."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"NODE_MONIKER=\nCHAIN_ID=provider\nNODE_HOME=\n\ngaiad init $NODE_MONIKER --chain-id $CHAIN_ID --home $NODE_HOME\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Add your key to the keyring - more details available ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/main/run-node/keyring",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["In this example we will use the ",(0,i.jsx)(n.code,{children:"test"})," keyring-backend. This option is not safe to use in production."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad keys add --keyring-backend test\n\n# save the address as variable for later use\nMY_VALIDATOR_ADDRESS=$(gaiad keys show my_validator -a --keyring-backend test)\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Before issuing any transactions, use the ",(0,i.jsx)(n.code,{children:"provider"})," testnet faucet to add funds to your address."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'curl https://faucet.rs-testnet.polypore.xyz/request?address=$MY_VALIDATOR_ADDRESS&chain=provider\n\n# example output:\n{\n "address": "cosmos17p3erf5gv2436fd4vyjwmudakts563a497syuz",\n "amount": "10000000uatom",\n "chain": "provider",\n "hash": "10BFEC53C80C9B649B66549FD88A0B6BCF09E8FCE468A73B4C4243422E724985",\n "status": "success"\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Then, use the account associated with the keyring to issue a ",(0,i.jsx)(n.code,{children:"create-validator"})," transaction which will register your validator on chain."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'gaiad tx staking create-validator \\\n --amount=1000000uatom \\\n --pubkey=$(gaiad tendermint show-validator) \\\n --moniker="choose a moniker" \\\n --chain-id=$CHAIN_ID" \\\n --commission-rate="0.10" \\\n --commission-max-rate="0.20" \\\n --commission-max-change-rate="0.01" \\\n --min-self-delegation="1000000" \\\n --gas="auto" \\\n --gas-prices="0.0025uatom" \\\n --from=\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Check this ",(0,i.jsx)(n.a,{href:"https://hub.cosmos.network/main/validators/validator-setup#edit-validator-description",children:"guide"})," to edit your validator."]})}),"\n",(0,i.jsxs)(n.p,{children:["After this step, your validator is created and you can start your node and catch up to the rest of the network. It is recommended that you use ",(0,i.jsx)(n.code,{children:"statesync"})," to catch up to the rest of the network."]}),"\n",(0,i.jsxs)(n.p,{children:["You can use this script to modify your ",(0,i.jsx)(n.code,{children:"config.toml"})," with the required statesync parameters."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# create the statesync script\n$: cd $NODE_HOME\n$: touch statesync.sh\n$ chmod 700 statesync.sh # make executable\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Paste the following instructions into the ",(0,i.jsx)(n.code,{children:"statesync.sh"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'#!/bin/bash\n\nSNAP_RPC="https://rpc.provider-state-sync-01.rs-testnet.polypore.xyz:443"\n\nLATEST_HEIGHT=$(curl -s $SNAP_RPC/block | jq -r .result.block.header.height); \\\nBLOCK_HEIGHT=$((LATEST_HEIGHT - 2000)); \\\nTRUST_HASH=$(curl -s "$SNAP_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash)\n\nsed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\\1true| ; \\\ns|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\\1\\"$SNAP_RPC,$SNAP_RPC\\"| ; \\\ns|^(trust_height[[:space:]]+=[[:space:]]+).*$|\\1$BLOCK_HEIGHT| ; \\\ns|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\\1\\"$TRUST_HASH\\"|" $NODE_HOME/config/config.toml\n'})}),"\n",(0,i.jsx)(n.p,{children:"Then, you can execute the script:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"$: ./statesync.sh # setup config.toml for statesync\n"})}),"\n",(0,i.jsx)(n.p,{children:"Finally, copy the provider genesis and start your node:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'$: GENESIS_URL=https://github.com/cosmos/testnets/raw/master/interchain-security/provider/provider-genesis.json\n$: wget $GENESIS_URL -O genesis.json\n$: genesis.json $NODE_HOME/config/genesis.json\n# start the service\n$: gaiad start --x-crisis-skip-assert-invariants --home $NODE_HOME --p2p.seeds="08ec17e86dac67b9da70deb20177655495a55407@provider-seed-01.rs-testnet.polypore.xyz:26656,4ea6e56300a2f37b90e58de5ee27d1c9065cf871@provider-seed-02.rs-testnet.polypore.xyz:26656"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Additional scripts to setup your nodes are available ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/provider/join-ics-provider.sh",children:"here"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/provider/join-ics-provider-cv.sh",children:"here"}),". The scripts will configure your node and create the required services - the scripts only work in linux environments."]}),"\n",(0,i.jsx)(n.h2,{id:"joining-consumer-chains",children:"Joining consumer chains"}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"Once you reach the active set on the provider chain, you will be required to validate all available consumer chains."}),(0,i.jsxs)(n.p,{children:["We strongly recommend that you assign a separate key for each consumer chain.\nCheck out this ",(0,i.jsx)(n.a,{href:"/interchain-security/features/key-assignment",children:"guide"})," to learn more about key assignment in interchain security."]})]}),"\n",(0,i.jsx)(n.p,{children:"To join consumer chains, simply replicate the steps above for each consumer using the correct consumer chain binaries."}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["When running the provider chain and consumers on the same machine please update the ",(0,i.jsx)(n.code,{children:"PORT"})," numbers for each of them and make sure they do not overlap (otherwise the binaries will not start)."]}),(0,i.jsx)(n.p,{children:"Important ports to re-configure:"}),(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--rpc.laddr"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--p2p.laddr"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--api.address"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--grpc.address"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--grpc-web.address"})}),"\n"]})]}),"\n",(0,i.jsx)(n.h2,{id:"re-using-consensus-key",children:"Re-using consensus key"}),"\n",(0,i.jsxs)(n.p,{children:["To reuse the key on the provider and consumer chains, simply initialize your consumer chain and place the ",(0,i.jsx)(n.code,{children:"priv_validator_key.json"})," into the home directory of your consumer chain (",(0,i.jsx)(n.code,{children:"/config/priv_validator_key.json"}),")."]}),"\n",(0,i.jsx)(n.p,{children:"When you start the chain, the consensus key will be the same on the provider and the consumer chain."}),"\n",(0,i.jsx)(n.h2,{id:"assigning-consensus-keys",children:"Assigning consensus keys"}),"\n",(0,i.jsx)(n.p,{children:"Whenever you initialize a new node, it will be configured with a consensus key you can use."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'# machine running consumer chain\nconsumerd init --home --chain-id consumer-1\n\n# use the output of this command to get the consumer chain consensus key\nconsumerd tendermint show-validator\n# output: {"@type":"/cosmos.crypto.ed25519.PubKey","key":""}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Then, let the provider know which key you will be using for the consumer chain:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# machine running the provider chain\ngaiad tx provider assign-consensus-key consumer-1 '' --from --home $NODE_HOME --gas 900000 -b sync -y -o json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["After this step, you are ready to copy the consumer genesis into your nodes's ",(0,i.jsx)(n.code,{children:"/config"})," folder, start your consumer chain node and catch up to the network."]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>a,a:()=>o});var i=s(7294);const t={},r=i.createContext(t);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/53123775.fe1cc72c.js b/assets/js/53123775.fe1cc72c.js
new file mode 100644
index 0000000000..a4f9de860f
--- /dev/null
+++ b/assets/js/53123775.fe1cc72c.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2234],{8621:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>p,frontMatter:()=>o,metadata:()=>t,toc:()=>c});var s=r(5893),i=r(1151);const o={sidebar_position:1},a="Upgrading to ICS v5.0.0",t={id:"upgrading/migrate_v4_v5",title:"Upgrading to ICS v5.0.0",description:"This ICS version uses cosmos-sdk v0.50.x and ibc-go v8.x.",source:"@site/versioned_docs/version-v5.0.0/upgrading/migrate_v4_v5.md",sourceDirName:"upgrading",slug:"/upgrading/migrate_v4_v5",permalink:"/interchain-security/v5.0.0/upgrading/migrate_v4_v5",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Technical Specification",permalink:"/interchain-security/v5.0.0/introduction/technical-specification"},next:{title:"Key Assignment",permalink:"/interchain-security/v5.0.0/features/key-assignment"}},d={},c=[{value:"Provider",id:"provider",level:2},{value:"Keeper initialization",id:"keeper-initialization",level:3},{value:"Protocol changes",id:"protocol-changes",level:3},{value:"Revert AfterUnbondingInitiated",id:"revert-afterunbondinginitiated",level:4},{value:"Migration (v4 -> v5)",id:"migration-v4---v5",level:3},{value:"Additions",id:"additions",level:3},{value:"MsgUpdateParams transaction",id:"msgupdateparams-transaction",level:3},{value:"Governance proposals",id:"governance-proposals",level:3},{value:"Consumer",id:"consumer",level:2},{value:"Keeper initialization",id:"keeper-initialization-1",level:3},{value:"Additions",id:"additions-1",level:3},{value:"MsgUpdateParams transaction",id:"msgupdateparams-transaction-1",level:4},{value:"Params Query",id:"params-query",level:4},{value:"Migration (v2 -> v3)",id:"migration-v2---v3",level:3},{value:"Interface method changes",id:"interface-method-changes",level:3},{value:"Democracy",id:"democracy",level:2},{value:"Note:",id:"note",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"upgrading-to-ics-v500",children:"Upgrading to ICS v5.0.0"}),"\n",(0,s.jsx)(n.p,{children:"This ICS version uses cosmos-sdk v0.50.x and ibc-go v8.x."}),"\n",(0,s.jsxs)(n.p,{children:["To migrate you application to cosmos-sdk v0.50.x please use this ",(0,s.jsx)(n.a,{href:"https://docs.cosmos.network/v0.50/build/migrations/upgrading",children:"guide"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"To migrate your application to ibc-go v8.x.y please use the following guides:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://ibc.cosmos.network/main/migrations/v7-to-v8",children:"migrate ibc-go to v8.0.0"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://ibc.cosmos.network/main/migrations/v8-to-v8_1",children:"migrate ibc-go to v8.1.0"})}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"ICS specific changes are outlined below."}),"\n",(0,s.jsxs)(n.p,{children:["Pre-requisite version for this upgrade: ",(0,s.jsx)(n.code,{children:"v4.x"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"provider",children:"Provider"}),"\n",(0,s.jsx)(n.h3,{id:"keeper-initialization",children:"Keeper initialization"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-diff",children:"// app.go\n\napp.ProviderKeeper = ibcproviderkeeper.NewKeeper(\n appCodec,\n keys[providertypes.StoreKey],\n app.GetSubspace(providertypes.ModuleName),\n scopedIBCProviderKeeper,\n app.IBCKeeper.ChannelKeeper,\n- app.IBCKeeper.PortKeeper\n+ app.IBCKeeper.PortKeeper,\n app.IBCKeeper.ConnectionKeeper,\n app.IBCKeeper.ClientKeeper,\n app.StakingKeeper,\n app.SlashingKeeper,\n app.AccountKeeper,\n app.DistrKeeper,\n app.BankKeeper,\n *app.GovKeeper,\n+ authtypes.NewModuleAddress(govtypes.ModuleName).String(),\n+ authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),\n+ authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),\n authtypes.FeeCollectorName,\n)\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"authority"})," was added - requirement for executing ",(0,s.jsx)(n.code,{children:"MsgUpdateParams"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["uses ",(0,s.jsx)(n.code,{children:"x/gov"})," module address by default"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"validatorAddressCodec"})," & ",(0,s.jsx)(n.code,{children:"consensusAddressCodec"})," were added - they must match the bech32 address codec used by ",(0,s.jsx)(n.code,{children:"x/auth"}),", ",(0,s.jsx)(n.code,{children:"x/bank"}),", ",(0,s.jsx)(n.code,{children:"x/staking"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"protocol-changes",children:"Protocol changes"}),"\n",(0,s.jsxs)(n.h4,{id:"revert-afterunbondinginitiated",children:["Revert ",(0,s.jsx)(n.code,{children:"AfterUnbondingInitiated"})]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"AfterUnbondingInitiated"})," behavior was reverted to ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/v1.2.0-multiden/x/ccv/provider/keeper/hooks.go#L53",children:"ICS@v1.2.0-multiden"})]}),"\n",(0,s.jsx)(n.p,{children:"The revert re-introduces an additional state check."}),"\n",(0,s.jsxs)(n.p,{children:["See this ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/1045",children:"issue"})," for more context and the actions taken."]}),"\n",(0,s.jsx)(n.h3,{id:"migration-v4---v5",children:"Migration (v4 -> v5)"}),"\n",(0,s.jsxs)(n.p,{children:["ConensusVersion was bumped to ",(0,s.jsx)(n.code,{children:"5"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The migration allows storing the provider module params in the ",(0,s.jsx)(n.code,{children:"x/ccv/provider"})," module store instead of relying on legacy ",(0,s.jsx)(n.code,{children:"x/param"})," store."]}),"\n",(0,s.jsx)(n.p,{children:"There are no special requirements for executing this migration."}),"\n",(0,s.jsx)(n.h3,{id:"additions",children:"Additions"}),"\n",(0,s.jsx)(n.h3,{id:"msgupdateparams-transaction",children:"MsgUpdateParams transaction"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"x/gov"})," module account is selected as the default ",(0,s.jsx)(n.code,{children:"authority"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["It is available when using ",(0,s.jsx)(n.code,{children:"gov"})," CLI commands:"]}),"\n",(0,s.jsx)(n.p,{children:"Drafting a proposal:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:'interchain-security-pd tx gov draft-proposal\n# select "other"\n# find and select "/interchain_security.ccv.provider.v1.MsgUpdateParams"\n'})}),"\n",(0,s.jsx)(n.p,{children:"Submitting a proposal:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd tx gov submit-proposal \n"})}),"\n",(0,s.jsxs)(n.p,{children:["Example ",(0,s.jsx)(n.code,{children:"proposal-message.json"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "messages": [\n {\n "@type": "/interchain_security.ccv.provider.v1.MsgUpdateParams",\n "authority": "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn",\n "params": {\n "trusting_period_fraction": "0.66",\n "ccv_timeout_period": "2419200s",\n "init_timeout_period": "604800s",\n "vsc_timeout_period": "3024000s",\n "slash_meter_replenish_period": "3s",\n "slash_meter_replenish_fraction": "1.0",\n "consumer_reward_denom_registration_fee": {\n "denom": "stake",\n "amount": "10000000"\n },\n "blocks_per_epoch": "600"\n }\n }\n ],\n "metadata": "ipfs://CID",\n "deposit": "10000stake",\n "title": "Update Provider params",\n "summary": "Update Provider params",\n "expedited": false\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:""}),"\n",(0,s.jsxs)(n.p,{children:["When updating parameters ",(0,s.jsx)(n.strong,{children:"all"})," parameters fields must be specified. Make sure you are only changing parameters that you are interested in."]}),"\n",(0,s.jsx)(n.p,{children:"To avoid accidentally changing parameters you can first check the current on-chain provider params using:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:'interchain-security-pd q provider params -o json\n\n{\n "template_client": {...},\n "trusting_period_fraction": "0.66",\n "ccv_timeout_period": "2419200s",\n "init_timeout_period": "604800s",\n "vsc_timeout_period": "3024000s",\n "slash_meter_replenish_period": "3s",\n "slash_meter_replenish_fraction": "1.0",\n "consumer_reward_denom_registration_fee": {\n "denom": "stake",\n "amount": "10000000"\n },\n "blocks_per_epoch": "600"\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"governance-proposals",children:"Governance proposals"}),"\n",(0,s.jsx)(n.p,{children:"Submitting the following legacy proposals is still supported:"}),"\n",(0,s.jsx)(n.h1,{id:"consumer-addition-proposal",children:"Consumer addition proposal"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd tx gov submit-legacy-proposal consumer-addition \n"})}),"\n",(0,s.jsx)(n.h1,{id:"consumer-removal-proposal",children:"Consumer removal proposal"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd tx gov submit-legacy-proposal consumer-removal \n"})}),"\n",(0,s.jsx)(n.h1,{id:"consumer-addition-proposal-1",children:"Consumer addition proposal"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd tx gov submit-legacy-proposal change-reward-denoms \n"})}),"\n",(0,s.jsxs)(n.p,{children:["You may also submit proposal messages above using ",(0,s.jsx)(n.code,{children:"submit-proposal"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"consumer",children:"Consumer"}),"\n",(0,s.jsx)(n.h3,{id:"keeper-initialization-1",children:"Keeper initialization"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-diff",children:"// pre-initialize ConsumerKeeper to satsfy ibckeeper.NewKeeper\napp.ConsumerKeeper = ibcconsumerkeeper.NewNonZeroKeeper(\n appCodec,\n keys[ibcconsumertypes.StoreKey],\n app.GetSubspace(ibcconsumertypes.ModuleName),\n)\n\napp.IBCKeeper = ibckeeper.NewKeeper(\n appCodec,\n keys[ibchost.StoreKey],\n app.GetSubspace(ibchost.ModuleName),\n app.ConsumerKeeper,\n app.UpgradeKeeper,\n scopedIBCKeeper,\n authtypes.NewModuleAddress(govtypes.ModuleName).String(),\n)\n\n// initialize the actual consumer keeper\napp.ConsumerKeeper = ibcconsumerkeeper.NewKeeper(\n appCodec,\n keys[ibcconsumertypes.StoreKey],\n app.GetSubspace(ibcconsumertypes.ModuleName),\n scopedIBCConsumerKeeper,\n app.IBCKeeper.ChannelKeeper,\n- &app.IBCKeeper.PortKeeper,\n+ app.IBCKeeper.PortKeeper,\n app.IBCKeeper.ConnectionKeeper,\n app.IBCKeeper.ClientKeeper,\n app.SlashingKeeper,\n app.BankKeeper,\n app.AccountKeeper,\n &app.TransferKeeper,\n app.IBCKeeper,\n authtypes.FeeCollectorName,\n\n // make sure the authority address makes sense for your chain\n // the exact module account may differ depending on your setup (x/gov, x/admin or custom module)\n // for x/ccv/democracy using the x/gov module address is correct\n // if you don't have a way of updating consumer params you may still use the line below as it will have no affect\n+ authtypes.NewModuleAddress(govtypes.ModuleName).String(),\n \n // add address codecs \n+ authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),\n+ authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),\n)\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"authority"})," was added - requirement for executing ",(0,s.jsx)(n.code,{children:"MsgUpdateParams"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"make sure the authority address makes sense for your chain"}),"\n",(0,s.jsxs)(n.li,{children:["the exact module account may differ depending on your setup (",(0,s.jsx)(n.code,{children:"x/gov"}),", ",(0,s.jsx)(n.code,{children:"x/admin"})," or custom module)"]}),"\n",(0,s.jsxs)(n.li,{children:["for ",(0,s.jsx)(n.code,{children:"x/ccv/democracy"})," using the ",(0,s.jsx)(n.code,{children:"x/gov"})," module address is correct"]}),"\n",(0,s.jsxs)(n.li,{children:["if you don't have a way of updating consumer params you may use ",(0,s.jsx)(n.code,{children:"authtypes.NewModuleAddress(govtypes.ModuleName).String()"})," (has no effect on functionality)"]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"validatorAddressCodec"})," & ",(0,s.jsx)(n.code,{children:"consensusAddressCodec"})," were added - they must match the bech32 address codec used by ",(0,s.jsx)(n.code,{children:"x/auth"}),", ",(0,s.jsx)(n.code,{children:"x/bank"}),", ",(0,s.jsx)(n.code,{children:"x/staking"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"additions-1",children:"Additions"}),"\n",(0,s.jsxs)(n.h4,{id:"msgupdateparams-transaction-1",children:[(0,s.jsx)(n.code,{children:"MsgUpdateParams"})," transaction"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["This functionality is not supported on ",(0,s.jsx)(n.code,{children:"x/ccv/consumer"})," without additional configuration."]})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["if you are using ",(0,s.jsx)(n.code,{children:"x/ccv/democracy"})," the feature is supported out of the box"]}),"\n",(0,s.jsxs)(n.li,{children:["if you are using custom logic for changing consumer params, please update your code by providing the appropriate ",(0,s.jsx)(n.code,{children:"authority"})," module account during ",(0,s.jsx)(n.code,{children:"ConsumerKeeper"})," initialization in ",(0,s.jsx)(n.code,{children:"app.go"}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["You must add ",(0,s.jsx)(n.code,{children:'"/interchain_security.ccv.consumer.v1.MsgUpdateParams"'})," to your parameters whitelist to be able to change ",(0,s.jsx)(n.code,{children:"ccvconsumer"})," parameters via governance."]})}),"\n",(0,s.jsxs)(n.p,{children:["It is available when using ",(0,s.jsx)(n.code,{children:"gov"})," CLI commands:"]}),"\n",(0,s.jsx)(n.p,{children:"Drafting a proposal:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:'interchain-security-cd tx gov draft-proposal\n# select "other"\n# find and select "/interchain_security.ccv.consumer.v1.MsgUpdateParams"\n'})}),"\n",(0,s.jsx)(n.p,{children:"Submitting a proposal:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsxs)(n.strong,{children:["this proposal cannot be executed on chains without access to ",(0,s.jsx)(n.code,{children:"x/gov"})," or other modules for managing governance"]})}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"\ninterchain-security-cdd tx gov submit-proposal \n\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Example ",(0,s.jsx)(n.code,{children:"proposal-message.json"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "messages": [\n {\n "@type": "/interchain_security.ccv.consumer.v1.MsgUpdateParams",\n "authority": "consumer10d07y265gmmuvt4z0w9aw880jnsr700jlh7295",\n "params": {\n "enabled": true,\n "blocks_per_distribution_transmission": "20",\n "distribution_transmission_channel": "channel-1",\n "provider_fee_pool_addr_str": "",\n "ccv_timeout_period": "2419200s",\n "transfer_timeout_period": "3000s",\n "consumer_redistribution_fraction": "0.75",\n "historical_entries": "10000",\n "unbonding_period": "1209600s",\n "soft_opt_out_threshold": "0.05",\n "reward_denoms": [],\n "provider_reward_denoms": [],\n "retry_delay_period": "3000s"\n }\n }\n ],\n "metadata": "ipfs://CID",\n "deposit": "1000uatom",\n "title": "Update Consumer Params -- change transfer_timeout_period to 3000s",\n "summary": "Test Update Consumer Params",\n "expedited": false\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["When updating parameters ",(0,s.jsx)(n.strong,{children:"all"})," parameters fields must be specified. Make sure you are only changing parameters that you are interested in."]}),"\n",(0,s.jsx)(n.p,{children:"To avoid accidentally changing parameters you can first check the current on-chain consumer params using:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"interchain-security-pd q ccvconsumer params -o json\n"})}),"\n",(0,s.jsx)(n.h4,{id:"params-query",children:"Params Query"}),"\n",(0,s.jsx)(n.p,{children:"Consumer params query was added:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:'interchain-security-cd q ccvconsumer params -o json\n\n{\n "params": {\n "enabled": true,\n "blocks_per_distribution_transmission": "1000",\n "distribution_transmission_channel": "",\n "provider_fee_pool_addr_str": "",\n "ccv_timeout_period": "2419200s",\n "transfer_timeout_period": "3600s",\n "consumer_redistribution_fraction": "0.75",\n "historical_entries": "10000",\n "unbonding_period": "1209600s",\n "soft_opt_out_threshold": "0.05",\n "reward_denoms": [],\n "provider_reward_denoms": [],\n "retry_delay_period": "3600s"\n }\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"migration-v2---v3",children:"Migration (v2 -> v3)"}),"\n",(0,s.jsxs)(n.p,{children:["ConensusVersion was bumped to ",(0,s.jsx)(n.code,{children:"3"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The migration allows storing the consumer module params in the ",(0,s.jsx)(n.code,{children:"x/ccv/consumer"})," module store instead of relying on legacy ",(0,s.jsx)(n.code,{children:"x/param"})," store."]}),"\n",(0,s.jsx)(n.p,{children:"There are no special requirements for executing this migration."}),"\n",(0,s.jsx)(n.h3,{id:"interface-method-changes",children:"Interface method changes"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer methods were changed to match the cosmos-sdk ",(0,s.jsx)(n.code,{children:"StakingKeeper"})," interface.\nYou will not need to change your code, unless you are using the ",(0,s.jsx)(n.code,{children:"ConsumerKeeper"})," inside custom tests or you have developed custom app functionality that relies on ",(0,s.jsx)(n.code,{children:"ConsumerKeeper"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"Please check the list below if you are using any of the consumer methods:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-go",children:"type StakingKeeper interface {\n UnbondingTime(ctx context.Context) (time.Duration, error)\n GetValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) (stakingtypes.Validator, error)\n GetLastValidatorPower(ctx context.Context, operator sdk.ValAddress) (int64, error)\n Jail(context.Context, sdk.ConsAddress) error // jail a validator\n Slash(ctx context.Context, consAddr sdk.ConsAddress, infractionHeight, power int64, slashFactor math.LegacyDec) (math.Int, error)\n SlashWithInfractionReason(ctx context.Context, consAddr sdk.ConsAddress, infractionHeight, power int64, slashFactor math.LegacyDec, infraction stakingtypes.Infraction) (math.Int, error)\n Unjail(ctx context.Context, addr sdk.ConsAddress) error\n GetValidator(ctx context.Context, addr sdk.ValAddress) (stakingtypes.Validator, error)\n IterateLastValidatorPowers(ctx context.Context, cb func(addr sdk.ValAddress, power int64) (stop bool)) error\n IterateValidators(ctx context.Context, f func(index int64, validator stakingtypes.ValidatorI) (stop bool)) error\n Validator(ctx context.Context, addr sdk.ValAddress) (stakingtypes.ValidatorI, error)\n IsValidatorJailed(ctx context.Context, addr sdk.ConsAddress) (bool, error)\n ValidatorByConsAddr(ctx context.Context, consAddr sdk.ConsAddress) (stakingtypes.ValidatorI, error)\n Delegation(ctx context.Context, addr sdk.AccAddress, valAddr sdk.ValAddress) (stakingtypes.DelegationI, error)\n MaxValidators(ctx context.Context) (uint32, error)\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The consumer implements the ",(0,s.jsx)(n.code,{children:"StakingKeeper"})," interface shown above."]}),"\n",(0,s.jsx)(n.h2,{id:"democracy",children:"Democracy"}),"\n",(0,s.jsxs)(n.p,{children:["Changes in ",(0,s.jsx)(n.code,{children:"Consumer"})," also apply to ",(0,s.jsx)(n.code,{children:"Democracy"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Democracy ",(0,s.jsx)(n.code,{children:"x/staking"}),", ",(0,s.jsx)(n.code,{children:"x/distribution"})," and ",(0,s.jsx)(n.code,{children:"x/gov"})," were updated to reflect changes in ",(0,s.jsx)(n.code,{children:"cosmos-sdk v0.50.x"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["There were no notable changes arising to the module functionality aside from conforming to ",(0,s.jsx)(n.code,{children:"cosmos-sdk v0.50.x"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"note",children:"Note:"}),"\n",(0,s.jsxs)(n.p,{children:["You must add ",(0,s.jsx)(n.code,{children:'"/interchain_security.ccv.consumer.v1.MsgUpdateParams"'})," to your parameters whitelist to be able to change ",(0,s.jsx)(n.code,{children:"consumer"})," parameters via governance."]})]})}function p(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>t,a:()=>a});var s=r(7294);const i={},o=s.createContext(i);function a(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/536acd9c.29001796.js b/assets/js/536acd9c.29001796.js
new file mode 100644
index 0000000000..2add7ac9ef
--- /dev/null
+++ b/assets/js/536acd9c.29001796.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4279],{8276:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var i=a(5893),t=a(1151);const s={sidebar_position:4},o="Validator Instructions for Changeover Procedure",r={id:"validators/changeover-procedure",title:"Validator Instructions for Changeover Procedure",description:"More details available in Changeover Procedure documentation.",source:"@site/versioned_docs/version-v4.2.0-docs/validators/changeover-procedure.md",sourceDirName:"validators",slug:"/validators/changeover-procedure",permalink:"/interchain-security/v4.2.0/validators/changeover-procedure",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"Withdrawing consumer chain validator rewards",permalink:"/interchain-security/v4.2.0/validators/withdraw_rewards"},next:{title:"Joining Neutron",permalink:"/interchain-security/v4.2.0/validators/joining-neutron"}},d={},c=[{value:"Timeline",id:"timeline",level:2},{value:"1. ConsumerAdditionProposal on provider chain",id:"1-consumeradditionproposal-on-provider-chain",level:3},{value:"2. SoftwareUpgradeProposal on the standalone/consumer chain",id:"2-softwareupgradeproposal-on-the-standaloneconsumer-chain",level:3},{value:"3. Assigning a consumer key",id:"3-assigning-a-consumer-key",level:3},{value:"4. Perform the software upgrade on standalone chain",id:"4-perform-the-software-upgrade-on-standalone-chain",level:3},{value:"FAQ",id:"faq",level:2},{value:"Can I reuse the same validator key for the consumer chain that I am already using on the standalone chain? Will I need to perform a AssignConsumerKey tx with this key before spawn time?",id:"can-i-reuse-the-same-validator-key-for-the-consumer-chain-that-i-am-already-using-on-the-standalone-chain-will-i-need-to-perform-a-assignconsumerkey-tx-with-this-key-before-spawn-time",level:3},{value:"Can I continue using the same node that was validating the standalone chain?",id:"can-i-continue-using-the-same-node-that-was-validating-the-standalone-chain",level:3},{value:"Can I set up a new node to validate the standalone/consumer chain after it transitions to replicated security?",id:"can-i-set-up-a-new-node-to-validate-the-standaloneconsumer-chain-after-it-transitions-to-replicated-security",level:3},{value:"What happens to the standalone validator set after it transitions to replicated security?",id:"what-happens-to-the-standalone-validator-set-after-it-transitions-to-replicated-security",level:3},{value:"Credits",id:"credits",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"validator-instructions-for-changeover-procedure",children:"Validator Instructions for Changeover Procedure"}),"\n",(0,i.jsxs)(n.p,{children:["More details available in ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/changeover-procedure",children:"Changeover Procedure documentation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A major difference between launching a new consumer chain vs. onboarding a standalone chain to ICS is that there is no consumer genesis available for the standalone chain. Since a standalone chain already exists, its state must be preserved once it transitions to being a consumer chain."}),"\n",(0,i.jsx)(n.h2,{id:"timeline",children:"Timeline"}),"\n",(0,i.jsxs)(n.p,{children:["Upgrading standalone chains can be best visualised using a timeline, such as the one available ",(0,i.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Excalidraw graphic by Stride"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"There is some flexibility with regards to how the changeover procedure is executed, so please make sure to follow the guides provided by the team doing the changeover."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Standalone to consumer transition timeline",src:a(7509).Z+"",width:"5307",height:"2157"})}),"\n",(0,i.jsxs)(n.h3,{id:"1-consumeradditionproposal-on-provider-chain",children:["1. ",(0,i.jsx)(n.code,{children:"ConsumerAdditionProposal"})," on provider chain"]}),"\n",(0,i.jsxs)(n.p,{children:["This step will add the standalone chain to the list of consumer chains secured by the provider.\nThis step dictates the ",(0,i.jsx)(n.code,{children:"spawn_time"}),". After ",(0,i.jsx)(n.code,{children:"spawn_time"})," the CCV state (initial validator set of the provider) will be available to the consumer."]}),"\n",(0,i.jsx)(n.p,{children:"To obtain it from the provider use:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad q provider consumer-genesis stride-1 -o json > ccv-state.json\njq -s '.[0].app_state.ccvconsumer = .[1] | .[0]' genesis.json ccv-state.json > ccv.json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Transformation of the exported consumer genesis state to the target version of the consumer might be needed in case the provider and consumer formats are incompatible.\nRefer to the compatibility notes ",(0,i.jsx)(n.a,{href:"../../../RELEASES.md#backwards-compatibility",children:"here"})," to check if data transformation is needed for your case.\nInstructions on how to transform the exported CCV genesis state (",(0,i.jsx)(n.code,{children:"ccv-state.json"})," in the example above) to the required target version can be found ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/consumer-genesis-transformation",children:"here"})]}),"\n",(0,i.jsxs)(n.h3,{id:"2-softwareupgradeproposal-on-the-standaloneconsumer-chain",children:["2. ",(0,i.jsx)(n.code,{children:"SoftwareUpgradeProposal"})," on the standalone/consumer chain"]}),"\n",(0,i.jsx)(n.p,{children:"This upgrade proposal will introduce ICS to the standalone chain, making it a consumer."}),"\n",(0,i.jsx)(n.h3,{id:"3-assigning-a-consumer-key",children:"3. Assigning a consumer key"}),"\n",(0,i.jsxs)(n.p,{children:["After ",(0,i.jsx)(n.code,{children:"spawn_time"}),", make sure to assign a consumer key if you intend to use one."]}),"\n",(0,i.jsxs)(n.p,{children:["Instructions are available ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/key-assignment",children:"here"})]}),"\n",(0,i.jsx)(n.h3,{id:"4-perform-the-software-upgrade-on-standalone-chain",children:"4. Perform the software upgrade on standalone chain"}),"\n",(0,i.jsx)(n.p,{children:"Please use instructions provided by the standalone chain team and make sure to reach out if you are facing issues.\nThe upgrade preparation depends on your setup, so please make sure you prepare ahead of time."}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"ccv.json"})," from step 1. must be made available on the machine running the standalone/consumer chain at standalone chain ",(0,i.jsx)(n.code,{children:"upgrade_height"}),". This file contains the initial validator set and parameters required for normal ICS operation."]}),(0,i.jsxs)(n.p,{children:["Usually, the file is placed in ",(0,i.jsx)(n.code,{children:"$NODE_HOME/config"})," but this is not a strict requirement. The exact details are available in the upgrade code of the standalone/consumer chain."]})]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Performing this upgrade will transition the standalone chain to be a consumer chain."})}),"\n",(0,i.jsxs)(n.p,{children:['After 3 blocks, the standalone chain will stop using the "old" validator set and begin using the ',(0,i.jsx)(n.code,{children:"provider"})," validator set."]}),"\n",(0,i.jsx)(n.h2,{id:"faq",children:"FAQ"}),"\n",(0,i.jsxs)(n.h3,{id:"can-i-reuse-the-same-validator-key-for-the-consumer-chain-that-i-am-already-using-on-the-standalone-chain-will-i-need-to-perform-a-assignconsumerkey-tx-with-this-key-before-spawn-time",children:["Can I reuse the same validator key for the ",(0,i.jsx)(n.code,{children:"consumer"})," chain that I am already using on the ",(0,i.jsx)(n.code,{children:"standalone"})," chain? Will I need to perform a ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx with this key before spawn time?"]}),"\n",(0,i.jsxs)(n.p,{children:["Validators must either assign a key or use the same key as on the ",(0,i.jsx)(n.code,{children:"provider"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["If you are validating both the ",(0,i.jsx)(n.code,{children:"standalone"})," and the ",(0,i.jsx)(n.code,{children:"provider"}),", you ",(0,i.jsx)(n.strong,{children:"can"})," use your current ",(0,i.jsx)(n.code,{children:"standalone"})," key with some caveats:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["you must submit an ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx with your current ",(0,i.jsx)(n.code,{children:"standalone"})," validator key"]}),"\n",(0,i.jsxs)(n.li,{children:["it is best to submit ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx before ",(0,i.jsx)(n.code,{children:"spawn_time"})]}),"\n",(0,i.jsxs)(n.li,{children:["if you do not submit the Tx, it is assumed that you will be re-using your ",(0,i.jsx)(n.code,{children:"provider"})," key to validate the ",(0,i.jsx)(n.code,{children:"standalone/consumer"})," chain"]}),"\n"]}),"\n",(0,i.jsxs)(n.h3,{id:"can-i-continue-using-the-same-node-that-was-validating-the-standalone-chain",children:["Can I continue using the same node that was validating the ",(0,i.jsx)(n.code,{children:"standalone"})," chain?"]}),"\n",(0,i.jsx)(n.p,{children:"Yes."}),"\n",(0,i.jsx)(n.p,{children:"Please assign your consensus key as stated above."}),"\n",(0,i.jsxs)(n.h3,{id:"can-i-set-up-a-new-node-to-validate-the-standaloneconsumer-chain-after-it-transitions-to-replicated-security",children:["Can I set up a new node to validate the ",(0,i.jsx)(n.code,{children:"standalone/consumer"})," chain after it transitions to replicated security?"]}),"\n",(0,i.jsx)(n.p,{children:"Yes."}),"\n",(0,i.jsxs)(n.p,{children:["If you are planning to do this please make sure that the node is synced with ",(0,i.jsx)(n.code,{children:"standalone"})," network and to submit ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx before ",(0,i.jsx)(n.code,{children:"spawn_time"}),"."]}),"\n",(0,i.jsxs)(n.h3,{id:"what-happens-to-the-standalone-validator-set-after-it-transitions-to-replicated-security",children:["What happens to the ",(0,i.jsx)(n.code,{children:"standalone"})," validator set after it transitions to replicated security?"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"standalone"})," chain validators will stop being validators after the first 3 blocks are created while using replicated security. The ",(0,i.jsx)(n.code,{children:"standalone"})," validators will become ",(0,i.jsx)(n.strong,{children:"governors"})," and still can receive delegations if the ",(0,i.jsx)(n.code,{children:"consumer"})," chain is using the ",(0,i.jsx)(n.code,{children:"consumer-democracy"})," module."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Governors DO NOT VALIDATE BLOCKS"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Instead, they can participate in the governance process and take on other chain-specific roles."}),"\n",(0,i.jsx)(n.h2,{id:"credits",children:"Credits"}),"\n",(0,i.jsx)(n.p,{children:"Thank you Stride team for providing detailed instructions about the changeover procedure."})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},7509:(e,n,a)=>{a.d(n,{Z:()=>i});const i=a.p+"assets/images/ics_changeover_timeline_stride-9bcad1834fef24a0fea7f2c80c9ccd71.png"},1151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var i=a(7294);const t={},s=i.createContext(t);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/54e4400b.e2f60025.js b/assets/js/54e4400b.e2f60025.js
new file mode 100644
index 0000000000..9b22e744f6
--- /dev/null
+++ b/assets/js/54e4400b.e2f60025.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2344],{6064:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>i,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var r=s(5893),t=s(1151);const a={sidebar_position:3,title:"Key Assignment"},i="ADR 001: Key Assignment",o={id:"adrs/adr-001-key-assignment",title:"Key Assignment",description:"Changelog",source:"@site/docs/adrs/adr-001-key-assignment.md",sourceDirName:"adrs",slug:"/adrs/adr-001-key-assignment",permalink:"/interchain-security/adrs/adr-001-key-assignment",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Key Assignment"},sidebar:"tutorialSidebar",previous:{title:"Pause validator unbonding during equivocation proposal",permalink:"/interchain-security/adrs/adr-007-pause-unbonding-on-eqv-prop"},next:{title:"Jail Throttling",permalink:"/interchain-security/adrs/adr-002-throttle"}},d={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"State required",id:"state-required",level:3},{value:"Protocol overview",id:"protocol-overview",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"adr-001-key-assignment",children:"ADR 001: Key Assignment"}),"\n",(0,r.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"2022-12-01: Initial Draft"}),"\n",(0,r.jsx)(n.li,{children:"2024-03-01: Updated to take into account they key-assigment-replacement deprecation."}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,r.jsx)(n.p,{children:"Accepted"}),"\n",(0,r.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,r.jsx)(n.p,{children:"KeyAssignment is the name of the feature that allows validator operators to use different consensus keys for each consumer chain validator node that they operate."}),"\n",(0,r.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,r.jsxs)(n.p,{children:["It is possible to change the keys at any time by submitting a transaction (i.e., ",(0,r.jsx)(n.code,{children:"MsgAssignConsumerKey"}),")."]}),"\n",(0,r.jsx)(n.h3,{id:"state-required",children:"State required"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ValidatorConsumerPubKey"})," - Stores the validator assigned keys for every consumer chain."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"ConsumerValidatorsBytePrefix | len(chainID) | chainID | providerConsAddress -> consumerKey\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ValidatorByConsumerAddr"})," - Stores the mapping from validator addresses on consumer chains to validator addresses on the provider chain. Needed for the consumer initiated slashing sub-protocol."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"ValidatorsByConsumerAddrBytePrefix | len(chainID) | chainID | consumerConsAddress -> providerConsAddress\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ConsumerAddrsToPrune"})," - Stores the mapping from VSC ids to consumer validators addresses. Needed for pruning ",(0,r.jsx)(n.code,{children:"ValidatorByConsumerAddr"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"ConsumerAddrsToPruneBytePrefix | len(chainID) | chainID | vscID -> []consumerConsAddresses\n"})}),"\n",(0,r.jsx)(n.h3,{id:"protocol-overview",children:"Protocol overview"}),"\n",(0,r.jsxs)(n.p,{children:["On receiving a ",(0,r.jsx)(n.code,{children:"MsgAssignConsumerKey(chainID, providerAddr, consumerKey)"})," message:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"// get validator from staking module \nvalidator, found := stakingKeeper.GetValidator(providerAddr)\nif !found {\n return ErrNoValidatorFound\n}\nproviderConsAddr := validator.GetConsAddr()\n\n// make sure consumer key is not in use\nconsumerAddr := utils.TMCryptoPublicKeyToConsAddr(consumerKey)\nif _, found := GetValidatorByConsumerAddr(ChainID, consumerAddr); found {\n return ErrInvalidConsumerConsensusPubKey\n}\n\n// check whether the consumer chain is already registered\n// i.e., a client to the consumer was already created\nif _, consumerRegistered := GetConsumerClientId(chainID); consumerRegistered {\n // get the previous key assigned for this validator on this consumer chain\n oldConsumerKey, found := GetValidatorConsumerPubKey(chainID, providerConsAddr)\n if found {\n // mark this old consumer key as prunable once the VSCMaturedPacket\n // for the current VSC ID is received\n oldConsumerAddr := utils.TMCryptoPublicKeyToConsAddr(oldConsumerKey)\n vscID := GetValidatorSetUpdateId()\n AppendConsumerAddrsToPrune(chainID, vscID, oldConsumerAddr)\n }\n} else {\n // if the consumer chain is not registered, then remove the previous reverse mapping\n if oldConsumerKey, found := GetValidatorConsumerPubKey(chainID, providerConsAddr); found {\n oldConsumerAddr := utils.TMCryptoPublicKeyToConsAddr(oldConsumerKey)\n DeleteValidatorByConsumerAddr(chainID, oldConsumerAddr)\n }\n}\n\n\n// set the mapping from this validator's provider address to the new consumer key\nSetValidatorConsumerPubKey(chainID, providerConsAddr, consumerKey)\n\n// set the reverse mapping: from this validator's new consensus address \n// on the consumer to its consensus address on the provider\nSetValidatorByConsumerAddr(chainID, consumerAddr, providerConsAddr)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["When a new consumer chain is registered, i.e., a client to the consumer chain is created, the provider constructs the consumer CCV module part of the genesis state (see ",(0,r.jsx)(n.code,{children:"MakeConsumerGenesis"}),")."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func (k Keeper) MakeConsumerGenesis(chainID string) (gen consumertypes.GenesisState, nextValidatorsHash []byte, err error) {\n // ...\n // get initial valset from the staking module\n var updates []abci.ValidatorUpdate{}\n stakingKeeper.IterateLastValidatorPowers(func(providerAddr sdk.ValAddress, power int64) (stop bool) {\n validator := stakingKeeper.GetValidator(providerAddr)\n providerKey := validator.TmConsPublicKey()\n\t\tupdates = append(updates, abci.ValidatorUpdate{PubKey: providerKey, Power: power})\n\t\treturn false\n\t})\n\n // applies the key assignment to the initial validator\n\tfor i, update := range updates {\n\t\tproviderAddr := utils.TMCryptoPublicKeyToConsAddr(update.PubKey)\n\t\tif consumerKey, found := GetValidatorConsumerPubKey(chainID, providerAddr); found {\n\t\t\tupdates[i].PubKey = consumerKey\n\t\t}\n\t}\n gen.InitialValSet = updates\n\n // get a hash of the consumer validator set from the update\n\tupdatesAsValSet := tendermint.PB2TM.ValidatorUpdates(updates)\n\thash := tendermint.NewValidatorSet(updatesAsValSet).Hash()\n\n\treturn gen, hash, nil\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Note that key assignment works hand-in-hand with ",(0,r.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-014-epochs.md",children:"epochs"}),".\nFor each consumer chain, we store the consumer validator set that is currently (i.e., in this epoch) validating the consumer chain.\nSpecifically, for each validator in the set we store among others, the public key that it is using on the consumer chain during the current (i.e., ongoing) epoch.\nAt the end of every epoch, if there were validator set changes on the provider, then for every consumer chain, we construct a ",(0,r.jsx)(n.code,{children:"VSCPacket"}),"\nwith all the validator updates and add it to the list of ",(0,r.jsx)(n.code,{children:"PendingVSCPacket"}),"s. We compute the validator updates needed by a consumer chain by\ncomparing the stored list of consumer validators with the current bonded validators on the provider, with something similar to this:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"// get the valset that has been validating the consumer chain during this epoch \ncurrentValidators := GetConsumerValSet(consumerChain)\n// generate the validator updates needed to be sent through a `VSCPacket` by comparing the current validators \n// in the epoch with the latest bonded validators\nvalUpdates := DiffValidators(currentValidators, stakingmodule.GetBondedValidators())\n// update the current validators set for the upcoming epoch to be the latest bonded validators instead\nSetConsumerValSet(stakingmodule.GetBondedValidators())\n"})}),"\n",(0,r.jsxs)(n.p,{children:["where ",(0,r.jsx)(n.code,{children:"DiffValidators"})," internally checks if the consumer public key for a validator has changed since the last\nepoch and if so generates a validator update. This way, a validator can change its consumer public key for a consumer\nchain an arbitrary amount of times and only the last set consumer public key would be taken into account."]}),"\n",(0,r.jsxs)(n.p,{children:["On receiving a ",(0,r.jsx)(n.code,{children:"SlashPacket"})," from a consumer chain with id ",(0,r.jsx)(n.code,{children:"chainID"})," for a infraction of a validator ",(0,r.jsx)(n.code,{children:"data.Validator"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func HandleSlashPacket(chainID string, data ccv.SlashPacketData) (success bool, err error) {\n // ...\n // the slash packet validator address may be known only on the consumer chain;\n\t// in this case, it must be mapped back to the consensus address on the provider chain\n consumerAddr := sdk.ConsAddress(data.Validator.Address)\n providerAddr, found := GetValidatorByConsumerAddr(chainID, consumerAddr)\n if !found {\n // the validator has the same key on the consumer as on the provider\n providerAddr = consumerAddr\n }\n // ...\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["On receiving a ",(0,r.jsx)(n.code,{children:"VSCMatured"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func OnRecvVSCMaturedPacket(packet channeltypes.Packet, data ccv.VSCMaturedPacketData) exported.Acknowledgement {\n // ...\n // prune previous consumer validator address that are no longer needed\n consumerAddrs := GetConsumerAddrsToPrune(chainID, data.ValsetUpdateId)\n\tfor _, addr := range consumerAddrs {\n\t\tDeleteValidatorByConsumerAddr(chainID, addr)\n\t}\n\tDeleteConsumerAddrsToPrune(chainID, data.ValsetUpdateId)\n // ...\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"On stopping a consumer chain:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan bool) (err error) {\n // ...\n // deletes all the state needed for key assignments on this consumer chain\n // ...\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,r.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Validators can use different consensus keys on the consumer chains."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"None"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The consensus state necessary to create a client to the consumer chain must use the hash returned by the ",(0,r.jsx)(n.code,{children:"MakeConsumerGenesis"})," method as the ",(0,r.jsx)(n.code,{children:"nextValsHash"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The consumer chain can no longer check the initial validator set against the consensus state on ",(0,r.jsx)(n.code,{children:"InitGenesis"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/26",children:"Key assignment issue"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>o,a:()=>i});var r=s(7294);const t={},a=r.createContext(t);function i(e){const n=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),r.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/578fb1aa.9d55eaef.js b/assets/js/578fb1aa.9d55eaef.js
new file mode 100644
index 0000000000..2d61664424
--- /dev/null
+++ b/assets/js/578fb1aa.9d55eaef.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2323],{8522:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>l,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var i=r(5893),t=r(1151);const s={sidebar_position:2},o="Reward Distribution",a={id:"features/reward-distribution",title:"Reward Distribution",description:"Sending and distributing rewards from consumer chains to the provider chain is handled by the Reward Distribution sub-protocol.",source:"@site/docs/features/reward-distribution.md",sourceDirName:"features",slug:"/features/reward-distribution",permalink:"/interchain-security/features/reward-distribution",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Key Assignment",permalink:"/interchain-security/features/key-assignment"},next:{title:"ICS Provider Proposals",permalink:"/interchain-security/features/proposals"}},d={},c=[{value:"Whitelisting Reward Denoms",id:"whitelisting-reward-denoms",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"reward-distribution",children:"Reward Distribution"}),"\n",(0,i.jsxs)(n.p,{children:["Sending and distributing rewards from consumer chains to the provider chain is handled by the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/overview_and_basic_concepts.md#reward-distribution",children:"Reward Distribution sub-protocol"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Consumer chains have the option of sharing (a portion of) their block rewards (inflation tokens and fees) with the provider chain validators and delegators.\nIn Interchain Security, block rewards are periodically sent from the consumer to the provider according to consumer chain parameters using an IBC transfer channel.\nThis channel is created during consumer chain initialization, unless it is provided via the ",(0,i.jsx)(n.code,{children:"ConsumerAdditionProposal"})," when adding a new consumer chain.\nFor more details, see the ",(0,i.jsx)(n.a,{href:"/interchain-security/introduction/params#reward-distribution-parameters",children:"reward distribution parameters"}),"."]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Providing an IBC transfer channel (see ",(0,i.jsx)(n.code,{children:"DistributionTransmissionChannel"}),") enables a consumer chain to re-use one of the existing channels to the provider for consumer chain rewards distribution. This will preserve the ",(0,i.jsx)(n.code,{children:"ibc denom"})," that may already be in use.\nThis is especially important for standalone chains transitioning to become consumer chains.\nFor more details, see the ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/changeover-procedure",children:"changeover procedure"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Reward distribution on the provider is handled by the distribution module."}),"\n",(0,i.jsx)(n.h2,{id:"whitelisting-reward-denoms",children:"Whitelisting Reward Denoms"}),"\n",(0,i.jsxs)(n.p,{children:["The ICS distribution system works by allowing consumer chains to send rewards to a module address on the provider called the ",(0,i.jsx)(n.code,{children:"ConsumerRewardsPool"}),".\nTo avoid spam, the provider must whitelist denoms before accepting them as ICS rewards.\nOnly whitelisted denoms are transferred from the ",(0,i.jsx)(n.code,{children:"ConsumerRewardsPool"})," to the ",(0,i.jsx)(n.code,{children:"FeePoolAddress"}),", to be distributed to delegators and validators.\nThe whitelisted denoms can be adjusted through governance by sending a ",(0,i.jsx)(n.a,{href:"/interchain-security/features/proposals#changerewarddenomproposal",children:(0,i.jsx)(n.code,{children:"ChangeRewardDenomProposal"})}),"."]}),"\n",(0,i.jsx)(n.p,{children:"To query the list of whitelisted reward denoms on the Cosmos Hub, use the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"> gaiad q provider registered-consumer-reward-denoms\ndenoms:\n- ibc/0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5\n- ibc/6B8A3F5C2AD51CD6171FA41A7E8C35AD594AB69226438DB94450436EA57B3A89\n- uatom\n"})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsxs)(n.p,{children:["Use the following command to get a human readable denom from the ",(0,i.jsx)(n.code,{children:"ibc/*"})," denom trace format:"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"> gaiad query ibc-transfer denom-trace ibc/0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5\ndenom_trace:\n base_denom: untrn\n path: transfer/channel-569\n"})})]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>o});var i=r(7294);const t={},s=i.createContext(t);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/5cdffc34.eacf780d.js b/assets/js/5cdffc34.eacf780d.js
new file mode 100644
index 0000000000..533c5b1dbd
--- /dev/null
+++ b/assets/js/5cdffc34.eacf780d.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4895],{8961:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>a,metadata:()=>o,toc:()=>h});var s=i(5893),t=i(1151);const a={sidebar_position:1},r="Overview",o={id:"validators/overview",title:"Overview",description:"We advise that you join the Replicated Security testnet to gain hands-on experience with running consumer chains.",source:"@site/versioned_docs/version-v5.0.0/validators/overview.md",sourceDirName:"validators",slug:"/validators/overview",permalink:"/interchain-security/v5.0.0/validators/overview",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Consumer Genesis Transformation",permalink:"/interchain-security/v5.0.0/consumer-development/consumer-genesis-transformation"},next:{title:"Joining Interchain Security testnet",permalink:"/interchain-security/v5.0.0/validators/joining-testnet"}},c={},h=[{value:"Startup sequence overview",id:"startup-sequence-overview",level:2},{value:"1. Consumer Chain init + 2. Genesis generation",id:"1-consumer-chain-init--2-genesis-generation",level:3},{value:"3. Submit Proposal",id:"3-submit-proposal",level:3},{value:"4. CCV Genesis state generation",id:"4-ccv-genesis-state-generation",level:3},{value:"5. Updating the genesis file",id:"5-updating-the-genesis-file",level:3},{value:"6. Chain start",id:"6-chain-start",level:3},{value:"7. Creating IBC connections",id:"7-creating-ibc-connections",level:3},{value:"Downtime Infractions",id:"downtime-infractions",level:2},{value:"Double-signing Infractions",id:"double-signing-infractions",level:2},{value:"Key assignment",id:"key-assignment",level:2},{value:"References:",id:"references",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["We advise that you join the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security",children:"Replicated Security testnet"})," to gain hands-on experience with running consumer chains."]})}),"\n",(0,s.jsx)(n.p,{children:"At present, replicated security requires all validators of the provider chain (ie. Cosmos Hub) to run validator nodes for all governance-approved consumer chains."}),"\n",(0,s.jsxs)(n.p,{children:["Once a ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})," passes, validators need to prepare to run the consumer chain binaries (these will be linked in their proposals) and set up validator nodes on governance-approved consumer chains."]}),"\n",(0,s.jsx)(n.p,{children:"Provider chain and consumer chains represent standalone chains that only share the validator set ie. the same validator operators are tasked with running all chains."}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"To validate a consumer chain and be eligible for rewards validators are required to be in the active set of the provider chain (first 180 validators for Cosmos Hub)."})}),"\n",(0,s.jsx)(n.h2,{id:"startup-sequence-overview",children:"Startup sequence overview"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer chains cannot start and be secured by the validator set of the provider unless a ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})," is passed.\nEach proposal contains defines a ",(0,s.jsx)(n.code,{children:"spawn_time"})," - the timestamp when the consumer chain genesis is finalized and the consumer chain clients get initialized on the provider."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["Validators are required to run consumer chain binaries only after ",(0,s.jsx)(n.code,{children:"spawn_time"})," has passed."]})}),"\n",(0,s.jsx)(n.p,{children:"Please note that any additional instructions pertaining to specific consumer chain launches will be available before spawn time. The chain start will be stewarded by the Cosmos Hub team and the teams developing their respective consumer chains."}),"\n",(0,s.jsxs)(n.p,{children:["The image below illustrates the startup sequence\n",(0,s.jsx)(n.img,{alt:"startup",src:i(9558).Z+"",width:"942",height:"632"})]}),"\n",(0,s.jsx)(n.h3,{id:"1-consumer-chain-init--2-genesis-generation",children:"1. Consumer Chain init + 2. Genesis generation"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer chain team initializes the chain genesis.json and prepares binaries which will be listed in the ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})]}),"\n",(0,s.jsx)(n.h3,{id:"3-submit-proposal",children:"3. Submit Proposal"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer chain team (or their advocates) submits a ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"}),".\nThe most important parameters for validators are:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"spawn_time"})," - the time after which the consumer chain must be started"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"genesis_hash"})," - hash of the pre-ccv genesis.json; the file does not contain any validator info -> the information is available only after the proposal is passed and ",(0,s.jsx)(n.code,{children:"spawn_time"})," is reached"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"binary_hash"})," - hash of the consumer chain binary used to validate the software builds"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"4-ccv-genesis-state-generation",children:"4. CCV Genesis state generation"}),"\n",(0,s.jsxs)(n.p,{children:["After reaching ",(0,s.jsx)(n.code,{children:"spawn_time"})," the provider chain will automatically create the CCV validator states that will be used to populate the corresponding fields in the consumer chain ",(0,s.jsx)(n.code,{children:"genesis.json"}),". The CCV validator set consists of the validator set on the provider at ",(0,s.jsx)(n.code,{children:"spawn_time"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"The state can be queried on the provider chain (in this case the Cosmos Hub):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:" gaiad query provider consumer-genesis -o json > ccvconsumer_genesis.json\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This is used by the launch coordinator to create the final ",(0,s.jsx)(n.code,{children:"genesis.json"})," that will be distributed to validators in step 5."]}),"\n",(0,s.jsx)(n.h3,{id:"5-updating-the-genesis-file",children:"5. Updating the genesis file"}),"\n",(0,s.jsxs)(n.p,{children:["Upon reaching the ",(0,s.jsx)(n.code,{children:"spawn_time"})," the initial validator set state will become available on the provider chain. The initial validator set is included in the ",(0,s.jsx)(n.strong,{children:"final genesis.json"})," of the consumer chain."]}),"\n",(0,s.jsx)(n.h3,{id:"6-chain-start",children:"6. Chain start"}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"The consumer chain will start producing blocks as soon as 66.67% of the provider chain's voting power comes online (on the consumer chain). The relayer should be started after block production commences."})}),"\n",(0,s.jsxs)(n.p,{children:["The new ",(0,s.jsx)(n.code,{children:"genesis.json"})," containing the initial validator set will be distributed to validators by the consumer chain team (launch coordinator). Each validator should use the provided ",(0,s.jsx)(n.code,{children:"genesis.json"})," to start their consumer chain node."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["Please pay attention to any onboarding repositories provided by the consumer chain teams.\nRecommendations are available in ",(0,s.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/onboarding",children:"Consumer Onboarding Checklist"}),".\nAnother comprehensive guide is available in the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md",children:"Interchain Security testnet repo"}),"."]})}),"\n",(0,s.jsx)(n.h3,{id:"7-creating-ibc-connections",children:"7. Creating IBC connections"}),"\n",(0,s.jsx)(n.p,{children:"Finally, to fully establish interchain security an IBC relayer is used to establish connections and create the required channels."}),"\n",(0,s.jsx)(n.admonition,{type:"warning",children:(0,s.jsx)(n.p,{children:"The relayer can establish the connection only after the consumer chain starts producing blocks."})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"hermes create connection --a-chain --a-client 07-tendermint-0 --b-client \nhermes create channel --a-chain --a-port consumer --b-port provider --order ordered --a-connection connection-0 --channel-version 1\nhermes start\n"})}),"\n",(0,s.jsx)(n.h2,{id:"downtime-infractions",children:"Downtime Infractions"}),"\n",(0,s.jsxs)(n.p,{children:["At present, the consumer chain can report evidence about downtime infractions to the provider chain. The ",(0,s.jsx)(n.code,{children:"min_signed_per_window"})," and ",(0,s.jsx)(n.code,{children:"signed_blocks_window"})," can be different on each consumer chain and are subject to changes via consumer chain governance."]}),"\n",(0,s.jsxs)(n.admonition,{type:"info",children:[(0,s.jsx)(n.p,{children:"Causing a downtime infraction on any consumer chain will not incur a slash penalty. Instead, the offending validator will be jailed on the provider chain and consequently on all consumer chains."}),(0,s.jsxs)(n.p,{children:["To unjail, the validator must wait for the jailing period to elapse on the provider chain and ",(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup#unjail-validator",children:"submit an unjail transaction"})," on the provider chain. After unjailing on the provider, the validator will be unjailed on all consumer chains."]}),(0,s.jsxs)(n.p,{children:["More information is available in ",(0,s.jsx)(n.a,{href:"/interchain-security/v5.0.0/features/slashing#downtime-infractions",children:"Downtime Slashing documentation"})]})]}),"\n",(0,s.jsx)(n.h2,{id:"double-signing-infractions",children:"Double-signing Infractions"}),"\n",(0,s.jsxs)(n.p,{children:["To learn more about equivocation handling in interchain security check out the ",(0,s.jsx)(n.a,{href:"/interchain-security/v5.0.0/features/slashing",children:"Slashing"})," documentation section."]}),"\n",(0,s.jsx)(n.h2,{id:"key-assignment",children:"Key assignment"}),"\n",(0,s.jsx)(n.p,{children:"Validators can use different consensus keys on the provider and each of the consumer chains. The consumer chain consensus key must be registered on the provider before use."}),"\n",(0,s.jsxs)(n.p,{children:["For more information check out the ",(0,s.jsx)(n.a,{href:"/interchain-security/v5.0.0/features/key-assignment",children:"Key assignment overview and guide"})]}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-faq",children:"Cosmos Hub Validators FAQ"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup",children:"Cosmos Hub Running a validator"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md#chain-launch",children:"Startup Sequence"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup#unjail-validator",children:"Submit Unjailing Transaction"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},9558:(e,n,i)=>{i.d(n,{Z:()=>s});const s=i.p+"assets/images/hypha-consumer-start-process-2141109f76c584706dd994d7965fd692.svg"},1151:(e,n,i)=>{i.d(n,{Z:()=>o,a:()=>r});var s=i(7294);const t={},a=s.createContext(t);function r(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/5cee3276.e8f98637.js b/assets/js/5cee3276.e8f98637.js
new file mode 100644
index 0000000000..c4ed92676d
--- /dev/null
+++ b/assets/js/5cee3276.e8f98637.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1996],{434:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>l});var i=t(5893),o=t(1151);const r={sidebar_position:1},a="Overview",s={id:"introduction/overview",title:"Overview",description:"Replicated security (aka interchain security V1) is an open sourced IBC application which allows cosmos blockchains to lease their proof-of-stake security to one another.",source:"@site/versioned_docs/version-v5.0.0/introduction/overview.md",sourceDirName:"introduction",slug:"/introduction/overview",permalink:"/interchain-security/v5.0.0/introduction/overview",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Interchain Security Docs",permalink:"/interchain-security/v5.0.0/"},next:{title:"Terminology",permalink:"/interchain-security/v5.0.0/introduction/terminology"}},c={},l=[{value:"Why Replicated Security?",id:"why-replicated-security",level:2},{value:"Core protocol",id:"core-protocol",level:2},{value:"Downtime Slashing",id:"downtime-slashing",level:3},{value:"Tokenomics and Rewards",id:"tokenomics-and-rewards",level:3}];function d(e){const n={a:"a",admonition:"admonition",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"overview",children:"Overview"}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsx)(n.p,{children:"Replicated security (aka interchain security V1) is an open sourced IBC application which allows cosmos blockchains to lease their proof-of-stake security to one another."}),(0,i.jsx)("br",{}),(0,i.jsx)(n.p,{children:'Replicated security allows anyone to launch a "consumer" blockchain using the same validator set as the "provider" blockchain by creating a governance proposal. If the proposal is accepted, provider chain validators start validating the consumer chain as well. Consumer chains will therefore inherit the full security and decentralization of the provider.'})]}),"\n",(0,i.jsx)(n.h2,{id:"why-replicated-security",children:"Why Replicated Security?"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Full provider security. At launch, consumer chains are secured by the full validator set and market cap of the provider chain."}),"\n",(0,i.jsx)(n.li,{children:"Independent block-space. Transactions on consumer chains do not compete with any other applications. This means that there will be no unexpected congestion, and performance will generally be much better than on a shared smart contract platform such as Ethereum."}),"\n",(0,i.jsx)(n.li,{children:"Projects keep majority of gas fees. Depending on configuration, these fees either go to the project\u2019s community DAO, or can be used in the protocol in other ways."}),"\n",(0,i.jsx)(n.li,{children:"No validator search. Consumer chains do not have their own validator sets, and so do not need to find validators one by one. A governance vote will take place for a chain to get adopted by the provider validators which will encourage participation and signal strong buy-in into the project's long-term success."}),"\n",(0,i.jsx)(n.li,{children:"Instant sovereignty. Consumers can run arbitrary app logic similar to standalone chains. At any time in the future, a consumer chain can elect to become a completely standalone chain, with its own validator set."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"core-protocol",children:"Core protocol"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Protocol specification is available as ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/overview_and_basic_concepts.md",children:"ICS-028"})," in the IBC repository."]})}),"\n",(0,i.jsx)(n.p,{children:"Once an IBC connection and proper channel is established between a provider and consumer chain, the provider will continually send validator set updates to the consumer over IBC. The consumer uses these validator set updates to update its own validator set in Comet. Thus, the provider validator set is effectively replicated on the consumer."}),"\n",(0,i.jsx)(n.p,{children:"To ensure the security of the consumer chain, provider delegators cannot unbond their tokens until the unbonding periods of each consumer chain has passed. In practice this will not be noticeable to the provider delegators, since consumer chains will be configured to have a slightly shorter unbonding period than the provider."}),"\n",(0,i.jsx)(n.h3,{id:"downtime-slashing",children:"Downtime Slashing"}),"\n",(0,i.jsx)(n.p,{children:"If downtime is initiated by a validator on a consumer chain, a downtime packet will be relayed to the provider to jail that validator for a set amount of time. The validator who committed downtime will then miss out on staking rewards for the configured jailing period."}),"\n",(0,i.jsx)(n.h3,{id:"tokenomics-and-rewards",children:"Tokenomics and Rewards"}),"\n",(0,i.jsx)(n.p,{children:"Consumer chains are free to create their own native token which can be used for fees, and can be created on the consumer chain in the form of inflationary rewards. These rewards can be used to incentivize user behavior, for example, LPing or staking. A portion of these fees and rewards will be sent to provider chain stakers, but that proportion is completely customizable by the developers, and subject to governance."})]})}function h(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>s,a:()=>a});var i=t(7294);const o={},r=i.createContext(o);function a(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/5e95c892.e9a018bf.js b/assets/js/5e95c892.e9a018bf.js
new file mode 100644
index 0000000000..562d508c4f
--- /dev/null
+++ b/assets/js/5e95c892.e9a018bf.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9661],{1892:(e,s,r)=>{r.r(s),r.d(s,{default:()=>l});r(7294);var t=r(512),u=r(1944),a=r(5281),c=r(8790),n=r(6040),i=r(5893);function l(e){return(0,i.jsx)(u.FG,{className:(0,t.Z)(a.k.wrapper.docsPages),children:(0,i.jsx)(n.Z,{children:(0,c.H)(e.route.routes)})})}}}]);
\ No newline at end of file
diff --git a/assets/js/5fa9786a.fa4ac172.js b/assets/js/5fa9786a.fa4ac172.js
new file mode 100644
index 0000000000..f6d8b5cc25
--- /dev/null
+++ b/assets/js/5fa9786a.fa4ac172.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2341],{5370:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>l,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=r(5893),t=r(1151);const o={sidebar_position:6},s="Consumer Genesis Transformation",a={id:"consumer-development/consumer-genesis-transformation",title:"Consumer Genesis Transformation",description:"Preparing a consumer chain for onboarding requires some information explaining how to run your chain. This includes a genesis file with CCV data where the CCV data is exported from the provider chain and added to the consumers genesis file (for more details check the documentation on Onboarding and Changeover).",source:"@site/versioned_docs/version-v4.2.0-docs/consumer-development/consumer-genesis-transformation.md",sourceDirName:"consumer-development",slug:"/consumer-development/consumer-genesis-transformation",permalink:"/interchain-security/v4.2.0/consumer-development/consumer-genesis-transformation",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Changeover Procedure",permalink:"/interchain-security/v4.2.0/consumer-development/changeover-procedure"},next:{title:"Overview",permalink:"/interchain-security/v4.2.0/validators/overview"}},c={},d=[{value:"1. Prerequisite",id:"1-prerequisite",level:2},{value:"2. Export the CCV data",id:"2-export-the-ccv-data",level:2},{value:"3. Transform CCV data",id:"3-transform-ccv-data",level:2}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"consumer-genesis-transformation",children:"Consumer Genesis Transformation"}),"\n",(0,i.jsxs)(n.p,{children:["Preparing a consumer chain for onboarding requires some information explaining how to run your chain. This includes a genesis file with CCV data where the CCV data is exported from the provider chain and added to the consumers genesis file (for more details check the documentation on ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/onboarding",children:"Onboarding"})," and ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/changeover-procedure",children:"Changeover"}),").\nIn case that the provider chain is running an older version of the InterChainSecurity (ICS) module than the consumer chain - or vice versa - the exported CCV data might need to be transformed to the format supported by the ICS implementation run on the consumer chain. This is the case if the consumer chain runs version 4 of ICS or later and the provider is running version 3 or older of the ICS module."]}),"\n",(0,i.jsxs)(n.p,{children:["Check the ",(0,i.jsx)(n.a,{href:"../../../RELEASES.md#backwards-compatibility",children:"compatibility notes"})," for known incompatibilities between provider and consumer versions and indications if a consumer genesis transformation is required."]}),"\n",(0,i.jsx)(n.p,{children:"To transform such CCV data follow the instructions below"}),"\n",(0,i.jsx)(n.h2,{id:"1-prerequisite",children:"1. Prerequisite"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["used provider and consumer versions require transformation step as indicated in in the ",(0,i.jsx)(n.a,{href:"../../../RELEASES.md#backwards-compatibility",children:"compatibility notes"})]}),"\n",(0,i.jsx)(n.li,{children:"interchain-security-cd application supports the versions used by the consumer and provider"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"2-export-the-ccv-data",children:"2. Export the CCV data"}),"\n",(0,i.jsxs)(n.p,{children:["Export the CCV data from the provider chain as described in the ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/onboarding",children:"Onboarding"})," and ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/changeover-procedure",children:"Changeover"})," your following.\nAs a result the CCV data will be stored in a file in JSON format."]}),"\n",(0,i.jsx)(n.h2,{id:"3-transform-ccv-data",children:"3. Transform CCV data"}),"\n",(0,i.jsx)(n.p,{children:"To transform the CCV data"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["to the format supported by the current version of the consumer run the following command:","\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"interchain-security-cd genesis transform [genesis-file]\n"})}),"\n","where 'genesis-file' is the path to the file containing the CCV data exported in ",(0,i.jsx)(n.a,{href:"#2-export-the-ccv-data",children:"step 2"}),".\nAs a result the CCV data in the new format will be written to standard output."]}),"\n",(0,i.jsxs)(n.li,{children:["a specific target version of a consumer run the following command:","\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"interchain-security-cd genesis transform --to [genesis-file]\n\n"})}),"\n","where ",(0,i.jsx)(n.code,{children:"{r.d(n,{Z:()=>a,a:()=>s});var i=r(7294);const t={},o=i.createContext(t);function s(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/61e9b0fd.babea3e2.js b/assets/js/61e9b0fd.babea3e2.js
new file mode 100644
index 0000000000..bd4e6c5778
--- /dev/null
+++ b/assets/js/61e9b0fd.babea3e2.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5402],{5615:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>h,contentTitle:()=>o,default:()=>l,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var i=t(5893),r=t(1151);const s={sidebar_position:5,title:"Frequently Asked Questions",slug:"/faq"},o=void 0,a={id:"frequently-asked-questions",title:"Frequently Asked Questions",description:"What is the meaning of Validator Set Replication?",source:"@site/versioned_docs/version-v5.0.0/frequently-asked-questions.md",sourceDirName:".",slug:"/faq",permalink:"/interchain-security/v5.0.0/faq",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:5,frontMatter:{sidebar_position:5,title:"Frequently Asked Questions",slug:"/faq"},sidebar:"tutorialSidebar",previous:{title:"Joining Stride",permalink:"/interchain-security/v5.0.0/validators/joining-stride"},next:{title:"ADRs",permalink:"/interchain-security/v5.0.0/adrs/intro"}},h={},c=[{value:"What is the meaning of Validator Set Replication?",id:"what-is-the-meaning-of-validator-set-replication",level:2},{value:"What is a consumer chain?",id:"what-is-a-consumer-chain",level:2},{value:"What happens to consumer if provider is down?",id:"what-happens-to-consumer-if-provider-is-down",level:2},{value:"What happens to provider if consumer is down?",id:"what-happens-to-provider-if-consumer-is-down",level:2},{value:"Can I run the provider and consumer chains on the same machine?",id:"can-i-run-the-provider-and-consumer-chains-on-the-same-machine",level:2},{value:"Can the consumer chain have its own token?",id:"can-the-consumer-chain-have-its-own-token",level:2},{value:"How are Tx fees paid on consumer?",id:"how-are-tx-fees-paid-on-consumer",level:2},{value:"Are there any restrictions the consumer chains need to abide by?",id:"are-there-any-restrictions-the-consumer-chains-need-to-abide-by",level:2},{value:"What's in it for the validators and stakers?",id:"whats-in-it-for-the-validators-and-stakers",level:2},{value:"Can the consumer chain have its own governance?",id:"can-the-consumer-chain-have-its-own-governance",level:2},{value:"Can validators opt-out of replicated security?",id:"can-validators-opt-out-of-replicated-security",level:2},{value:"How does Equivocation Governance Slashing work?",id:"how-does-equivocation-governance-slashing-work",level:2},{value:"Can Consumer Chains perform Software Upgrades?",id:"can-consumer-chains-perform-software-upgrades",level:2},{value:"How can I connect to the testnets?",id:"how-can-i-connect-to-the-testnets",level:2},{value:"How do I start using ICS?",id:"how-do-i-start-using-ics",level:2},{value:"Which relayers are supported?",id:"which-relayers-are-supported",level:2},{value:"How does key delegation work in ICS?",id:"how-does-key-delegation-work-in-ics",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"what-is-the-meaning-of-validator-set-replication",children:"What is the meaning of Validator Set Replication?"}),"\n",(0,i.jsx)(n.p,{children:"VSR simply means that the same validator set is used to secure both the provider and consumer chains. VSR is ensured through ICS protocol which keeps consumers up to date with the validator set of the provider."}),"\n",(0,i.jsx)(n.h2,{id:"what-is-a-consumer-chain",children:"What is a consumer chain?"}),"\n",(0,i.jsx)(n.p,{children:"Consumer chain is blockchain operated by the same validator operators as the provider chain. The ICS protocol ensures the validator set replication properties (informs consumer chain about the current state of the validator set on the provider)"}),"\n",(0,i.jsx)(n.p,{children:"Consumer chains are run on infrastructure (virtual or physical machines) distinct from the provider, have their own configurations and operating requirements."}),"\n",(0,i.jsx)(n.h2,{id:"what-happens-to-consumer-if-provider-is-down",children:"What happens to consumer if provider is down?"}),"\n",(0,i.jsx)(n.p,{children:"In case the provider chain halts or experiences difficulties the consumer chain will keep operating - the provider chain and consumer chains represent different networks, which only share the validator set."}),"\n",(0,i.jsx)(n.p,{children:"The consumer chain will not halt if the provider halts because they represent distinct networks and distinct infrastructures. Provider chain liveness does not impact consumer chain liveness."}),"\n",(0,i.jsxs)(n.p,{children:["However, if the ",(0,i.jsx)(n.code,{children:"trusting_period"})," (currently 5 days for protocol safety reasons) elapses without receiving any updates from the provider, the consumer chain will essentially transition to a Proof of Authority chain.\nThis means that the validator set on the consumer will be the last validator set of the provider that the consumer knows about."]}),"\n",(0,i.jsx)(n.p,{children:'Steps to recover from this scenario and steps to "release" the validators from their duties will be specified at a later point.\nAt the very least, the consumer chain could replace the validator set, remove the ICS module and perform a genesis restart. The impact of this on the IBC clients and connections is currently under careful consideration.'}),"\n",(0,i.jsx)(n.h2,{id:"what-happens-to-provider-if-consumer-is-down",children:"What happens to provider if consumer is down?"}),"\n",(0,i.jsx)(n.p,{children:"Consumer chains do not impact the provider chain.\nThe ICS protocol is concerned only with validator set replication and the only communication that the provider requires from the consumer is information about validator activity (essentially keeping the provider informed about slash events)."}),"\n",(0,i.jsx)(n.h2,{id:"can-i-run-the-provider-and-consumer-chains-on-the-same-machine",children:"Can I run the provider and consumer chains on the same machine?"}),"\n",(0,i.jsx)(n.p,{children:"Yes, but you should favor running them in separate environments so failure of one machine does not impact your whole operation."}),"\n",(0,i.jsx)(n.h2,{id:"can-the-consumer-chain-have-its-own-token",children:"Can the consumer chain have its own token?"}),"\n",(0,i.jsx)(n.p,{children:"As any other cosmos-sdk chain the consumer chain can issue its own token, manage inflation parameters and use them to pay gas fees."}),"\n",(0,i.jsx)(n.h2,{id:"how-are-tx-fees-paid-on-consumer",children:"How are Tx fees paid on consumer?"}),"\n",(0,i.jsx)(n.p,{children:"The consumer chain operates as any other cosmos-sdk chain. The ICS protocol does not impact the normal chain operations."}),"\n",(0,i.jsx)(n.h2,{id:"are-there-any-restrictions-the-consumer-chains-need-to-abide-by",children:"Are there any restrictions the consumer chains need to abide by?"}),"\n",(0,i.jsx)(n.p,{children:"No. Consumer chains are free to choose how they wish to operate, which modules to include, use CosmWASM in a permissioned or a permissionless way.\nThe only thing that separates consumer chains from standalone chains is that they share their validator set with the provider chain."}),"\n",(0,i.jsx)(n.h2,{id:"whats-in-it-for-the-validators-and-stakers",children:"What's in it for the validators and stakers?"}),"\n",(0,i.jsxs)(n.p,{children:["The consumer chains sends a portion of its fees and inflation as reward to the provider chain as defined by ",(0,i.jsx)(n.code,{children:"ConsumerRedistributionFraction"}),". The rewards are distributed (sent to the provider) every ",(0,i.jsx)(n.code,{children:"BlocksPerDistributionTransmission"}),"."]}),"\n",(0,i.jsx)(n.admonition,{type:"note",children:(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"ConsumerRedistributionFraction"})," and ",(0,i.jsx)(n.code,{children:"BlocksPerDistributionTransmission"})," are parameters defined in the ",(0,i.jsx)(n.code,{children:"ConsumerAdditionProposal"})," used to create the consumer chain. These parameters can be changed via consumer chain governance."]})}),"\n",(0,i.jsx)(n.h2,{id:"can-the-consumer-chain-have-its-own-governance",children:"Can the consumer chain have its own governance?"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Yes."})}),"\n",(0,i.jsx)(n.p,{children:'In that case the validators are not necessarily part of the governance structure. Instead, their place in governance is replaced by "representatives" (governors). The representatives do not need to run validators, they simply represent the interests of a particular interest group on the consumer chain.'}),"\n",(0,i.jsx)(n.p,{children:"Validators can also be representatives but representatives are not required to run validator nodes."}),"\n",(0,i.jsx)(n.p,{children:"This feature discerns between validator operators (infrastructure) and governance representatives which further democratizes the ecosystem. This also reduces the pressure on validators to be involved in on-chain governance."}),"\n",(0,i.jsx)(n.h2,{id:"can-validators-opt-out-of-replicated-security",children:"Can validators opt-out of replicated security?"}),"\n",(0,i.jsx)(n.p,{children:"At present, the validators cannot opt-out of validating consumer chains."}),"\n",(0,i.jsx)(n.p,{children:"There are multiple opt-out mechanisms under active research."}),"\n",(0,i.jsx)(n.h2,{id:"how-does-equivocation-governance-slashing-work",children:"How does Equivocation Governance Slashing work?"}),"\n",(0,i.jsx)(n.p,{children:"To avoid potential attacks directed at provider chain validators, a new mechanism was introduced:"}),"\n",(0,i.jsx)(n.p,{children:"When a validator double-signs on the consumer chain, a special type of slash packet is relayed to the provider chain. The provider will store information about the double signing validator and allow a governance proposal to be submitted.\nIf the double-signing proposal passes, the offending validator will be slashed on the provider chain and tombstoned. Tombstoning will permanently exclude the validator from the active set of the provider."}),"\n",(0,i.jsx)(n.admonition,{type:"caution",children:(0,i.jsx)(n.p,{children:"An equivocation proposal cannot be submitted for a validator that did not double sign on any of the consumer chains."})}),"\n",(0,i.jsx)(n.h2,{id:"can-consumer-chains-perform-software-upgrades",children:"Can Consumer Chains perform Software Upgrades?"}),"\n",(0,i.jsx)(n.p,{children:"Consumer chains are standalone chains, in the sense that they can run arbitrary logic and use any modules they want (ie CosmWASM)."}),"\n",(0,i.jsx)(n.p,{children:"Consumer chain upgrades are unlikely to impact the provider chain, as long as there are no changes to the ICS module."}),"\n",(0,i.jsx)(n.h2,{id:"how-can-i-connect-to-the-testnets",children:"How can I connect to the testnets?"}),"\n",(0,i.jsxs)(n.p,{children:["Check out the ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/validators/joining-testnet",children:"Joining Replicated Security testnet"})," section."]}),"\n",(0,i.jsx)(n.h2,{id:"how-do-i-start-using-ics",children:"How do I start using ICS?"}),"\n",(0,i.jsxs)(n.p,{children:["To become a consumer chain use this ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/onboarding",children:"checklist"})," and check the ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/app-integration",children:"App integration section"})]}),"\n",(0,i.jsx)(n.h2,{id:"which-relayers-are-supported",children:"Which relayers are supported?"}),"\n",(0,i.jsx)(n.p,{children:"Currently supported versions:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Hermes 1.4.1"}),"\n",(0,i.jsxs)(n.li,{children:["Support for the CCV module was added to the Go ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/relayer",children:"relayer"})," in v2.2.0 but v2.4.0 has significant performance fixes which makes it the earliest suggested version to use."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"how-does-key-delegation-work-in-ics",children:"How does key delegation work in ICS?"}),"\n",(0,i.jsxs)(n.p,{children:["You can check the ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/features/key-assignment",children:"Key Assignment Guide"})," for specific instructions."]})]})}function l(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>o});var i=t(7294);const r={},s=i.createContext(r);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/624b8b53.ef004408.js b/assets/js/624b8b53.ef004408.js
new file mode 100644
index 0000000000..ba2f068468
--- /dev/null
+++ b/assets/js/624b8b53.ef004408.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9709],{1461:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var i=s(5893),o=s(1151);const r={sidebar_position:13,title:"Separate Releasing"},t="ADR 012: Separate Releasing",a={id:"adrs/adr-012-separate-releasing",title:"Separate Releasing",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-012-separate-releasing.md",sourceDirName:"adrs",slug:"/adrs/adr-012-separate-releasing",permalink:"/interchain-security/v5.0.0/adrs/adr-012-separate-releasing",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:13,frontMatter:{sidebar_position:13,title:"Separate Releasing"},sidebar:"tutorialSidebar",previous:{title:"Improving testing and increasing confidence",permalink:"/interchain-security/v5.0.0/adrs/adr-011-improving-test-confidence"},next:{title:"Slashing on the provider for consumer equivocation",permalink:"/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing"}},l={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Spike results",id:"spike-results",level:3},{value:"Why go.mod split is not the way to go",id:"why-gomod-split-is-not-the-way-to-go",level:3},{value:"Why separate repos is cool but also not the way to go",id:"why-separate-repos-is-cool-but-also-not-the-way-to-go",level:3},{value:"Decision",id:"decision",level:2},{value:"Example release flow",id:"example-release-flow",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function c(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-012-separate-releasing",children:"ADR 012: Separate Releasing"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[8/18/22,": Initial draft of idea in ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801",children:"#801"})]}),"\n",(0,i.jsxs)(n.li,{children:[8/22/22,": Put idea in this ADR"]}),"\n",(0,i.jsxs)(n.li,{children:[.05,": Reject this ADR"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Rejected"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.h3,{id:"spike-results",children:"Spike results"}),"\n",(0,i.jsxs)(n.p,{children:["I explored the idea of ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801",children:"#801"})," with this ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/shawn%2Fgo-mod-split-aug-spike",children:"spike branch"}),". Here's my conclusions:"]}),"\n",(0,i.jsxs)(n.p,{children:["Splitting this repo to have multiple go.mods is possible. However there are various intricacies involved in decoupling the package hierarchy to have ",(0,i.jsx)(n.code,{children:"x/ccv/types"})," as the lowest level dep, with ",(0,i.jsx)(n.code,{children:"x/ccv/consumer"})," and ",(0,i.jsx)(n.code,{children:"x/ccv/provider"})," being one dep layer above, with high-level tests depending on all three of the mentioned packages. I'd estimate this decoupling would take 2-5 workdays to finish, and require significant review effort."]}),"\n",(0,i.jsx)(n.h3,{id:"why-gomod-split-is-not-the-way-to-go",children:"Why go.mod split is not the way to go"}),"\n",(0,i.jsxs)(n.p,{children:["Let's take a step back and remember the issue we're trying to solve - ",(0,i.jsx)(n.strong,{children:"We need a clean way to decouple semver/releasing for the consumer and provider modules"}),". After more consideration, splitting up go.mods gives us little benefit in achieving this. Reasons:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The ",(0,i.jsx)(n.code,{children:"go.mod"})," dependency system is tied to git tags for the entire repo (ex: ",(0,i.jsx)(n.code,{children:"require github.com/cometbft/cometbft v0.37.2"})," refers to a historical tag for the entire cometbft repo)."]}),"\n",(0,i.jsx)(n.li,{children:"It'd be an odd dev experience to allow modules to reference past releases of other modules in the same repo. When would we ever want the consumer module to reference a past release of the types module for example?"}),"\n",(0,i.jsxs)(n.li,{children:["If we allow for ",(0,i.jsx)(n.code,{children:"go.mod"})," replace statements to build from local source code, why split up the package deps at all?"]}),"\n",(0,i.jsxs)(n.li,{children:["Splitting go.mods adds a bunch of complexity with ",(0,i.jsx)(n.code,{children:"go.work"})," files and all that shiz. VSCode does not play well with multiple module repos either."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"why-separate-repos-is-cool-but-also-not-the-way-to-go",children:"Why separate repos is cool but also not the way to go"}),"\n",(0,i.jsxs)(n.p,{children:["All this considered, the cleanest solution to decoupling semver/releasing for the consumer and provider modules would be to have multiple repos, each with their own go.mod (3-4 repos total including high level tests). With this scheme we could separately tag each repo as changes are merged, they could share some code from ",(0,i.jsx)(n.code,{children:"types"})," being an external dep, etc."]}),"\n",(0,i.jsx)(n.p,{children:"I don't think any of us want to split up the monorepo, that's a lot of work and seems like bikeshedding. There's another solution that's very simple.."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsxs)(n.p,{children:["Slightly adapting ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/cca008d856e3ffc60ec1a486871d0faa702abe26/CONTRIBUTING.md#semantic-versioning",children:"the current semver ruleset"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"A library API breaking change to EITHER the provider or consumer module will result in an increase of the MAJOR version number for BOTH modules (X.y.z-provider AND X.y.z-consumer)."}),"\n",(0,i.jsx)(n.li,{children:"A state breaking change (change requiring coordinated upgrade and/or state migration) will result in an increase of the MINOR version number for the AFFECTED module(s) (x.Y.z-provider AND/OR x.Y.z-consumer)."}),"\n",(0,i.jsx)(n.li,{children:"Any other changes (including node API breaking changes) will result in an increase of the PATCH version number for the AFFECTED module(s) (x.y.Z-provider AND/OR x.y.Z-consumer)."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"example-release-flow",children:"Example release flow"}),"\n",(0,i.jsxs)(n.p,{children:["We upgrade ",(0,i.jsx)(n.code,{children:"main"})," to use a new version of SDK. This is a major version bump, triggering a new release for both the provider and consumer modules, ",(0,i.jsx)(n.code,{children:"v5.0.0-provider"})," and ",(0,i.jsx)(n.code,{children:"v5.0.0-consumer"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["A state breaking change is merged to ",(0,i.jsx)(n.code,{children:"main"})," for the provider module. We release only a ",(0,i.jsx)(n.code,{children:"v5.1.0-provider"})," off main."]}),"\n",(0,i.jsxs)(n.li,{children:["Another state breaking change is merged to ",(0,i.jsx)(n.code,{children:"main"})," for the provider module. We release only a ",(0,i.jsx)(n.code,{children:"v5.2.0-provider"})," off main."]}),"\n",(0,i.jsxs)(n.li,{children:["At this point, the latest consumer version is still ",(0,i.jsx)(n.code,{children:"v5.0.0-consumer"}),". We now merge a state breaking change for the consumer module to ",(0,i.jsx)(n.code,{children:"main"}),", and consequently release ",(0,i.jsx)(n.code,{children:"v5.1.0-consumer"}),". Note that ",(0,i.jsx)(n.code,{children:"v5.1.0-consumer"})," is tagged off a LATER commit from main than ",(0,i.jsx)(n.code,{children:"v5.2.0-provider"}),". This is fine, as the consumer module should not be affected by the provider module's state breaking changes."]}),"\n",(0,i.jsxs)(n.li,{children:["Once either module sees a library API breaking change, we bump the major version for both modules. For example, we merge a library API breaking change to ",(0,i.jsx)(n.code,{children:"main"})," for the provider module. We release ",(0,i.jsx)(n.code,{children:"v6.0.0-provider"})," and ",(0,i.jsx)(n.code,{children:"v6.0.0-consumer"})," off main. Note that most often, a library API breaking change will affect both modules simultaneously (example being bumping sdk version)."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Consumer repos have clear communication of what tagged versions are relevant to them. Consumer devs should know to never reference an ICS version that starts with ",(0,i.jsx)(n.code,{children:"provider"}),", even if it'd technically build."]}),"\n",(0,i.jsx)(n.li,{children:"Consumer and provider modules do not deviate as long as we continually release off a shared main branch. Backporting remains relatively unchanged besides being explicit about what module(s) your changes should affect."}),"\n",(0,i.jsx)(n.li,{children:"No code changes, just changes in process. Very simple."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"~~Slightly more complexity.~~Considerably more complex to manage the ICS library.\nThis is because ICS needs to support multiple versions of SDK (e.g., 0.45, 0.47, 0.50).\nIn addition, ICS needs to support a special fork of SDK (with LSM included) for the Cosmos Hub.\nThis means that instead of focusing on main the development team needs to manage multiple release\nbranches with different dependency trees."}),"\n",(0,i.jsx)(n.li,{children:"This solution does not allow having provider and consumer on separate versions of e.g. the Cosmos SDK."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801",children:"#801"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801#issuecomment-1683349298",children:"#801 comment"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>a,a:()=>t});var i=s(7294);const o={},r=i.createContext(o);function t(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:t(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/6382e28e.7f81451b.js b/assets/js/6382e28e.7f81451b.js
new file mode 100644
index 0000000000..51ad8dae5e
--- /dev/null
+++ b/assets/js/6382e28e.7f81451b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1660],{3501:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var t=n(5893),i=n(1151);const r={sidebar_position:4,title:"Offboarding Checklist"},s="Consumer Offboarding",a={id:"consumer-development/offboarding",title:"Offboarding Checklist",description:"To offboard a consumer chain simply submit a ConsumerRemovalProposal governance proposal listing a stop_time. After stop time passes, the provider chain will remove the chain from the ICS protocol (it will stop sending validator set updates).",source:"@site/versioned_docs/version-v4.2.0-docs/consumer-development/offboarding.md",sourceDirName:"consumer-development",slug:"/consumer-development/offboarding",permalink:"/interchain-security/v4.2.0/consumer-development/offboarding",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Offboarding Checklist"},sidebar:"tutorialSidebar",previous:{title:"Onboarding Checklist",permalink:"/interchain-security/v4.2.0/consumer-development/onboarding"},next:{title:"Changeover Procedure",permalink:"/interchain-security/v4.2.0/consumer-development/changeover-procedure"}},c={},d=[];function l(e){const o={code:"code",h1:"h1",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(o.h1,{id:"consumer-offboarding",children:"Consumer Offboarding"}),"\n",(0,t.jsxs)(o.p,{children:["To offboard a consumer chain simply submit a ",(0,t.jsx)(o.code,{children:"ConsumerRemovalProposal"})," governance proposal listing a ",(0,t.jsx)(o.code,{children:"stop_time"}),". After stop time passes, the provider chain will remove the chain from the ICS protocol (it will stop sending validator set updates)."]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-js",children:'// ConsumerRemovalProposal is a governance proposal on the provider chain to remove (and stop) a consumer chain.\n// If it passes, all the consumer chain\'s state is removed from the provider chain. The outstanding unbonding\n// operation funds are released.\n{\n // the title of the proposal\n "title": "This was a great chain",\n "description": "Here is a .md formatted string specifying removal details",\n // the chain-id of the consumer chain to be stopped\n "chain_id": "consumerchain-1",\n // the time on the provider chain at which all validators are responsible to stop their consumer chain validator node\n "stop_time": "2023-03-07T12:40:00.000000Z",\n}\n'})}),"\n",(0,t.jsx)(o.p,{children:"More information will be listed in a future version of this document."})]})}function p(e={}){const{wrapper:o}={...(0,i.a)(),...e.components};return o?(0,t.jsx)(o,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},1151:(e,o,n)=>{n.d(o,{Z:()=>a,a:()=>s});var t=n(7294);const i={},r=t.createContext(i);function s(e){const o=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(r.Provider,{value:o},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/68191a78.4b39d7fe.js b/assets/js/68191a78.4b39d7fe.js
new file mode 100644
index 0000000000..2a7e739619
--- /dev/null
+++ b/assets/js/68191a78.4b39d7fe.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4438],{266:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>d,toc:()=>c});var i=t(5893),s=t(1151);const r={sidebar_position:12,title:"Improving testing and increasing confidence"},o="ADR 011: Improving testing and increasing confidence",d={id:"adrs/adr-011-improving-test-confidence",title:"Improving testing and increasing confidence",description:"Changelog",source:"@site/docs/adrs/adr-011-improving-test-confidence.md",sourceDirName:"adrs",slug:"/adrs/adr-011-improving-test-confidence",permalink:"/interchain-security/adrs/adr-011-improving-test-confidence",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:12,frontMatter:{sidebar_position:12,title:"Improving testing and increasing confidence"},sidebar:"tutorialSidebar",previous:{title:"Standalone to Consumer Changeover",permalink:"/interchain-security/adrs/adr-010-standalone-changeover"},next:{title:"Separate Releasing",permalink:"/interchain-security/adrs/adr-012-separate-releasing"}},a={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Current state of testing",id:"current-state-of-testing",level:4},{value:"Unit testing",id:"unit-testing",level:3},{value:"Integration testing",id:"integration-testing",level:3},{value:"End-to-end testing",id:"end-to-end-testing",level:3},{value:"Decision",id:"decision",level:2},{value:"1. Connect specifications to code and tooling",id:"1-connect-specifications-to-code-and-tooling",level:3},{value:"Decision context and hypothesis",id:"decision-context-and-hypothesis",level:4},{value:"Main benefit",id:"main-benefit",level:4},{value:"2. Improve e2e tooling",id:"2-improve-e2e-tooling",level:3},{value:"Matrix tests",id:"matrix-tests",level:4},{value:"Introducing e2e regression testing",id:"introducing-e2e-regression-testing",level:4},{value:"Introducing e2e CometMock tests",id:"introducing-e2e-cometmock-tests",level:4},{value:"3. Introduce innovative testing approaches",id:"3-introduce-innovative-testing-approaches",level:3},{value:"Model",id:"model",level:4},{value:"Driver",id:"driver",level:4},{value:"Harness",id:"harness",level:4},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-011-improving-testing-and-increasing-confidence",children:"ADR 011: Improving testing and increasing confidence"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2023-08-11: Proposed, first draft of ADR."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Proposed"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.p,{children:"Testing, QA, and maintenance of interchain-security libraries is an ever-evolving area of software engineering we have to keep incrementally improving. The purpose of the QA process is to catch bugs as early as possible. In an ideal development workflow a bug should never reach production. A bug found in the specification stage is a lot cheaper to resolve than a bug discovered in production (or even in testnet). Ideally, all bugs should be found during the CI execution, and we hope that no bugs will ever even reach the testnet (although nothing can replace actual system stress test under load interacting with users)."}),"\n",(0,i.jsx)(n.p,{children:"During development and testnet operation the following types of bugs were the most commonly found:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"improper iterator usage"}),"\n",(0,i.jsx)(n.li,{children:"unbounded array access/iteration"}),"\n",(0,i.jsx)(n.li,{children:"improper input handling and validation"}),"\n",(0,i.jsx)(n.li,{children:"improper cached context usage"}),"\n",(0,i.jsx)(n.li,{children:"non-determinism check (improper use of maps in go, relying on random values)"}),"\n",(0,i.jsx)(n.li,{children:"KV store management and/or how keys are defined"}),"\n",(0,i.jsx)(n.li,{children:"deserialization issues arising from consumer/provider versioning mismatch"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Such bugs can be discovered earlier with better tooling. Some of these bugs can induce increases in block times, chain halts, state corruption, or introduce an attack surface which is difficult to remove if other systems have started depending on that behavior."}),"\n",(0,i.jsx)(n.h4,{id:"current-state-of-testing",children:"Current state of testing"}),"\n",(0,i.jsx)(n.p,{children:"Our testing suites consist of multiple parts, each with their own trade-offs and benefits with regards to code coverage, complexity and confidence they provide."}),"\n",(0,i.jsx)(n.h3,{id:"unit-testing",children:"Unit testing"}),"\n",(0,i.jsxs)(n.p,{children:["Unit testing is employed mostly for testing single-module functionality. It is the first step in testing and often the most practical. While highly important, unit tests often ",(0,i.jsx)(n.strong,{children:"test a single piece of code"})," and don't test relationships between different moving parts, this makes them less valuable when dealing with multi-module interactions."]}),"\n",(0,i.jsx)(n.p,{children:"Unit tests often employ mocks to abstract parts of the system that are not under test. Mocks are not equivalent to actual models and should not be treated as such."}),"\n",(0,i.jsx)(n.p,{children:"Out of all the approaches used, unit testing has the most tools available and the coverage can simply be displayed as % of code lines tested. Although this is a very nice and very easy to understand metric, it does not speak about the quality of the test coverage."}),"\n",(0,i.jsx)(n.p,{children:"Since distributed systems testing is a lot more involved, unit tests are oftentimes not sufficient to cover complex interactions. Unit tests are still necessary and helpful, but in cases where unit tests are not helpful e2e or integration tests should be favored."}),"\n",(0,i.jsx)(n.h3,{id:"integration-testing",children:"Integration testing"}),"\n",(0,i.jsxs)(n.p,{children:["With integration testing we ",(0,i.jsx)(n.strong,{children:"test the multi-module interactions"})," while isolating them from the remainder of the system.\nIntegration tests can uncover bugs that are often missed by unit tests."]}),"\n",(0,i.jsxs)(n.p,{children:["It is very difficult to gauge the actual test coverage imparted by integration tests and the available tooling is limited.\nIn interchain-security we employ the ",(0,i.jsx)(n.code,{children:"ibc-go/testing"})," framework to test interactions in-memory."]}),"\n",(0,i.jsx)(n.p,{children:"At present, integration testing does not involve the consensus layer - it is only concerned with application level state and logic."}),"\n",(0,i.jsx)(n.h3,{id:"end-to-end-testing",children:"End-to-end testing"}),"\n",(0,i.jsx)(n.p,{children:"In our context end-to-end testing comprises of tests that use the actual application binaries in an isolated environment (e.g. docker container). During test execution the inputs are meant to simulate actual user interaction, either by submitting transactions/queries using the command line or using gRPC/REST APIs and checking for state changes after an action has been performed. With this testing strategy we also include the consensus layer in all of our runs. This is the closest we can get to testing user interactions without starting a full testnet."}),"\n",(0,i.jsx)(n.p,{children:"End-to-end testing strategies vary between different teams and projects and we strive to unify our approach to the best of our ability (at least for ICS and gaia)."}),"\n",(0,i.jsx)(n.p,{children:"The available tooling does not give us significant (or relevant) line of code coverage information since most of the tools are geared towards analyzing unit tests and simple code branch evaluation."}),"\n",(0,i.jsx)(n.p,{children:"We aim to adapt our best practices by learning from other similar systems and projects such as cosmos-sdk, ibc-go and CometBFT."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.h3,{id:"1-connect-specifications-to-code-and-tooling",children:"1. Connect specifications to code and tooling"}),"\n",(0,i.jsx)(n.p,{children:"Oftentimes, specifications are disconnected from the development and QA processes. This gives rise to problems where the specification does not reflect the actual state of the system and vice-versa.\nUsually specifications are just text files that are rarely used and go unmaintained after a while, resulting in consistency issues and misleading instructions/expectations about system behavior."}),"\n",(0,i.jsx)(n.h4,{id:"decision-context-and-hypothesis",children:"Decision context and hypothesis"}),"\n",(0,i.jsx)(n.p,{children:"Specifications written in a dedicated and executable specification language are easier to maintain than the ones written entirely in text.\nAdditionally, we can create models based on the specification OR make the model equivalent to a specification."}),"\n",(0,i.jsxs)(n.p,{children:["Models do not care about the intricacies of implementation and neither do specifications. Since both models and specifications care about concisely and accurately describing a system (such as a finite state machine), we see a benefit of adding model based tools (such as ",(0,i.jsx)(n.a,{href:"https://github.com/informalsystems/quint",children:"quint"}),") to our testing and development workflows."]}),"\n",(0,i.jsx)(n.h4,{id:"main-benefit",children:"Main benefit"}),"\n",(0,i.jsx)(n.p,{children:"MBT tooling can be used to generate test traces that can be executed by multiple different testing setups."}),"\n",(0,i.jsx)(n.h3,{id:"2-improve-e2e-tooling",children:"2. Improve e2e tooling"}),"\n",(0,i.jsx)(n.h4,{id:"matrix-tests",children:"Matrix tests"}),"\n",(0,i.jsxs)(n.p,{children:["Instead of only running tests against current ",(0,i.jsx)(n.code,{children:"main"})," branch we should adopt an approach where we also:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"run regression tests against different released software versions"})," (",(0,i.jsx)(n.code,{children:"ICS v1 vs v2 vs v3"}),")"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.strong,{children:"run non-determinism tests to uncover issues quickly"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Matrix tests can be implemented using ",(0,i.jsx)(n.a,{href:"https://github.com/informalsystems/CometMock",children:"CometMock"})," and refactoring our current e2e CI setup."]}),"\n",(0,i.jsx)(n.h4,{id:"introducing-e2e-regression-testing",children:"Introducing e2e regression testing"}),"\n",(0,i.jsx)(n.p,{children:"This e2e test suite would execute using a cronjob in our CI (nightly, multiple times a day etc.)"}),"\n",(0,i.jsxs)(n.p,{children:["Briefly, the same set of traces is run against different ",(0,i.jsx)(n.strong,{children:"maintained"})," versions of the software and the ",(0,i.jsx)(n.code,{children:"main"})," branch.\nThis would allow us to discover potential issues during development instead of in a testnet scenarios."]}),"\n",(0,i.jsxs)(n.p,{children:["The most valuable issues that can be discovered in this way are ",(0,i.jsx)(n.strong,{children:"state breaking changes"}),", ",(0,i.jsx)(n.strong,{children:"regressions"})," and ",(0,i.jsx)(n.strong,{children:"version incompatibilities"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The setup is illustrated by the image below.\n",(0,i.jsx)(n.img,{alt:"e2e matrix tests",src:t(4839).Z+"",width:"2170",height:"1624"})]}),"\n",(0,i.jsx)(n.p,{children:"This table explains which versions are tested against each other for the same set of test traces:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\u2705 marks a passing test"}),"\n",(0,i.jsx)(n.li,{children:"\u274c marks a failing test"}),"\n"]}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"USES: ICS v1 PROVIDER"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"start chain"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"add key"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"delegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"undelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"redelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"downtime"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"equivocation"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"stop chain"})})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v1 consumer (sdk45,ibc4.3)"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v2 consumer (sdk45, ibc4.4)"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v3 consumer (sdk47, ibc7)"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"main consumer"})}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"neutron"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"stride"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"})]})]})]}),"\n",(0,i.jsx)(n.h4,{id:"introducing-e2e-cometmock-tests",children:"Introducing e2e CometMock tests"}),"\n",(0,i.jsxs)(n.p,{children:["CometMock is a mock implementation of the ",(0,i.jsx)(n.a,{href:"https://github.com/cometbft/cometbft",children:"CometBFT"})," consensus engine. It supports most operations performed by CometBFT while also being lightweight and relatively easy to use."]}),"\n",(0,i.jsxs)(n.p,{children:['CometMock tests allow more nuanced control of test scenarios because CometMock can "fool" the blockchain app into thinking that a certain number of blocks had passed.\n',(0,i.jsx)(n.strong,{children:"This allows us to test very nuanced scenarios, difficult edge cases and long-running operations (such as unbonding operations)."})]}),"\n",(0,i.jsx)(n.p,{children:"Examples of tests made easier with CometMock are listed below:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"regression tests"}),"\n",(0,i.jsx)(n.li,{children:"non-determinism tests"}),"\n",(0,i.jsx)(n.li,{children:"upgrade tests"}),"\n",(0,i.jsx)(n.li,{children:"state-breaking changes"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["With CometMock, the ",(0,i.jsx)(n.strong,{children:"matrix test"})," approach can also be used. The image below illustrates a CometMock setup that can be used to discover non-deterministic behavior and state-breaking changes.\n",(0,i.jsx)(n.img,{alt:"e2e matrix tests",src:t(9008).Z+"",width:"3714",height:"2082"})]}),"\n",(0,i.jsx)(n.p,{children:"This table explains which versions are tested against each other for the same set of test traces:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\u2705 marks a passing test"}),"\n",(0,i.jsx)(n.li,{children:"\u274c marks a failing test"}),"\n"]}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"SCENARIO"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"start chain"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"add key"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"delegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"undelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"redelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"downtime"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"equivocation"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"stop chain"})})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v3 provi + v3 consu"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"main provi + main consu"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"commit provi + commit consu"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"})]})]})]}),"\n",(0,i.jsxs)(n.p,{children:["Briefly; multiple versions of the application are run against the same CometMock instance and any deviations in app behavior would result in ",(0,i.jsx)(n.code,{children:"app hash"})," errors (the apps would be in different states after performing the same set of actions)."]}),"\n",(0,i.jsx)(n.h3,{id:"3-introduce-innovative-testing-approaches",children:"3. Introduce innovative testing approaches"}),"\n",(0,i.jsx)(n.p,{children:"When discussing e2e testing, some very important patterns emerge - especially if test traces are used instead of ad-hoc tests written by hand."}),"\n",(0,i.jsx)(n.p,{children:"We see a unique opportunity to clearly identify concerns and modularize the testing architecture."}),"\n",(0,i.jsxs)(n.p,{children:["The e2e testing frameworks can be split into a ",(0,i.jsx)(n.strong,{children:"pipeline consisting of 3 parts: model, driver and harness"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"model",children:"Model"}),"\n",(0,i.jsx)(n.p,{children:"Model is the part of the system that can emulate the behavior of the system under test.\nIdeally, it is very close to the specification and is written in a specification language such as quint, TLA+ or similar.\nOne of the purposes of the model is that it can be used to generate test traces."}),"\n",(0,i.jsx)(n.h4,{id:"driver",children:"Driver"}),"\n",(0,i.jsx)(n.p,{children:"The purpose of the driver is to accept test traces (generated by the model or written by hand), process them and provide inputs to the next part of the pipeline."}),"\n",(0,i.jsx)(n.p,{children:"Basically, the driver sits between the model and the actual infrastructure on which the test traces are being executed on."}),"\n",(0,i.jsx)(n.h4,{id:"harness",children:"Harness"}),"\n",(0,i.jsx)(n.p,{children:"Harness is the infrastructure layer of the pipeline that accepts inputs from the driver."}),"\n",(0,i.jsx)(n.p,{children:"There can be multiple harnesses as long as they can perform four things:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"bootstrap a test execution environment (local, docker, k8s\u2026)"}),"\n",(0,i.jsx)(n.li,{children:"accept inputs from drivers"}),"\n",(0,i.jsx)(n.li,{children:"perform the action specified by the driver"}),"\n",(0,i.jsx)(n.li,{children:"report results after performing actions"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.p,{children:"The procedure outlined in this ADR is not an all-or-nothing approach. Concepts introduced here do not rely on each other, so this ADR may only be applied partially without negative impact on test coverage and code confidence."}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"introduction of maintainable MBT solutions"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:'improvement over the current "difftest" setup that relies on an opinionated typescript model and go driver'}),"\n"]}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsx)(n.li,{children:"increased code coverage and confidence"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"using CometMock allows us to run more tests in less time"}),"\n",(0,i.jsx)(n.li,{children:"adding matrix e2e tests allows us to quickly pinpoint differences between code versions"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsx)(n.p,{children:"It might be easier to forgo the MBT tooling and instead focus on pure property based testing"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/667",children:"PBT proof of concept"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/flyingmutant/rapid",children:"property based testing in go"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:'The solutions are potentially expensive if we increase usage of the CI pipeline - this is fixed by running "expensive" tests using a cronjob, instead of running them on every commit.'}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsx)(n.p,{children:"The process of changing development and testing process is not something that can be thought of and delivered quickly. Luckily, the changes can be rolled out incrementally without impacting existing workflows."}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/gaia/issues/2427",children:"https://github.com/cosmos/gaia/issues/2427"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/gaia/issues/2420",children:"https://github.com/cosmos/gaia/issues/2420"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc-go/tree/main/e2e",children:"ibc-go e2e tests"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},9008:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/cometmock_matrix_test-714f36252aff9df4214823e3145d0ef5.png"},4839:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/matrix_e2e_tests-30681305077301daaf3097e1952b54bb.png"},1151:(e,n,t)=>{t.d(n,{Z:()=>d,a:()=>o});var i=t(7294);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/69416719.7aa395e3.js b/assets/js/69416719.7aa395e3.js
new file mode 100644
index 0000000000..6a21c9ff88
--- /dev/null
+++ b/assets/js/69416719.7aa395e3.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6873],{5911:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>s,metadata:()=>i,toc:()=>p});var a=n(5893),o=n(1151);const s={sidebar_position:5},r="Democracy modules",i={id:"features/democracy-modules",title:"Democracy modules",description:"This section is relevant for chains transitioning from a standalone chain and new consumer chains that require some functionality from the x/staking module.",source:"@site/docs/features/democracy-modules.md",sourceDirName:"features",slug:"/features/democracy-modules",permalink:"/interchain-security/features/democracy-modules",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"tutorialSidebar",previous:{title:"Consumer Initiated Slashing",permalink:"/interchain-security/features/slashing"},next:{title:"Partial Set Security",permalink:"/interchain-security/features/partial-set-security"}},c={},p=[{value:"Staking",id:"staking",level:2},{value:"Implications for consumer chains",id:"implications-for-consumer-chains",level:3},{value:"Governators (aka. Governors)",id:"governators-aka-governors",level:4},{value:"Tokenomics",id:"tokenomics",level:4},{value:"Integration",id:"integration",level:3},{value:"1. confirm that no modules are returning validator updates",id:"1-confirm-that-no-modules-are-returning-validator-updates",level:4},{value:"2. wire the module in app.go",id:"2-wire-the-module-in-appgo",level:4},{value:"Governance",id:"governance",level:2},{value:"Integration",id:"integration-1",level:3},{value:"Distribution",id:"distribution",level:2},{value:"How it works",id:"how-it-works",level:3},{value:"Integration",id:"integration-2",level:3}];function d(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h1,{id:"democracy-modules",children:"Democracy modules"}),"\n",(0,a.jsxs)(t.p,{children:["This section is relevant for chains transitioning from a standalone chain and new consumer chains that require some functionality from the ",(0,a.jsx)(t.code,{children:"x/staking"})," module."]}),"\n",(0,a.jsxs)(t.p,{children:["The democracy modules comprise ",(0,a.jsx)(t.code,{children:"x/staking"}),", ",(0,a.jsx)(t.code,{children:"x/distribution"})," and ",(0,a.jsx)(t.code,{children:"x/governance"})," with overrides and extensions required for normal operation when participating in interchain security."]}),"\n",(0,a.jsx)(t.p,{children:"The modules are plug-and-play and only require small wiring changes to be enabled."}),"\n",(0,a.jsxs)(t.p,{children:["For a full integration check the ",(0,a.jsx)(t.code,{children:"consumer-democracy"})," ",(0,a.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/app/consumer-democracy/app.go",children:"example app"}),"."]}),"\n",(0,a.jsx)(t.h2,{id:"staking",children:"Staking"}),"\n",(0,a.jsxs)(t.p,{children:["The democracy staking module allows the cosmos-sdk ",(0,a.jsx)(t.code,{children:"x/staking"})," module to be used alongside the interchain security ",(0,a.jsx)(t.code,{children:"consumer"})," module."]}),"\n",(0,a.jsxs)(t.p,{children:["The module uses overrides that allow the full ",(0,a.jsx)(t.code,{children:"x/staking"})," functionality with one notable difference - the staking module will no longer be used to provide the consensus validator set."]}),"\n",(0,a.jsx)(t.h3,{id:"implications-for-consumer-chains",children:"Implications for consumer chains"}),"\n",(0,a.jsxs)(t.p,{children:["The ",(0,a.jsx)(t.code,{children:"x/ccv/democracy/staking"})," allows consumer chains to separate governance from block production."]}),"\n",(0,a.jsx)(t.admonition,{type:"info",children:(0,a.jsx)(t.p,{children:"The validator set coming from the provider chain does not need to participate in governance - they only provide infrastructure (create blocks and maintain consensus)."})}),"\n",(0,a.jsx)(t.h4,{id:"governators-aka-governors",children:"Governators (aka. Governors)"}),"\n",(0,a.jsxs)(t.p,{children:["Validators registered with the ",(0,a.jsx)(t.code,{children:"x/staking"}),' module become "Governators".']}),"\n",(0,a.jsx)(t.p,{children:"Unlike Validators, Governators are not required to run any chain infastructure since they are not signing any blocks."}),"\n",(0,a.jsx)(t.p,{children:"However, Governators retain a subset of the validator properties:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["new Governators can be created (via ",(0,a.jsx)(t.code,{children:"MsgCreateValidator"}),")"]}),"\n",(0,a.jsx)(t.li,{children:"Governators can accept delegations"}),"\n",(0,a.jsx)(t.li,{children:"Governators can vote on governance proposals (with their self stake and delegations)"}),"\n",(0,a.jsx)(t.li,{children:"Governators earn token rewards"}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"With these changes, Governators can become community advocates that can specialize in chain governance and they get rewarded for their participation the same way the validators do."}),"\n",(0,a.jsx)(t.p,{children:"Additionally, Governators can choose to provide additional infrastructure such as RPC/API access points, archive nodes, indexers and similar software."}),"\n",(0,a.jsx)(t.h4,{id:"tokenomics",children:"Tokenomics"}),"\n",(0,a.jsx)(t.p,{children:"The consumer chain's token will remain a governance and reward token. The token's parameters (inflation, max supply, burn rate) are not affected."}),"\n",(0,a.jsx)(t.admonition,{type:"info",children:(0,a.jsx)(t.p,{children:"Staking rewards are distributed to all Governators and their delegators after distributing the rewards to the provider chain's validator set."})}),"\n",(0,a.jsx)(t.h3,{id:"integration",children:"Integration"}),"\n",(0,a.jsxs)(t.p,{children:["The ",(0,a.jsx)(t.code,{children:"x/ccv/democracy/staking"})," module provides these ",(0,a.jsx)(t.code,{children:"x/staking"})," overrides:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-golang",children:"\n// InitGenesis delegates the InitGenesis call to the underlying x/staking module,\n// however, it returns no validator updates as validators are tracked via the\n// consumer chain's x/cvv/consumer module and so this module is not responsible for returning the initial validator set.\nfunc (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {\n\tvar genesisState types.GenesisState\n\n\tcdc.MustUnmarshalJSON(data, &genesisState)\n\t_ = am.keeper.InitGenesis(ctx, &genesisState) // run staking InitGenesis\n\n\treturn []abci.ValidatorUpdate{} // do not return validator updates\n}\n\n// EndBlock delegates the EndBlock call to the underlying x/staking module.\n// However, no validator updates are returned as validators are tracked via the\n// consumer chain's x/cvv/consumer module.\nfunc (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {\n\t_ = am.keeper.BlockValidatorUpdates(ctx) // perform staking BlockValidatorUpdates\n\treturn []abci.ValidatorUpdate{} // do not return validator updates\n}\n"})}),"\n",(0,a.jsxs)(t.p,{children:["To integrate the ",(0,a.jsx)(t.code,{children:"democracy/staking"})," follow this guide:"]}),"\n",(0,a.jsx)(t.h4,{id:"1-confirm-that-no-modules-are-returning-validator-updates",children:"1. confirm that no modules are returning validator updates"}),"\n",(0,a.jsx)(t.admonition,{type:"tip",children:(0,a.jsxs)(t.p,{children:["Only the ",(0,a.jsx)(t.code,{children:"x/ccv/consumer"})," module should be returning validator updates."]})}),"\n",(0,a.jsx)(t.p,{children:"If some of your modules are returning validator updates please disable them while maintaining your business logic:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-diff",children:"func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {\n\tvar genesisState types.GenesisState\n\n\tcdc.MustUnmarshalJSON(data, &genesisState)\n-\treturn am.keeper.InitGenesis(ctx, &genesisState)\n+ \t_ = am.keeper.InitGenesis(ctx, &genesisState) // run InitGenesis but drop the result\n+\treturn []abci.ValidatorUpdate{} // return empty validator updates\n}\n\n\nfunc (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {\n-\treturn am.keeper.BlockValidatorUpdates(ctx)\n+ \t_ = am.keeper.BlockValidatorUpdates(ctx) // perform staking BlockValidatorUpdates\n+\treturn []abci.ValidatorUpdate{} // return empty validator updates\n}\n"})}),"\n",(0,a.jsx)(t.h4,{id:"2-wire-the-module-in-appgo",children:"2. wire the module in app.go"}),"\n",(0,a.jsxs)(t.p,{children:["You ",(0,a.jsx)(t.strong,{children:"do not need to remove"})," the cosmos-sdk ",(0,a.jsx)(t.code,{children:"StakingKeeper"})," from your wiring."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-diff",children:'import (\n ...\n+ ccvstaking "github.com/cosmos/interchain-security/v4/x/ccv/democracy/staking"\n)\n\nvar (\n // replace the staking.AppModuleBasic\n\tModuleBasics = module.NewBasicManager(\n\t\tauth.AppModuleBasic{},\n\t\tgenutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),\n\t\tbank.AppModuleBasic{},\n\t\tcapability.AppModuleBasic{},\n-\t\tsdkstaking.AppModuleBasic{},\n+\t\tccvstaking.AppModuleBasic{}, // replace sdkstaking\n ...\n )\n)\n\n\nfunc NewApp(...) {\n ...\n\n\t// use sdk StakingKeepeer\n\tapp.StakingKeeper = stakingkeeper.NewKeeper(\n\t\tappCodec,\n\t\tkeys[stakingtypes.StoreKey],\n\t\tapp.AccountKeeper,\n\t\tapp.BankKeeper,\n\t\tauthtypes.NewModuleAddress(govtypes.ModuleName).String(),\n\t)\n\n\tapp.MintKeeper = mintkeeper.NewKeeper(\n\t\tappCodec,\n\t\tkeys[minttypes.StoreKey],\n\t\tapp.StakingKeeper,\n\t\tapp.AccountKeeper,\n\t\tapp.BankKeeper,\n\t\tauthtypes.FeeCollectorName,\n\t\tauthtypes.NewModuleAddress(govtypes.ModuleName).String(),\n\t)\n\n\t// no changes required for the distribution keeper\n app.DistrKeeper = distrkeeper.NewKeeper(\n\t\tappCodec,\n\t\tkeys[distrtypes.StoreKey],\n\t\tapp.AccountKeeper,\n\t\tapp.BankKeeper,\n\t\tapp.StakingKeeper, // keep StakingKeeper!\n\t\tauthtypes.FeeCollectorName,\n\t\tauthtypes.NewModuleAddress(govtypes.ModuleName).String(),\n\t)\n\n+ // pre-initialize ConsumerKeeper to satsfy ibckeeper.NewKeeper\n+\tapp.ConsumerKeeper = consumerkeeper.NewNonZeroKeeper(\n+\t\tappCodec,\n+\t\tkeys[consumertypes.StoreKey],\n+\t\tapp.GetSubspace(consumertypes.ModuleName),\n+\t)\n+\n+\tapp.IBCKeeper = ibckeeper.NewKeeper(\n+\t\tappCodec,\n+\t\tkeys[ibchost.StoreKey],\n+\t\tapp.GetSubspace(ibchost.ModuleName),\n+\t\t&app.ConsumerKeeper,\n+\t\tapp.UpgradeKeeper,\n+\t\tscopedIBCKeeper,\n+\t)\n+\n+\t// Create CCV consumer and modules\n+\tapp.ConsumerKeeper = consumerkeeper.NewKeeper(\n+\t\tappCodec,\n+\t\tkeys[consumertypes.StoreKey],\n+\t\tapp.GetSubspace(consumertypes.ModuleName),\n+\t\tscopedIBCConsumerKeeper,\n+\t\tapp.IBCKeeper.ChannelKeeper,\n+\t\t&app.IBCKeeper.PortKeeper,\n+\t\tapp.IBCKeeper.ConnectionKeeper,\n+\t\tapp.IBCKeeper.ClientKeeper,\n+\t\tapp.SlashingKeeper,\n+\t\tapp.BankKeeper,\n+\t\tapp.AccountKeeper,\n+\t\t&app.TransferKeeper,\n+\t\tapp.IBCKeeper,\n+\t\tauthtypes.FeeCollectorName,\n+\t)\n+\n+\t// Setting the standalone staking keeper is only needed for standalone to consumer changeover chains\n+ \t// New chains using the democracy/staking do not need to set this\n+\tapp.ConsumerKeeper.SetStandaloneStakingKeeper(app.StakingKeeper)\n\n\n\n\t// change the slashing keeper dependency\n\tapp.SlashingKeeper = slashingkeeper.NewKeeper(\n\t\tappCodec,\n\t\tlegacyAmino,\n\t\tkeys[slashingtypes.StoreKey],\n-\t\tapp.StakingKeeper,\n+\t\t&app.ConsumerKeeper, // ConsumerKeeper implements StakingKeeper interface\n\t\tauthtypes.NewModuleAddress(govtypes.ModuleName).String(),\n\t)\n\n\t// register slashing module StakingHooks to the consumer keeper\n+\tapp.ConsumerKeeper = *app.ConsumerKeeper.SetHooks(app.SlashingKeeper.Hooks())\n+\tconsumerModule := consumer.NewAppModule(app.ConsumerKeeper, app.GetSubspace(consumertypes.ModuleName))\n\n\t // register the module with module manager\n // replace the x/staking module\n\tapp.MM = module.NewManager(\n\t\t...\n-\t\tsdkstaking.NewAppModule(appCodec, &app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)),\n+\t\tccvstaking.NewAppModule(appCodec, *app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)),\n\t\t...\n\t)\n}\n'})}),"\n",(0,a.jsx)(t.h2,{id:"governance",children:"Governance"}),"\n",(0,a.jsxs)(t.p,{children:["The ",(0,a.jsx)(t.code,{children:"x/ccv/democracy/governance"})," module extends the ",(0,a.jsx)(t.code,{children:"x/governance"})," module with the functionality to filter proposals."]}),"\n",(0,a.jsx)(t.admonition,{type:"tip",children:(0,a.jsx)(t.p,{children:"Consumer chains can limit in the types of governance proposals that can be executed on chain to avoid inadvertent changes to interchain security protocol that could affect security properties."})}),"\n",(0,a.jsxs)(t.p,{children:["The module uses ",(0,a.jsx)(t.code,{children:"AnteHandler"})," to limit the types of proposals that can be executed."]}),"\n",(0,a.jsx)(t.h3,{id:"integration-1",children:"Integration"}),"\n",(0,a.jsxs)(t.p,{children:["Add new ",(0,a.jsx)(t.code,{children:"AnteHandler"})," to your ",(0,a.jsx)(t.code,{children:"app"}),"."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-go",children:'\n// app/ante/forbidden_proposals.go\npackage ante\n\nimport (\n\t"fmt"\n\n\tsdk "github.com/cosmos/cosmos-sdk/types"\n\tgovv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"\n\tgovv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"\n\tibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"\n\n\t"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"\n\t"github.com/cosmos/cosmos-sdk/x/params/types/proposal"\n)\n\ntype ForbiddenProposalsDecorator struct {\n\tisLegacyProposalWhitelisted func(govv1beta1.Content) bool\n\tisModuleWhiteList func(string) bool\n}\n\nfunc NewForbiddenProposalsDecorator(\n\twhiteListFn func(govv1beta1.Content) bool,\n\tisModuleWhiteList func(string) bool,\n) ForbiddenProposalsDecorator {\n\treturn ForbiddenProposalsDecorator{\n\t\tisLegacyProposalWhitelisted: whiteListFn,\n\t\tisModuleWhiteList: isModuleWhiteList,\n\t}\n}\n\nfunc (decorator ForbiddenProposalsDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {\n\tcurrHeight := ctx.BlockHeight()\n\n\tfor _, msg := range tx.GetMsgs() {\n\t\t// if the message is MsgSubmitProposal, check if proposal is whitelisted\n\t\tsubmitProposalMgs, ok := msg.(*govv1.MsgSubmitProposal)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\n\t\tmessages := submitProposalMgs.GetMessages()\n\t\tfor _, message := range messages {\n\t\t\tif sdkMsg, isLegacyProposal := message.GetCachedValue().(*govv1.MsgExecLegacyContent); isLegacyProposal {\n\t\t\t\t// legacy gov proposal content\n\t\t\t\tcontent, err := govv1.LegacyContentFromMessage(sdkMsg)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn ctx, fmt.Errorf("tx contains invalid LegacyContent")\n\t\t\t\t}\n\t\t\t\tif !decorator.isLegacyProposalWhitelisted(content) {\n\t\t\t\t\treturn ctx, fmt.Errorf("tx contains unsupported proposal message types at height %d", currHeight)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// not legacy gov proposal content and not whitelisted\n\t\t\tif !decorator.isModuleWhiteList(message.TypeUrl) {\n\t\t\t\treturn ctx, fmt.Errorf("tx contains unsupported proposal message types at height %d", currHeight)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn next(ctx, tx, simulate)\n}\n\nfunc IsProposalWhitelisted(content v1beta1.Content) bool {\n\tswitch c := content.(type) {\n\tcase *proposal.ParameterChangeProposal:\n\t\treturn isLegacyParamChangeWhitelisted(c.Changes)\n\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc isLegacyParamChangeWhitelisted(paramChanges []proposal.ParamChange) bool {\n\tfor _, paramChange := range paramChanges {\n\t\t_, found := LegacyWhitelistedParams[legacyParamChangeKey{Subspace: paramChange.Subspace, Key: paramChange.Key}]\n\t\tif !found {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\ntype legacyParamChangeKey struct {\n\tSubspace, Key string\n}\n\n// Legacy params can be whitelisted\nvar LegacyWhitelistedParams = map[legacyParamChangeKey]struct{}{\n\t{Subspace: ibctransfertypes.ModuleName, Key: "SendEnabled"}: {},\n\t{Subspace: ibctransfertypes.ModuleName, Key: "ReceiveEnabled"}: {},\n}\n\n// New proposal types can be whitelisted\nvar WhiteListModule = map[string]struct{}{\n\t"/cosmos.gov.v1.MsgUpdateParams": {},\n\t"/cosmos.bank.v1beta1.MsgUpdateParams": {},\n\t"/cosmos.staking.v1beta1.MsgUpdateParams": {},\n\t"/cosmos.distribution.v1beta1.MsgUpdateParams": {},\n\t"/cosmos.mint.v1beta1.MsgUpdateParams": {},\n}\n\nfunc IsModuleWhiteList(typeUrl string) bool {\n\t_, found := WhiteListModule[typeUrl]\n\treturn found\n}\n'})}),"\n",(0,a.jsxs)(t.p,{children:["Add the ",(0,a.jsx)(t.code,{children:"AnteHandler"})," to the list of supported antehandlers:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-diff",children:'// app/ante_handler.go\npackage app\n\nimport (\n\t...\n\n+\tdemocracyante "github.com/cosmos/interchain-security/v4/app/consumer-democracy/ante"\n+\tconsumerante "github.com/cosmos/interchain-security/v4/app/consumer/ante"\n+\ticsconsumerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/consumer/keeper"\n)\n\ntype HandlerOptions struct {\n\tante.HandlerOptions\n\n\tIBCKeeper *ibckeeper.Keeper\n+\tConsumerKeeper ibcconsumerkeeper.Keeper\n}\n\nfunc NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {\n\t....\n\n\tanteDecorators := []sdk.AnteDecorator{\n ...\n+\t\tconsumerante.NewMsgFilterDecorator(options.ConsumerKeeper),\n+\t\tconsumerante.NewDisabledModulesDecorator("/cosmos.evidence", "/cosmos.slashing"),\n+\t\tdemocracyante.NewForbiddenProposalsDecorator(IsProposalWhitelisted, IsModuleWhiteList),\n\t\t...\n\t}\n\n\treturn sdk.ChainAnteDecorators(anteDecorators...), nil\n}\n'})}),"\n",(0,a.jsxs)(t.p,{children:["Wire the module in ",(0,a.jsx)(t.code,{children:"app.go"}),"."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-diff",children:'// app/app.go\npackage app\nimport (\n ...\n sdkgov "github.com/cosmos/cosmos-sdk/x/gov"\n\tgovkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"\n\tgovtypes "github.com/cosmos/cosmos-sdk/x/gov/types"\n\tgovv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"\n\n+\tccvgov "github.com/cosmos/interchain-security/v4/x/ccv/democracy/governance"\n)\n\nvar (\n\n // use sdk governance module\n\tModuleBasics = module.NewBasicManager(\n\t\t...\n\t\tsdkgov.NewAppModuleBasic(\n\t\t\t[]govclient.ProposalHandler{\n\t\t\t\tparamsclient.ProposalHandler,\n\t\t\t\tupgradeclient.LegacyProposalHandler,\n\t\t\t\tupgradeclient.LegacyCancelProposalHandler,\n\t\t\t},\n\t\t),\n )\n)\n\nfunc NewApp(...) {\n // retain sdk gov router and keeper registrations\n\tsdkgovRouter := govv1beta1.NewRouter()\n\tsdkgovRouter.\n\t\tAddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).\n\t\tAddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).\n\t\tAddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(&app.UpgradeKeeper))\n\tgovConfig := govtypes.DefaultConfig()\n\n\tapp.GovKeeper = *govkeeper.NewKeeper(\n\t\tappCodec,\n\t\tkeys[govtypes.StoreKey],\n\t\tapp.AccountKeeper,\n\t\tapp.BankKeeper,\n\t\tapp.StakingKeeper,\n\t\tapp.MsgServiceRouter(),\n\t\tgovConfig,\n\t\tauthtypes.NewModuleAddress(govtypes.ModuleName).String(),\n\t)\n\n\tapp.GovKeeper.SetLegacyRouter(sdkgovRouter)\n\n\n // register the module with module manager\n // replace the x/gov module\n\tapp.MM = module.NewManager(\n-\t\tsdkgov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper, IsProposalWhitelisted, app.GetSubspace(govtypes.ModuleName), IsModuleWhiteList),\n+\t\tccvgov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper, IsProposalWhitelisted, app.GetSubspace(govtypes.ModuleName), IsModuleWhiteList),\n\t\t...\n )\n}\n'})}),"\n",(0,a.jsx)(t.h2,{id:"distribution",children:"Distribution"}),"\n",(0,a.jsx)(t.admonition,{type:"tip",children:(0,a.jsxs)(t.p,{children:["The ",(0,a.jsx)(t.code,{children:"democracy/distribution"})," module allows the consumer chain to send rewards to the provider chain while retaining the ",(0,a.jsx)(t.code,{children:"x/distribution"})," module for internal reward distribution to Governators and stakers."]})}),"\n",(0,a.jsx)(t.h3,{id:"how-it-works",children:"How it works"}),"\n",(0,a.jsx)(t.p,{children:"First, a % of rewards to be distributed to the provider chain's validator set is calculated and sent to the provider chain. Only opted-in validators from the provider chain will receive the consumer rewards."}),"\n",(0,a.jsx)(t.p,{children:"Second, the remaining rewards get distributed to the consumer chain's Governators and their delegators."}),"\n",(0,a.jsxs)(t.admonition,{type:"info",children:[(0,a.jsxs)(t.p,{children:["The % that is sent to the provider chain corresponds to ",(0,a.jsx)(t.code,{children:"1 - ConsumerRedistributionFraction"}),"."]}),(0,a.jsxs)(t.p,{children:["e.g. ",(0,a.jsx)(t.code,{children:'ConsumerRedistributionFraction = "0.75"'})]}),(0,a.jsx)(t.p,{children:"means that the consumer chain retains 75% of the rewards, while 25% gets sent to the provider chain to be distributed as rewards to provider chain validators."})]}),"\n",(0,a.jsx)(t.h3,{id:"integration-2",children:"Integration"}),"\n",(0,a.jsxs)(t.p,{children:["Change the wiring in ",(0,a.jsx)(t.code,{children:"app.go"})]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-diff",children:'import (\n ...\n distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"\n\tdistrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"\n sdkdistr "github.com/cosmos/cosmos-sdk/x/distribution"\n\n+ ccvdistr "github.com/cosmos/interchain-security/v4/x/ccv/democracy/distribution"\n)\n\nvar (\n // replace sdk distribution AppModuleBasic\n\tModuleBasics = module.NewBasicManager(\n\t\tauth.AppModuleBasic{},\n\t\tgenutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),\n\t\tbank.AppModuleBasic{},\n\t\tcapability.AppModuleBasic{},\n\t\tccvstaking.AppModuleBasic{}, // make sure you first swap the staking keeper\n\t\tmint.AppModuleBasic{},\n-\t\tsdkdistr.AppModuleBasic{},\n+\t\tccvdistr.AppModuleBasic{},\n )\n)\n\nfunc NewApp(...) {\n ....\n\n\tapp.DistrKeeper = distrkeeper.NewKeeper(\n\t\tappCodec,\n\t\tkeys[distrtypes.StoreKey],\n\t\tapp.AccountKeeper,\n\t\tapp.BankKeeper,\n\t\tapp.StakingKeeper, // connect to sdk StakingKeeper\n\t\tconsumertypes.ConsumerRedistributeName,\n\t\tauthtypes.NewModuleAddress(govtypes.ModuleName).String(),\n\t)\n\n // register with the module manager\n\tapp.MM = module.NewManager(\n\t\t...\n-\t\tsdkdistr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, *app.StakingKeeper, authtypes.FeeCollectorName, app.GetSubspace(distrtypes.ModuleName)),\n\n+\t\tccvdistr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, *app.StakingKeeper, authtypes.FeeCollectorName, app.GetSubspace(distrtypes.ModuleName)),\n\t\tccvstaking.NewAppModule(appCodec, *app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)),\n\t\t...\n )\n}\n'})})]})}function l(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>i,a:()=>r});var a=n(7294);const o={},s=a.createContext(o);function r(e){const t=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),a.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/6b52739c.dc8af5b8.js b/assets/js/6b52739c.dc8af5b8.js
new file mode 100644
index 0000000000..7b24fe16bf
--- /dev/null
+++ b/assets/js/6b52739c.dc8af5b8.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9419],{6319:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>l,frontMatter:()=>s,metadata:()=>r,toc:()=>d});var n=o(5893),i=o(1151);const s={sidebar_position:16,title:"Partial Set Security"},a="ADR 015: Partial Set Security",r={id:"adrs/adr-015-partial-set-security",title:"Partial Set Security",description:"Changelog",source:"@site/docs/adrs/adr-015-partial-set-security.md",sourceDirName:"adrs",slug:"/adrs/adr-015-partial-set-security",permalink:"/interchain-security/adrs/adr-015-partial-set-security",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:16,frontMatter:{sidebar_position:16,title:"Partial Set Security"},sidebar:"tutorialSidebar",previous:{title:"Epochs",permalink:"/interchain-security/adrs/adr-014-epochs"},next:{title:"Security aggregation",permalink:"/interchain-security/adrs/adr-016-securityaggregation"}},c={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"How do consumer chains join?",id:"how-do-consumer-chains-join",level:3},{value:"State & Query",id:"state--query",level:4},{value:"How do validators opt in?",id:"how-do-validators-opt-in",level:3},{value:"State & Query",id:"state--query-1",level:4},{value:"When do validators opt in?",id:"when-do-validators-opt-in",level:4},{value:"How do validators opt out?",id:"how-do-validators-opt-out",level:3},{value:"State & Query",id:"state--query-2",level:4},{value:"When does a consumer chain start?",id:"when-does-a-consumer-chain-start",level:3},{value:"How do we send the partial validator sets to the consumer chains?",id:"how-do-we-send-the-partial-validator-sets-to-the-consumer-chains",level:3},{value:"How do we distribute rewards?",id:"how-do-we-distribute-rewards",level:3},{value:"Misbehaviour",id:"misbehaviour",level:3},{value:"Fraud votes",id:"fraud-votes",level:4},{value:"Double signing",id:"double-signing",level:4},{value:"Downtime",id:"downtime",level:4},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function h(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"adr-015-partial-set-security",children:"ADR 015: Partial Set Security"}),"\n",(0,n.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"2024-01-22: Proposed, first draft of ADR."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,n.jsx)(t.p,{children:"Accepted"}),"\n",(0,n.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,n.jsxs)(t.p,{children:["Currently, in ",(0,n.jsx)(t.em,{children:"Replicated Security"}),", the entire validator set of the provider chain is used to secure consumer chains. There are at least three concerns with this approach.\nFirst, a large number of validators might be forced to validate consumer chains they are not interested in securing.\nSecond, it is costly for small validators to secure additional chains. This concern is only partially addressed through ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-009-soft-opt-out.md",children:"soft opt-out"})," that allows small validators to opt out from validating consumer chains.\nThird and for the above reasons, it is challenging for a new consumer chain to join Replicated Security."]}),"\n",(0,n.jsxs)(t.p,{children:["As a solution, we present ",(0,n.jsx)(t.em,{children:"Partial Set Security"})," (PSS). As the name suggests, PSS allows for every consumer chain to be secured by only a subset of the provider validator set.\nIn what follows we propose the exact steps we need to take to implement PSS. This is a first iteration of PSS, and therefore we present the most minimal solution that make PSS possible."]}),"\n",(0,n.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,n.jsxs)(t.p,{children:["In Replicated Security, all the provider validators have to secure every consumer chain (with the exception of those validators allowed to opt out through the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-009-soft-opt-out.md",children:"soft opt-out"})," feature)."]}),"\n",(0,n.jsxs)(t.p,{children:["In PSS, we allow validators to opt in and out of validating any given consumer chain.\nThis has one exception: we introduce a parameter ",(0,n.jsx)(t.code,{children:"N"})," for each consumer chain and require that the validators in top ",(0,n.jsx)(t.code,{children:"N%"})," of the provider's voting power have to secure the consumer chain.\nValidators outside of the top ",(0,n.jsx)(t.code,{children:"N%"})," can dynamically opt in if they want to validate on the consumer chain."]}),"\n",(0,n.jsxs)(t.p,{children:["For example, if a consumer chain has ",(0,n.jsx)(t.code,{children:"N = 95%"}),", then it ultimately receives the same security it receives today with Replicated Security (with a default ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-009-soft-opt-out.md",children:"SoftOptOutThreshold"})," of 5%).\nOn the other hand, if a consumer chain has ",(0,n.jsx)(t.code,{children:"N = 0%"}),", then no validator is forced to validate the chain, but validators can opt in to do so instead."]}),"\n",(0,n.jsxs)(t.p,{children:["For the remainder of this ADR, we call a consumer chain ",(0,n.jsx)(t.em,{children:"Top N"})," if it has joined as a Top N chain with ",(0,n.jsx)(t.code,{children:"N > 0"})," and ",(0,n.jsx)(t.em,{children:"Opt In"})," chain otherwise. An Opt In consumer chain is secured only by the validators that have opted in to secure that chain."]}),"\n",(0,n.jsxs)(t.p,{children:["We intend to implement PSS using a feature branch off ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/tree/v4.0.0",children:"v4.0.0 interchain security"}),"."]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-consumer-chains-join",children:"How do consumer chains join?"}),"\n",(0,n.jsxs)(t.p,{children:["As a simplification and to avoid ",(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/pss-permissionless-vs-premissioned-lite-opt-in-consumer-chains/12984/17",children:"chain id squatting"}),", a consumer chain can only join PSS through a governance proposal and not in a permissionless way."]}),"\n",(0,n.jsx)(t.p,{children:'However, this proposal type will be modified so that it requires a lower quorum percentage than normal proposal, and every validator who voted "YES" on the proposal will form the consumer chain\'s initial validator set.'}),"\n",(0,n.jsxs)(t.p,{children:["Consumer chains join PSS the same way chains now join Replicated Security, namely through a ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})," proposal.\nWe extend ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/proto/interchain_security/ccv/provider/v1/provider.proto#L27",children:(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})})," with one optional field:"]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.code,{children:"uint32 top_N"}),": Corresponds to the percentage of validators that join under the Top N case.\nFor example, ",(0,n.jsx)(t.code,{children:"53"})," corresponds to a Top 53% chain, meaning that the top ",(0,n.jsx)(t.code,{children:"53%"})," provider validators have to validate the proposed consumer chain.\n",(0,n.jsx)(t.code,{children:"top_N"})," can be ",(0,n.jsx)(t.code,{children:"0"})," or include any value in ",(0,n.jsx)(t.code,{children:"[50, 100]"}),". A chain can join with ",(0,n.jsx)(t.code,{children:"top_N == 0"})," as an Opt In, or with ",(0,n.jsx)(t.code,{children:"top_N \u2208 [50, 100]"})," as a Top N chain."]}),"\n",(0,n.jsxs)(t.p,{children:["In case of a Top N chain, we restrict the possible values of ",(0,n.jsx)(t.code,{children:"top_N"})," from ",(0,n.jsx)(t.code,{children:"(0, 100]"})," to ",(0,n.jsx)(t.code,{children:"[50, 100]"}),".\nBy having ",(0,n.jsx)(t.code,{children:"top_N >= 50"})," we can guarantee that we cannot have a successful attack, assuming that at most ",(0,n.jsx)(t.code,{children:"1/3"})," of provider validators can be malicious.\nThis is because, a Top N chain with ",(0,n.jsx)(t.code,{children:"N >= 50%"})," would have at least ",(0,n.jsx)(t.code,{children:"1/3"})," honest validators, which is sufficient to stop attacks.\nAdditionally, by having ",(0,n.jsx)(t.code,{children:"N >= 50%"})," (and hence ",(0,n.jsx)(t.code,{children:"N > (VetoThreshold = 33.4%)"}),") we enable the top N validators to ",(0,n.jsx)(t.code,{children:"Veto"})," any ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})," for consumer chains they do not want to validate."]}),"\n",(0,n.jsxs)(t.p,{children:["If a proposal has the ",(0,n.jsx)(t.code,{children:"top_N"})," argument wrongly set, it should get rejected in [ValidateBasic] (",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/proposal.go#L86",children:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/proposal.go#L86"}),")."]}),"\n",(0,n.jsxs)(t.p,{children:["In the code, we distinguish whether a chain is ",(0,n.jsx)(t.em,{children:"Top N"})," or ",(0,n.jsx)(t.em,{children:"Opt In"})," by checking whether ",(0,n.jsx)(t.code,{children:"top_N"})," is zero or not."]}),"\n",(0,n.jsxs)(t.p,{children:["In a future version of PSS, we intend to introduce a ",(0,n.jsx)(t.code,{children:"ConsumerModificationProposal"})," so that we can modify the parameters of a consumer chain, e.g, a chain that is ",(0,n.jsx)(t.em,{children:"Opt In"})," to become ",(0,n.jsx)(t.em,{children:"Top N"}),", etc."]}),"\n",(0,n.jsx)(t.h4,{id:"state--query",children:"State & Query"}),"\n",(0,n.jsxs)(t.p,{children:["We augment the provider module\u2019s state to keep track of the ",(0,n.jsx)(t.code,{children:"top_N"})," value for each consumer chain. The key to store this information would be:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"topNBytePrefix | len(chainID) | chainID\n"})}),"\n",(0,n.jsxs)(t.p,{children:["To create the above key, we can use ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/keys.go#L418",children:(0,n.jsx)(t.code,{children:"ChainIdWithLenKey"})}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["Then in the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/keeper.go",children:"keeper"})," we introduce methods as follows:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-golang",children:"func (k Keeper) SetTopN(ctx sdk.Context, chainID string, topN uint32)\nfunc (k Keeper) IsTopN(ctx sdk.Context, chainID string) bool\nfunc (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool\n\n// returns the N if Top N chain, otherwise an error\nfunc (k Keeper) GetTopN(ctx sdk.Context, chainID string) (uint32, error)\n"})}),"\n",(0,n.jsxs)(t.p,{children:["We also extend the ",(0,n.jsx)(t.code,{children:"interchain-security-pd query provider list-consumer-chains"}),' query to return information on whether a consumer chain is an Opt In or a Top N chain and with what N.\nThis way, block explorers can present informative messages such as "This chain is secured by N% of the provider chain" for consumer chains.']}),"\n",(0,n.jsx)(t.h3,{id:"how-do-validators-opt-in",children:"How do validators opt in?"}),"\n",(0,n.jsxs)(t.p,{children:["A validator can opt in by sending a new type of message that we introduce in ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/proto/interchain_security/ccv/provider/v1/tx.proto#L1",children:"tx.proto"}),"."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-protobuf",children:"message MsgOptIn {\n // the chain id of the consumer chain to opt in to\n string chainID = 1;\n // the provider address of the validator\n string providerAddr = 2;\n // (optional) the consensus public key to use on the consumer\n optional string consumerKey = 3;\n}\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Note that in a Top N consumer chain, the top ",(0,n.jsx)(t.code,{children:"N%"})," provider validators have to validate the consumer chain.\nNevertheless, validators in the bottom ",(0,n.jsx)(t.code,{children:"(100 - N)%"})," can opt in to validate as well.\nProvider validators that belong or enter the top ",(0,n.jsx)(t.code,{children:"N%"})," validators are ",(0,n.jsx)(t.em,{children:"automatically"})," opted in to validate a Top N consumer chain.\nThis means that if a validator ",(0,n.jsx)(t.code,{children:"V"})," belongs to the top ",(0,n.jsx)(t.code,{children:"N%"})," validators but later falls (e.g., due to undelegations) to the bottom ",(0,n.jsx)(t.code,{children:"(100 - N)%"}),", ",(0,n.jsx)(t.code,{children:"V"})," is still considered opted in and has to validate unless ",(0,n.jsx)(t.code,{children:"V"})," sends a ",(0,n.jsx)(t.code,{children:"MsgOptOut"})," message (see below).\nBy automatically opting in validators when they enter the top ",(0,n.jsx)(t.code,{children:"N%"})," validators and by forcing top ",(0,n.jsx)(t.code,{children:"N%"})," validators to explicitly opt out in case they fall to the ",(0,n.jsx)(t.code,{children:"(100 - N)%"})," bottom validators we simplify the design of PSS."]}),"\n",(0,n.jsxs)(t.p,{children:["Note that a validator can send a ",(0,n.jsx)(t.code,{children:"MsgOptIn"})," message even if the consumer chain is not yet running. To do this we reuse the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/key_assignment.go#L644",children:(0,n.jsx)(t.code,{children:"IsConsumerProposedOrRegistered"})}),". If the ",(0,n.jsx)(t.code,{children:"chainID"})," does not exist, the ",(0,n.jsx)(t.code,{children:"MsgOptIn"})," should fail, as well as if the provider address does not exist."]}),"\n",(0,n.jsxs)(t.p,{children:["Optionally, a validator that opts in can provide a ",(0,n.jsx)(t.code,{children:"consumerKey"})," so that it assigns a different consumer key (from the provider) to the consumer chain.\nNaturally, a validator can always change the consumer key on a consumer chain by sending a ",(0,n.jsx)(t.code,{children:"MsgAssignConsumerKey"})," message at a later point in time, as is done in Replicated Security."]}),"\n",(0,n.jsx)(t.h4,{id:"state--query-1",children:"State & Query"}),"\n",(0,n.jsxs)(t.p,{children:["For each validator, we store a pair ",(0,n.jsx)(t.code,{children:"(blockHeight, isOptedIn)"})," that contains the block height the validator opted in and whether the validator is currently opted in or not, under the key:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"optedInBytePrefix | len(chainID) | chainID | addr\n"})}),"\n",(0,n.jsxs)(t.p,{children:["By using a prefix iterator on ",(0,n.jsx)(t.code,{children:"optedInBytePrefix | len(chainID) | chainID"})," we retrieve all the opted in validators."]}),"\n",(0,n.jsxs)(t.p,{children:["We introduce the following ",(0,n.jsx)(t.code,{children:"Keeper"})," methods."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-golang",children:"// returns all the validators that have opted in on chain `chainID`\nfunc (k Keeper) GetOptedInValidators(ctx sdk.Context, chainID string) []Validators\n\nfunc (k Keeper) IsValidatorOptedIn(ctx sdk.Context, chainID string, val Validator) bool\n"})}),"\n",(0,n.jsx)(t.p,{children:"We introduce the following two queries:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"interchain-security-pd query provider optedInValidators $chainID\ninterchain-security-pd query provider hasToValidate $providerAddr\n"})}),"\n",(0,n.jsx)(t.p,{children:"One query to retrieve the validators that are opted in and hence the validators that need to validate the consumer chain and one query that given a validator's address returns all the chains this validator has to validate."}),"\n",(0,n.jsx)(t.h4,{id:"when-do-validators-opt-in",children:"When do validators opt in?"}),"\n",(0,n.jsxs)(t.p,{children:["As described earlier, validators can manually opt in by sending a ",(0,n.jsx)(t.code,{children:"MsgOptIn"})," message.\nAdditionally, in a Top N chain, a validator is automatically opted in when it moves from the bottom ",(0,n.jsx)(t.code,{children:"(100 - N)%"})," to the top ",(0,n.jsx)(t.code,{children:"N%"})," validators."]}),"\n",(0,n.jsxs)(t.p,{children:["Lastly, validators can also opt in if they vote ",(0,n.jsx)(t.code,{children:"Yes"})," during the ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})," that introduces a consumer chain.\nThis simplifies validators operations because they do not have to send an additional message to opt in."]}),"\n",(0,n.jsxs)(t.p,{children:["Because the ",(0,n.jsx)(t.code,{children:"Tally"})," method ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.7/x/gov/keeper/tally.go#L71",children:"deletes the votes"})," after reading them, we cannot check the votes of the validators after the votes have been tallied.\nTo circumvent this, we introduce a hook for ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.7/x/gov/keeper/vote.go#L35",children:(0,n.jsx)(t.code,{children:"AfterProposalVote"})})," and keep track of all the votes cast by a validator.\nIf a validator casts more than one vote, we only consider the latest vote.\nFinally, we only consider a validator has opted in if it casts a 100% ",(0,n.jsx)(t.code,{children:"Yes"})," vote in case of a ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-037-gov-split-vote.md",children:"weighted vote"}),"."]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-validators-opt-out",children:"How do validators opt out?"}),"\n",(0,n.jsx)(t.p,{children:"Validators that have opted in on a chain can opt out by sending the following message:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-protobuf",children:"message MsgOptOut {\n // the chain id of the consumer chain to opt out from\n string chainID = 1;\n // the provider address of the validator\n string providerAddr = 2;\n}\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Validators can only opt out after a consumer chain has started and hence the above message returns an error if the chain with ",(0,n.jsx)(t.code,{children:"chainID"})," is not running.\nAdditionally, a validator that belongs to the top ",(0,n.jsx)(t.code,{children:"N%"})," validators cannot opt out from a Top N chain and hence a ",(0,n.jsx)(t.code,{children:"MsgOptOut"})," would error in such a case."]}),"\n",(0,n.jsx)(t.h4,{id:"state--query-2",children:"State & Query"}),"\n",(0,n.jsx)(t.p,{children:"We also update the state of the opted-in validators when a validator has opted out by removing the opted-out validator."}),"\n",(0,n.jsxs)(t.p,{children:["Note that only opted-in validators can be punished for downtime on a consumer chain.\nFor this, we use historical info of all the validators that have opted in; We can examine the ",(0,n.jsx)(t.code,{children:"blockHeight"})," stored under the key ",(0,n.jsx)(t.code,{children:"optedInBytePrefix | len(chainID) | chainID | addr"})," to see if a validator was opted in.\nThis way we can jail validators for downtime knowing that indeed the validators have opted in at some point in the past.\nOtherwise, we can think of a scenario where a validator ",(0,n.jsx)(t.code,{children:"V"})," is down for a period of time, but before ",(0,n.jsx)(t.code,{children:"V"})," gets punished for downtime, validator ",(0,n.jsx)(t.code,{children:"V"})," opts out, and then we do not know whether ",(0,n.jsx)(t.code,{children:"V"})," should be punished or not."]}),"\n",(0,n.jsx)(t.h3,{id:"when-does-a-consumer-chain-start",children:"When does a consumer chain start?"}),"\n",(0,n.jsxs)(t.p,{children:["A Top N consumer chain always starts at the specified date (",(0,n.jsx)(t.code,{children:"spawn_time"}),") if the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/proto/interchain_security/ccv/provider/v1/provider.proto#L27",children:(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})})," has passed.\nAn Opt In consumer chain only starts if at least one validator has opted in. We check this in ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/proposal.go#L357",children:"BeginBlockInit"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-golang",children:'func (k Keeper) BeginBlockInit(ctx sdk.Context) {\n propsToExecute := k.GetConsumerAdditionPropsToExecute(ctx)\n\n for _, prop := range propsToExecute {\n chainID := prop.ChainId\n if !k.IsTopN(ctx, chainID) && len(k.GetOptedInValidators(ctx, chainID)) == 0 {\n // drop the proposal\n ctx.Logger().Info("could not start chain because no validator has opted in")\n continue\n } \n ...\n'})}),"\n",(0,n.jsx)(t.h3,{id:"how-do-we-send-the-partial-validator-sets-to-the-consumer-chains",children:"How do we send the partial validator sets to the consumer chains?"}),"\n",(0,n.jsxs)(t.p,{children:["A consumer chain should only be validated by opted in validators.\nWe introduce logic to do this when we ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/relay.go#L213",children:"queue"})," the ",(0,n.jsx)(t.code,{children:"VSCPacket"}),"s.\nThe logic behind this, is not as straightforward as it seems because CometBFT does not receive the validator set that has to validate a chain, but rather a delta of ",(0,n.jsx)(t.a,{href:"https://docs.cometbft.com/v0.37/spec/abci/abci++_methods#validatorupdate",children:"validator updates"}),".\nFor example, to remove an opted-out validator from a consumer chain, we have to send a validator update with a ",(0,n.jsx)(t.code,{children:"power"})," of ",(0,n.jsx)(t.code,{children:"0"}),", similarly to what is done in the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/key_assignment.go#L525",children:"assignment of consumer keys"}),".\nWe intend to update this ADR at a later stage on how exactly we intend to implement this logic."]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-we-distribute-rewards",children:"How do we distribute rewards?"}),"\n",(0,n.jsxs)(t.p,{children:["Currently, rewards are distributed as follows: The consumer ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/consumer/keeper/distribution.go#L148",children:"periodically sends rewards"})," on the provider ",(0,n.jsx)(t.code,{children:"ConsumerRewardsPool"})," address.\nThe provider then ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/distribution.go#L77",children:"transfers those rewards to the fee collector address"})," and those transferred rewards are distributed to validators and delegators."]}),"\n",(0,n.jsx)(t.p,{children:"In PSS, we distribute rewards only to validators that actually validate the consumer chain.\nTo do this, we have a pool associated with each consumer chain and consumers IBC transfer the rewards to this pool.\nWe then extract the rewards from each consumer pool and distribute them to the opted in validators."}),"\n",(0,n.jsx)(t.p,{children:"Note that we only distribute rewards to validators that have been opted in for some time (e.g., 10000 blocks) to avoid cases where validators opt in just to receive rewards and then opt out immediately afterward."}),"\n",(0,n.jsx)(t.h3,{id:"misbehaviour",children:"Misbehaviour"}),"\n",(0,n.jsx)(t.h4,{id:"fraud-votes",children:"Fraud votes"}),"\n",(0,n.jsxs)(t.p,{children:["In an Opt In chain, a set of validators might attempt to perform an attack. To deter such potential attacks, PSS allows for the use of fraud votes.\nA ",(0,n.jsx)(t.em,{children:"fraud vote"})," is a governance proposal that enables the slashing of validators that performed an attack.\nDue to their inherent complexity, we intend to introduce fraud votes in a different ADR and at a future iteration of PSS."]}),"\n",(0,n.jsx)(t.h4,{id:"double-signing",children:"Double signing"}),"\n",(0,n.jsx)(t.p,{children:"We do not change the way slashing for double signing and light client attacks functions.\nIf a validator misbehaves on a consumer, then we slash that validator on the provider."}),"\n",(0,n.jsx)(t.h4,{id:"downtime",children:"Downtime"}),"\n",(0,n.jsx)(t.p,{children:"We do not change the way downtime jailing functions.\nIf a validator is down on a consumer chain for an adequate amount of time, we jail this validator on the provider but only if the validator was opted in on this consumer chain in the recent past."}),"\n",(0,n.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,n.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Easier for new consumer chains to consume the provider's chain economic security because proposals are more likely to pass if not everyone is forced to validate."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Smaller validators are not forced to validate chains anymore if they do not want to."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"We can deprecate the soft opt-out implementation."}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["A consumer chain does not receive the same economic security as with Replicated Security (assuming the value of ",(0,n.jsx)(t.code,{children:"SoftOptOutThreshold"})," is ",(0,n.jsx)(t.code,{children:"5%"}),"), unless it is a Top N chain with ",(0,n.jsx)(t.code,{children:"N >= 95%"}),"."]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/pss-permissionless-vs-premissioned-lite-opt-in-consumer-chains/12984",children:"PSS: Permissionless vs premissioned-lite opt-in consumer chains"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/chips-discussion-phase-partial-set-security-updated/11775",children:"CHIPs discussion phase: Partial Set Security (updated)"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/pss-exclusive-vs-inclusive-top-n/13058",children:"PSS: Exclusive vs Inclusive Top-N"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1518",children:"Initial PSS ADR and notes #1518"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://informal.systems/blog/replicated-vs-mesh-security",children:"Replicated vs. Mesh Security"})}),"\n"]})]})}function l(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},1151:(e,t,o)=>{o.d(t,{Z:()=>r,a:()=>a});var n=o(7294);const i={},s=n.createContext(i);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/6b8df643.b0ee3105.js b/assets/js/6b8df643.b0ee3105.js
new file mode 100644
index 0000000000..c88893bf23
--- /dev/null
+++ b/assets/js/6b8df643.b0ee3105.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4335],{8355:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>o,metadata:()=>a,toc:()=>h});var s=t(5893),i=t(1151);const o={sidebar_position:15,title:"Epochs"},r="ADR 014: Epochs",a={id:"adrs/adr-014-epochs",title:"Epochs",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-014-epochs.md",sourceDirName:"adrs",slug:"/adrs/adr-014-epochs",permalink:"/interchain-security/v4.2.0/adrs/adr-014-epochs",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:15,frontMatter:{sidebar_position:15,title:"Epochs"},sidebar:"tutorialSidebar",previous:{title:"Slashing on the provider for consumer equivocation",permalink:"/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing"},next:{title:"Partial Set Security",permalink:"/interchain-security/v4.2.0/adrs/adr-015-partial-set-security"}},c={},h=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"adr-014-epochs",children:"ADR 014: Epochs"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"2024-01-05: Proposed, first draft of ADR."}),"\n",(0,s.jsx)(n.li,{children:"2024-02-29: Updated so that it describes the implementation where we store the whole consumer validator set."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsx)(n.p,{children:"Proposed"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsxs)(n.p,{children:["In every block that the provider valset changes, a ",(0,s.jsx)(n.code,{children:"VSCPacket"})," must be sent to every consumer and a corresponding ",(0,s.jsx)(n.code,{children:"VSCMaturedPacket"})," sent back.\nGiven that the validator powers may change very often on the provider chain (e.g., the Cosmos Hub), this approach results in a large workload for the relayers.\nAlthough the validator powers may change very often, these changes are usually small and have an insignificant impact on the chain's security.\nIn other words, the valset on the consumers can be slightly outdated without affecting security.\nAs a matter of fact, this already happens due to relaying delays."]}),"\n",(0,s.jsxs)(n.p,{children:["As a solution, this ADR introduces the concept of ",(0,s.jsx)(n.em,{children:"epochs"}),".\nAn epoch consists of multiple blocks.\nThe provider sends ",(0,s.jsx)(n.code,{children:"VSCPacket"}),"s once per epoch.\nA ",(0,s.jsx)(n.code,{children:"VSCPacket"})," contains all the validator updates that are needed by a consumer chain."]}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsx)(n.p,{children:"The implementation of epochs requires the following changes:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"For each consumer chain, we store the consumer validator set that is currently (i.e., in this epoch) validating the\nconsumer chain. For each validator in the set we store i) its voting power, and ii) the public key that it is\nusing on the consumer chain during the current (i.e., ongoing) epoch.\nThe initial consumer validator set for a chain is set during the creation of the consumer genesis."}),"\n",(0,s.jsxs)(n.li,{children:["We introduce the ",(0,s.jsx)(n.code,{children:"BlocksPerEpoch"})," param that sets the number of blocks in an epoch. By default, ",(0,s.jsx)(n.code,{children:"BlocksPerEpoch"})," is\nset to be 600 which corresponds to 1 hour, assuming 6 seconds per block. This param can be changed through\na ",(0,s.jsx)(n.em,{children:"governance proposal"}),". In the provider ",(0,s.jsx)(n.code,{children:"EndBlock"})," we check ",(0,s.jsx)(n.code,{children:"BlockHeight() % BlocksPerEpoch() == 0"}),"\nto decide when an epoch has ended."]}),"\n",(0,s.jsxs)(n.li,{children:["At the end of every epoch, if there were validator set changes on the provider, then for every consumer chain, we\nconstruct a ",(0,s.jsx)(n.code,{children:"VSCPacket"})," with all the validator updates and add it to the list of ",(0,s.jsx)(n.code,{children:"PendingVSCPackets"}),". We compute the\nvalidator updates needed by a consumer chain by comparing the stored list of consumer validators with the current\nbonded validators on the provider, with something similar to this:"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-go",children:"// get the valset that has been validating the consumer chain during this epoch \ncurrentValidators := GetConsumerValSet(consumerChain)\n// generate the validator updates needed to be sent through a `VSCPacket` by comparing the current validators \n// in the epoch with the latest bonded validators\nvalUpdates := DiffValidators(currentValidators, stakingmodule.GetBondedValidators())\n// update the current validators set for the upcoming epoch to be the latest bonded validators instead\nSetConsumerValSet(stakingmodule.GetBondedValidators())\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Note that a validator can change its consumer public key for a specific consumer chain an arbitrary amount of times during\na block and during an epoch. Then, when we generate the validator updates in ",(0,s.jsx)(n.code,{children:"DiffValidators"}),", we have to check whether\nthe current consumer public key (retrieved by calling ",(0,s.jsx)(n.code,{children:"GetValidatorConsumerPubKey"}),") is different from the consumer public\nkey the validator was using in the current epoch."]}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Reduce the cost of relaying."}),"\n",(0,s.jsx)(n.li,{children:"Reduce the amount of IBC packets needed for ICS."}),"\n",(0,s.jsxs)(n.li,{children:["Simplifies ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-001-key-assignment.md",children:"key-assignment code"})," because\nwe only need to check if the ",(0,s.jsx)(n.code,{children:"consumer_public_key"})," has been modified since the last epoch to generate an update."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Increase the delay in the propagation of validator set changes (but for reasonable epoch lengths on the order of ~hours or less, this is unlikely to be significant)."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,s.jsx)(n.p,{children:"N/A"}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/1087",children:"EPIC"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>r});var s=t(7294);const i={},o=s.createContext(i);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/6cc1db80.b94c8d42.js b/assets/js/6cc1db80.b94c8d42.js
new file mode 100644
index 0000000000..ce3ea8ae44
--- /dev/null
+++ b/assets/js/6cc1db80.b94c8d42.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8714],{6187:(n,e,t)=>{t.r(e),t.d(e,{assets:()=>a,contentTitle:()=>s,default:()=>l,frontMatter:()=>o,metadata:()=>c,toc:()=>u});var i=t(5893),r=t(1151);const o={sidebar_position:5},s="Joining Neutron",c={id:"validators/joining-neutron",title:"Joining Neutron",description:"Neutron is the first consumer chain to implement ICS.",source:"@site/versioned_docs/version-v5.0.0/validators/joining-neutron.md",sourceDirName:"validators",slug:"/validators/joining-neutron",permalink:"/interchain-security/v5.0.0/validators/joining-neutron",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"tutorialSidebar",previous:{title:"Validator Instructions for Changeover Procedure",permalink:"/interchain-security/v5.0.0/validators/changeover-procedure"},next:{title:"Joining Stride",permalink:"/interchain-security/v5.0.0/validators/joining-stride"}},a={},u=[{value:"Resources",id:"resources",level:2}];function d(n){const e={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.a)(),...n.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"joining-neutron",children:"Joining Neutron"}),"\n",(0,i.jsx)(e.p,{children:"Neutron is the first consumer chain to implement ICS."}),"\n",(0,i.jsxs)(e.p,{children:["You can find instructions on joining the mainnet ",(0,i.jsx)(e.a,{href:"https://docs.neutron.org/neutron/consumer-chain-launch",children:"here"}),"."]}),"\n",(0,i.jsxs)(e.p,{children:["To join Neutron chain on the interchain security testnet check ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security/pion-1",children:"here"})]}),"\n",(0,i.jsx)(e.h2,{id:"resources",children:"Resources"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://docs.neutron.org",children:"Neutron docs"})}),"\n"]})]})}function l(n={}){const{wrapper:e}={...(0,r.a)(),...n.components};return e?(0,i.jsx)(e,{...n,children:(0,i.jsx)(d,{...n})}):d(n)}},1151:(n,e,t)=>{t.d(e,{Z:()=>c,a:()=>s});var i=t(7294);const r={},o=i.createContext(r);function s(n){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function c(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(r):n.components||r:s(n.components),i.createElement(o.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/6df65b06.eb6ae8e7.js b/assets/js/6df65b06.eb6ae8e7.js
new file mode 100644
index 0000000000..12fb167bc9
--- /dev/null
+++ b/assets/js/6df65b06.eb6ae8e7.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4366],{4878:(s,e,a)=>{a.r(e),a.d(e,{assets:()=>h,contentTitle:()=>l,default:()=>d,frontMatter:()=>t,metadata:()=>r,toc:()=>c});var i=a(5893),n=a(1151);const t={sidebar_position:3,title:"Jail Throttling"},l="ADR 002: Jail Throttling",r={id:"adrs/adr-002-throttle",title:"Jail Throttling",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-002-throttle.md",sourceDirName:"adrs",slug:"/adrs/adr-002-throttle",permalink:"/interchain-security/v4.2.0/adrs/adr-002-throttle",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Jail Throttling"},sidebar:"tutorialSidebar",previous:{title:"Key Assignment",permalink:"/interchain-security/v4.2.0/adrs/adr-001-key-assignment"},next:{title:"Equivocation governance proposal",permalink:"/interchain-security/v4.2.0/adrs/adr-003-equivocation-gov-proposal"}},h={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Required State",id:"required-state",level:3},{value:"Params",id:"params",level:3},{value:"Protocol Overview",id:"protocol-overview",level:3},{value:"OnRecvSlashPacket",id:"onrecvslashpacket",level:4},{value:"OnRecvVSCMaturedPacket",id:"onrecvvscmaturedpacket",level:4},{value:"Endblocker",id:"endblocker",level:4},{value:"Slash Meter Replenishment",id:"slash-meter-replenishment",level:5},{value:"Handle Leading VSCMaturedPackets",id:"handle-leading-vscmaturedpackets",level:5},{value:"Handle Throttle Queues",id:"handle-throttle-queues",level:5},{value:"System Properties",id:"system-properties",level:3},{value:"Main Throttling Property",id:"main-throttling-property",level:3},{value:"How Unjailing Affects the Main Throttling Property",id:"how-unjailing-affects-the-main-throttling-property",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function m(s){const e={a:"a",annotation:"annotation",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",li:"li",math:"math",mfrac:"mfrac",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",msub:"msub",ol:"ol",p:"p",pre:"pre",semantics:"semantics",span:"span",strong:"strong",ul:"ul",...(0,n.a)(),...s.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"adr-002-jail-throttling",children:"ADR 002: Jail Throttling"}),"\n",(0,i.jsx)(e.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"2023-01-26: Initial Draft"}),"\n",(0,i.jsx)(e.li,{children:"2023-02-07: Property refined, ADR ready to review/merge"}),"\n",(0,i.jsx)(e.li,{children:"2023-11-22: Refactor for better understanding"}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(e.p,{children:"Accepted"}),"\n",(0,i.jsx)(e.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(e.p,{children:"The CCV spec is based around the assumption that the provider binary and all consumers binaries are non-malicious, and follow the defined protocols.\nIn practice, this assumption may not hold.\nA malicious consumer binary could potentially include code which is able to send many slash/jail packets at once to the provider."}),"\n",(0,i.jsx)(e.p,{children:"Before the throttling feature was implemented, the following attack was possible.\nAttacker(s) would create provider validators just below the provider's active set.\nUsing a malicious consumer binary, slash packets would be relayed to the provider, that would slash/jail a significant portion (or all) of honest validator at once.\nControl of the provider would then pass over to the attackers' validators.\nThis enables the attacker(s) to halt the provider.\nOr even worse, commit arbitrary state on the provider, potentially stealing all tokens bridged to the provider over IBC."}),"\n",(0,i.jsx)(e.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(e.p,{children:"The throttling feature was designed to slow down the mentioned attack from above, allowing validators and the community to appropriately respond to the attack,\ni.e., this feature limits (enforced by on-chain params) the rate that the provider validator set can be jailed over time."}),"\n",(0,i.jsx)(e.h3,{id:"required-state",children:"Required State"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Slash meter:"})," There exists one slash meter on the provider which stores an amount of voting power (integer), corresponding to an allowance of validators that can be jailed over time.\nThis meter is initialized to a certain value on genesis, decremented by the amount of voting power jailed whenever a slash packet is handled, and periodically replenished as decided by on-chain params."]}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Global entry queue:"}),' There exists a single queue which stores "global slash entries".\nThese entries allow the provider to appropriately handle slash packets sent from any consumer in FIFO ordering.\nThis queue is responsible for coordinating the order that slash packets (from multiple chains) are handled over time.']}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Per-chain data queue:"}),' For each established consumer, there exists a queue which stores "throttled packet data",\ni.e.,pending slash packet data is queued together with pending VSC matured packet data in FIFO ordering.\nOrder is enforced by IBC sequence number.\nThese "per-chain" queues are responsible for coordinating the order that slash packets are handled in relation to VSC matured packets from the same chain.']}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.em,{children:"Note:"})," The reason for a multiple-queue design is the ",(0,i.jsx)(e.em,{children:"VSC Maturity and Slashing Order"})," property (see ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#consumer-initiated-slashing",children:"spec"}),").\nThere are other ways to ensure such a property (like a queue of linked lists, etc.), but the proposed approach seemed to be the most understandable and easiest to implement with a KV store."]}),"\n",(0,i.jsx)(e.h3,{id:"params",children:"Params"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishPeriod"})," -- the period after which the slash meter is replenished."]}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," -- the portion (in range [0, 1]) of total voting power that is replenished to the slash meter when a replenishment occurs. This param also serves as a maximum fraction of total voting power that the slash meter can hold."]}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.code,{children:"MaxThrottledPackets"})," -- the maximum amount of throttled slash or vsc matured packets that can be queued from a single consumer before the provider chain halts, it should be set to a large value.\nThis param would allow provider binaries to panic deterministically in the event that packet throttling results in a large amount of state-bloat. In such a scenario, packet throttling could prevent a violation of safety caused by a malicious consumer, at the cost of provider liveness."]}),"\n",(0,i.jsx)(e.h3,{id:"protocol-overview",children:"Protocol Overview"}),"\n",(0,i.jsx)(e.h4,{id:"onrecvslashpacket",children:"OnRecvSlashPacket"}),"\n",(0,i.jsx)(e.p,{children:"Upon the provider receiving a slash packet from any of the established consumers during block execution, two things occur:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsx)(e.li,{children:"A global slash entry is queued."}),"\n",(0,i.jsx)(e.li,{children:"The data of such a packet is added to the per-chain queue."}),"\n"]}),"\n",(0,i.jsx)(e.h4,{id:"onrecvvscmaturedpacket",children:"OnRecvVSCMaturedPacket"}),"\n",(0,i.jsx)(e.p,{children:"Upon the provider receiving a VSCMatured packet from any of the established consumers during block execution, the VSCMatured packet data is added to the per-chain queue."}),"\n",(0,i.jsx)(e.h4,{id:"endblocker",children:"Endblocker"}),"\n",(0,i.jsxs)(e.p,{children:["In the ",(0,i.jsx)(e.code,{children:"EndBlock"})," of the provider CCV module, there are three actions performed:"]}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"replenish the slash meter;"}),"\n",(0,i.jsxs)(e.li,{children:["handle the leading ",(0,i.jsx)(e.code,{children:"VSCMaturedPackets"}),";"]}),"\n",(0,i.jsx)(e.li,{children:"and handle the throttle queues."}),"\n"]}),"\n",(0,i.jsx)(e.h5,{id:"slash-meter-replenishment",children:"Slash Meter Replenishment"}),"\n",(0,i.jsxs)(e.p,{children:["Once the slash meter becomes not full, it'll be replenished after ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishPeriod"})," by incrementing the meter with its allowance for the replenishment block, where ",(0,i.jsx)(e.code,{children:"allowance"})," = ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," * ",(0,i.jsx)(e.code,{children:"currentTotalVotingPower"}),".\nThe slash meter will never exceed its current allowance (function of the total voting power for the block) in value."]}),"\n",(0,i.jsx)(e.p,{children:"Note a few things:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsx)(e.li,{children:"The slash meter can go negative in value, and will do so when handling a single slash packet that jails a validator with significant voting power.\nIn such a scenario, the slash meter may take multiple replenishment periods to once again reach a positive value (or 0), meaning no other slash packets may be handled for multiple replenishment periods."}),"\n",(0,i.jsx)(e.li,{children:"Total voting power of a chain changes over time, especially as validators are jailed.\nAs validators are jailed, total voting power decreases, and so does the jailing allowance.\nSee below for more detailed throttling property discussion."}),"\n",(0,i.jsxs)(e.li,{children:["The voting power allowance added to the slash meter during replenishment will always be greater than or equal to 1.\nIf the ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," is set too low, integer rounding will put this minimum value into effect.\nThat is, if ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," * ",(0,i.jsx)(e.code,{children:"currentTotalVotingPower"})," < 1, then the effective allowance would be 1.\nThis min value of allowance ensures that there's some packets handled over time, even if that is a very long time.\nIt's a crude solution to an edge case caused by too small of a replenishment fraction."]}),"\n"]}),"\n",(0,i.jsxs)(e.p,{children:["The behavior described above is achieved by executing ",(0,i.jsx)(e.code,{children:"CheckForSlashMeterReplenishment()"})," every ",(0,i.jsx)(e.code,{children:"EndBlock"}),", BEFORE ",(0,i.jsx)(e.code,{children:"HandleThrottleQueues()"})," is executed."]}),"\n",(0,i.jsx)(e.h5,{id:"handle-leading-vscmaturedpackets",children:"Handle Leading VSCMaturedPackets"}),"\n",(0,i.jsxs)(e.p,{children:["In every block, it is possible that ",(0,i.jsx)(e.code,{children:"VSCMaturedPacket"}),' data was queued before any slash packet data.\nSince this "leading" VSCMatured packet data does not have to be throttled (see ',(0,i.jsx)(e.em,{children:"VSC Maturity and Slashing Order"}),"), we can handle all VSCMatured packet data at the head of the queue, before the any throttling or packet data handling logic executes."]}),"\n",(0,i.jsx)(e.h5,{id:"handle-throttle-queues",children:"Handle Throttle Queues"}),"\n",(0,i.jsxs)(e.p,{children:["In every ",(0,i.jsx)(e.code,{children:"EndBlock"}),", the following logic is executed to handle data from the throttle queues."]}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-typescript",children:"meter := getSlashMeter()\n\n// Keep iterating as long as the meter has a positive (or 0) value, and global slash entries exist \nwhile meter.IsPositiveOrZero() && entriesExist() {\n // Get next entry in queue\n entry := getNextGlobalSlashEntry()\n // Decrement slash meter by the voting power that will be removed from the valset from handling this slash packet\n valPower := entry.getValPower()\n meter = meter - valPower\n // Using the per-chain queue, handle the single slash packet using its queued data,\n // then handle all trailing VSCMatured packets for this consumer\n handleSlashPacketAndTrailingVSCMaturedPackets(entry)\n // Delete entry in global queue, delete handled data\n entry.Delete()\n deleteThrottledSlashPacketData()\n deleteTrailingVSCMaturedPacketData()\n}\n"})}),"\n",(0,i.jsx)(e.h3,{id:"system-properties",children:"System Properties"}),"\n",(0,i.jsxs)(e.p,{children:["All CCV system properties should be maintained by implementing this feature, see ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#consumer-initiated-slashing",children:"CCV spec - Consumer Initiated Slashing"}),"."]}),"\n",(0,i.jsxs)(e.p,{children:["One implementation-specific property introduced is that if any of the chain-specific packet data queues become larger than ",(0,i.jsx)(e.code,{children:"MaxThrottledPackets"}),", then the provider binary will panic, and the provider chain will halt.\nTherefore this param should be set carefully. See ",(0,i.jsx)(e.code,{children:"SetThrottledPacketDataSize"}),".\nThis behavior ensures that if the provider binaries are queuing up more packet data than machines can handle, the provider chain halts deterministically between validators."]}),"\n",(0,i.jsx)(e.h3,{id:"main-throttling-property",children:"Main Throttling Property"}),"\n",(0,i.jsx)(e.p,{children:"Using on-chain params and the sub protocol defined, slash packet throttling is implemented such that the following property holds under some conditions."}),"\n",(0,i.jsx)(e.p,{children:"First, we introduce the following definitions:"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:'A consumer initiated slash attack "starts" when the first slash packet from such an attack is received by the provider.'}),"\n",(0,i.jsx)(e.li,{children:'The "initial validator set" for the attack is the validator set that existed on the provider when the attack started.'}),"\n",(0,i.jsxs)(e.li,{children:["There is a list of honest validators such that if they are jailed, ",(0,i.jsx)(e.code,{children:"X"}),"% of the initial validator set will be jailed."]}),"\n"]}),"\n",(0,i.jsx)(e.p,{children:"For the Throttling Property to hold, the following assumptions must be true:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsx)(e.li,{children:"We assume the total voting power of the chain (as a function of delegations) does not increase over the course of the attack."}),"\n",(0,i.jsxs)(e.li,{children:["No validator has more than ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," of total voting power on the provider."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," is large enough that ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," * ",(0,i.jsx)(e.code,{children:"currentTotalVotingPower"})," > 1,\ni.e., the replenish fraction is set high enough that we can ignore the effects of rounding."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishPeriod"})," is sufficiently longer than the time it takes to produce a block."]}),"\n"]}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.em,{children:"Note if these assumptions do not hold, throttling will still slow down the described attack in most cases, just not in a way that can be succinctly described. It's possible that more complex properties can be defined."})}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Throttling Property"}),": The time it takes to jail/tombstone ",(0,i.jsx)(e.code,{children:"X"}),"% of the initial validator set will be greater than or equal to\n",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"d"})]}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"c"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"n"})]})]}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"d"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathit{SlashMeterReplenishPeriod} \\cdot \\frac{X}{\\mathit{SlashMeterReplenishFraction}} - 2 \\cdot \\mathit{SlashMeterReplenishPeriod}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishPeriod"})}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.3534em",verticalAlign:"-0.4811em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8723em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"SlashMeterReplenishFraction"})})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.394em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"})})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.4811em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,i.jsx)(e.span,{className:"mord",children:"2"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishPeriod"})})]})]})]}),"."]}),"\n",(0,i.jsxs)(e.blockquote,{children:["\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"Intuition"})}),"\n",(0,i.jsx)(e.p,{children:"Let's use the following notation:"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"C"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"})]})})]}),": Number of replenishment cycles"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"P"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"P"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})})]}),": ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"d"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathit{SlashMeterReplenishPeriod}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishPeriod"})})]})})]})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"F"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"F"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})})]}),": ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"c"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"n"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathit{SlashMeterReplenishFraction}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishFraction"})})]})})]})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"V_{\\mathit{max}}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]}),": Max power of a validator as a fraction of total voting power"]}),"\n"]}),"\n",(0,i.jsxs)(e.p,{children:["In ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"C"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"})]})})]})," number of replenishment cycles, the fraction of total voting power that can be removed, ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"a"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"a"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",children:"a"})]})})]}),", is ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mo,{children:"\u2264"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"+"}),(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"a \\leq F \\cdot C + V_{\\mathit{max}}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7719em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",children:"a"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2264"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"+"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})]})]})," (where ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"V_{\\mathit{max}}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]})," is there to account for the power fraction of the last validator removed, one which pushes the meter to the negative value)."]}),"\n",(0,i.jsxs)(e.p,{children:["So, we need at least ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u2265"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})]}),(0,i.jsx)(e.mi,{children:"F"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\geq \\frac{a - V_{\\mathit{max}}}{F}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8193em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.2334em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8884em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.4101em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",children:"a"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1645em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.357em",marginLeft:"-0.2222em",marginRight:"0.0714em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.5em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size3 size1 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.143em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})," cycles to remove ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"a"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"a"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",children:"a"})]})})]})," fraction of the total voting power."]}),"\n",(0,i.jsxs)(e.p,{children:["Since we defined the start of the attack to be the moment when the first slash request arrives, then ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"F"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"F"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})})]})," fraction of the initial validator set can be jailed immediately. For the remaining ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"X - F"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})]})]})," fraction of the initial validator set to be jailed, it takes at least ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u2265"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mo,{stretchy:"false",children:"("}),(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mo,{stretchy:"false",children:")"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})]}),(0,i.jsx)(e.mi,{children:"F"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\geq \\frac{(X - F) - V_{\\mathit{max}}}{F}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8193em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.355em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"1.01em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.485em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mopen mtight",children:"("}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"}),(0,i.jsx)(e.span,{className:"mclose mtight",children:")"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1645em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.357em",marginLeft:"-0.2222em",marginRight:"0.0714em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.5em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size3 size1 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.143em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})," cycles. Using the assumption that ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]}),(0,i.jsx)(e.mo,{children:"\u2264"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"V_{\\mathit{max}} \\leq F"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2264"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})]})]})," (assumption 2), we get ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u2265"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.mi,{children:"F"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\geq \\frac{X - 2F}{F}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8193em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.2173em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8723em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.394em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mord mtight",children:"2"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})," cycles."]}),"\n",(0,i.jsxs)(e.p,{children:["In order to execute ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"C"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"})]})})]})," cycles, we need ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mi,{children:"P"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\cdot P"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})]})]})," time."]}),"\n",(0,i.jsxs)(e.p,{children:["Thus, jailing the remaining ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"X - F"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})]})]})," fraction of the initial validator set corresponds to ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mo,{stretchy:"false",children:"("}),(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,i.jsx)(e.mi,{children:"F"})]})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\frac{P \\cdot (X - 2F)}{F}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.355em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"1.01em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.485em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"P"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mopen mtight",children:"("}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mord mtight",children:"2"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"}),(0,i.jsx)(e.span,{className:"mclose mtight",children:")"})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})})]})," time."]}),"\n",(0,i.jsxs)(e.p,{children:["In other words, the attack must take at least ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mi,{children:"X"})]}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mi,{children:"P"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\frac{P \\cdot X}{F} - 2P"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.2173em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8723em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.394em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"P"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord",children:"2"}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})]})]})," time (in the units of replenish period ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"P"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"P"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})})]}),")."]}),"\n"]}),"\n",(0,i.jsxs)(e.p,{children:["This property is useful because it allows us to reason about the time it takes to jail a certain percentage of the initial provider validator set from consumer initiated slash requests.\nFor example, if ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," is set to ",(0,i.jsx)(e.code,{children:"0.06"}),", then it takes no less than 4 replenishment periods to jail 33% of the initial provider validator set on the Cosmos Hub.\nNote that as of writing this on 11/29/22, the Cosmos Hub does not have a validator with more than 6% of total voting power."]}),"\n",(0,i.jsx)(e.p,{children:"Note also that 4 replenishment period is a worst case scenario that depends on well crafted attack timings."}),"\n",(0,i.jsx)(e.h3,{id:"how-unjailing-affects-the-main-throttling-property",children:"How Unjailing Affects the Main Throttling Property"}),"\n",(0,i.jsx)(e.p,{children:"Note that the jailing allowance is directly proportional to the current total voting power of the provider chain. Therefore, if honest validators don't unjail themselves during the attack, the total voting power of the provider chain will decrease over the course of the attack, and the attack will be slowed down, main throttling property is maintained."}),"\n",(0,i.jsx)(e.p,{children:"If honest validators do unjail themselves, the total voting power of the provider chain will still not become higher than when the attack started (unless new token delegations happen), therefore the main property is still maintained. Moreover, honest validators unjailing themselves helps prevent the attacking validators from gaining control of the provider."}),"\n",(0,i.jsx)(e.p,{children:"In summary, the throttling mechanism as designed has desirable properties whether or not honest validators unjail themselves over the course of the attack."}),"\n",(0,i.jsx)(e.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(e.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"The described attack is slowed down in seemingly all cases."}),"\n",(0,i.jsx)(e.li,{children:"If certain assumptions hold, the described attack is slowed down in a way that can be precisely time-bounded."}),"\n"]}),"\n",(0,i.jsx)(e.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["Throttling introduces a vector for a malicious consumer chain to halt the provider, see issue below.\nHowever, this is sacrificing liveness in a edge case scenario for the sake of security.\nAs an improvement, ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/713",children:"using retries"})," would fully prevent this attack vector."]}),"\n"]}),"\n",(0,i.jsx)(e.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"Additional state is introduced to the provider chain."}),"\n",(0,i.jsx)(e.li,{children:"VSCMatured and slash packet data is not always handled in the same block that it is received."}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/404",children:"Original issue inspiring throttling feature"})}),"\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/594",children:"Issue on DOS vector"})}),"\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/685",children:"Consideration of another attack vector"})}),"\n"]})]})}function d(s={}){const{wrapper:e}={...(0,n.a)(),...s.components};return e?(0,i.jsx)(e,{...s,children:(0,i.jsx)(m,{...s})}):m(s)}},1151:(s,e,a)=>{a.d(e,{Z:()=>r,a:()=>l});var i=a(7294);const n={},t=i.createContext(n);function l(s){const e=i.useContext(t);return i.useMemo((function(){return"function"==typeof s?s(e):{...e,...s}}),[e,s])}function r(s){let e;return e=s.disableParentContext?"function"==typeof s.components?s.components(n):s.components||n:l(s.components),i.createElement(t.Provider,{value:e},s.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/6f71328c.dbe2f06e.js b/assets/js/6f71328c.dbe2f06e.js
new file mode 100644
index 0000000000..51617e65df
--- /dev/null
+++ b/assets/js/6f71328c.dbe2f06e.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8560],{9371:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>h,contentTitle:()=>a,default:()=>l,frontMatter:()=>t,metadata:()=>r,toc:()=>d});var i=o(5893),s=o(1151);const t={sidebar_position:14,title:"Slashing on the provider for consumer equivocation"},a="ADR 013: Slashing on the provider for consumer equivocation",r={id:"adrs/adr-013-equivocation-slashing",title:"Slashing on the provider for consumer equivocation",description:"Changelog",source:"@site/docs/adrs/adr-013-equivocation-slashing.md",sourceDirName:"adrs",slug:"/adrs/adr-013-equivocation-slashing",permalink:"/interchain-security/adrs/adr-013-equivocation-slashing",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:14,frontMatter:{sidebar_position:14,title:"Slashing on the provider for consumer equivocation"},sidebar:"tutorialSidebar",previous:{title:"Separate Releasing",permalink:"/interchain-security/adrs/adr-012-separate-releasing"},next:{title:"Epochs",permalink:"/interchain-security/adrs/adr-014-epochs"}},h={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Single-chain slashing",id:"single-chain-slashing",level:3},{value:"Slashing undelegations and redelegations",id:"slashing-undelegations-and-redelegations",level:4},{value:"Slashing delegations",id:"slashing-delegations",level:4},{value:"Old evidence",id:"old-evidence",level:4},{value:"Slashing for equivocation on the consumer",id:"slashing-for-equivocation-on-the-consumer",level:3},{value:"Proposed solution",id:"proposed-solution",level:2},{value:"Implementation",id:"implementation",level:3},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function c(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-013-slashing-on-the-provider-for-consumer-equivocation",children:"ADR 013: Slashing on the provider for consumer equivocation"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"1st Sept. 2023: Initial draft"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Accepted"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsxs)(n.p,{children:["This ADR presents some approaches on how to slash on the provider chain validators that performed equivocations on consumer chains.\nCurrently, the provider chain can ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"receive and verify evidence of equivocation"}),", but it cannot slash the misbehaving validator."]}),"\n",(0,i.jsx)(n.p,{children:"In the remainder of this section, we explain how slashing is performed on a single chain and show why slashing on the provider for equivocation on the consumer is challenging."}),"\n",(0,i.jsxs)(n.p,{children:["Note that future versions of the Cosmos SDK, CometBFT, and ibc-go could modify the way we slash, etc. Therefore, a future reader of this ADR, should note that when we refer to Cosmos SDK, CometBFT, and ibc-go we specifically refer to their ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/intro/overview",children:"v0.47"}),", ",(0,i.jsx)(n.a,{href:"https://docs.cometbft.com/v0.37/",children:"v0.37"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc-go/blob/v7.3.0",children:"v7.3.0"})," versions respectively."]}),"\n",(0,i.jsx)(n.h3,{id:"single-chain-slashing",children:"Single-chain slashing"}),"\n",(0,i.jsxs)(n.p,{children:["Slashing is implemented across the ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/slashing",children:"slashing"}),"\nand ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/staking",children:"staking"})," modules.\nThe slashing module's keeper calls the staking module's ",(0,i.jsx)(n.code,{children:"Slash()"})," method, passing among others, the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," (i.e., the height when the equivocation occurred), the validator's ",(0,i.jsx)(n.code,{children:"power"})," at the infraction height, and the ",(0,i.jsx)(n.code,{children:"slashFactor"})," (currently set to ",(0,i.jsx)(n.code,{children:"5%"})," in case of equivocation on the Cosmos Hub)."]}),"\n",(0,i.jsx)(n.h4,{id:"slashing-undelegations-and-redelegations",children:"Slashing undelegations and redelegations"}),"\n",(0,i.jsxs)(n.p,{children:["To slash undelegations, ",(0,i.jsx)(n.code,{children:"Slash"})," goes through all undelegations and checks whether they started before or after the infraction occurred. If an undelegation started before the ",(0,i.jsx)(n.code,{children:"infractionHeight"}),", then it is ",(0,i.jsx)(n.strong,{children:"not"})," slashed, otherwise it is slashed by ",(0,i.jsx)(n.code,{children:"slashFactor"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The slashing of redelegations happens in a similar way, meaning that ",(0,i.jsx)(n.code,{children:"Slash"})," goes through all redelegations and checks whether the redelegations started before or after the ",(0,i.jsx)(n.code,{children:"infractionHeight"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"slashing-delegations",children:"Slashing delegations"}),"\n",(0,i.jsxs)(n.p,{children:["Besides undelegations and redelegations, the validator's delegations need to also be slashed.\nThis is performed by deducting the appropriate amount of tokens from the validator. Note that this deduction is computed based on the voting ",(0,i.jsx)(n.code,{children:"power"})," the misbehaving validator had at the height of the equivocation. As a result of the tokens deduction,\nthe ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/staking#delegator-shares",children:"tokens per share"}),"\nreduce and hence later on, when delegators undelegate or redelegate, the delegators retrieve back less\ntokens, effectively having their tokens slashed. The rationale behind this slashing mechanism, as mentioned in the ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/staking#delegator-shares",children:"Cosmos SDK documentation"})]}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"[...] is to simplify the accounting around slashing. Rather than iteratively slashing the tokens of every delegation entry, instead the Validators total bonded tokens can be slashed, effectively reducing the value of each issued delegator share."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["This approach of slashing delegations does not utilize the\n",(0,i.jsx)(n.code,{children:"infractionHeight"})," in any way and hence the following scenario could occur:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["a validator ",(0,i.jsx)(n.code,{children:"V"})," performs an equivocation at a height ",(0,i.jsx)(n.code,{children:"Hi"})]}),"\n",(0,i.jsxs)(n.li,{children:["a new delegator ",(0,i.jsx)(n.code,{children:"D"})," delegates to ",(0,i.jsx)(n.code,{children:"V"})," after height ",(0,i.jsx)(n.code,{children:"Hi"})]}),"\n",(0,i.jsxs)(n.li,{children:["evidence of the equivocation by validator ",(0,i.jsx)(n.code,{children:"V"})," is received"]}),"\n",(0,i.jsxs)(n.li,{children:["the tokens of delegator ",(0,i.jsx)(n.code,{children:"D"})," are slashed"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["In the above scenario, delegator ",(0,i.jsx)(n.code,{children:"D"})," is slashed, even though ",(0,i.jsx)(n.code,{children:"D"}),"'s voting power did not contribute to the infraction."]}),"\n",(0,i.jsx)(n.h4,{id:"old-evidence",children:"Old evidence"}),"\n",(0,i.jsxs)(n.p,{children:["In the single-chain case, old evidence (e.g., from 3 years ago) is ignored. This is achieved through\n",(0,i.jsx)(n.a,{href:"https://docs.cometbft.com/v0.37/spec/consensus/evidence",children:"CometBFT"})," that ignores old evidence based on the parameters ",(0,i.jsx)(n.code,{children:"MaxAgeNumBlocks"})," and ",(0,i.jsx)(n.code,{children:"MaxAgeDuration"})," (see ",(0,i.jsx)(n.a,{href:"https://github.com/cometbft/cometbft/blob/v0.37.0/evidence/pool.go#271",children:"here"}),").\nAdditionally, note that when the evidence is sent by CometBFT to the application, the evidence is rechecked in the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/evidence/keeper/infraction.go#L54",children:"evidence module"})," of Cosmos SDK and if it is old, the evidence is ignored.\nIn Cosmos Hub, the ",(0,i.jsx)(n.code,{children:"MaxAgeNumBlocks"})," is set to 1000000 (i.e., ~70 days if we assume we need ~6 sec per block) and ",(0,i.jsx)(n.code,{children:"MaxAgeDuration"})," is set to 172800000000000 ns (i.e., 2 days). Because of this check, we can easily exclude old evidence."]}),"\n",(0,i.jsx)(n.h3,{id:"slashing-for-equivocation-on-the-consumer",children:"Slashing for equivocation on the consumer"}),"\n",(0,i.jsxs)(n.p,{children:["In the single-chain case, slashing requires both the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and the voting ",(0,i.jsx)(n.code,{children:"power"}),".\nIn order to slash on the provider for an equivocation on a consumer, we need to have both the provider's ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and voting ",(0,i.jsx)(n.code,{children:"power"}),".\nNote that the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," on the consumer chain must be mapped to a height on the provider chain.\nUnless we have a way to find the corresponding ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and ",(0,i.jsx)(n.code,{children:"power"})," on the provider chain, we cannot slash for equivocation on the consumer in the same way as we would slash in the single-chain case."]}),"\n",(0,i.jsxs)(n.p,{children:["The challenge of figuring out the corresponding ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and ",(0,i.jsx)(n.code,{children:"power"})," values on the provider chain is due to the following trust assumption:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["We trust the consensus layer and validator set of the consumer chains, ",(0,i.jsx)(n.em,{children:"but we do not trust the application layer"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["As a result, we cannot trust anything that stems from the ",(0,i.jsx)(n.em,{children:"application state"})," of a consumer chain."]}),"\n",(0,i.jsxs)(n.p,{children:["Note that when a relayer or a user sends evidence through a ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"MsgSubmitConsumerDoubleVoting"})," message, the provider gets access to ",(0,i.jsx)(n.a,{href:"https://github.com/cometbft/cometbft/blob/v0.37.0/types/evidence.go#L35",children:"DuplicateVoteEvidence"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-protobuf",children:'type DuplicateVoteEvidence struct {\n\tVoteA *Vote `json:"vote_a"`\n\tVoteB *Vote `json:"vote_b"`\n\n\t// abci specific information\n\tTotalVotingPower int64\n\tValidatorPower int64\n\tTimestamp time.Time\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:['The "abci specific information" fields cannot be trusted because they are not signed. Therefore,\nwe can use neither ',(0,i.jsx)(n.code,{children:"ValidatorPower"})," for slashing on the provider chain, nor the ",(0,i.jsx)(n.code,{children:"Timestamp"})," to check the evidence age. We can get the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," from the votes, but this ",(0,i.jsx)(n.code,{children:"infractionHeight"})," corresponds to the infraction height on the consumer and ",(0,i.jsx)(n.strong,{children:"not"})," on the provider chain.\nSimilarly, when a relayer or a user sends evidence through a ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/826",children:"MsgSubmitConsumerMisbehaviour"})," message, the provider gets access to ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc-go/blob/v7.3.0/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L79",children:"Misbehaviour"})," that we cannot use to extract the infraction height, power, or the time on the provider chain."]}),"\n",(0,i.jsx)(n.h2,{id:"proposed-solution",children:"Proposed solution"}),"\n",(0,i.jsx)(n.p,{children:"As a first iteration, we propose the following approach. At the moment the provider receives evidence of equivocation on a consumer:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["slash all the undelegations and redelegations using ",(0,i.jsx)(n.code,{children:"slashFactor"}),";"]}),"\n",(0,i.jsxs)(n.li,{children:["slash all delegations using as voting ",(0,i.jsx)(n.code,{children:"power"})," the sum of the voting power of the misbehaving validator and the power of all the ongoing undelegations and redelegations."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Evidence expiration:"})," Additionally, because we cannot infer the actual time of the evidence (i.e., the timestamp of the evidence cannot be trusted), we do not consider ",(0,i.jsx)(n.em,{children:"evidence expiration"})," and hence old evidence is never ignored (e.g., the provider would act on 3 year-old evidence of equivocation on a consumer).\nAdditionally, we do not need to store equivocation evidence to avoid slashing a validator more than once, because we ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/evidence/keeper/infraction.go#L94",children:"do not slash"})," tombstoned validators and we ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/evidence/keeper/infraction.go#L138",children:"tombstone"})," a validator when slashed."]}),"\n",(0,i.jsxs)(n.p,{children:["We do not act on evidence that was signed by a validator ",(0,i.jsx)(n.a,{href:"https://tutorials.cosmos.network/tutorials/9-path-to-prod/3-keys.html#what-validator-keys",children:"consensus key"})," that is ",(0,i.jsx)(n.em,{children:"pruned"})," when we receive the evidence. We prune a validator's consensus key if the validator has assigned a new consumer key (using ",(0,i.jsx)(n.code,{children:"MsgAssignConsumerKey"}),") and an unbonding period on the consumer chain has elapsed (see ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-001-key-assignment.md",children:"key assignment ADR"}),"). Note that the provider chain is informed that the unbonding period has elapsed on the consumer when the provider receives a ",(0,i.jsx)(n.code,{children:"VSCMaturedPacket"})," and because of this, if the consumer delays the sending of a ",(0,i.jsx)(n.code,{children:"VSCMaturedPacket"}),", we would delay the pruning of the key as well."]}),"\n",(0,i.jsx)(n.h3,{id:"implementation",children:"Implementation"}),"\n",(0,i.jsxs)(n.p,{children:["The following logic needs to be added to the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"HandleConsumerDoubleVoting"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/826",children:"HandleConsumerMisbehaviour"})," methods:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:"undelegationsInTokens := sdk.NewInt(0)\nfor _, v := range k.stakingKeeper.GetUnbondingDelegationsFromValidator(ctx, validatorAddress) {\n for _, entry := range v.Entries {\n if entry.IsMature(now) && !entry.OnHold() {\n // undelegation no longer eligible for slashing, skip it\n continue\n }\n undelegationsInTokens = undelegationsInTokens.Add(entry.InitialBalance)\n }\n}\n\nredelegationsInTokens := sdk.NewInt(0)\nfor _, v := range k.stakingKeeper.GetRedelegationsFromSrcValidator(ctx, validatorAddress) {\n for _, entry := range v.Entries {\n if entry.IsMature(now) && !entry.OnHold() {\n // redelegation no longer eligible for slashing, skip it\n continue\n }\n redelegationsInTokens = redelegationsInTokens.Add(entry.InitialBalance)\n }\n}\n\ninfractionHeight := 0\nundelegationsAndRedelegationsInPower = sdk.TokensToConsensusPower(undelegationsInTokens.Add(redelegationsInTokens))\ntotalPower := validator's voting power + undelegationsAndRedelegationsInPower\nslashFraction := k.slashingKeeper.SlashFractionDoubleSign(ctx)\n\nk.stakingKeeper.Slash(ctx, validatorConsAddress, infractionHeight, totalPower, slashFraction, DoubleSign)\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Infraction height:"})," We provide a zero ",(0,i.jsx)(n.code,{children:"infractionHeight"})," to the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L33",children:"Slash"})," method in order to slash all ongoing undelegations and redelegations (see checks in ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L92",children:"Slash"}),", ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L195",children:"SlashUnbondingDelegation"}),", and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L249",children:"SlashRedelegation"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Power:"})," We pass the sum of the voting power of the misbehaving validator when the evidence was received (i.e., at evidence height) and the power of all the ongoing undelegations and redelegations.\nIf we assume that the ",(0,i.jsx)(n.code,{children:"slashFactor"})," is ",(0,i.jsx)(n.code,{children:"5%"}),", then the voting power we pass is ",(0,i.jsx)(n.code,{children:"power + totalPower(undelegations) + totalPower(redelegations)"}),".\nHence, when the ",(0,i.jsx)(n.code,{children:"Slash"})," method slashes all the undelegations and redelegations it would end up with ",(0,i.jsx)(n.code,{children:"0.05 * power + 0.05 * totalPower(undelegations) + 0.05 * totalPower(redelegations) - 0.05 * totalPower(undelegations) - 0.05 * totalPower(redelegations) = 0.05 * power"})," and hence it would slash ",(0,i.jsx)(n.code,{children:"5%"})," of the validator's power when the evidence is received."]}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsx)(n.p,{children:"With the proposed approach we can quickly implement slashing functionality on the provider chain for consumer chain equivocations.\nThis approach does not need to change the staking module and therefore does not change in any way how slashing is performed today for a single chain."}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["We ",(0,i.jsx)(n.em,{children:"definitely"})," slash more when it comes to undelegations and redelegations because we slash for all of them without considering an ",(0,i.jsx)(n.code,{children:"infractionHeight"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["We ",(0,i.jsx)(n.em,{children:"potentially"})," slash more than what we would have slashed if we knew the voting ",(0,i.jsx)(n.code,{children:"power"})," at the corresponding ",(0,i.jsx)(n.code,{children:"infractionHeight"})," in the provider chain."]}),"\n",(0,i.jsx)(n.li,{children:"We slash on old evidence of equivocation on a consumer."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-005-cryptographic-equivocation-verification.md",children:"ADR 005: Cryptographic verification of equivocation evidence"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/732",children:"EPIC tracking cryptographic equivocation feature"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://forum.cosmos.network/t/cryptographic-equivocation-slashing-design/11400",children:"Cosmos Hub Forum discussion on cryptographic equivocation slashing"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>r,a:()=>a});var i=o(7294);const s={},t=i.createContext(s);function a(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/700b5f22.48455c22.js b/assets/js/700b5f22.48455c22.js
new file mode 100644
index 0000000000..785e97a2aa
--- /dev/null
+++ b/assets/js/700b5f22.48455c22.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5612],{8734:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>s,default:()=>l,frontMatter:()=>a,metadata:()=>r,toc:()=>h});var t=n(5893),o=n(1151);const a={sidebar_position:6},s="Partial Set Security",r={id:"validators/partial-set-security-for-validators",title:"Partial Set Security",description:"Partial Set Security allows consumer chains to join as Opt-In or Top N.",source:"@site/docs/validators/partial-set-security-for-validators.md",sourceDirName:"validators",slug:"/validators/partial-set-security-for-validators",permalink:"/interchain-security/validators/partial-set-security-for-validators",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Joining Stride",permalink:"/interchain-security/validators/joining-stride"},next:{title:"Frequently Asked Questions",permalink:"/interchain-security/faq"}},c={},h=[{value:"Messages",id:"messages",level:2},{value:"How to opt in to a consumer chain?",id:"how-to-opt-in-to-a-consumer-chain",level:3},{value:"How to opt out from a consumer chain?",id:"how-to-opt-out-from-a-consumer-chain",level:3},{value:"How to set specific per consumer chain commission rate?",id:"how-to-set-specific-per-consumer-chain-commission-rate",level:3},{value:"Queries",id:"queries",level:2},{value:"Which chains does a validator have to validate?",id:"which-chains-does-a-validator-have-to-validate",level:3},{value:"How do you know how much voting power you need to have to be in the top N for a chain?",id:"how-do-you-know-how-much-voting-power-you-need-to-have-to-be-in-the-top-n-for-a-chain",level:3},{value:"How to retrieve all the opted-in validators on a consumer chain?",id:"how-to-retrieve-all-the-opted-in-validators-on-a-consumer-chain",level:3},{value:"How to retrieve all the consumer validators on a consumer chain?",id:"how-to-retrieve-all-the-consumer-validators-on-a-consumer-chain",level:3},{value:"How can we see the commission rate a validator has set on a consumer chain?",id:"how-can-we-see-the-commission-rate-a-validator-has-set-on-a-consumer-chain",level:3}];function d(e){const i={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(i.h1,{id:"partial-set-security",children:"Partial Set Security"}),"\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.a,{href:"/interchain-security/features/partial-set-security",children:"Partial Set Security"})," allows consumer chains to join as Opt-In or Top N.\nHere, we show how a validator can opt in, opt out, or set a custom commission rate on a consumer chain, as well\nas useful queries that a validator can use to figure out which chains it has to validate, etc."]}),"\n",(0,t.jsx)(i.h2,{id:"messages",children:"Messages"}),"\n",(0,t.jsx)(i.h3,{id:"how-to-opt-in-to-a-consumer-chain",children:"How to opt in to a consumer chain?"}),"\n",(0,t.jsx)(i.admonition,{type:"warning",children:(0,t.jsx)(i.p,{children:"A validator is automatically opted in to a Top N chain if the validator belongs to the top N% of the validators on the provider chain."})}),"\n",(0,t.jsx)(i.p,{children:"In a Top N chain, a validator that does not belong to the top N% of the validators on the provider can still choose\nto opt in to a consumer chain. In other words, validators can opt in, in both Opt-In and Top N chains."}),"\n",(0,t.jsx)(i.p,{children:"A validator can opt in to a consumer chain by issuing the following message:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd tx provider opt-in \n"})}),"\n",(0,t.jsx)(i.p,{children:"where"}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.code,{children:"consumer-chain-id"})," is the string identifier of the consumer chain the validator wants to opt in to;"]}),"\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.code,{children:"consumer-pub-key"})," corresponds to the public key the validator wants to use on the consumer chain, and it has the\nfollowing format ",(0,t.jsx)(i.code,{children:'{"@type":"/cosmos.crypto.ed25519.PubKey","key":""}'}),"."]}),"\n"]}),"\n",(0,t.jsxs)(i.p,{children:["A validator can opt in to an existing consumer chain that is already running, or to a ",(0,t.jsx)(i.a,{href:"/interchain-security/features/proposals",children:"proposed"}),"\nconsumer chain that is still being voted on. A validator can use the following command to retrieve the currently existing\nconsumer chains:"]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider list-consumer-chains\n"})}),"\n",(0,t.jsx)(i.p,{children:"and this command to see the currently proposed consumer chains:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider list-proposed-consumer-chains\n"})}),"\n",(0,t.jsx)(i.admonition,{type:"tip",children:(0,t.jsxs)(i.p,{children:["By setting the ",(0,t.jsx)(i.code,{children:"consumer-pub-key"}),", a validator can both opt in to a chain and assign a\npublic key on a consumer chain. Note that a validator can always ",(0,t.jsx)(i.a,{href:"/interchain-security/features/key-assignment",children:"assign"}),"\na new consumer key at a later stage. The key-assignment ",(0,t.jsx)(i.a,{href:"/interchain-security/features/key-assignment#rules",children:"rules"}),"\nstill apply when setting ",(0,t.jsx)(i.code,{children:"consumer-pub-key"})," when opting in."]})}),"\n",(0,t.jsx)(i.admonition,{type:"info",children:(0,t.jsx)(i.p,{children:"A validator is only eligible for consumer rewards from a consumer chain if the validator is opted into that chain."})}),"\n",(0,t.jsx)(i.h3,{id:"how-to-opt-out-from-a-consumer-chain",children:"How to opt out from a consumer chain?"}),"\n",(0,t.jsx)(i.p,{children:"A validator can opt out from a consumer by issuing the following message:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd tx provider opt-out \n"})}),"\n",(0,t.jsx)(i.p,{children:"where"}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.code,{children:"consumer-chain-id"})," is the string identifier of the consumer chain."]}),"\n"]}),"\n",(0,t.jsx)(i.admonition,{type:"warning",children:(0,t.jsx)(i.p,{children:"A validator cannot opt out from a Top N chain if it belongs to the top N% validators of the provider."})}),"\n",(0,t.jsx)(i.admonition,{type:"warning",children:(0,t.jsxs)(i.p,{children:["If a validator moves from the Top N to outside of the top N% of the validators on the provider, it will ",(0,t.jsx)(i.strong,{children:"not"}),"\nbe automatically opted-out. The validator has to manually opt out."]})}),"\n",(0,t.jsx)(i.admonition,{type:"warning",children:(0,t.jsxs)(i.p,{children:["A validator can stop its node on a consumer chain ",(0,t.jsx)(i.strong,{children:"only"})," after opting out and confirming through the ",(0,t.jsx)(i.code,{children:"has-to-validate"}),"\nquery (see ",(0,t.jsx)(i.a,{href:"/interchain-security/validators/partial-set-security-for-validators#which-chains-does-a-validator-have-to-validate",children:"below"}),") that it does\nnot have to validate the consumer chain any longer."]})}),"\n",(0,t.jsx)(i.admonition,{type:"warning",children:(0,t.jsx)(i.p,{children:"If all validators opt out from an Opt-In chain, the chain will halt with a consensus failure upon receiving the VSCPacket with an empty validator set."})}),"\n",(0,t.jsx)(i.h3,{id:"how-to-set-specific-per-consumer-chain-commission-rate",children:"How to set specific per consumer chain commission rate?"}),"\n",(0,t.jsx)(i.p,{children:"A validator can choose to set a different commission rate on each of the consumer chains.\nThis can be done with the following command:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd tx provider set-consumer-commission-rate \n"})}),"\n",(0,t.jsx)(i.p,{children:"where"}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.code,{children:"consumer-chain-id"})," is the string identifier of the consumer chain;"]}),"\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.code,{children:"comission-rate"})," decimal in ",(0,t.jsx)(i.code,{children:"[minRate, 1]"})," where ",(0,t.jsx)(i.code,{children:"minRate"})," corresponds to the minimum commission rate set on the\nprovider chain (see ",(0,t.jsx)(i.code,{children:"min_commission_rate"})," in ",(0,t.jsx)(i.code,{children:"interchain-security-pd query staking params"}),")."]}),"\n"]}),"\n",(0,t.jsx)(i.p,{children:"If a validator does not set a commission rate on a consumer chain, the commission rate defaults to their commission rate on the provider chain."}),"\n",(0,t.jsx)(i.admonition,{type:"tip",children:(0,t.jsx)(i.p,{children:"Validators can set their commission rate even for consumer chains that they are not currently opted in on, and the commission rate will be applied when they opt in. This is particularly useful for Top N chains, where validators might be opted in automatically,\nso validators can set the commission rate in advance."})}),"\n",(0,t.jsx)(i.admonition,{type:"tip",children:(0,t.jsxs)(i.p,{children:["If a validator opts out and then back in, this will ",(0,t.jsx)(i.em,{children:"not"})," reset their commission rate back to the default. Instead, their\nset commission rate still applies."]})}),"\n",(0,t.jsx)(i.h2,{id:"queries",children:"Queries"}),"\n",(0,t.jsx)(i.p,{children:"Partial Set Security introduces a number of queries to assist validators determine which consumer chains they have to\nvalidate, their commission rate per chain, etc."}),"\n",(0,t.jsx)(i.h3,{id:"which-chains-does-a-validator-have-to-validate",children:"Which chains does a validator have to validate?"}),"\n",(0,t.jsx)(i.p,{children:"Naturally, a validator is aware of the Opt-In chains it has to validate because in order to validate an Opt-In chain,\na validator has to manually opt in to the chain. This is not the case for Top N chains where a validator might be required\nto validate such a chain without explicitly opting in if it belongs to the top N% of the validators on the provider."}),"\n",(0,t.jsx)(i.p,{children:"We introduce the following query:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider has-to-validate \n"})}),"\n",(0,t.jsxs)(i.p,{children:["that can be used by validator with ",(0,t.jsx)(i.code,{children:"provider-validator-address"})," address to retrieve the list of chains that it has to validate."]}),"\n",(0,t.jsx)(i.admonition,{type:"tip",children:(0,t.jsxs)(i.p,{children:["As a validator, the list of chains returned by ",(0,t.jsx)(i.code,{children:"has-to-validate"})," is the list of chains you ",(0,t.jsx)(i.strong,{children:"should"})," be validating to avoid\ngetting jailed for downtime."]})}),"\n",(0,t.jsx)(i.h3,{id:"how-do-you-know-how-much-voting-power-you-need-to-have-to-be-in-the-top-n-for-a-chain",children:"How do you know how much voting power you need to have to be in the top N for a chain?"}),"\n",(0,t.jsxs)(i.p,{children:["This can be seen as part of the ",(0,t.jsx)(i.code,{children:"list-consumer-chains"})," query:"]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider list-consumer-chains\n"})}),"\n",(0,t.jsxs)(i.p,{children:["where the ",(0,t.jsx)(i.code,{children:"min_power_in_top_N"})," field shows the minimum voting power required to be\nautomatically opted in to the chain."]}),"\n",(0,t.jsx)(i.admonition,{type:"tip",children:(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.code,{children:"list-consumer-chains"})," shows the minimal voting power ",(0,t.jsx)(i.em,{children:"right now"}),", but\nthe automatic opt-in happens only when epochs end on the provider.\nIn consequence, a validators power might be large enough to be automatically opted in\nduring an epoch, but if their power is sufficiently decreased before the epoch ends,\nthey will not be opted in automatically."]})}),"\n",(0,t.jsx)(i.h3,{id:"how-to-retrieve-all-the-opted-in-validators-on-a-consumer-chain",children:"How to retrieve all the opted-in validators on a consumer chain?"}),"\n",(0,t.jsx)(i.p,{children:"With the following query:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider consumer-opted-in-validators \n"})}),"\n",(0,t.jsxs)(i.p,{children:["we can see all the opted-in validators on ",(0,t.jsx)(i.code,{children:"consumer-chain-id"})," that were manually or automatically opted in."]}),"\n",(0,t.jsx)(i.h3,{id:"how-to-retrieve-all-the-consumer-validators-on-a-consumer-chain",children:"How to retrieve all the consumer validators on a consumer chain?"}),"\n",(0,t.jsx)(i.p,{children:"With the following query:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider consumer-validators \n"})}),"\n",(0,t.jsxs)(i.p,{children:["we can see all the ",(0,t.jsx)(i.em,{children:"consumer validators"})," (i.e., validator set) of ",(0,t.jsx)(i.code,{children:"consumer-chain-id"}),". The consumer validators are the\nones that are currently (or in the future, see warning) validating the consumer chain. A ",(0,t.jsx)(i.em,{children:"consumer validator"})," is an opted-in\nvalidator but not vice versa. For example, an opted-in validator ",(0,t.jsx)(i.code,{children:"V"})," might not be a consumer validator because ",(0,t.jsx)(i.code,{children:"V"})," is\ndenylisted or because ",(0,t.jsx)(i.code,{children:"V"})," is removed due to a validator-set cap."]}),"\n",(0,t.jsx)(i.admonition,{type:"warning",children:(0,t.jsxs)(i.p,{children:["The returned consumer validators from this query do not necessarily correspond to the validator set that is\nvalidating the consumer chain at this exact moment. This is because the ",(0,t.jsx)(i.code,{children:"VSCPacket"})," sent to a consumer chain might be\ndelayed and hence this query might return the validator set that the consumer chain would have at some future\npoint in time."]})}),"\n",(0,t.jsx)(i.h3,{id:"how-can-we-see-the-commission-rate-a-validator-has-set-on-a-consumer-chain",children:"How can we see the commission rate a validator has set on a consumer chain?"}),"\n",(0,t.jsx)(i.p,{children:"Using the following query:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider validator-consumer-commission-rate \n"})}),"\n",(0,t.jsxs)(i.p,{children:["we retrieve the commission rate set by validator with ",(0,t.jsx)(i.code,{children:"provider-validator-address"})," address on ",(0,t.jsx)(i.code,{children:"consumer-chain-id"}),"."]})]})}function l(e={}){const{wrapper:i}={...(0,o.a)(),...e.components};return i?(0,t.jsx)(i,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,i,n)=>{n.d(i,{Z:()=>r,a:()=>s});var t=n(7294);const o={},a=t.createContext(o);function s(e){const i=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function r(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),t.createElement(a.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/70938a03.0a87b3b7.js b/assets/js/70938a03.0a87b3b7.js
new file mode 100644
index 0000000000..f41a3a17f4
--- /dev/null
+++ b/assets/js/70938a03.0a87b3b7.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5457],{5610:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>l,frontMatter:()=>a,metadata:()=>r,toc:()=>d});var t=i(5893),s=i(1151);const a={sidebar_position:5},o="Changeover Procedure",r={id:"consumer-development/changeover-procedure",title:"Changeover Procedure",description:"Chains that were not initially launched as consumers of Interchain Security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the changeover procedure and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain.",source:"@site/docs/consumer-development/changeover-procedure.md",sourceDirName:"consumer-development",slug:"/consumer-development/changeover-procedure",permalink:"/interchain-security/consumer-development/changeover-procedure",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"tutorialSidebar",previous:{title:"Offboarding Checklist",permalink:"/interchain-security/consumer-development/offboarding"},next:{title:"Consumer Genesis Transformation",permalink:"/interchain-security/consumer-development/consumer-genesis-transformation"}},c={},d=[{value:"Overview",id:"overview",level:2},{value:"1. ConsumerAddition proposal submitted to the provider chain",id:"1-consumeraddition-proposal-submitted-to-the-provider-chain",level:3},{value:"2. upgrade proposal on standalone chain",id:"2-upgrade-proposal-on-standalone-chain",level:3},{value:"3. spawn time is reached",id:"3-spawn-time-is-reached",level:3},{value:"4. standalone chain upgrade",id:"4-standalone-chain-upgrade",level:3},{value:"Notes",id:"notes",level:4},{value:"Onboarding Checklist",id:"onboarding-checklist",level:2},{value:"1. Complete testing & integration",id:"1-complete-testing--integration",level:2},{value:"2. Create an Onboarding Repository",id:"2-create-an-onboarding-repository",level:2},{value:"3. Submit a ConsumerChainAddition Governance Proposal to the provider",id:"3-submit-a-consumerchainaddition-governance-proposal-to-the-provider",level:2},{value:"3. Submit an Upgrade Proposal & Prepare for Changeover",id:"3-submit-an-upgrade-proposal--prepare-for-changeover",level:2},{value:"4. Upgrade time \ud83d\ude80",id:"4-upgrade-time-",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",input:"input",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"changeover-procedure",children:"Changeover Procedure"}),"\n",(0,t.jsxs)(n.p,{children:["Chains that were ",(0,t.jsx)(n.strong,{children:"not"})," initially launched as consumers of Interchain Security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the ",(0,t.jsx)(n.strong,{children:"changeover procedure"})," and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain."]}),"\n",(0,t.jsx)(n.p,{children:"The relevant protocol specifications are available below:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/overview_and_basic_concepts.md#channel-initialization-existing-chains",children:"ICS-28 with existing chains"}),"."]}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/interchain-security/adrs/adr-010-standalone-changeover",children:"ADR in ICS repo"})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,t.jsx)(n.p,{children:"Standalone to consumer changeover procedure can roughly be separated into 4 parts:"}),"\n",(0,t.jsxs)(n.h3,{id:"1-consumeraddition-proposal-submitted-to-the-provider-chain",children:["1. ConsumerAddition proposal submitted to the ",(0,t.jsx)(n.code,{children:"provider"})," chain"]}),"\n",(0,t.jsx)(n.p,{children:'The proposal is equivalent to the "normal" ConsumerAddition proposal submitted by new consumer chains.'}),"\n",(0,t.jsx)(n.p,{children:"However, here are the most important notes and differences between a new consumer chain and a standalone chain performing a changeover:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"chain_id"})," must be equal to the standalone chain id"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"initial_height"})," field has additional rules to abide by:"]}),"\n"]}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:'{\n...\n "initial_height" : {\n // must correspond to current revision number of standalone chain\n // e.g. stride-1 => "revision_number": 1\n "revision_number": 1,\n\n // must correspond to a height that is at least 1 block after the upgrade\n // that will add the `consumer` module to the standalone chain\n // e.g. "upgrade_height": 100 => "revision_height": 101\n "revision_height": 1,\n },\n...\n}\n'})}),(0,t.jsx)(n.p,{children:"RevisionNumber: 0, RevisionHeight: 111"})]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"genesis_hash"})," can be safely ignored because the chain is already running. A hash of the standalone chain's initial genesis may be used"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"binary_hash"})," may not be available ahead of time. All chains performing the changeover go through rigorous testing - if bugs are caught and fixed the hash listed in the proposal may not be the most recent one."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"spawn_time"})," listed in the proposal MUST be before the ",(0,t.jsx)(n.code,{children:"upgrade_height"})," listed in the upgrade proposal on the standalone chain."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"spawn_time"})," must occur before the ",(0,t.jsx)(n.code,{children:"upgrade_height"})," on the standalone chain is reached because the ",(0,t.jsx)(n.code,{children:"provider"})," chain must generate the ",(0,t.jsx)(n.code,{children:"ConsumerGenesis"})," that contains the ",(0,t.jsx)(n.strong,{children:"validator set"})," that will be used after the changeover."]})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"unbonding_period"})," must correspond to the value used on the standalone chain. Otherwise, the clients used for the ccv protocol may be incorrectly initialized."]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"distribution_transmission_channel"})," ",(0,t.jsx)(n.strong,{children:"should be set"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.admonition,{type:"note",children:[(0,t.jsxs)(n.p,{children:["Populating ",(0,t.jsx)(n.code,{children:"distribution_transmission_channel"})," will enable the standalone chain to reuse one of the existing channels to the provider for consumer chain rewards distribution. This will preserve the ",(0,t.jsx)(n.code,{children:"ibc denom"})," that may already be in use."]}),(0,t.jsx)(n.p,{children:"If the parameter is not set, a new channel will be created."})]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ccv_timeout_period"})," has no important notes"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"transfer_timeout_period"})," has no important notes"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"consumer_redistribution_fraction"})," has no important notes"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"blocks_per_distribution_transmission"})," has no important notes"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"historical_entries"})," has no important notes"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"2-upgrade-proposal-on-standalone-chain",children:"2. upgrade proposal on standalone chain"}),"\n",(0,t.jsxs)(n.p,{children:["The standalone chain creates an upgrade proposal to include the ",(0,t.jsx)(n.code,{children:"interchain-security/x/ccv/consumer"})," module."]}),"\n",(0,t.jsx)(n.admonition,{type:"caution",children:(0,t.jsxs)(n.p,{children:["The upgrade height in the proposal should correspond to a height that is after the ",(0,t.jsx)(n.code,{children:"spawn_time"})," in the consumer addition proposal submitted to the ",(0,t.jsx)(n.code,{children:"provider"})," chain."]})}),"\n",(0,t.jsx)(n.p,{children:"Otherwise, the upgrade is indistinguishable from a regular on-chain upgrade proposal."}),"\n",(0,t.jsx)(n.h3,{id:"3-spawn-time-is-reached",children:"3. spawn time is reached"}),"\n",(0,t.jsxs)(n.p,{children:["When the ",(0,t.jsx)(n.code,{children:"spawn_time"})," is reached on the ",(0,t.jsx)(n.code,{children:"provider"})," it will generate a ",(0,t.jsx)(n.code,{children:"ConsumerGenesis"})," that contains the validator set that will supersede the ",(0,t.jsx)(n.code,{children:"standalone"})," validator set."]}),"\n",(0,t.jsxs)(n.p,{children:["This ",(0,t.jsx)(n.code,{children:"ConsumerGenesis"})," must be available on the standalone chain during the on-chain upgrade."]}),"\n",(0,t.jsx)(n.h3,{id:"4-standalone-chain-upgrade",children:"4. standalone chain upgrade"}),"\n",(0,t.jsxs)(n.p,{children:["Performing the on-chain upgrade on the standalone chain will add the ",(0,t.jsx)(n.code,{children:"ccv/consumer"})," module and allow the chain to become a ",(0,t.jsx)(n.code,{children:"consumer"})," of Interchain Security."]}),"\n",(0,t.jsxs)(n.admonition,{type:"caution",children:[(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"ConsumerGenesis"})," must be exported to a file and placed in the correct folder on the standalone chain before the upgrade."]}),(0,t.jsx)(n.p,{children:"The file must be placed at the exact specified location, otherwise the upgrade will not be executed correctly."}),(0,t.jsxs)(n.p,{children:["Usually the file is placed in ",(0,t.jsx)(n.code,{children:"$NODE_HOME/config"}),", but the file name and the exact directory is dictated by the upgrade code on the ",(0,t.jsx)(n.code,{children:"standalone"})," chain."]}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["please check exact instructions provided by the ",(0,t.jsx)(n.code,{children:"standalone"})," chain team"]}),"\n"]})]}),"\n",(0,t.jsxs)(n.p,{children:["After the ",(0,t.jsx)(n.code,{children:"genesis.json"})," file has been made available, the process is equivalent to a normal on-chain upgrade. The standalone validator set will sign the next couple of blocks before transferring control to ",(0,t.jsx)(n.code,{children:"provider"})," validator set."]}),"\n",(0,t.jsxs)(n.p,{children:["The standalone validator set can still be slashed for any infractions if evidence is submitted within the ",(0,t.jsx)(n.code,{children:"unboding_period"}),"."]}),"\n",(0,t.jsx)(n.h4,{id:"notes",children:"Notes"}),"\n",(0,t.jsx)(n.p,{children:"The changeover procedure may be updated in the future to create a seamless way of providing the validator set information to the standalone chain."}),"\n",(0,t.jsx)(n.h2,{id:"onboarding-checklist",children:"Onboarding Checklist"}),"\n",(0,t.jsxs)(n.p,{children:["This onboarding checklist is slightly different from the one under ",(0,t.jsx)(n.a,{href:"/interchain-security/consumer-development/onboarding",children:"Onboarding"})]}),"\n",(0,t.jsxs)(n.p,{children:["Additionally, you can check the ",(0,t.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md",children:"testnet repo"})," for a comprehensive guide on preparing and launching consumer chains."]}),"\n",(0,t.jsx)(n.h2,{id:"1-complete-testing--integration",children:"1. Complete testing & integration"}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test integration with gaia"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test your protocol with supported relayer versions (minimum hermes 1.4.1)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test the changeover procedure"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","reach out to the ICS team if you are facing issues"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"2-create-an-onboarding-repository",children:"2. Create an Onboarding Repository"}),"\n",(0,t.jsx)(n.p,{children:"To help validators and other node runners onboard onto your chain, please prepare a repository with information on how to run your chain."}),"\n",(0,t.jsx)(n.p,{children:"This should include (at minimum):"}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json with CCV data (after spawn time passes). Check if CCV data needs to be transformed (see ",(0,t.jsx)(n.a,{href:"/interchain-security/consumer-development/consumer-genesis-transformation",children:"Transform Consumer Genesis"}),")"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","information about relevant seed/peer nodes you are running"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","relayer information (compatible versions)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","copy of your governance proposal (as JSON)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","a script showing how to start your chain and connect to peers (optional)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take feedback from other developers, validators and community regarding your onboarding repo and make improvements where applicable"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Example of such a repository can be found ",(0,t.jsx)(n.a,{href:"https://github.com/hyphacoop/ics-testnets/tree/main/game-of-chains-2022/sputnik",children:"here"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"3-submit-a-consumerchainaddition-governance-proposal-to-the-provider",children:"3. Submit a ConsumerChainAddition Governance Proposal to the provider"}),"\n",(0,t.jsxs)(n.p,{children:["Before you submit a ",(0,t.jsx)(n.code,{children:"ConsumerChainAddition"})," proposal, please provide a ",(0,t.jsx)(n.code,{children:"spawn_time"})," that is ",(0,t.jsx)(n.strong,{children:"before"})," the ",(0,t.jsx)(n.code,{children:"upgrade_height"})," of the upgrade that will introduce the ",(0,t.jsx)(n.code,{children:"ccv module"})," to your chain."]}),"\n",(0,t.jsx)(n.admonition,{type:"danger",children:(0,t.jsxs)(n.p,{children:["If the ",(0,t.jsx)(n.code,{children:"spawn_time"})," happens after your ",(0,t.jsx)(n.code,{children:"upgrade_height"})," the provider will not be able to communicate the new validator set to be used after the changeover."]})}),"\n",(0,t.jsxs)(n.p,{children:["Additionally, reach out to the community via the ",(0,t.jsx)(n.a,{href:"https://forum.cosmos.network/",children:"forum"})," to formalize your intention to become an ICS consumer, gather community support and accept feedback from the community, validators and developers."]}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine your chain's spawn time"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine consumer chain parameters to be put in the proposal"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take note to include a link to your onboarding repository"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Example of a consumer chain addition proposal (compare with the ",(0,t.jsx)(n.a,{href:"/interchain-security/consumer-development/onboarding#3-submit-a-governance-proposal",children:"ConsumerAdditionProposal"})," in the ICS Provider Proposals section for chains that ",(0,t.jsx)(n.em,{children:"launch"})," as consumers):"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'// ConsumerAdditionProposal is a governance proposal on the provider chain to spawn a new consumer chain or add a standalone chain.\n// If it passes, then a subset (i.e., depends on `top_N` and on the power shaping parameters) of validators on the provider chain are expected\n// to validate the consumer chain at spawn time. It is recommended that spawn time occurs after the proposal end time and that it is \n// scheduled to happen before the standalone chain upgrade that sill introduce the ccv module.\n{\n // Title of the proposal\n "title": "Changeover Standalone chain",\n // Description of the proposal\n // format the text as a .md file and include the file in your onboarding repository\n "description": ".md description of your chain and all other relevant information",\n // Proposed chain-id of the new consumer chain.\n // Must be unique from all other consumer chain ids of the executing provider chain.\n "chain_id": "standalone-1",\n // Initial height of new consumer chain.\n "initial_height" : {\n // must correspond to current revision number of standalone chain\n // e.g. standalone-1 => "revision_number": 1\n "revision_number": 1,\n\n // must correspond to a height that is at least 1 block after the upgrade\n // that will add the `consumer` module to the standalone chain\n // e.g. "upgrade_height": 100 => "revision_height": 101\n "revision_number": 1,\n },\n // Hash of the consumer chain genesis state without the consumer CCV module genesis params.\n // => not relevant for changeover procedure\n "genesis_hash": "d86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0",\n // Hash of the consumer chain binary that should be run by validators on standalone chain upgrade\n // => not relevant for changeover procedure as it may become stale\n "binary_hash": "376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1",\n // Time on the provider chain at which the consumer chain genesis is finalized and all validators\n // will be responsible for starting their consumer chain validator node.\n "spawn_time": "2023-02-28T20:40:00.000000Z",\n // Unbonding period for the consumer chain.\n // It should should be smaller than that of the provider.\n "unbonding_period": 86400000000000,\n // Timeout period for CCV related IBC packets.\n // Packets are considered timed-out after this interval elapses.\n "ccv_timeout_period": 259200000000000,\n // IBC transfer packets will timeout after this interval elapses.\n "transfer_timeout_period": 1800000000000,\n // The fraction of tokens allocated to the consumer redistribution address during distribution events.\n // The fraction is a string representing a decimal number. For example "0.75" would represent 75%.\n // The reward amount distributed to the provider is calculated as: 1 - consumer_redistribution_fraction.\n "consumer_redistribution_fraction": "0.75",\n // BlocksPerDistributionTransmission is the number of blocks between IBC token transfers from the consumer chain to the provider chain.\n // eg. send rewards to the provider every 1000 blocks\n "blocks_per_distribution_transmission": 1000,\n // The number of historical info entries to persist in store.\n // This param is a part of the cosmos sdk staking module. In the case of\n // a ccv enabled consumer chain, the ccv module acts as the staking module.\n "historical_entries": 10000,\n // The ID of a token transfer channel used for the Reward Distribution\n\t// sub-protocol. If DistributionTransmissionChannel == "", a new transfer\n\t// channel is created on top of the same connection as the CCV channel.\n\t// Note that transfer_channel_id is the ID of the channel end on the consumer chain.\n // it is most relevant for chains performing a standalone to consumer changeover\n // in order to maintain the existing ibc transfer channel\n "distribution_transmission_channel": "channel-123" // NOTE: use existing transfer channel if available\n // Corresponds to the percentage of validators that have to validate the chain under the Top N case.\n // For example, 53 corresponds to a Top 53% chain, meaning that the top 53% provider validators by voting power\n // have to validate the proposed consumer chain. top_N can either be 0 or any value in [50, 100].\n // A chain can join with top_N == 0 as an Opt In chain, or with top_N \u2208 [50, 100] as a Top N chain.\n "top_N": 95,\n // Corresponds to the maximum power (percentage-wise) a validator can have on the consumer chain. For instance, if\n // `validators_power_cap` is set to 32, it means that no validator can have more than 32% of the voting power on the\n // consumer chain. Note that this might not be feasible. For example, think of a consumer chain with only\n // 5 validators and with `validators_power_cap` set to 10%. In such a scenario, at least one validator would need\n // to have more than 20% of the total voting power. Therefore, `validators_power_cap` operates on a best-effort basis.\n "validators_power_cap": 0,\n // Corresponds to the maximum number of validators that can validate a consumer chain.\n // Only applicable to Opt In chains. Setting `validator_set_cap` on a Top N chain is a no-op.\n "validator_set_cap": 0,\n // Corresponds to a list of provider consensus addresses of validators that are the ONLY ones that can validate\n // the consumer chain.\n "allowlist": [],\n // Corresponds to a list of provider consensus addresses of validators that CANNOT validate the consumer chain.\n "denylist": []\n}\n'})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["As seen in the ",(0,t.jsx)(n.code,{children:"ConsumerAdditionProposal"})," example above, the changeover procedure can be used together with ",(0,t.jsx)(n.a,{href:"/interchain-security/adrs/adr-015-partial-set-security",children:"Partial Set Security"}),".\nThis means, that a standalone chain can choose to only be validated by some of the validators of the provider chain by setting ",(0,t.jsx)(n.code,{children:"top_N"})," appropriately, or by\nadditionally setting a validators-power cap, validator-set cap, etc. by using the ",(0,t.jsx)(n.a,{href:"/interchain-security/features/power-shaping",children:"power-shaping parameters"}),"."]})}),"\n",(0,t.jsx)(n.h2,{id:"3-submit-an-upgrade-proposal--prepare-for-changeover",children:"3. Submit an Upgrade Proposal & Prepare for Changeover"}),"\n",(0,t.jsxs)(n.p,{children:["This proposal should add the ccv ",(0,t.jsx)(n.code,{children:"consumer"})," module to your chain."]}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","proposal ",(0,t.jsx)(n.code,{children:"upgrade_height"})," must happen after ",(0,t.jsx)(n.code,{children:"spawn_time"})," in the ",(0,t.jsx)(n.code,{children:"ConsumerAdditionProposal"})]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","advise validators about the exact procedure for your chain and point them to your onboarding repository"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"4-upgrade-time-",children:"4. Upgrade time \ud83d\ude80"}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","after ",(0,t.jsx)(n.code,{children:"spawn_time"}),", request ",(0,t.jsx)(n.code,{children:"ConsumerGenesis"})," from the ",(0,t.jsx)(n.code,{children:"provider"})," and place it in ",(0,t.jsx)(n.code,{children:"/.sovereign/config/genesis.json"})]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","upgrade the binary to the one listed in your ",(0,t.jsx)(n.code,{children:"UpgradeProposal"})]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:['The chain starts after at least 66.67% of standalone voting power comes online. The consumer chain is considered interchain secured once the "old" validator set signs a couple of blocks and transfers control to the ',(0,t.jsx)(n.code,{children:"provider"})," validator set."]}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","provide a repo with onboarding instructions for validators (it should already be listed in the proposal)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json after ",(0,t.jsx)(n.code,{children:"spawn_time"})," obtained from ",(0,t.jsx)(n.code,{children:"provider"})," (MUST contain the initial validator set)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","maintenance & emergency contact info (relevant discord, telegram, slack or other communication channels)"]}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>o});var t=i(7294);const s={},a=t.createContext(s);function o(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/72e9af3b.840537aa.js b/assets/js/72e9af3b.840537aa.js
new file mode 100644
index 0000000000..167031113e
--- /dev/null
+++ b/assets/js/72e9af3b.840537aa.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[903],{8161:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>d});var n=o(5893),i=o(1151);const s={sidebar_position:10,title:"Soft Opt-Out"},a=void 0,r={id:"adrs/adr-009-soft-opt-out",title:"Soft Opt-Out",description:"ADR 009: Soft Opt-Out",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-009-soft-opt-out.md",sourceDirName:"adrs",slug:"/adrs/adr-009-soft-opt-out",permalink:"/interchain-security/v5.0.0/adrs/adr-009-soft-opt-out",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:10,frontMatter:{sidebar_position:10,title:"Soft Opt-Out"},sidebar:"tutorialSidebar",previous:{title:"Throttle with retries",permalink:"/interchain-security/v5.0.0/adrs/adr-008-throttle-retries"},next:{title:"Standalone to Consumer Changeover",permalink:"/interchain-security/v5.0.0/adrs/adr-010-standalone-changeover"}},l={},d=[{value:"ADR 009: Soft Opt-Out",id:"adr-009-soft-opt-out",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function c(e){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"adr-009-soft-opt-out",children:"ADR 009: Soft Opt-Out"}),"\n",(0,n.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"6/13/23: Initial draft of ADR. Feature already implemented and in production."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,n.jsx)(t.p,{children:"Accepted"}),"\n",(0,n.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,n.jsxs)(t.p,{children:["Some small validators may not have the resources needed to validate all consumer chains. Therefore a need exists to allow the bottom ",(0,n.jsx)(t.code,{children:"x%"})," of validators to opt-out of validating a consumer chain. Meaning downtime infractions for these validators are dropped without ever reaching the provider."]}),"\n",(0,n.jsx)(t.p,{children:"This document specifies a modification to the ccv protocol which allows the bottom x% of the validator set by power to opt out of validating consumer chains without being jailed or otherwise punished for it. The feature is implemented with entirely consumer-side code."}),"\n",(0,n.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,n.jsxs)(t.p,{children:["A consumer param exists, known as ",(0,n.jsx)(t.code,{children:"SoftOptOutThreshold"}),", which is a string decimal in the range of [0, 0.2], that determines the portion of validators which are allowed to opt out of validating that specific consumer."]}),"\n",(0,n.jsxs)(t.p,{children:["In every consumer beginblocker, a function is ran which determines the so called ",(0,n.jsx)(t.em,{children:"smallest non opt-out voting power"}),". Validators with voting power greater than or equal to this value must validate the consumer chain, while validators below this value may opt out of validating the consumer chain."]}),"\n",(0,n.jsxs)(t.p,{children:["The smallest non opt-out voting power is recomputed every beginblocker in ",(0,n.jsx)(t.code,{children:"UpdateSmallestNonOptOutPower()"}),". In a nutshell, the method obtains the total voting power of the consumer, iterates through the full valset (ordered power ascending) keeping track of a power sum, and when ",(0,n.jsx)(t.code,{children:"powerSum / totalPower > SoftOptOutThreshold"}),", the ",(0,n.jsx)(t.code,{children:"SmallestNonOptOutPower"})," is found and persisted."]}),"\n",(0,n.jsxs)(t.p,{children:["Then, whenever the ",(0,n.jsx)(t.code,{children:"Slash()"})," interface is executed on the consumer, if the voting power of the relevant validator being slashed is less than ",(0,n.jsx)(t.code,{children:"SmallestNonOptOutPower"})," for that block, the slash request is dropped and never sent to the provider."]}),"\n",(0,n.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,n.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Small validators can opt out of validating specific consumers without being punished for it."}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["The bottom ",(0,n.jsx)(t.code,{children:"x%"})," is still part of the total voting power of the consumer chain. This means that if the soft opt-out threshold is set to ",(0,n.jsx)(t.code,{children:"10%"})," for example, and every validator in the bottom ",(0,n.jsx)(t.code,{children:"10%"})," opts out from validating the consumer, then a ",(0,n.jsx)(t.code,{children:"24%"})," downtime of the remaining voting power would halt the chain. This may be especially problematic during consumer upgrades."]}),"\n",(0,n.jsxs)(t.li,{children:["In nominal scenarios, consumers with soft opt out enabled will be constructing slash packets for small vals, which may be dropped. This is wasted computation, but necessary to keep implementation simple. Note that the sdk's ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/d3f09c222243bb3da3464969f0366330dcb977a8/x/slashing/keeper/infractions.go#L75",children:"full downtime logic"})," is always executed on the consumer, which can be computationally expensive and slow down certain blocks."]}),"\n",(0,n.jsx)(t.li,{children:"In a consumer chain, when a validator that has opted out becomes the proposer, there will naturally be no proposal made and validators would need to move to the next consensus round for the same height to reach a decision. As a result, we would need more time to finalize blocks on a consumer chain."}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"neutral",children:"Neutral"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Validators in the bottom of the valset who don't have to validate, may receive large delegation(s) which suddenly boost the validator to the subset that has to validate. This may catch the validator off guard."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Original issue with some napkin math ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/784",children:"#784"})]}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},1151:(e,t,o)=>{o.d(t,{Z:()=>r,a:()=>a});var n=o(7294);const i={},s=n.createContext(i);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/7380b9fa.932b3293.js b/assets/js/7380b9fa.932b3293.js
new file mode 100644
index 0000000000..d78624d70a
--- /dev/null
+++ b/assets/js/7380b9fa.932b3293.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1877],{6263:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>d});var o=i(5893),s=i(1151);const t={sidebar_position:4,title:"Equivocation governance proposal"},a="ADR 003: Equivocation governance proposal",r={id:"adrs/adr-003-equivocation-gov-proposal",title:"Equivocation governance proposal",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-003-equivocation-gov-proposal.md",sourceDirName:"adrs",slug:"/adrs/adr-003-equivocation-gov-proposal",permalink:"/interchain-security/v4.2.0/adrs/adr-003-equivocation-gov-proposal",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Equivocation governance proposal"},sidebar:"tutorialSidebar",previous:{title:"Jail Throttling",permalink:"/interchain-security/v4.2.0/adrs/adr-002-throttle"},next:{title:"Cryptographic verification of equivocation evidence",permalink:"/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification"}},c={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"adr-003-equivocation-governance-proposal",children:"ADR 003: Equivocation governance proposal"}),"\n",(0,o.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"2023-02-06: Initial draft"}),"\n",(0,o.jsx)(n.li,{children:"2023-11-30: Change status to deprecated"}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,o.jsx)(n.p,{children:"Deprecated"}),"\n",(0,o.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Note:"})," ADR deprecated as the equivocation proposal was removed by the\ncryptographic verification of equivocation feature\n(see ",(0,o.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR-005"})," and\n",(0,o.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing",children:"ADR-013"}),")."]}),"\n",(0,o.jsx)(n.p,{children:"We want to limit the possibilities of a consumer chain to execute actions on the provider chain to maintain and ensure optimum security of the provider chain."}),"\n",(0,o.jsx)(n.p,{children:"For instance, a malicious consumer consumer chain can send slash packet to the provider chain, which will slash a validator without the need of providing an evidence."}),"\n",(0,o.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,o.jsx)(n.p,{children:"To protect against a malicious consumer chain, slash packets unrelated to downtime are ignored by the provider chain. Thus, an other mechanism is required to punish validators that have committed a double-sign on a consumer chain."}),"\n",(0,o.jsxs)(n.p,{children:["A new kind of governance proposal is added to the ",(0,o.jsx)(n.code,{children:"provider"})," module, allowing to slash and tombstone a validator for double-signing in case of any harmful action on the consumer chain."]}),"\n",(0,o.jsxs)(n.p,{children:["If such proposal passes, the proposal handler delegates to the ",(0,o.jsx)(n.code,{children:"evidence"})," module to process the equivocation. This module ensures the evidence isn\u2019t too old, or else ignores it (see ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/21021b837882d1d40f1d79bcbc4fad2e79a3fefe/x/evidence/keeper/infraction.go#L54-L62",children:"code"}),"). ",(0,o.jsx)(n.em,{children:"Too old"})," is determined by 2 consensus params :"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"evidence.max_age_duration"})," number of nanoseconds before an evidence is considered too old"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"evidence.max_age_numblocks"})," number of blocks before an evidence is considered too old."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"On the hub, those parameters are equals to"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'// From https://cosmos-rpc.polkachu.com/consensus_params?height=13909682\n(...)\n"evidence": {\n\t"max_age_num_blocks": "1000000",\n\t"max_age_duration": "172800000000000",\n (...)\n},\n(...)\n'})}),"\n",(0,o.jsxs)(n.p,{children:["A governance proposal takes 14 days, so those parameters must be big enough so the evidence provided in the proposal is not ignored by the ",(0,o.jsx)(n.code,{children:"evidence"})," module when the proposal passes and is handled by the hub."]}),"\n",(0,o.jsxs)(n.p,{children:["For ",(0,o.jsx)(n.code,{children:"max_age_num_blocks=1M"}),", the parameter is big enough if we consider the hub produces 12k blocks per day (",(0,o.jsx)(n.code,{children:"blocks_per_year/365 = 436,0000/365"}),"). The evidence can be up to 83 days old (",(0,o.jsx)(n.code,{children:"1,000,000/12,000"}),") and not be ignored."]}),"\n",(0,o.jsxs)(n.p,{children:["For ",(0,o.jsx)(n.code,{children:"max_age_duration=172,800,000,000,000"}),", the parameter is too low, because the value is in nanoseconds so it\u2019s 2 days. Fortunately the condition that checks those 2 parameters uses a ",(0,o.jsx)(n.strong,{children:"AND"}),", so if ",(0,o.jsx)(n.code,{children:"max_age_num_blocks"})," condition passes, the evidence won\u2019t be ignored."]}),"\n",(0,o.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,o.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Remove the possibility from a malicious consumer chain to \u201cattack\u201d the provider chain by slashing/jailing validators."}),"\n",(0,o.jsx)(n.li,{children:"Provide a more acceptable implementation for the validator community."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Punishment action of double-signing isn\u2019t \u201cautomated\u201d, a governance proposal is required which takes more time."}),"\n",(0,o.jsx)(n.li,{children:"You need to pay 250ATOM to submit an equivocation evidence."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,o.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["PR that ignores non downtime slash packet : ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/692",children:"https://github.com/cosmos/interchain-security/pull/692"})]}),"\n",(0,o.jsxs)(n.li,{children:["PR that adds the governance slash proposal: ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/703",children:"https://github.com/cosmos/interchain-security/pull/703"})]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>a});var o=i(7294);const s={},t=o.createContext(s);function a(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/758625d4.17c5d74a.js b/assets/js/758625d4.17c5d74a.js
new file mode 100644
index 0000000000..de663e7cc9
--- /dev/null
+++ b/assets/js/758625d4.17c5d74a.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[321],{5477:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>t,default:()=>h,frontMatter:()=>s,metadata:()=>d,toc:()=>c});var a=n(5893),i=n(1151);const s={sidebar_position:3},t="Consumer chain validator rewards",d={id:"validators/withdraw_rewards",title:"Consumer chain validator rewards",description:"A validator can only receive rewards from a consumer chain if the validator has been validating the consumer chain",source:"@site/docs/validators/withdraw_rewards.md",sourceDirName:"validators",slug:"/validators/withdraw_rewards",permalink:"/interchain-security/validators/withdraw_rewards",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"tutorialSidebar",previous:{title:"Joining Interchain Security testnet",permalink:"/interchain-security/validators/joining-testnet"},next:{title:"Validator Instructions for Changeover Procedure",permalink:"/interchain-security/validators/changeover-procedure"}},o={},c=[{value:"Withdrawing rewards",id:"withdrawing-rewards",level:2},{value:"Querying validator rewards",id:"querying-validator-rewards",level:2},{value:"Withdrawing rewards and commission",id:"withdrawing-rewards-and-commission",level:2},{value:"1. Withdraw rewards",id:"1-withdraw-rewards",level:3},{value:"2. Confirm withdrawal",id:"2-confirm-withdrawal",level:3}];function l(e){const r={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(r.h1,{id:"consumer-chain-validator-rewards",children:"Consumer chain validator rewards"}),"\n",(0,a.jsx)(r.admonition,{type:"warning",children:(0,a.jsxs)(r.p,{children:["A validator can only receive rewards from a consumer chain if the validator has been validating the consumer chain\nfor some time. Specifically, the validator has to be a consumer validator of the consumer chain for at least\n",(0,a.jsx)(r.code,{children:"NumberOfEpochsToStartReceivingRewards * BlocksPerEpoch"})," blocks (run ",(0,a.jsx)(r.code,{children:"interchain-security-pd query provider params"})," for\nthe actual values of the ",(0,a.jsx)(r.code,{children:"NumberOfEpochsToStartReceivingRewards"})," and ",(0,a.jsx)(r.code,{children:"BlocksPerEpoch"})," params)."]})}),"\n",(0,a.jsx)(r.h2,{id:"withdrawing-rewards",children:"Withdrawing rewards"}),"\n",(0,a.jsx)(r.p,{children:"Here are example steps for withdrawing rewards from consumer chains in the provider chain"}),"\n",(0,a.jsxs)(r.admonition,{type:"info",children:[(0,a.jsxs)(r.p,{children:["The examples used are from ",(0,a.jsx)(r.code,{children:"rs-testnet"}),", the Interchain Security persistent testnet."]}),(0,a.jsxs)(r.p,{children:["Validator operator address: ",(0,a.jsx)(r.code,{children:"cosmosvaloper1e5yfpc8l6g4808fclmlyd38tjgxuwshnmjkrq6"}),"\nSelf-delegation address: ",(0,a.jsx)(r.code,{children:"cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf"})]})]}),"\n",(0,a.jsx)(r.p,{children:"Prior to withdrawing rewards, query balances for self-delegation address:"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:'gaiad q bank balances cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf\n\nbalances:\n- amount: "1000000000000"\n denom: uatom\npagination:\n next_key: null\n total: "0"\n'})}),"\n",(0,a.jsx)(r.h2,{id:"querying-validator-rewards",children:"Querying validator rewards"}),"\n",(0,a.jsx)(r.p,{children:"Query rewards for the validator address:"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:'gaiad q distribution rewards cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf cosmosvaloper1e5yfpc8l6g4808fclmlyd38tjgxuwshnmjkrq6\n\nrewards:\n- amount: "158.069895000000000000"\n denom: ibc/2CB0E87E2A742166FEC0A18D6FBF0F6AD4AA1ADE694792C1BD6F5E99088D67FD\n- amount: "841842390516.072526500000000000"\n denom: uatom\n'})}),"\n",(0,a.jsxs)(r.p,{children:["The ",(0,a.jsx)(r.code,{children:"ibc/2CB0E87E2A742166FEC0A18D6FBF0F6AD4AA1ADE694792C1BD6F5E99088D67FD"})," denom represents rewards from a consumer chain."]}),"\n",(0,a.jsx)(r.h2,{id:"withdrawing-rewards-and-commission",children:"Withdrawing rewards and commission"}),"\n",(0,a.jsx)(r.h3,{id:"1-withdraw-rewards",children:"1. Withdraw rewards"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:"gaiad tx distribution withdraw-rewards cosmosvaloper1e5yfpc8l6g4808fclmlyd38tjgxuwshnmjkrq6 --from cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf --commission --chain-id provider --gas auto --fees 500uatom -b block -y\n\ntxhash: A7E384FB1958211B43B7C06527FC7D4471FB6B491EE56FDEA9C5634D76FF1B9A\n"})}),"\n",(0,a.jsx)(r.h3,{id:"2-confirm-withdrawal",children:"2. Confirm withdrawal"}),"\n",(0,a.jsx)(r.p,{children:"After withdrawing rewards self-delegation address balance to confirm rewards were withdrawn:"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:'gaiad q bank balances cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf\n\nbalances:\n- amount: "216"\n denom: ibc/2CB0E87E2A742166FEC0A18D6FBF0F6AD4AA1ADE694792C1BD6F5E99088D67FD\n- amount: "2233766225342"\n denom: uatom\npagination:\n next_key: null\n total: "0"\n'})})]})}function h(e={}){const{wrapper:r}={...(0,i.a)(),...e.components};return r?(0,a.jsx)(r,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},1151:(e,r,n)=>{n.d(r,{Z:()=>d,a:()=>t});var a=n(7294);const i={},s=a.createContext(i);function t(e){const r=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function d(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),a.createElement(s.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/75f9ba63.bf714c2a.js b/assets/js/75f9ba63.bf714c2a.js
new file mode 100644
index 0000000000..4d3ac11e70
--- /dev/null
+++ b/assets/js/75f9ba63.bf714c2a.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5296],{2372:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>s,default:()=>l,frontMatter:()=>a,metadata:()=>r,toc:()=>h});var o=n(5893),t=n(1151);const a={sidebar_position:6},s="Partial Set Security",r={id:"validators/partial-set-security-for-validators",title:"Partial Set Security",description:"Partial Set Security allows consumer chains to join as Opt-In or Top N.",source:"@site/versioned_docs/version-v4.2.0-docs/validators/partial-set-security-for-validators.md",sourceDirName:"validators",slug:"/validators/partial-set-security-for-validators",permalink:"/interchain-security/v4.2.0/validators/partial-set-security-for-validators",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Joining Stride",permalink:"/interchain-security/v4.2.0/validators/joining-stride"},next:{title:"Frequently Asked Questions",permalink:"/interchain-security/v4.2.0/faq"}},c={},h=[{value:"Messages",id:"messages",level:2},{value:"How to opt in to a consumer chain?",id:"how-to-opt-in-to-a-consumer-chain",level:3},{value:"How to opt out from a consumer chain?",id:"how-to-opt-out-from-a-consumer-chain",level:3},{value:"How to set specific per consumer chain commission rate?",id:"how-to-set-specific-per-consumer-chain-commission-rate",level:3},{value:"Queries",id:"queries",level:2},{value:"Which chains does a validator have to validate?",id:"which-chains-does-a-validator-have-to-validate",level:3},{value:"How do you know how much voting power you need to have to be in the top N for a chain?",id:"how-do-you-know-how-much-voting-power-you-need-to-have-to-be-in-the-top-n-for-a-chain",level:3},{value:"How to retrieve all the opted-in validators on a consumer chain?",id:"how-to-retrieve-all-the-opted-in-validators-on-a-consumer-chain",level:3},{value:"How to retrieve all the consumer validators on a consumer chain?",id:"how-to-retrieve-all-the-consumer-validators-on-a-consumer-chain",level:3},{value:"How can we see the commission rate a validator has set on a consumer chain?",id:"how-can-we-see-the-commission-rate-a-validator-has-set-on-a-consumer-chain",level:3}];function d(e){const i={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(i.h1,{id:"partial-set-security",children:"Partial Set Security"}),"\n",(0,o.jsxs)(i.p,{children:[(0,o.jsx)(i.a,{href:"/interchain-security/v4.2.0/features/partial-set-security",children:"Partial Set Security"})," allows consumer chains to join as Opt-In or Top N.\nHere, we show how a validator can opt in, opt out, or set a custom commission rate on a consumer chain, as well\nas useful queries that a validator can use to figure out which chains it has to validate, etc."]}),"\n",(0,o.jsx)(i.h2,{id:"messages",children:"Messages"}),"\n",(0,o.jsx)(i.h3,{id:"how-to-opt-in-to-a-consumer-chain",children:"How to opt in to a consumer chain?"}),"\n",(0,o.jsx)(i.admonition,{type:"warning",children:(0,o.jsx)(i.p,{children:"A validator is automatically opted in to a Top N chain if the validator belongs to the top N% of the validators on the provider chain."})}),"\n",(0,o.jsx)(i.p,{children:"In a Top N chain, a validator that does not belong to the top N% of the validators on the provider can still choose\nto opt in to a consumer chain. In other words, validators can opt in, in both Opt-In and Top N chains."}),"\n",(0,o.jsx)(i.p,{children:"A validator can opt in to a consumer chain by issuing the following message:"}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd tx provider opt-in \n"})}),"\n",(0,o.jsx)(i.p,{children:"where"}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"consumer-chain-id"})," is the string identifier of the consumer chain the validator wants to opt in to;"]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"consumer-pub-key"})," corresponds to the public key the validator wants to use on the consumer chain, and it has the\nfollowing format ",(0,o.jsx)(i.code,{children:'{"@type":"/cosmos.crypto.ed25519.PubKey","key":""}'}),"."]}),"\n"]}),"\n",(0,o.jsxs)(i.p,{children:["A validator can opt in to an existing consumer chain that is already running, or to a ",(0,o.jsx)(i.a,{href:"/interchain-security/v4.2.0/features/proposals",children:"proposed"}),"\nconsumer chain that is still being voted on. A validator can use the following command to retrieve the currently existing\nconsumer chains:"]}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider list-consumer-chains\n"})}),"\n",(0,o.jsx)(i.p,{children:"and this command to see the currently proposed consumer chains:"}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider list-proposed-consumer-chains\n"})}),"\n",(0,o.jsx)(i.admonition,{type:"tip",children:(0,o.jsxs)(i.p,{children:["By setting the ",(0,o.jsx)(i.code,{children:"consumer-pub-key"}),", a validator can both opt in to a chain and assign a\npublic key on a consumer chain. Note that a validator can always ",(0,o.jsx)(i.a,{href:"/interchain-security/v4.2.0/features/key-assignment",children:"assign"}),"\na new consumer key at a later stage. The key-assignment ",(0,o.jsx)(i.a,{href:"/interchain-security/v4.2.0/features/key-assignment#rules",children:"rules"}),"\nstill apply when setting ",(0,o.jsx)(i.code,{children:"consumer-pub-key"})," when opting in."]})}),"\n",(0,o.jsx)(i.admonition,{type:"info",children:(0,o.jsx)(i.p,{children:"A validator is only eligible for consumer rewards from a consumer chain if the validator is opted into that chain."})}),"\n",(0,o.jsx)(i.h3,{id:"how-to-opt-out-from-a-consumer-chain",children:"How to opt out from a consumer chain?"}),"\n",(0,o.jsx)(i.p,{children:"A validator can opt out from a consumer by issuing the following message:"}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd tx provider opt-out \n"})}),"\n",(0,o.jsx)(i.p,{children:"where"}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"consumer-chain-id"})," is the string identifier of the consumer chain."]}),"\n"]}),"\n",(0,o.jsx)(i.admonition,{type:"warning",children:(0,o.jsx)(i.p,{children:"A validator cannot opt out from a Top N chain if it belongs to the top N% validators of the provider."})}),"\n",(0,o.jsx)(i.admonition,{type:"warning",children:(0,o.jsxs)(i.p,{children:["If a validator moves from the Top N to outside of the top N% of the validators on the provider, it will ",(0,o.jsx)(i.strong,{children:"not"}),"\nbe automatically opted-out. The validator has to manually opt out."]})}),"\n",(0,o.jsx)(i.admonition,{type:"warning",children:(0,o.jsxs)(i.p,{children:["A validator can stop its node on a consumer chain ",(0,o.jsx)(i.strong,{children:"only"})," after opting out and confirming through the ",(0,o.jsx)(i.code,{children:"has-to-validate"}),"\nquery (see ",(0,o.jsx)(i.a,{href:"/interchain-security/v4.2.0/validators/partial-set-security-for-validators#which-chains-does-a-validator-have-to-validate",children:"below"}),") that it does\nnot have to validate the consumer chain any longer."]})}),"\n",(0,o.jsx)(i.admonition,{type:"warning",children:(0,o.jsx)(i.p,{children:"If all validators opt out from an Opt-In chain, the chain will halt with a consensus failure upon receiving the VSCPacket with an empty validator set."})}),"\n",(0,o.jsx)(i.h3,{id:"how-to-set-specific-per-consumer-chain-commission-rate",children:"How to set specific per consumer chain commission rate?"}),"\n",(0,o.jsx)(i.p,{children:"A validator can choose to set a different commission rate on each of the consumer chains.\nThis can be done with the following command:"}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd tx provider set-consumer-commission-rate \n"})}),"\n",(0,o.jsx)(i.p,{children:"where"}),"\n",(0,o.jsxs)(i.ul,{children:["\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"consumer-chain-id"})," is the string identifier of the consumer chain;"]}),"\n",(0,o.jsxs)(i.li,{children:[(0,o.jsx)(i.code,{children:"comission-rate"})," decimal in ",(0,o.jsx)(i.code,{children:"[minRate, 1]"})," where ",(0,o.jsx)(i.code,{children:"minRate"})," corresponds to the minimum commission rate set on the\nprovider chain (see ",(0,o.jsx)(i.code,{children:"min_commission_rate"})," in ",(0,o.jsx)(i.code,{children:"interchain-security-pd query staking params"}),")."]}),"\n"]}),"\n",(0,o.jsx)(i.p,{children:"If a validator does not set a commission rate on a consumer chain, the commission rate defaults to their commission rate on the provider chain."}),"\n",(0,o.jsx)(i.admonition,{type:"tip",children:(0,o.jsx)(i.p,{children:"Validators can set their commission rate even for consumer chains that they are not currently opted in on, and the commission rate will be applied when they opt in. This is particularly useful for Top N chains, where validators might be opted in automatically,\nso validators can set the commission rate in advance."})}),"\n",(0,o.jsx)(i.admonition,{type:"tip",children:(0,o.jsxs)(i.p,{children:["If a validator opts out and then back in, this will ",(0,o.jsx)(i.em,{children:"not"})," reset their commission rate back to the default. Instead, their\nset commission rate still applies."]})}),"\n",(0,o.jsx)(i.h2,{id:"queries",children:"Queries"}),"\n",(0,o.jsx)(i.p,{children:"Partial Set Security introduces a number of queries to assist validators determine which consumer chains they have to\nvalidate, their commission rate per chain, etc."}),"\n",(0,o.jsx)(i.h3,{id:"which-chains-does-a-validator-have-to-validate",children:"Which chains does a validator have to validate?"}),"\n",(0,o.jsx)(i.p,{children:"Naturally, a validator is aware of the Opt-In chains it has to validate because in order to validate an Opt-In chain,\na validator has to manually opt in to the chain. This is not the case for Top N chains where a validator might be required\nto validate such a chain without explicitly opting in if it belongs to the top N% of the validators on the provider."}),"\n",(0,o.jsx)(i.p,{children:"We introduce the following query:"}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider has-to-validate \n"})}),"\n",(0,o.jsxs)(i.p,{children:["that can be used by validator with ",(0,o.jsx)(i.code,{children:"provider-validator-address"})," address to retrieve the list of chains that it has to validate."]}),"\n",(0,o.jsx)(i.admonition,{type:"tip",children:(0,o.jsxs)(i.p,{children:["As a validator, the list of chains returned by ",(0,o.jsx)(i.code,{children:"has-to-validate"})," is the list of chains you ",(0,o.jsx)(i.strong,{children:"should"})," be validating to avoid\ngetting jailed for downtime."]})}),"\n",(0,o.jsx)(i.h3,{id:"how-do-you-know-how-much-voting-power-you-need-to-have-to-be-in-the-top-n-for-a-chain",children:"How do you know how much voting power you need to have to be in the top N for a chain?"}),"\n",(0,o.jsxs)(i.p,{children:["This can be seen as part of the ",(0,o.jsx)(i.code,{children:"list-consumer-chains"})," query:"]}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider list-consumer-chains\n"})}),"\n",(0,o.jsxs)(i.p,{children:["where the ",(0,o.jsx)(i.code,{children:"min_power_in_top_N"})," field shows the minimum voting power required to be\nautomatically opted in to the chain."]}),"\n",(0,o.jsx)(i.admonition,{type:"tip",children:(0,o.jsxs)(i.p,{children:[(0,o.jsx)(i.code,{children:"list-consumer-chains"})," shows the minimal voting power ",(0,o.jsx)(i.em,{children:"right now"}),", but\nthe automatic opt-in happens only when epochs end on the provider.\nIn consequence, a validators power might be large enough to be automatically opted in\nduring an epoch, but if their power is sufficiently decreased before the epoch ends,\nthey will not be opted in automatically."]})}),"\n",(0,o.jsx)(i.h3,{id:"how-to-retrieve-all-the-opted-in-validators-on-a-consumer-chain",children:"How to retrieve all the opted-in validators on a consumer chain?"}),"\n",(0,o.jsx)(i.p,{children:"With the following query:"}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider consumer-opted-in-validators \n"})}),"\n",(0,o.jsxs)(i.p,{children:["we can see all the opted-in validators on ",(0,o.jsx)(i.code,{children:"consumer-chain-id"})," that were manually or automatically opted in."]}),"\n",(0,o.jsx)(i.h3,{id:"how-to-retrieve-all-the-consumer-validators-on-a-consumer-chain",children:"How to retrieve all the consumer validators on a consumer chain?"}),"\n",(0,o.jsx)(i.p,{children:"With the following query:"}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider consumer-validators \n"})}),"\n",(0,o.jsxs)(i.p,{children:["we can see all the ",(0,o.jsx)(i.em,{children:"consumer validators"})," (i.e., validator set) of ",(0,o.jsx)(i.code,{children:"consumer-chain-id"}),". The consumer validators are the\nones that are currently (or in the future, see warning) validating the consumer chain. A ",(0,o.jsx)(i.em,{children:"consumer validator"})," is an opted-in\nvalidator but not vice versa. For example, an opted-in validator ",(0,o.jsx)(i.code,{children:"V"})," might not be a consumer validator because ",(0,o.jsx)(i.code,{children:"V"})," is\ndenylisted or because ",(0,o.jsx)(i.code,{children:"V"})," is removed due to a validator-set cap."]}),"\n",(0,o.jsx)(i.admonition,{type:"warning",children:(0,o.jsxs)(i.p,{children:["The returned consumer validators from this query do not necessarily correspond to the validator set that is\nvalidating the consumer chain at this exact moment. This is because the ",(0,o.jsx)(i.code,{children:"VSCPacket"})," sent to a consumer chain might be\ndelayed and hence this query might return the validator set that the consumer chain would have at some future\npoint in time."]})}),"\n",(0,o.jsx)(i.h3,{id:"how-can-we-see-the-commission-rate-a-validator-has-set-on-a-consumer-chain",children:"How can we see the commission rate a validator has set on a consumer chain?"}),"\n",(0,o.jsx)(i.p,{children:"Using the following query:"}),"\n",(0,o.jsx)(i.pre,{children:(0,o.jsx)(i.code,{className:"language-bash",children:"interchain-security-pd query provider validator-consumer-commission-rate \n"})}),"\n",(0,o.jsxs)(i.p,{children:["we retrieve the commission rate set by validator with ",(0,o.jsx)(i.code,{children:"provider-validator-address"})," address on ",(0,o.jsx)(i.code,{children:"consumer-chain-id"}),"."]})]})}function l(e={}){const{wrapper:i}={...(0,t.a)(),...e.components};return i?(0,o.jsx)(i,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},1151:(e,i,n)=>{n.d(i,{Z:()=>r,a:()=>s});var o=n(7294);const t={},a=o.createContext(t);function s(e){const i=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function r(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),o.createElement(a.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/7616f23a.837a872f.js b/assets/js/7616f23a.837a872f.js
new file mode 100644
index 0000000000..32be2a2d4e
--- /dev/null
+++ b/assets/js/7616f23a.837a872f.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2247],{1422:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>r,metadata:()=>s,toc:()=>h});var o=i(5893),t=i(1151);const r={sidebar_position:1},a="Overview",s={id:"introduction/overview",title:"Overview",description:"Interchain Security is an open sourced IBC application which allows cosmos blockchains to lease their proof-of-stake security to one another.",source:"@site/docs/introduction/overview.md",sourceDirName:"introduction",slug:"/introduction/overview",permalink:"/interchain-security/introduction/overview",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Interchain Security Docs",permalink:"/interchain-security/"},next:{title:"Terminology",permalink:"/interchain-security/introduction/terminology"}},c={},h=[{value:"Why Interchain Security?",id:"why-interchain-security",level:2},{value:"Core protocol",id:"core-protocol",level:2},{value:"Downtime Slashing",id:"downtime-slashing",level:3},{value:"Tokenomics and Rewards",id:"tokenomics-and-rewards",level:3}];function l(e){const n={a:"a",admonition:"admonition",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,t.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"overview",children:"Overview"}),"\n",(0,o.jsxs)(n.admonition,{type:"info",children:[(0,o.jsx)(n.p,{children:"Interchain Security is an open sourced IBC application which allows cosmos blockchains to lease their proof-of-stake security to one another."}),(0,o.jsx)("br",{}),(0,o.jsx)(n.p,{children:'Interchain Security allows anyone to launch a "consumer" blockchain using a subset, or even the entire, validator set from the "provider" blockchain by creating a governance proposal. If the proposal is accepted, provider chain validators start validating the consumer chain as well. Consumer chains will therefore inherit security and decentralization from the provider.'})]}),"\n",(0,o.jsx)(n.h2,{id:"why-interchain-security",children:"Why Interchain Security?"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"The right amount of security for each application. Consumer chains can choose to inherit the whole validator set from the provider, or they can launch as an opt in chain where only a subset of the provider validators validate the consumer chain. This allows for a wide range of security tradeoffs."}),"\n",(0,o.jsx)(n.li,{children:"Independent block-space. Transactions on consumer chains do not compete with any other applications. This means that there will be no unexpected congestion, and performance will generally be much better than on a shared smart contract platform such as Ethereum."}),"\n",(0,o.jsx)(n.li,{children:"Projects keep majority of gas fees. Depending on configuration, these fees either go to the project\u2019s community DAO, or can be used in the protocol in other ways."}),"\n",(0,o.jsx)(n.li,{children:"No validator search. Consumer chains do not have their own validator sets, and so do not need to find validators one by one. Validators from the provider chain validate on the consumer chain with their stake on the provider chain, earning additional rewards. For the consumer chain, this comes with the benefit of exposing their chain to the wider audience of the provider chain."}),"\n",(0,o.jsx)(n.li,{children:"Instant sovereignty. Consumers can run arbitrary app logic similar to standalone chains. At any time in the future, a consumer chain can elect to become a completely standalone chain, with its own validator set."}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"core-protocol",children:"Core protocol"}),"\n",(0,o.jsx)(n.admonition,{type:"info",children:(0,o.jsxs)(n.p,{children:["Protocol specification is available as ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/overview_and_basic_concepts.md",children:"ICS-028"})," in the IBC repository."]})}),"\n",(0,o.jsx)(n.p,{children:"Once an IBC connection and proper channel is established between a provider and consumer chain, the provider will continually send validator set updates to the consumer over IBC. The consumer uses these validator set updates to update its own validator set in Comet. Thus, the provider validator set is effectively replicated on the consumer."}),"\n",(0,o.jsx)(n.p,{children:"To ensure the security of the consumer chain, provider delegators cannot unbond their tokens until the unbonding periods of each consumer chain has passed. In practice this will not be noticeable to the provider delegators, since consumer chains will be configured to have a slightly shorter unbonding period than the provider."}),"\n",(0,o.jsx)(n.h3,{id:"downtime-slashing",children:"Downtime Slashing"}),"\n",(0,o.jsx)(n.p,{children:"If downtime is initiated by a validator on a consumer chain, a downtime packet will be relayed to the provider to jail that validator for a set amount of time. The validator who committed downtime will then miss out on staking rewards for the configured jailing period."}),"\n",(0,o.jsx)(n.h3,{id:"tokenomics-and-rewards",children:"Tokenomics and Rewards"}),"\n",(0,o.jsx)(n.p,{children:"Consumer chains are free to create their own native token which can be used for fees, and can be created on the consumer chain in the form of inflationary rewards. These rewards can be used to incentivize user behavior, for example, LPing or staking. A portion of these fees and rewards will be sent to provider chain stakers, but that proportion is completely customizable by the developers, and subject to governance."})]})}function d(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>s,a:()=>a});var o=i(7294);const t={},r=o.createContext(t);function a(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/775e2592.0e85c471.js b/assets/js/775e2592.0e85c471.js
new file mode 100644
index 0000000000..f3bd13a045
--- /dev/null
+++ b/assets/js/775e2592.0e85c471.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7375],{6180:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var i=n(5893),s=n(1151);const r={sidebar_position:7,title:"Throttle with retries"},a=void 0,o={id:"adrs/adr-008-throttle-retries",title:"Throttle with retries",description:"ADR 008: Throttle with retries",source:"@site/docs/adrs/adr-008-throttle-retries.md",sourceDirName:"adrs",slug:"/adrs/adr-008-throttle-retries",permalink:"/interchain-security/adrs/adr-008-throttle-retries",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:7,frontMatter:{sidebar_position:7,title:"Throttle with retries"},sidebar:"tutorialSidebar",previous:{title:"Cryptographic verification of equivocation evidence",permalink:"/interchain-security/adrs/adr-005-cryptographic-equivocation-verification"},next:{title:"Soft Opt-Out",permalink:"/interchain-security/adrs/adr-009-soft-opt-out"}},d={},c=[{value:"ADR 008: Throttle with retries",id:"adr-008-throttle-with-retries",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consumer changes",id:"consumer-changes",level:3},{value:"Consumer pending packets storage optimization",id:"consumer-pending-packets-storage-optimization",level:4},{value:"Provider changes",id:"provider-changes",level:3},{value:"Handling VSCMaturedPackets immediately",id:"handling-vscmaturedpackets-immediately",level:4},{value:"Why the provider can handle VSCMatured packets immediately",id:"why-the-provider-can-handle-vscmatured-packets-immediately",level:4},{value:"Splitting of PRs and Upgrade Order",id:"splitting-of-prs-and-upgrade-order",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"adr-008-throttle-with-retries",children:"ADR 008: Throttle with retries"}),"\n",(0,i.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"6/9/23: Initial draft"}),"\n",(0,i.jsx)(t.li,{children:"6/22/23: added note on consumer pending packets storage optimization"}),"\n",(0,i.jsx)(t.li,{children:"7/14/23: Added note on upgrade order"}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(t.p,{children:"Accepted"}),"\n",(0,i.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,i.jsxs)(t.p,{children:["For context on why the throttling mechanism exists, see ",(0,i.jsx)(t.a,{href:"/interchain-security/adrs/adr-002-throttle",children:"ADR 002"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Note the terms slash throttling and jail throttling are synonymous, since in Interchain Security a ",(0,i.jsx)(t.code,{children:"SlashPacket"})," simply jails a validator for downtime infractions."]}),"\n",(0,i.jsxs)(t.p,{children:["Currently the throttling mechanism is designed so that provider logic (slash meter, etc.) dictates how many ",(0,i.jsx)(t.code,{children:"SlashPackets"})," can be handled over time.\nThrottled ",(0,i.jsx)(t.code,{children:"SlashPackets"})," are persisted on the provider, leading to multiple possible issues. Namely:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["If ",(0,i.jsx)(t.code,{children:"SlashPackets"})," or ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," are actually throttled/queued on the provider, state can grow and potentially lead to a DoS attack.\nWe have short term solutions around this, but overall they come with their own weaknesses.\nSee ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/594",children:"#594"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:["If a jailing attack described in ",(0,i.jsx)(t.a,{href:"/interchain-security/adrs/adr-002-throttle",children:"ADR 002"})," were actually to be carried out with the current throttling design, we'd likely have to halt the provider, and perform an emergency upgrade and/or migration to clear the queues of ",(0,i.jsx)(t.code,{children:"SlashPackets"})," that were deemed to be malicious.\nAlternatively, validators would just have to ",(0,i.jsx)(t.em,{children:"tough it out"})," and wait for the queues to clear, during which all/most validators would be jailed.\nRight after being jailed, validators would have to unjail themselves promptly to ensure safety.\nThe coordination required to maintain safety in such a scenario is not ideal."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"As a solution, we can improve the throttling mechanism to instead queue/persist relevant data on each consumer, and have consumers retry slash requests as needed."}),"\n",(0,i.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(t.h3,{id:"consumer-changes",children:"Consumer changes"}),"\n",(0,i.jsxs)(t.p,{children:["Note the consumer already queues up both ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," via ",(0,i.jsx)(t.code,{children:"AppendPendingPacket"}),".\nThose packets are dequeued in every ",(0,i.jsx)(t.code,{children:"EndBlock"})," in ",(0,i.jsx)(t.code,{children:"SendPackets"})," and sent to the provider."]}),"\n",(0,i.jsxs)(t.p,{children:["Instead, we will now introduce the following logic on ",(0,i.jsx)(t.code,{children:"EndBlock"}),":"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["Slash packets will always be sent to the provider once they're at the head of the queue.\nHowever, once sent, the consumer will not send any subsequent ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," from the queue until the provider responds with an acknowledgement that the sent ",(0,i.jsx)(t.code,{children:"SlashPacket"})," has been handled, i.e., validator was jailed.\nThat is, ",(0,i.jsx)(t.code,{children:"SlashPackets"})," block the sending of subsequent ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," in the consumer queue."]}),"\n",(0,i.jsxs)(t.li,{children:["If two ",(0,i.jsx)(t.code,{children:"SlashPackets"})," are at the head of the queue, the consumer will send the first ",(0,i.jsx)(t.code,{children:"SlashPacket"}),", and then wait for a success acknowledgement from the provider before sending the second ",(0,i.jsx)(t.code,{children:"SlashPacket"}),".\nThis seems like it'd simplify implementation."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," at the head of the queue (i.e., NOT following a ",(0,i.jsx)(t.code,{children:"SlashPacket"}),") can be sent immediately, and do not block any other packets in the queue, since the provider always handles them immediately."]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["To prevent the provider from having to keep track of what ",(0,i.jsx)(t.code,{children:"SlashPackets"})," have been rejected, the consumer will have to retry the sending of ",(0,i.jsx)(t.code,{children:"SlashPackets"})," over some period of time.\nThis can be achieved with an on-chain consumer param, i.e., ",(0,i.jsx)(t.code,{children:"RetryDelayPeriod"}),".\nTo reduce the amount of redundant re-sends, we recommend setting ",(0,i.jsx)(t.code,{children:"RetryDelayPeriod ~ SlashMeterReplenishmentPeriod"}),", i.e., waiting for the provider slash meter to be replenished before resending the rejected ",(0,i.jsx)(t.code,{children:"SlashPacket"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"Note to prevent weird edge case behavior, a retry would not be attempted until either a success or failure acknowledgement has been received from the provider."}),"\n",(0,i.jsxs)(t.p,{children:["With the behavior described, we maintain very similar behavior to the previous throttling mechanism regarding the timing that ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," are handled on the provider.\nObviously the queueing and blocking logic is moved, and the two chains would have to send more messages between one another (only in the case the throttling mechanism is triggered)."]}),"\n",(0,i.jsxs)(t.p,{children:["In the normal case, when no or a few ",(0,i.jsx)(t.code,{children:"SlashPackets"})," are being sent, the ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," will not be delayed, and hence unbonding will not be delayed."]}),"\n",(0,i.jsxs)(t.p,{children:["For the implementation of this design, see ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/fec3eccad59416cbdb6844e279f59e3f81242888/x/ccv/consumer/keeper/throttle_retry.go",children:"throttle_retry.go"}),"."]}),"\n",(0,i.jsx)(t.h4,{id:"consumer-pending-packets-storage-optimization",children:"Consumer pending packets storage optimization"}),"\n",(0,i.jsx)(t.p,{children:"In addition to the mentioned consumer changes, an optimization will need to be made to the consumer's pending packets storage to properly implement the feature from this ADR."}),"\n",(0,i.jsxs)(t.p,{children:['The consumer ccv module previously queued "pending packets" to be sent in each ',(0,i.jsx)(t.code,{children:"EndBlock"})," in ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/3bc4e7135066d848aac60b0787364c07157fd36d/x/ccv/consumer/keeper/relay.go#L178",children:"SendPackets"}),".\nThese packets are queued in state with a protobuf list of ",(0,i.jsx)(t.code,{children:"ConsumerPacketData"}),".\nFor a single append operation, the entire list is deserialized, then a packet is appended to that list, and the list is serialized again.\nSee older version of ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/05c2dae7c6372b1252b9e97215d07c6aa7618f33/x/ccv/consumer/keeper/keeper.go#L606",children:"AppendPendingPacket"}),".\nThat is, a single append operation has O(N) complexity, where N is the size of the list."]}),"\n",(0,i.jsxs)(t.p,{children:["This poor append performance isn't a problem when the pending packets list is small.\nBut with this ADR being implemented, the pending packets list could potentially grow to the order of thousands of entries when ",(0,i.jsx)(t.code,{children:"SlashPackets"})," need to be resent."]}),"\n",(0,i.jsx)(t.p,{children:"We can improve the append time for this queue by converting it from a protobuf-esq list, to a queue implemented with sdk-esq code.\nThe idea is to persist a uint64 index that will be incremented each time you queue up a packet.\nYou can think of this as storing the tail of the queue.\nThen, packet data will be keyed by that index, making the data naturally ordered byte-wise for sdk's iterator.\nThe index will also be stored in the packet data value bytes, so that the index can later be used to delete certain packets from the queue."}),"\n",(0,i.jsx)(t.p,{children:"Two things are achieved with this approach:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"More efficient packet append/enqueue times"}),"\n",(0,i.jsx)(t.li,{children:"The ability to delete select packets from the queue (previously all packets were deleted at once)"}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"provider-changes",children:"Provider changes"}),"\n",(0,i.jsxs)(t.p,{children:["The main change needed for the provider is the removal of queuing logic for ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," upon being received."]}),"\n",(0,i.jsxs)(t.p,{children:["Instead, the provider will consult the slash meter to determine if a ",(0,i.jsx)(t.code,{children:"SlashPacket"})," can be handled immediately.\nIf not, the provider will return an acknowledgement message to the consumer communicating that the ",(0,i.jsx)(t.code,{children:"SlashPacket"})," could not be handled, and needs to be sent again in the future (retried)."]}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," will always be handled immediately upon being received by the provider."]}),"\n",(0,i.jsxs)(t.p,{children:["Note ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#consumer-initiated-slashing",children:"spec"}),". Specifically the section on ",(0,i.jsx)(t.em,{children:"VSC Maturity and Slashing Order"}),". Previously the onus was on the provider to maintain this property via queuing packets and handling them FIFO."]}),"\n",(0,i.jsxs)(t.p,{children:["Now this property will be maintained by the consumer sending packets in the correct order, and blocking the sending of ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," as needed. Then, the ordered IBC channel will ensure that ",(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," are received in the correct order on the provider."]}),"\n",(0,i.jsxs)(t.p,{children:["The provider's main responsibility regarding throttling will now be to determine if a received ",(0,i.jsx)(t.code,{children:"SlashPacket"})," can be handled via slash meter etc., and appropriately acknowledge to the sending consumer."]}),"\n",(0,i.jsxs)(t.h4,{id:"handling-vscmaturedpackets-immediately",children:["Handling ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," immediately"]}),"\n",(0,i.jsx)(t.h4,{id:"why-the-provider-can-handle-vscmatured-packets-immediately",children:"Why the provider can handle VSCMatured packets immediately"}),"\n",(0,i.jsxs)(t.p,{children:["A ",(0,i.jsx)(t.code,{children:"VSCMaturedPacket"})," communicates to the provider that sufficient time passed on the consumer since the corresponding ",(0,i.jsx)(t.code,{children:"VSCPacket"})," has been applied (on the consumer) such that infractions committed on the consumer could have been submitted."]}),"\n",(0,i.jsxs)(t.p,{children:["If the consumer is following the queuing/blocking protocol described, then no bad behavior occurs and the ",(0,i.jsx)(t.em,{children:"VSC Maturity and Slashing Order"})," property is maintained."]}),"\n",(0,i.jsxs)(t.p,{children:["If a consumer sends ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," too leniently -- the consumer is malicious and sends duplicate ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"}),", or sends the packets sooner than the CCV protocol specifies -- then the provider needs to handle ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," immediately to prevent DOS, state bloat, or other issues.\nThe only possible negative outcome is that the malicious consumer may not be able to jail a validator who should have been jailed.\nThe malicious behavior only creates a negative outcome for the consumer chain that is being malicious."]}),"\n",(0,i.jsxs)(t.p,{children:["If a consumer blocks the sending of ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"}),", then unbonding operations on the provider will be delayed, but only until the VSC timeout period has elapsed.\nAt that time, the consumer is removed.\nAgain the malicious behavior only creates a negative outcome for the consumer chain that is being malicious."]}),"\n",(0,i.jsx)(t.h3,{id:"splitting-of-prs-and-upgrade-order",children:"Splitting of PRs and Upgrade Order"}),"\n",(0,i.jsxs)(t.p,{children:["This feature will implement consumer changes in ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1024",children:"#1024"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["\u2757",(0,i.jsx)(t.em,{children:(0,i.jsx)(t.strong,{children:"These changes should be deployed to production for all consumers before the provider changes are deployed to production."})})]}),"\n",(0,i.jsxs)(t.p,{children:["In other words, the consumer changes in ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1024",children:"#1024"}),' are compatible with the current ("v1") provider implementation of throttling that\'s running on the Cosmos Hub as of July 2023.']}),"\n",(0,i.jsxs)(t.p,{children:["Once all consumers have deployed the changes in #1024, the provider changes from ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1321",children:"#1321"})," can be deployed to production, fully enabling v2 throttling."]}),"\n",(0,i.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Consumers will now have to manage their own queues, and retry logic."}),"\n",(0,i.jsx)(t.li,{children:"Consumers still aren't trustless, but the provider is now less susceptible to mismanaged or malicious consumers."}),"\n",(0,i.jsx)(t.li,{children:'Recovering from the "jailing attack" is more elegant.'}),"\n",(0,i.jsxs)(t.li,{children:["Some issues like ",(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/1001",children:"#1001"})," will now be handled implicitly by the improved throttling mechanism."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," can be handled immediately once received by the provider if the slash meter allows."]}),"\n",(0,i.jsxs)(t.li,{children:["In general, we reduce the amount of computation that happens in the provider ",(0,i.jsx)(t.code,{children:"EndBlock"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:['We no longer have to reason about a "global queue" and a "chain specific queue", and keeping those all in-sync.\nNow ',(0,i.jsx)(t.code,{children:"SlashPackets"})," and ",(0,i.jsx)(t.code,{children:"VSCMaturedPackets"})," queuing is handled on each consumer individually."]}),"\n",(0,i.jsx)(t.li,{children:"Due to the above, the throttling protocol becomes less complex overall."}),"\n",(0,i.jsx)(t.li,{children:"We no longer have to worry about throttle related DoS attack on the provider, since no queuing exists on the provider."}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Increased number of IBC packets being relayed anytime throttling logic is triggered."}),"\n",(0,i.jsx)(t.li,{children:"Consumer complexity increases, since consumers now have manage queuing themselves, and implement packet retry logic."}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Core throttling logic on the provider remains unchanged, i.e., slash meter, replenishment cycles, etc."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/713",children:"EPIC"})," tracking the changes proposed by this ADR"]}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/interchain-security/adrs/adr-002-throttle",children:"ADR 002: Jail Throttling"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/594",children:"#594"})}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>o,a:()=>a});var i=n(7294);const s={},r=i.createContext(s);function a(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/7aa430a8.3f0c815c.js b/assets/js/7aa430a8.3f0c815c.js
new file mode 100644
index 0000000000..bcb37d0081
--- /dev/null
+++ b/assets/js/7aa430a8.3f0c815c.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7506],{6525:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>c});var o=i(5893),s=i(1151);const t={sidebar_position:2,title:"ADR Template"},a="ADR 007: Pause validator unbonding during equivocation proposal",r={id:"adrs/adr-007-pause-unbonding-on-eqv-prop",title:"ADR Template",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-007-pause-unbonding-on-eqv-prop.md",sourceDirName:"adrs",slug:"/adrs/adr-007-pause-unbonding-on-eqv-prop",permalink:"/interchain-security/v4.2.0/adrs/adr-007-pause-unbonding-on-eqv-prop",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"ADR Template"},sidebar:"tutorialSidebar",previous:{title:"ADR Template",permalink:"/interchain-security/v4.2.0/adrs/adr-004-denom-dos-fixes"},next:{title:"ADR Template",permalink:"/interchain-security/v4.2.0/adrs/adr-template"}},d={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"How",id:"how",level:3},{value:"When pause",id:"when-pause",level:3},{value:"When unpause",id:"when-unpause",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"adr-007-pause-validator-unbonding-during-equivocation-proposal",children:"ADR 007: Pause validator unbonding during equivocation proposal"}),"\n",(0,o.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"2023-05-16: Initial Draft"}),"\n",(0,o.jsx)(n.li,{children:"2023-11-30: Change the status to rejected"}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,o.jsx)(n.p,{children:"Rejected"}),"\n",(0,o.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Note:"})," ADR rejected as the equivocation proposal was removed by the\ncryptographic verification of equivocation feature\n(see ",(0,o.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR-005"})," and\n",(0,o.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing",children:"ADR-013"}),")."]}),"\n",(0,o.jsx)(n.p,{children:"Currently, if an equivocation slashing proposal is created after more than one\nweek has passed since the equivocation, it is possible that the validator in\nquestion could unbond and get away without being slashed, since the unbonding\nperiod is 3 weeks, and the voting period is 2 weeks. For this reason, it might\nbe good to pause unbondings for validators named in an equivocation slashing\nproposal until the proposal's voting period is over."}),"\n",(0,o.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,o.jsx)(n.h3,{id:"how",children:"How"}),"\n",(0,o.jsxs)(n.p,{children:["Pausing the unbonding period is already possible thanks to the changes in the\n",(0,o.jsx)(n.code,{children:"staking"})," module of the cosmos-sdk:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"stakingKeeper.PutUnbondingOnHold"})," pauses an unbonding period"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"stakingKeeper.UnbondingCanComplete"})," unpauses an unbonding period"]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["These methods use a reference counter under the hood, that gets incremented\nevery time ",(0,o.jsx)(n.code,{children:"PutUnbondingOnHold"})," is called, and decreased when\n",(0,o.jsx)(n.code,{children:"UnbondingCanComplete"})," is called instead. A specific unbonding is considered\nfully unpaused when its underlying reference counter reaches 0. Therefore, as\nlong as we safeguard consistency - i.e. we make sure we eventually decrement\nthe reference counter for each time we have incremented it - we can safely use\nthis existing mechanism without conflicts with the ",(0,o.jsx)(n.em,{children:"Completion of Unbonding\nOperations"})," system."]}),"\n",(0,o.jsx)(n.h3,{id:"when-pause",children:"When pause"}),"\n",(0,o.jsxs)(n.p,{children:["The unbonding period (if there is any unbonding) should be paused once an\nequivocation proposal enters the voting period. For that, the ",(0,o.jsx)(n.code,{children:"gov"})," module's\nhook ",(0,o.jsx)(n.code,{children:"AfterProposalDeposit"})," can be used."]}),"\n",(0,o.jsx)(n.p,{children:"If the hook is triggered with a an equivocation proposal in voting period, then\nfor each equivocation of the proposal, the unbonding operations of the related\nvalidator that were initiated after the equivocation block time must be paused"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"i.e. the underlying reference counter has to be increased."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Note that even after the voting period has started, a proposal can receive\nadditional deposits. The hook is triggered however at arrival of a deposit, so\na check to verify that the proposal is not already in voting period is\nrequired."}),"\n",(0,o.jsx)(n.h3,{id:"when-unpause",children:"When unpause"}),"\n",(0,o.jsxs)(n.p,{children:["We can use a ",(0,o.jsx)(n.code,{children:"gov"})," module's hook also here and it is\n",(0,o.jsx)(n.code,{children:"AfterProposalVotingPeriodEnded"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"If the hook is triggered with an equivocation proposal, then for each\nassociated equivocation, the unbonding operations of the related validator that\nwere initiated between the equivocation block time and the start of the\nproposal voting period must be unpaused - i.e. decrease the underlying\nreference counter - regardless of the proposal outcome."}),"\n",(0,o.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,o.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Validators subject to an equivocation proposal cannot finish unbonding\ntheir tokens before the end of the voting period."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"A malicious consumer chain could forge slash packets enabling submission of\nan equivocation proposal on the provider chain, resulting in the freezing of\nvalidator's unbondings for an undeterminated amount of time."}),"\n",(0,o.jsx)(n.li,{children:"Misbehavior on a consumer chain can potentially go unpunished, if no one\nsubmits an equivocation proposal in time, or if the proposal doesn't pass."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"This feature can't be used for social slashing, because an equivocation\nproposal is only accepted if there's a slash log for the related\nvalidator(s), meaning the consumer chain has reported the equivocation to\nthe provider chain."}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/747",children:"https://github.com/cosmos/interchain-security/issues/747"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/791",children:"https://github.com/cosmos/interchain-security/pull/791"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>a});var o=i(7294);const s={},t=o.createContext(s);function a(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/829e00bf.265639bf.js b/assets/js/829e00bf.265639bf.js
new file mode 100644
index 0000000000..6e9f6cdc3b
--- /dev/null
+++ b/assets/js/829e00bf.265639bf.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8718],{1118:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>t,metadata:()=>d,toc:()=>l});var i=s(5893),o=s(1151);const t={sidebar_position:2,title:"ADR Template"},r="ADR 004: Denom DOS fixes",d={id:"adrs/adr-004-denom-dos-fixes",title:"ADR Template",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-004-denom-dos-fixes.md",sourceDirName:"adrs",slug:"/adrs/adr-004-denom-dos-fixes",permalink:"/interchain-security/v4.2.0/adrs/adr-004-denom-dos-fixes",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"ADR Template"},sidebar:"tutorialSidebar",previous:{title:"ADRs",permalink:"/interchain-security/v4.2.0/adrs/intro"},next:{title:"ADR Template",permalink:"/interchain-security/v4.2.0/adrs/adr-007-pause-unbonding-on-eqv-prop"}},a={},l=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Provider",id:"provider",level:3},{value:"Consumer",id:"consumer",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3}];function c(e){const n={h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-004-denom-dos-fixes",children:"ADR 004: Denom DOS fixes"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"5/9/2023: ADR created"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Accepted"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.p,{children:"The provider and consumer modules are vulnerable to similar issues involving an attacker sending millions of denoms to certain addresses and causing the chain to halt. This ADR outlines both fixes since they are similar. Both fixes involve processing only denoms that are on a whitelist to avoid iterating over millions of junk denoms but have different requirements and are implemented in different ways."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.h3,{id:"provider",children:"Provider"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Put the distribution module's FeePoolAddress back on the blocklist so that it cannot receive funds from users."}),"\n",(0,i.jsx)(n.li,{children:"Create a new address called ConsumerRewardPool and unblock it, allowing funds to be sent to it."}),"\n",(0,i.jsx)(n.li,{children:"Create a set of strings in the store for allowed ConsumerRewardDenoms."}),"\n",(0,i.jsx)(n.li,{children:"Create an endpoint called RegisterConsumerRewardDenom which deducts a fee from the sender's account, sends it to the community pool and adds a string to the ConsumerRewardDenoms set."}),"\n",(0,i.jsx)(n.li,{children:"Create a parameter called ConsumerRewardDenomRegistrationFee which determines the fee which is charged to register a consumer reward denom in the step above."}),"\n",(0,i.jsxs)(n.li,{children:["Create a function called TransferRewardsToFeeCollector which gets the entire ConsumerRewardDenoms set from the store, iterates over it, and for each entry:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Gets the balance of this denom for the ConsumerRewardPool account"}),"\n",(0,i.jsx)(n.li,{children:"Sends the entire balance out to the FeePoolAddress using SendCoinsFromModuleToModule which is not affected by the blocklist."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"Run TransferRewardsToFeeCollector in the endblock"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Now, nobody can send millions of junk denoms to the FeePoolAddress because it is on the block list. If they send millions of junk denoms to the ConsumerRewardPool, this does not matter because all balances are not iterated over, only those which are in the ConsumerRewardDenoms set."}),"\n",(0,i.jsx)(n.p,{children:"We also add a new tx: register-consumer-reward-denom, and a new query: registered-consumer-reward-denoms"}),"\n",(0,i.jsx)(n.h3,{id:"consumer",children:"Consumer"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Create a new param RewardDenoms with a list of strings"}),"\n",(0,i.jsx)(n.li,{children:"Create a new param ProviderRewardDenoms with a list of strings"}),"\n",(0,i.jsx)(n.li,{children:"Create a function AllowedRewardDenoms which iterates over ProviderRewardDenoms and converts each denom to its ibc-prefixed denom using the provider chain's ibc channel information, then concatenates the RewardDenoms list and returns the combined list of allowed denoms."}),"\n",(0,i.jsx)(n.li,{children:"In SendRewardsToProvider, instead of iterating over the balances of all denoms in the ToSendToProvider address, iterate over AllowedRewardDenoms"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Now, if somebody sends millions of junk denoms to ToSendToProvider, they will not be iterated over. Only the RewardDenoms and ProviderRewardDenoms will be iterated over. Since we do not require this feature to be permissionless on the consumer, the registration fee process is not needed."}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Denom DOS is no longer possible on either provider or consumer."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Consumer chain teams must pay a fee to register a denom for distribution on the provider, and add some extra parameters in their genesis file."}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>d,a:()=>r});var i=s(7294);const o={},t=i.createContext(o);function r(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/83f6d28d.5a6df8c0.js b/assets/js/83f6d28d.5a6df8c0.js
new file mode 100644
index 0000000000..bd7c5ff6bf
--- /dev/null
+++ b/assets/js/83f6d28d.5a6df8c0.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7534],{7915:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var i=t(5893),r=t(1151);const s={sidebar_position:6},o="Joining Stride",a={id:"validators/joining-stride",title:"Joining Stride",description:"Stride is the first consumer chain to perform the standalone to consumer changeover procedure and transition from a standalone validator set to using cosmoshub-4 validator set.",source:"@site/versioned_docs/version-v5.0.0/validators/joining-stride.md",sourceDirName:"validators",slug:"/validators/joining-stride",permalink:"/interchain-security/v5.0.0/validators/joining-stride",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Joining Neutron",permalink:"/interchain-security/v5.0.0/validators/joining-neutron"},next:{title:"Frequently Asked Questions",permalink:"/interchain-security/v5.0.0/faq"}},c={},d=[{value:"Note",id:"note",level:2},{value:"Resources",id:"resources",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"joining-stride",children:"Joining Stride"}),"\n",(0,i.jsxs)(n.p,{children:["Stride is the first consumer chain to perform the standalone to consumer changeover procedure and transition from a standalone validator set to using ",(0,i.jsx)(n.code,{children:"cosmoshub-4"})," validator set."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"stride-1"})," network (mainnet) will perform a software upgrade and at height ",(0,i.jsx)(n.code,{children:"4616678"})," that will transition the network to using the Cosmos Hub's (",(0,i.jsx)(n.code,{children:"cosmoshub-4"}),") validator set."]}),"\n",(0,i.jsxs)(n.p,{children:["You can find instructions about the Stride consumer chain launch and joining the mainnet ",(0,i.jsx)(n.a,{href:"https://github.com/Stride-Labs/mainnet/tree/main/ics-instructions",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This ",(0,i.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Excalidraw graphic"})," explains the timeline of Stride's changeover procedure."]}),"\n",(0,i.jsx)(n.h2,{id:"note",children:"Note"}),"\n",(0,i.jsxs)(n.p,{children:["Stride re-uses an existing ",(0,i.jsx)(n.code,{children:"transfer"})," channel to send consumer rewards to the provider chain, in order to preserve existing transfer IBC denom between ",(0,i.jsx)(n.code,{children:"stride-1"})," and ",(0,i.jsx)(n.code,{children:"cosmoshub-4"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"resources",children:"Resources"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.stride.zone/docs",children:"Stride docs"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Changeover procedure timeline"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/Stride-Labs/mainnet/tree/main/ics-instructions",children:"Changeover upgrade docs"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>o});var i=t(7294);const r={},s=i.createContext(r);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/852eba87.e3d2f27b.js b/assets/js/852eba87.e3d2f27b.js
new file mode 100644
index 0000000000..5628579cec
--- /dev/null
+++ b/assets/js/852eba87.e3d2f27b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2473],{8939:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>t,default:()=>h,frontMatter:()=>o,metadata:()=>d,toc:()=>a});var r=n(5893),s=n(1151);const o={sidebar_position:3},t="Interchain Security Parameters",d={id:"introduction/params",title:"Interchain Security Parameters",description:"The parameters necessary for Interchain Security (ICS) are defined in",source:"@site/versioned_docs/version-v4.2.0-docs/introduction/params.md",sourceDirName:"introduction",slug:"/introduction/params",permalink:"/interchain-security/v4.2.0/introduction/params",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"tutorialSidebar",previous:{title:"Terminology",permalink:"/interchain-security/v4.2.0/introduction/terminology"},next:{title:"Technical Specification",permalink:"/interchain-security/v4.2.0/introduction/technical-specification"}},c={},a=[{value:"Time-Based Parameters",id:"time-based-parameters",level:2},{value:"ProviderUnbondingPeriod",id:"providerunbondingperiod",level:3},{value:"ConsumerUnbondingPeriod",id:"consumerunbondingperiod",level:3},{value:"TrustingPeriodFraction",id:"trustingperiodfraction",level:3},{value:"CCVTimeoutPeriod",id:"ccvtimeoutperiod",level:3},{value:"InitTimeoutPeriod",id:"inittimeoutperiod",level:3},{value:"VscTimeoutPeriod",id:"vsctimeoutperiod",level:3},{value:"BlocksPerDistributionTransmission",id:"blocksperdistributiontransmission",level:3},{value:"TransferPeriodTimeout",id:"transferperiodtimeout",level:3},{value:"Reward Distribution Parameters",id:"reward-distribution-parameters",level:2},{value:"ConsumerRedistributionFraction",id:"consumerredistributionfraction",level:3},{value:"BlocksPerDistributionTransmission",id:"blocksperdistributiontransmission-1",level:3},{value:"TransferTimeoutPeriod",id:"transfertimeoutperiod",level:3},{value:"DistributionTransmissionChannel",id:"distributiontransmissionchannel",level:3},{value:"ProviderFeePoolAddrStr",id:"providerfeepooladdrstr",level:3},{value:"Slash Throttle Parameters",id:"slash-throttle-parameters",level:2},{value:"SlashMeterReplenishPeriod",id:"slashmeterreplenishperiod",level:3},{value:"SlashMeterReplenishFraction",id:"slashmeterreplenishfraction",level:3},{value:"MaxThrottledPackets",id:"maxthrottledpackets",level:3},{value:"RetryDelayPeriod",id:"retrydelayperiod",level:3},{value:"Epoch Parameters",id:"epoch-parameters",level:2},{value:"BlocksPerEpoch",id:"blocksperepoch",level:3}];function l(e){const i={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.h1,{id:"interchain-security-parameters",children:"Interchain Security Parameters"}),"\n",(0,r.jsx)(i.p,{children:"The parameters necessary for Interchain Security (ICS) are defined in"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["the ",(0,r.jsx)(i.code,{children:"Params"})," structure in ",(0,r.jsx)(i.code,{children:"proto/interchain_security/ccv/provider/v1/provider.proto"})," for the provider;"]}),"\n",(0,r.jsxs)(i.li,{children:["the ",(0,r.jsx)(i.code,{children:"Params"})," structure in ",(0,r.jsx)(i.code,{children:"proto/interchain_security/ccv/consumer/v1/consumer.proto"})," for the consumer."]}),"\n"]}),"\n",(0,r.jsx)(i.h2,{id:"time-based-parameters",children:"Time-Based Parameters"}),"\n",(0,r.jsx)(i.p,{children:"ICS relies on the following time-based parameters."}),"\n",(0,r.jsx)(i.h3,{id:"providerunbondingperiod",children:"ProviderUnbondingPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ProviderUnbondingPeriod"})," is the unbonding period on the provider chain as configured during chain genesis. This parameter can later be changed via governance."]}),"\n",(0,r.jsx)(i.h3,{id:"consumerunbondingperiod",children:"ConsumerUnbondingPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"})," is the unbonding period on the consumer chain."]}),"\n",(0,r.jsxs)(i.admonition,{type:"info",children:[(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"})," is set via the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})," governance proposal to add a new consumer chain.\nIt is recommended that every consumer chain set and unbonding period shorter than ",(0,r.jsx)(i.code,{children:"ProviderUnbondingPeriod"})]}),(0,r.jsx)("br",{}),(0,r.jsx)(i.p,{children:"Example:"}),(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod = ProviderUnbondingPeriod - one day\n"})})]}),"\n",(0,r.jsx)(i.p,{children:"Unbonding operations (such as undelegations) are completed on the provider only after the unbonding period elapses on every consumer."}),"\n",(0,r.jsx)(i.h3,{id:"trustingperiodfraction",children:"TrustingPeriodFraction"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TrustingPeriodFraction"})," is used to calculate the ",(0,r.jsx)(i.code,{children:"TrustingPeriod"})," of created IBC clients on both provider and consumer chains."]}),"\n",(0,r.jsxs)(i.p,{children:["Setting ",(0,r.jsx)(i.code,{children:"TrustingPeriodFraction"})," to ",(0,r.jsx)(i.code,{children:"0.5"})," would result in the following:"]}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{children:"TrustingPeriodFraction = 0.5\nProviderClientOnConsumerTrustingPeriod = ProviderUnbondingPeriod * 0.5\nConsumerClientOnProviderTrustingPeriod = ConsumerUnbondingPeriod * 0.5\n"})}),"\n",(0,r.jsxs)(i.p,{children:["Note that a light clients must be updated within the ",(0,r.jsx)(i.code,{children:"TrustingPeriod"})," in order to avoid being frozen."]}),"\n",(0,r.jsxs)(i.p,{children:["For more details, see the ",(0,r.jsx)(i.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/client/ics-007-tendermint-client/README.md",children:"IBC specification of Tendermint clients"}),"."]}),"\n",(0,r.jsx)(i.h3,{id:"ccvtimeoutperiod",children:"CCVTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"CCVTimeoutPeriod"})," is the period used to compute the timeout timestamp when sending IBC packets."]}),"\n",(0,r.jsxs)(i.p,{children:["For more details, see the ",(0,r.jsx)(i.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/core/ics-004-channel-and-packet-semantics/README.md#sending-packets",children:"IBC specification of Channel & Packet Semantics"}),"."]}),"\n",(0,r.jsx)(i.admonition,{type:"warning",children:(0,r.jsx)(i.p,{children:"If a sent packet is not relayed within this period, then the packet times out. The CCV channel used by the interchain security protocol is closed, and the corresponding consumer is removed."})}),"\n",(0,r.jsx)(i.p,{children:"CCVTimeoutPeriod may have different values on the provider and consumer chains."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"CCVTimeoutPeriod"})," on the provider ",(0,r.jsx)(i.strong,{children:"must"})," be larger than ",(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"})]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"CCVTimeoutPeriod"})," on the consumer is initial set via the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})]}),"\n"]}),"\n",(0,r.jsx)(i.h3,{id:"inittimeoutperiod",children:"InitTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"InitTimeoutPeriod"})," is the maximum allowed duration for CCV channel initialization to execute."]}),"\n",(0,r.jsxs)(i.p,{children:["For any consumer chain, if the CCV channel is not established within ",(0,r.jsx)(i.code,{children:"InitTimeoutPeriod"})," then the consumer chain will be removed and therefore will not be secured by the provider chain."]}),"\n",(0,r.jsxs)(i.p,{children:["The countdown starts when the ",(0,r.jsx)(i.code,{children:"spawn_time"})," specified in the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})," is reached."]}),"\n",(0,r.jsx)(i.h3,{id:"vsctimeoutperiod",children:"VscTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"VscTimeoutPeriod"})," is the provider-side param that enables the provider to timeout VSC packets even when a consumer chain is not live.\nIf the ",(0,r.jsx)(i.code,{children:"VscTimeoutPeriod"})," is ever reached for a consumer chain that chain will be considered not live and removed from interchain security."]}),"\n",(0,r.jsx)(i.admonition,{type:"tip",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"VscTimeoutPeriod"})," MUST be larger than the ",(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"}),"."]})}),"\n",(0,r.jsx)(i.h3,{id:"blocksperdistributiontransmission",children:"BlocksPerDistributionTransmission"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," is the number of blocks between rewards transfers from the consumer to the provider."]}),"\n",(0,r.jsx)(i.h3,{id:"transferperiodtimeout",children:"TransferPeriodTimeout"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TransferPeriodTimeout"})," is the period used to compute the timeout timestamp when sending IBC transfer packets from a consumer to the provider."]}),"\n",(0,r.jsxs)(i.p,{children:["If this timeout expires, then the transfer is attempted again after ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," blocks."]}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"TransferPeriodTimeout"})," on the consumer is initial set via the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})," gov proposal to add the consumer"]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"TransferPeriodTimeout"})," should be smaller than ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission x avg_block_time"})]}),"\n"]}),"\n",(0,r.jsx)(i.h2,{id:"reward-distribution-parameters",children:"Reward Distribution Parameters"}),"\n",(0,r.jsx)(i.admonition,{type:"tip",children:(0,r.jsxs)(i.p,{children:["The following chain parameters dictate consumer chain distribution amount and frequency.\nThey are set at consumer genesis and ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"}),", ",(0,r.jsx)(i.code,{children:"ConsumerRedistributionFraction"}),"\n",(0,r.jsx)(i.code,{children:"TransferTimeoutPeriod"})," must be provided in every ",(0,r.jsx)(i.code,{children:"ConsumerChainAddition"})," proposal."]})}),"\n",(0,r.jsx)(i.h3,{id:"consumerredistributionfraction",children:"ConsumerRedistributionFraction"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ConsumerRedistributionFraction"})," is the fraction of tokens allocated to the consumer redistribution address during distribution events. The fraction is a string representing a decimal number. For example ",(0,r.jsx)(i.code,{children:'"0.75"'})," would represent ",(0,r.jsx)(i.code,{children:"75%"}),"."]}),"\n",(0,r.jsxs)(i.admonition,{type:"tip",children:[(0,r.jsx)(i.p,{children:"Example:"}),(0,r.jsxs)(i.p,{children:["With ",(0,r.jsx)(i.code,{children:"ConsumerRedistributionFraction"})," set to ",(0,r.jsx)(i.code,{children:'"0.75"'})," the consumer chain would send ",(0,r.jsx)(i.code,{children:"75%"})," of its block rewards and accumulated fees to the consumer redistribution address, and the remaining ",(0,r.jsx)(i.code,{children:"25%"})," to the provider chain every ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," blocks."]})]}),"\n",(0,r.jsx)(i.h3,{id:"blocksperdistributiontransmission-1",children:"BlocksPerDistributionTransmission"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," is the number of blocks between IBC token transfers from the consumer chain to the provider chain."]}),"\n",(0,r.jsx)(i.h3,{id:"transfertimeoutperiod",children:"TransferTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TransferTimeoutPeriod"})," is the timeout period for consumer chain reward distribution IBC packets."]}),"\n",(0,r.jsx)(i.h3,{id:"distributiontransmissionchannel",children:"DistributionTransmissionChannel"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"DistributionTransmissionChannel"})," is the provider chain IBC channel used for receiving consumer chain reward distribution token transfers. This is automatically set during the consumer-provider handshake procedure."]}),"\n",(0,r.jsx)(i.h3,{id:"providerfeepooladdrstr",children:"ProviderFeePoolAddrStr"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ProviderFeePoolAddrStr"})," is the provider chain fee pool address used for receiving consumer chain reward distribution token transfers. This is automatically set during the consumer-provider handshake procedure."]}),"\n",(0,r.jsx)(i.h2,{id:"slash-throttle-parameters",children:"Slash Throttle Parameters"}),"\n",(0,r.jsx)(i.h3,{id:"slashmeterreplenishperiod",children:"SlashMeterReplenishPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"SlashMeterReplenishPeriod"})," exists on the provider such that once the slash meter becomes not-full, the slash meter is replenished after this period has elapsed."]}),"\n",(0,r.jsxs)(i.p,{children:["The meter is replenished to an amount equal to the slash meter allowance for that block, or ",(0,r.jsx)(i.code,{children:"SlashMeterReplenishFraction * CurrentTotalVotingPower"}),"."]}),"\n",(0,r.jsx)(i.h3,{id:"slashmeterreplenishfraction",children:"SlashMeterReplenishFraction"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"SlashMeterReplenishFraction"})," exists on the provider as the portion (in range [0, 1]) of total voting power that is replenished to the slash meter when a replenishment occurs."]}),"\n",(0,r.jsxs)(i.p,{children:["This param also serves as a maximum fraction of total voting power that the slash meter can hold. The param is set/persisted as a string, and converted to a ",(0,r.jsx)(i.code,{children:"sdk.Dec"})," when used."]}),"\n",(0,r.jsx)(i.h3,{id:"maxthrottledpackets",children:"MaxThrottledPackets"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"MaxThrottledPackets"})," exists on the provider as the maximum amount of throttled slash or vsc matured packets that can be queued from a single consumer before the provider chain halts, it should be set to a large value."]}),"\n",(0,r.jsx)(i.p,{children:"This param would allow provider binaries to panic deterministically in the event that packet throttling results in a large amount of state-bloat. In such a scenario, packet throttling could prevent a violation of safety caused by a malicious consumer, at the cost of provider liveness."}),"\n",(0,r.jsx)(i.admonition,{type:"info",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"MaxThrottledPackets"})," was deprecated in ICS versions >= v3.2.0 due to the implementation of ",(0,r.jsx)(i.a,{href:"/interchain-security/v4.2.0/adrs/adr-008-throttle-retries",children:"ADR-008"}),"."]})}),"\n",(0,r.jsx)(i.h3,{id:"retrydelayperiod",children:"RetryDelayPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"RetryDelayPeriod"})," exists on the consumer for ",(0,r.jsx)(i.strong,{children:"ICS versions >= v3.2.0"})," (introduced by the implementation of ",(0,r.jsx)(i.a,{href:"/interchain-security/v4.2.0/adrs/adr-008-throttle-retries",children:"ADR-008"}),") and is the period at which the consumer retries to send a ",(0,r.jsx)(i.code,{children:"SlashPacket"})," that was rejected by the provider."]}),"\n",(0,r.jsx)(i.h2,{id:"epoch-parameters",children:"Epoch Parameters"}),"\n",(0,r.jsx)(i.h3,{id:"blocksperepoch",children:"BlocksPerEpoch"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"BlocksPerEpoch"})," exists on the provider for ",(0,r.jsx)(i.strong,{children:"ICS versions >= 3.3.0"})," (introduced by the implementation of ",(0,r.jsx)(i.a,{href:"/interchain-security/v4.2.0/adrs/adr-014-epochs",children:"ADR-014"}),")\nand corresponds to the number of blocks that constitute an epoch. This param is set to 600 by default. Assuming we need 6 seconds to\ncommit a block, the duration of an epoch corresponds to 1 hour. This means that a ",(0,r.jsx)(i.code,{children:"VSCPacket"})," would be sent to a consumer\nchain once at the end of every epoch, so once every 600 blocks. This parameter can be adjusted via a governance proposal,\nhowever careful consideration is needed so that ",(0,r.jsx)(i.code,{children:"BlocksPerEpoch"})," is not too large. A large ",(0,r.jsx)(i.code,{children:"BlocksPerEpoch"})," could lead to a delay\nof ",(0,r.jsx)(i.code,{children:"VSCPacket"}),"s and hence potentially lead to ",(0,r.jsx)(i.a,{href:"https://informal.systems/blog/learning-to-live-with-unbonding-pausing",children:"unbonding pausing"}),".\nFor setting ",(0,r.jsx)(i.code,{children:"BlocksPerEpoch"}),", we also need to consider potential slow chain upgrades that could delay the sending of a\n",(0,r.jsx)(i.code,{children:"VSCPacket"}),", as well as potential increases in the time it takes to commit a block (e.g., from 6 seconds to 30 seconds)."]})]})}function h(e={}){const{wrapper:i}={...(0,s.a)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},1151:(e,i,n)=>{n.d(i,{Z:()=>d,a:()=>t});var r=n(7294);const s={},o=r.createContext(s);function t(e){const i=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function d(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:t(e.components),r.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/867425db.d47ee539.js b/assets/js/867425db.d47ee539.js
new file mode 100644
index 0000000000..28a160ecb8
--- /dev/null
+++ b/assets/js/867425db.d47ee539.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8477],{5024:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>h,contentTitle:()=>s,default:()=>l,frontMatter:()=>o,metadata:()=>r,toc:()=>c});var t=i(5893),a=i(1151);const o={sidebar_position:5,title:"Frequently Asked Questions",slug:"/faq"},s=void 0,r={id:"frequently-asked-questions",title:"Frequently Asked Questions",description:"What is a consumer chain?",source:"@site/versioned_docs/version-v4.2.0-docs/frequently-asked-questions.md",sourceDirName:".",slug:"/faq",permalink:"/interchain-security/v4.2.0/faq",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:5,frontMatter:{sidebar_position:5,title:"Frequently Asked Questions",slug:"/faq"},sidebar:"tutorialSidebar",previous:{title:"Partial Set Security",permalink:"/interchain-security/v4.2.0/validators/partial-set-security-for-validators"},next:{title:"ADRs",permalink:"/interchain-security/v4.2.0/adrs/intro"}},h={},c=[{value:"What is a consumer chain?",id:"what-is-a-consumer-chain",level:2},{value:"What happens to consumer if provider is down?",id:"what-happens-to-consumer-if-provider-is-down",level:2},{value:"What happens to provider if consumer is down?",id:"what-happens-to-provider-if-consumer-is-down",level:2},{value:"Can I run the provider and consumer chains on the same machine?",id:"can-i-run-the-provider-and-consumer-chains-on-the-same-machine",level:2},{value:"Can the consumer chain have its own token?",id:"can-the-consumer-chain-have-its-own-token",level:2},{value:"How are Tx fees paid on consumer?",id:"how-are-tx-fees-paid-on-consumer",level:2},{value:"Are there any restrictions the consumer chains need to abide by?",id:"are-there-any-restrictions-the-consumer-chains-need-to-abide-by",level:2},{value:"What's in it for the validators and stakers?",id:"whats-in-it-for-the-validators-and-stakers",level:2},{value:"Can the consumer chain have its own governance?",id:"can-the-consumer-chain-have-its-own-governance",level:2},{value:"Can validators opt out of validating a consumer chain?",id:"can-validators-opt-out-of-validating-a-consumer-chain",level:2},{value:"How does Slashing work?",id:"how-does-slashing-work",level:2},{value:"Can Consumer Chains perform Software Upgrades?",id:"can-consumer-chains-perform-software-upgrades",level:2},{value:"How can I connect to the testnets?",id:"how-can-i-connect-to-the-testnets",level:2},{value:"How do I start using ICS?",id:"how-do-i-start-using-ics",level:2},{value:"Which relayers are supported?",id:"which-relayers-are-supported",level:2},{value:"How does key delegation work in ICS?",id:"how-does-key-delegation-work-in-ics",level:2},{value:"How does Partial Set Security work?",id:"how-does-partial-set-security-work",level:2},{value:"How does a validator know which consumers chains it has to validate?",id:"how-does-a-validator-know-which-consumers-chains-it-has-to-validate",level:2},{value:"How many chains can a validator opt in to?",id:"how-many-chains-can-a-validator-opt-in-to",level:2},{value:"Can validators assign a consensus keys while a consumer-addition proposal is in voting period?",id:"can-validators-assign-a-consensus-keys-while-a-consumer-addition-proposal-is-in-voting-period",level:2},{value:"Can validators assign a consensus key during the voting period for a consumer-addition proposal if they are not in the top N?",id:"can-validators-assign-a-consensus-key-during-the-voting-period-for-a-consumer-addition-proposal-if-they-are-not-in-the-top-n",level:2},{value:"Can validators opt in to an Opt-in or Top N chain after its consumer-addition proposal voting period is over but before the spawn time?",id:"can-validators-opt-in-to-an-opt-in-or-top-n-chain-after-its-consumer-addition-proposal-voting-period-is-over-but-before-the-spawn-time",level:2},{value:"Can validators opt in to an Opt-in chain after the spawn time if nobody else opted in?",id:"can-validators-opt-in-to-an-opt-in-chain-after-the-spawn-time-if-nobody-else-opted-in",level:2},{value:"Can all validators opt out of an Opt-in chain?",id:"can-all-validators-opt-out-of-an-opt-in-chain",level:2},{value:"Can validators set a commission rate for chains they have not opted in to?",id:"can-validators-set-a-commission-rate-for-chains-they-have-not-opted-in-to",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,a.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"what-is-a-consumer-chain",children:"What is a consumer chain?"}),"\n",(0,t.jsx)(n.p,{children:"Consumer chain is a blockchain operated by (a subset of) the validators of the provider chain. The ICS protocol ensures that the consumer chain gets information about which validators should run it (informs consumer chain about the current state of the validator set and the opted in validators for this consumer chain on the provider)."}),"\n",(0,t.jsx)(n.p,{children:"Consumer chains are run on infrastructure (virtual or physical machines) distinct from the provider, have their own configurations and operating requirements."}),"\n",(0,t.jsx)(n.h2,{id:"what-happens-to-consumer-if-provider-is-down",children:"What happens to consumer if provider is down?"}),"\n",(0,t.jsx)(n.p,{children:"In case the provider chain halts or experiences difficulties the consumer chain will keep operating - the provider chain and consumer chains represent different networks, which only share the validator set."}),"\n",(0,t.jsx)(n.p,{children:"The consumer chain will not halt if the provider halts because they represent distinct networks and distinct infrastructures. Provider chain liveness does not impact consumer chain liveness."}),"\n",(0,t.jsxs)(n.p,{children:["However, if the ",(0,t.jsx)(n.code,{children:"trusting_period"})," (currently 5 days for protocol safety reasons) elapses without receiving any updates from the provider, the consumer chain will essentially transition to a Proof of Authority chain.\nThis means that the validator set on the consumer will be the last validator set of the provider that the consumer knows about."]}),"\n",(0,t.jsx)(n.p,{children:'Steps to recover from this scenario and steps to "release" the validators from their duties will be specified at a later point.\nAt the very least, the consumer chain could replace the validator set, remove the ICS module and perform a genesis restart. The impact of this on the IBC clients and connections is currently under careful consideration.'}),"\n",(0,t.jsx)(n.h2,{id:"what-happens-to-provider-if-consumer-is-down",children:"What happens to provider if consumer is down?"}),"\n",(0,t.jsx)(n.p,{children:"Consumer chains do not impact the provider chain.\nThe ICS protocol is concerned only with validator set management, and the only communication that the provider requires from the consumer is information about validator activity (essentially keeping the provider informed about slash events)."}),"\n",(0,t.jsx)(n.h2,{id:"can-i-run-the-provider-and-consumer-chains-on-the-same-machine",children:"Can I run the provider and consumer chains on the same machine?"}),"\n",(0,t.jsx)(n.p,{children:"Yes, but you should favor running them in separate environments so failure of one machine does not impact your whole operation."}),"\n",(0,t.jsx)(n.h2,{id:"can-the-consumer-chain-have-its-own-token",children:"Can the consumer chain have its own token?"}),"\n",(0,t.jsx)(n.p,{children:"As any other cosmos-sdk chain the consumer chain can issue its own token, manage inflation parameters and use them to pay gas fees."}),"\n",(0,t.jsx)(n.h2,{id:"how-are-tx-fees-paid-on-consumer",children:"How are Tx fees paid on consumer?"}),"\n",(0,t.jsx)(n.p,{children:"The consumer chain operates as any other cosmos-sdk chain. The ICS protocol does not impact the normal chain operations."}),"\n",(0,t.jsx)(n.h2,{id:"are-there-any-restrictions-the-consumer-chains-need-to-abide-by",children:"Are there any restrictions the consumer chains need to abide by?"}),"\n",(0,t.jsx)(n.p,{children:"No. Consumer chains are free to choose how they wish to operate, which modules to include, use CosmWASM in a permissioned or a permissionless way.\nThe only thing that separates consumer chains from standalone chains is that they share their validator set with the provider chain."}),"\n",(0,t.jsx)(n.h2,{id:"whats-in-it-for-the-validators-and-stakers",children:"What's in it for the validators and stakers?"}),"\n",(0,t.jsxs)(n.p,{children:["The consumer chains sends a portion of its fees and inflation as reward to the provider chain as defined by ",(0,t.jsx)(n.code,{children:"ConsumerRedistributionFraction"}),". The rewards are distributed (sent to the provider) every ",(0,t.jsx)(n.code,{children:"BlocksPerDistributionTransmission"}),"."]}),"\n",(0,t.jsx)(n.admonition,{type:"note",children:(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ConsumerRedistributionFraction"})," and ",(0,t.jsx)(n.code,{children:"BlocksPerDistributionTransmission"})," are parameters defined in the ",(0,t.jsx)(n.code,{children:"ConsumerAdditionProposal"})," used to create the consumer chain. These parameters can be changed via consumer chain governance."]})}),"\n",(0,t.jsx)(n.h2,{id:"can-the-consumer-chain-have-its-own-governance",children:"Can the consumer chain have its own governance?"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Yes."})}),"\n",(0,t.jsx)(n.p,{children:'In that case the validators are not necessarily part of the governance structure. Instead, their place in governance is replaced by "representatives" (governors). The representatives do not need to run validators, they simply represent the interests of a particular interest group on the consumer chain.'}),"\n",(0,t.jsx)(n.p,{children:"Validators can also be representatives but representatives are not required to run validator nodes."}),"\n",(0,t.jsx)(n.p,{children:"This feature discerns between validator operators (infrastructure) and governance representatives which further democratizes the ecosystem. This also reduces the pressure on validators to be involved in on-chain governance."}),"\n",(0,t.jsx)(n.h2,{id:"can-validators-opt-out-of-validating-a-consumer-chain",children:"Can validators opt out of validating a consumer chain?"}),"\n",(0,t.jsx)(n.p,{children:"A validator can always opt out from an Opt-In consumer chain.\nA validator can only opt out from a Top N chain if the validator does not belong to the top N% validators."}),"\n",(0,t.jsx)(n.h2,{id:"how-does-slashing-work",children:"How does Slashing work?"}),"\n",(0,t.jsxs)(n.p,{children:["Validators that perform an equivocation or a light-client attack on a consumer chain are slashed on the provider chain.\nWe achieve this by submitting the proof of the equivocation or the light-client attack to the provider chain (see ",(0,t.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/slashing",children:"slashing"}),")."]}),"\n",(0,t.jsx)(n.h2,{id:"can-consumer-chains-perform-software-upgrades",children:"Can Consumer Chains perform Software Upgrades?"}),"\n",(0,t.jsx)(n.p,{children:"Consumer chains are standalone chains, in the sense that they can run arbitrary logic and use any modules they want (ie CosmWASM)."}),"\n",(0,t.jsx)(n.p,{children:"Consumer chain upgrades are unlikely to impact the provider chain, as long as there are no changes to the ICS module."}),"\n",(0,t.jsx)(n.h2,{id:"how-can-i-connect-to-the-testnets",children:"How can I connect to the testnets?"}),"\n",(0,t.jsxs)(n.p,{children:["Check out the ",(0,t.jsx)(n.a,{href:"/interchain-security/v4.2.0/validators/joining-testnet",children:"Joining Replicated Security testnet"})," section."]}),"\n",(0,t.jsx)(n.h2,{id:"how-do-i-start-using-ics",children:"How do I start using ICS?"}),"\n",(0,t.jsxs)(n.p,{children:["To become a consumer chain use this ",(0,t.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/onboarding",children:"checklist"})," and check the ",(0,t.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/app-integration",children:"App integration section"})]}),"\n",(0,t.jsx)(n.h2,{id:"which-relayers-are-supported",children:"Which relayers are supported?"}),"\n",(0,t.jsx)(n.p,{children:"Currently supported versions:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Hermes 1.8.0"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"how-does-key-delegation-work-in-ics",children:"How does key delegation work in ICS?"}),"\n",(0,t.jsxs)(n.p,{children:["You can check the ",(0,t.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/key-assignment",children:"Key Assignment Guide"})," for specific instructions."]}),"\n",(0,t.jsx)(n.h2,{id:"how-does-partial-set-security-work",children:"How does Partial Set Security work?"}),"\n",(0,t.jsx)(n.p,{children:"Partial Set Security allows a provider chain to share only a subset of its validator set with a consumer chain. This subset can be determined by the top N% validators by voting power, or by validators opting in to validate the consumer chain. Partial Set Security allows for flexible tradeoffs between security, decentralization, and the budget a consumer chain spends on rewards to validators."}),"\n",(0,t.jsxs)(n.p,{children:["See the ",(0,t.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/partial-set-security",children:"Partial Set Security"})," section for more information."]}),"\n",(0,t.jsx)(n.h2,{id:"how-does-a-validator-know-which-consumers-chains-it-has-to-validate",children:"How does a validator know which consumers chains it has to validate?"}),"\n",(0,t.jsxs)(n.p,{children:["In order for a validator to keep track of all the chains it has to validate, the validator can use the\n",(0,t.jsxs)(n.a,{href:"/interchain-security/v4.2.0/validators/partial-set-security-for-validators#which-chains-does-a-validator-have-to-validate",children:[(0,t.jsx)(n.code,{children:"has-to-validate"})," query"]}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"how-many-chains-can-a-validator-opt-in-to",children:"How many chains can a validator opt in to?"}),"\n",(0,t.jsxs)(n.p,{children:["There is ",(0,t.jsx)(n.strong,{children:"no"})," limit in the number of consumers chains a validator can choose to opt in to."]}),"\n",(0,t.jsx)(n.h2,{id:"can-validators-assign-a-consensus-keys-while-a-consumer-addition-proposal-is-in-voting-period",children:"Can validators assign a consensus keys while a consumer-addition proposal is in voting period?"}),"\n",(0,t.jsxs)(n.p,{children:["Yes, see the ",(0,t.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/key-assignment",children:"Key Assignment Guide"})," for more information."]}),"\n",(0,t.jsx)(n.h2,{id:"can-validators-assign-a-consensus-key-during-the-voting-period-for-a-consumer-addition-proposal-if-they-are-not-in-the-top-n",children:"Can validators assign a consensus key during the voting period for a consumer-addition proposal if they are not in the top N?"}),"\n",(0,t.jsx)(n.p,{children:"Yes."}),"\n",(0,t.jsx)(n.h2,{id:"can-validators-opt-in-to-an-opt-in-or-top-n-chain-after-its-consumer-addition-proposal-voting-period-is-over-but-before-the-spawn-time",children:"Can validators opt in to an Opt-in or Top N chain after its consumer-addition proposal voting period is over but before the spawn time?"}),"\n",(0,t.jsx)(n.p,{children:"Yes."}),"\n",(0,t.jsx)(n.h2,{id:"can-validators-opt-in-to-an-opt-in-chain-after-the-spawn-time-if-nobody-else-opted-in",children:"Can validators opt in to an Opt-in chain after the spawn time if nobody else opted in?"}),"\n",(0,t.jsx)(n.p,{children:"No, the consumer chain will not be added if nobody opted in by the spawn time. At least one validator, regardless of its voting power, must opt in before the spawn time arrives in order for the chain can start."}),"\n",(0,t.jsx)(n.h2,{id:"can-all-validators-opt-out-of-an-opt-in-chain",children:"Can all validators opt out of an Opt-in chain?"}),"\n",(0,t.jsx)(n.p,{children:"Yes, the consumer chain will halt with an ERR CONSENSUS FAILURE error after the opt-out message for the last validator is received."}),"\n",(0,t.jsx)(n.h2,{id:"can-validators-set-a-commission-rate-for-chains-they-have-not-opted-in-to",children:"Can validators set a commission rate for chains they have not opted in to?"}),"\n",(0,t.jsx)(n.p,{children:"Yes, and this is useful for validators that are not in the top N% of the provider chain, but might move into the top N% in the future.\nBy setting the commission rate ahead of time, they can make sure that they immediately have a commission rate of their choosing as soon as they are in the top N%."})]})}function l(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>s});var t=i(7294);const a={},o=t.createContext(a);function s(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/8a86a05c.a622c0e8.js b/assets/js/8a86a05c.a622c0e8.js
new file mode 100644
index 0000000000..2d0f2fff9b
--- /dev/null
+++ b/assets/js/8a86a05c.a622c0e8.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5938],{8380:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var t=i(5893),s=i(1151);const a={sidebar_position:3,title:"Onboarding Checklist"},o="Consumer Onboarding Checklist",r={id:"consumer-development/onboarding",title:"Onboarding Checklist",description:"The following checklists will aid in onboarding a new consumer chain to interchain security.",source:"@site/versioned_docs/version-v5.0.0/consumer-development/onboarding.md",sourceDirName:"consumer-development",slug:"/consumer-development/onboarding",permalink:"/interchain-security/v5.0.0/consumer-development/onboarding",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Onboarding Checklist"},sidebar:"tutorialSidebar",previous:{title:"Consumer Chain Governance",permalink:"/interchain-security/v5.0.0/consumer-development/consumer-chain-governance"},next:{title:"Offboarding Checklist",permalink:"/interchain-security/v5.0.0/consumer-development/offboarding"}},c={},l=[{value:"1. Complete testing & integration",id:"1-complete-testing--integration",level:2},{value:"2. Create an Onboarding Repository",id:"2-create-an-onboarding-repository",level:2},{value:"3. Submit a Governance Proposal",id:"3-submit-a-governance-proposal",level:2},{value:"4. Launch",id:"4-launch",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",input:"input",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"consumer-onboarding-checklist",children:"Consumer Onboarding Checklist"}),"\n",(0,t.jsx)(n.p,{children:"The following checklists will aid in onboarding a new consumer chain to interchain security."}),"\n",(0,t.jsxs)(n.p,{children:["Additionally, you can check the ",(0,t.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md",children:"testnet repo"})," for a comprehensive guide on preparing and launching consumer chains."]}),"\n",(0,t.jsx)(n.h2,{id:"1-complete-testing--integration",children:"1. Complete testing & integration"}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test integration with gaia"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test your protocol with supported relayer versions (minimum hermes 1.4.1)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","reach out to the ICS team if you are facing issues"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"2-create-an-onboarding-repository",children:"2. Create an Onboarding Repository"}),"\n",(0,t.jsx)(n.p,{children:"To help validators and other node runners onboard onto your chain, please prepare a repository with information on how to run your chain."}),"\n",(0,t.jsx)(n.p,{children:"This should include (at minimum):"}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json without CCV data (before the proposal passes)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json with CCV data (after spawn time passes). Check if CCV data needs to be transformed (see ",(0,t.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/consumer-genesis-transformation",children:"Transform Consumer Genesis"}),")"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","information about relevant seed/peer nodes you are running"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","relayer information (compatible versions)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","copy of your governance proposal (as JSON)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","a script showing how to start your chain and connect to peers (optional)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take feedback from other developers, validators and community regarding your onboarding repo and make improvements where applicable"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Example of such a repository can be found ",(0,t.jsx)(n.a,{href:"https://github.com/hyphacoop/ics-testnets/tree/main/game-of-chains-2022/sputnik",children:"here"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"3-submit-a-governance-proposal",children:"3. Submit a Governance Proposal"}),"\n",(0,t.jsxs)(n.p,{children:["Before you submit a ",(0,t.jsx)(n.code,{children:"ConsumerChainAddition"})," proposal, please consider allowing at least a day between your proposal passing and the chain spawn time. This will allow the validators, other node operators and the community to prepare for the chain launch.\nIf possible, please set your spawn time so people from different parts of the globe can be available in case of emergencies. Ideally, you should set your spawn time to be between 12:00 UTC and 20:00 UTC so most validator operators are available and ready to respond to any issues."]}),"\n",(0,t.jsxs)(n.p,{children:["Additionally, reach out to the community via the ",(0,t.jsx)(n.a,{href:"https://forum.cosmos.network/",children:"forum"})," to formalize your intention to become an ICS consumer, gather community support and accept feedback from the community, validators and developers."]}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine your chain's spawn time"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine consumer chain parameters to be put in the proposal"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take note to include a link to your onboarding repository"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","describe the purpose and benefits of running your chain"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Example of a consumer chain addition proposal."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'// ConsumerAdditionProposal is a governance proposal on the provider chain to spawn a new consumer chain.\n// If it passes, then all validators on the provider chain are expected to validate the consumer chain at spawn time.\n// It is recommended that spawn time occurs after the proposal end time.\n{\n // Title of the proposal\n "title": "Add consumer chain",\n // Description of the proposal\n // format the text as a .md file and include the file in your onboarding repository\n "description": ".md description of your chain and all other relevant information",\n // Proposed chain-id of the new consumer chain.\n // Must be unique from all other consumer chain ids of the executing provider chain.\n "chain_id": "newchain-1",\n // Initial height of new consumer chain.\n // For a completely new chain, this will be {0,1}.\n "initial_height" : {\n "revision_height": 0,\n "revision_number": 1,\n },\n // Hash of the consumer chain genesis state without the consumer CCV module genesis params.\n // It is used for off-chain confirmation of genesis.json validity by validators and other parties.\n "genesis_hash": "d86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0",\n // Hash of the consumer chain binary that should be run by validators on chain initialization.\n // It is used for off-chain confirmation of binary validity by validators and other parties.\n "binary_hash": "376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1",\n // Time on the provider chain at which the consumer chain genesis is finalized and all validators\n // will be responsible for starting their consumer chain validator node.\n "spawn_time": "2023-02-28T20:40:00.000000Z",\n // Unbonding period for the consumer chain.\n // It should be smaller than that of the provider.\n "unbonding_period": 86400000000000,\n // Timeout period for CCV related IBC packets.\n // Packets are considered timed-out after this interval elapses.\n "ccv_timeout_period": 259200000000000,\n // IBC transfer packets will timeout after this interval elapses.\n "transfer_timeout_period": 1800000000000,\n // The fraction of tokens allocated to the consumer redistribution address during distribution events.\n // The fraction is a string representing a decimal number. For example "0.75" would represent 75%.\n // The reward amount distributed to the provider is calculated as: 1 - consumer_redistribution_fraction.\n "consumer_redistribution_fraction": "0.75",\n // BlocksPerDistributionTransmission is the number of blocks between IBC token transfers from the consumer chain to the provider chain.\n // eg. send rewards to the provider every 1000 blocks\n "blocks_per_distribution_transmission": 1000,\n // The number of historical info entries to persist in store.\n // This param is a part of the cosmos sdk staking module. In the case of\n // a ccv enabled consumer chain, the ccv module acts as the staking module.\n "historical_entries": 10000,\n // The ID of a token transfer channel used for the Reward Distribution\n\t// sub-protocol. If DistributionTransmissionChannel == "", a new transfer\n\t// channel is created on top of the same connection as the CCV channel.\n\t// Note that transfer_channel_id is the ID of the channel end on the consumer chain.\n // it is most relevant for chains performing a standalone to consumer changeover\n // in order to maintain the existing ibc transfer channel\n "distribution_transmission_channel": "channel-123"\n}\n'})}),"\n",(0,t.jsx)(n.h2,{id:"4-launch",children:"4. Launch"}),"\n",(0,t.jsx)(n.p,{children:"The consumer chain starts after at least 66.67% of all provider's voting power comes online. The consumer chain is considered interchain secured once the appropriate CCV channels are established and the first validator set update is propagated from the provider to the consumer"}),"\n",(0,t.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","provide a repo with onboarding instructions for validators (it should already be listed in the proposal)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json with ccv data populated (MUST contain the initial validator set)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","maintenance & emergency contact info (relevant discord, telegram, slack or other communication channels)"]}),"\n",(0,t.jsxs)(n.li,{className:"task-list-item",children:[(0,t.jsx)(n.input,{type:"checkbox",disabled:!0})," ","have a block explorer in place to track chain activity & health"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>o});var t=i(7294);const s={},a=t.createContext(s);function o(e){const n=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/8d3b6fe8.e2b00793.js b/assets/js/8d3b6fe8.e2b00793.js
new file mode 100644
index 0000000000..25e6030a63
--- /dev/null
+++ b/assets/js/8d3b6fe8.e2b00793.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1163],{6216:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>m,frontMatter:()=>s,metadata:()=>i,toc:()=>h});var o=t(5893),a=t(1151);const s={sidebar_position:2},r="Consumer Chain Governance",i={id:"consumer-development/consumer-chain-governance",title:"Consumer Chain Governance",description:'Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We\'ll cover what these are in the "Whitelist" section below.',source:"@site/versioned_docs/version-v4.2.0-docs/consumer-development/consumer-chain-governance.md",sourceDirName:"consumer-development",slug:"/consumer-development/consumer-chain-governance",permalink:"/interchain-security/v4.2.0/consumer-development/consumer-chain-governance",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Developing an ICS consumer chain",permalink:"/interchain-security/v4.2.0/consumer-development/app-integration"},next:{title:"Onboarding Checklist",permalink:"/interchain-security/v4.2.0/consumer-development/onboarding"}},c={},h=[{value:"Democracy module",id:"democracy-module",level:2},{value:"CosmWasm",id:"cosmwasm",level:2},{value:"The Whitelist",id:"the-whitelist",level:2}];function l(e){const n={a:"a",h1:"h1",h2:"h2",p:"p",...(0,a.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"consumer-chain-governance",children:"Consumer Chain Governance"}),"\n",(0,o.jsx)(n.p,{children:'Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We\'ll cover what these are in the "Whitelist" section below.'}),"\n",(0,o.jsx)(n.h2,{id:"democracy-module",children:"Democracy module"}),"\n",(0,o.jsx)(n.p,{children:"The democracy module provides a governance experience identical to what exists on a standalone Cosmos chain, with one small but important difference. On a standalone Cosmos chain validators can act as representatives for their delegators by voting with their stake, but only if the delegator themselves does not vote. This is a lightweight form of liquid democracy."}),"\n",(0,o.jsx)(n.p,{children:"Using the democracy module on a consumer chain is the exact same experience, except for the fact that it is not the actual validator set of the chain (since it is a consumer chain, these are the Cosmos Hub validators) acting as representatives. Instead, there is a separate representative role who token holders can delegate to and who can perform the functions that validators do in Cosmos governance, without participating in proof of stake consensus."}),"\n",(0,o.jsxs)(n.p,{children:["For an example, see the ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/main/app/consumer-democracy",children:"Democracy Consumer"})]}),"\n",(0,o.jsx)(n.h2,{id:"cosmwasm",children:"CosmWasm"}),"\n",(0,o.jsx)(n.p,{children:"There are several great DAO and governance frameworks written as CosmWasm contracts. These can be used as the main governance system for a consumer chain. Actions triggered by the CosmWasm governance contracts are able to affect parameters and trigger actions on the consumer chain."}),"\n",(0,o.jsxs)(n.p,{children:["For an example, see ",(0,o.jsx)(n.a,{href:"https://github.com/neutron-org/neutron/",children:"Neutron"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"the-whitelist",children:"The Whitelist"}),"\n",(0,o.jsxs)(n.p,{children:["Not everything on a consumer chain can be changed by the consumer's governance. Some settings having to do with consensus etc. can only be changed by the provider chain. Consumer chains include a whitelist of parameters that are allowed to be changed by the consumer chain governance. For an example, see ",(0,o.jsx)(n.a,{href:"https://github.com/neutron-org/neutron/blob/main/app/proposals_allowlisting.go",children:"Neutron's"})," whitelist."]})]})}function m(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>i,a:()=>r});var o=t(7294);const a={},s=o.createContext(a);function r(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/903c2771.18b9a08b.js b/assets/js/903c2771.18b9a08b.js
new file mode 100644
index 0000000000..4db8f2a766
--- /dev/null
+++ b/assets/js/903c2771.18b9a08b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6054],{461:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>d});var n=o(5893),i=o(1151);const s={sidebar_position:10,title:"Soft Opt-Out"},a=void 0,r={id:"adrs/adr-009-soft-opt-out",title:"Soft Opt-Out",description:"ADR 009: Soft Opt-Out",source:"@site/docs/adrs/adr-009-soft-opt-out.md",sourceDirName:"adrs",slug:"/adrs/adr-009-soft-opt-out",permalink:"/interchain-security/adrs/adr-009-soft-opt-out",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:10,frontMatter:{sidebar_position:10,title:"Soft Opt-Out"},sidebar:"tutorialSidebar",previous:{title:"Throttle with retries",permalink:"/interchain-security/adrs/adr-008-throttle-retries"},next:{title:"Standalone to Consumer Changeover",permalink:"/interchain-security/adrs/adr-010-standalone-changeover"}},l={},d=[{value:"ADR 009: Soft Opt-Out",id:"adr-009-soft-opt-out",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function c(e){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"adr-009-soft-opt-out",children:"ADR 009: Soft Opt-Out"}),"\n",(0,n.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"6/13/23: Initial draft of ADR. Feature already implemented and in production."}),"\n",(0,n.jsx)(t.li,{children:"6/19/24: Change status to deprecated"}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,n.jsxs)(t.p,{children:["Deprecated\nDeprecated by ",(0,n.jsx)(t.a,{href:"/interchain-security/adrs/adr-015-partial-set-security",children:"Partial Set Security"})]}),"\n",(0,n.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,n.jsxs)(t.p,{children:["Some small validators may not have the resources needed to validate all consumer chains. Therefore a need exists to allow the bottom ",(0,n.jsx)(t.code,{children:"x%"})," of validators to opt-out of validating a consumer chain. Meaning downtime infractions for these validators are dropped without ever reaching the provider."]}),"\n",(0,n.jsx)(t.p,{children:"This document specifies a modification to the ccv protocol which allows the bottom x% of the validator set by power to opt out of validating consumer chains without being jailed or otherwise punished for it. The feature is implemented with entirely consumer-side code."}),"\n",(0,n.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,n.jsxs)(t.p,{children:["A consumer param exists, known as ",(0,n.jsx)(t.code,{children:"SoftOptOutThreshold"}),", which is a string decimal in the range of [0, 0.2], that determines the portion of validators which are allowed to opt out of validating that specific consumer."]}),"\n",(0,n.jsxs)(t.p,{children:["In every consumer beginblocker, a function is ran which determines the so called ",(0,n.jsx)(t.em,{children:"smallest non opt-out voting power"}),". Validators with voting power greater than or equal to this value must validate the consumer chain, while validators below this value may opt out of validating the consumer chain."]}),"\n",(0,n.jsxs)(t.p,{children:["The smallest non opt-out voting power is recomputed every beginblocker in ",(0,n.jsx)(t.code,{children:"UpdateSmallestNonOptOutPower()"}),". In a nutshell, the method obtains the total voting power of the consumer, iterates through the full valset (ordered power ascending) keeping track of a power sum, and when ",(0,n.jsx)(t.code,{children:"powerSum / totalPower > SoftOptOutThreshold"}),", the ",(0,n.jsx)(t.code,{children:"SmallestNonOptOutPower"})," is found and persisted."]}),"\n",(0,n.jsxs)(t.p,{children:["Then, whenever the ",(0,n.jsx)(t.code,{children:"Slash()"})," interface is executed on the consumer, if the voting power of the relevant validator being slashed is less than ",(0,n.jsx)(t.code,{children:"SmallestNonOptOutPower"})," for that block, the slash request is dropped and never sent to the provider."]}),"\n",(0,n.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,n.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Small validators can opt out of validating specific consumers without being punished for it."}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["The bottom ",(0,n.jsx)(t.code,{children:"x%"})," is still part of the total voting power of the consumer chain. This means that if the soft opt-out threshold is set to ",(0,n.jsx)(t.code,{children:"10%"})," for example, and every validator in the bottom ",(0,n.jsx)(t.code,{children:"10%"})," opts out from validating the consumer, then a ",(0,n.jsx)(t.code,{children:"24%"})," downtime of the remaining voting power would halt the chain. This may be especially problematic during consumer upgrades."]}),"\n",(0,n.jsxs)(t.li,{children:["In nominal scenarios, consumers with soft opt out enabled will be constructing slash packets for small vals, which may be dropped. This is wasted computation, but necessary to keep implementation simple. Note that the sdk's ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/d3f09c222243bb3da3464969f0366330dcb977a8/x/slashing/keeper/infractions.go#L75",children:"full downtime logic"})," is always executed on the consumer, which can be computationally expensive and slow down certain blocks."]}),"\n",(0,n.jsx)(t.li,{children:"In a consumer chain, when a validator that has opted out becomes the proposer, there will naturally be no proposal made and validators would need to move to the next consensus round for the same height to reach a decision. As a result, we would need more time to finalize blocks on a consumer chain."}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"neutral",children:"Neutral"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Validators in the bottom of the valset who don't have to validate, may receive large delegation(s) which suddenly boost the validator to the subset that has to validate. This may catch the validator off guard."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Original issue with some napkin math ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/784",children:"#784"})]}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},1151:(e,t,o)=>{o.d(t,{Z:()=>r,a:()=>a});var n=o(7294);const i={},s=n.createContext(i);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/935f2afb.78bd90f6.js b/assets/js/935f2afb.78bd90f6.js
new file mode 100644
index 0000000000..78ff237bc2
--- /dev/null
+++ b/assets/js/935f2afb.78bd90f6.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"main","banner":"unreleased","badge":true,"noIndex":false,"className":"docs-version-current","isLast":false,"docsSidebars":{"tutorialSidebar":[{"type":"link","label":"Interchain Security Docs","href":"/interchain-security/","docId":"index","unlisted":false},{"type":"category","label":"Introduction","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Overview","href":"/interchain-security/introduction/overview","docId":"introduction/overview","unlisted":false},{"type":"link","label":"Terminology","href":"/interchain-security/introduction/terminology","docId":"introduction/terminology","unlisted":false},{"type":"link","label":"Interchain Security Parameters","href":"/interchain-security/introduction/params","docId":"introduction/params","unlisted":false},{"type":"link","label":"Technical Specification","href":"/interchain-security/introduction/technical-specification","docId":"introduction/technical-specification","unlisted":false}]},{"type":"category","label":"Upgrading","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Upgrading to ICS v5.0.0","href":"/interchain-security/upgrading/migrate_v4_v5","docId":"upgrading/migrate_v4_v5","unlisted":false}]},{"type":"category","label":"Features","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Key Assignment","href":"/interchain-security/features/key-assignment","docId":"features/key-assignment","unlisted":false},{"type":"link","label":"Reward Distribution","href":"/interchain-security/features/reward-distribution","docId":"features/reward-distribution","unlisted":false},{"type":"link","label":"ICS Provider Proposals","href":"/interchain-security/features/proposals","docId":"features/proposals","unlisted":false},{"type":"link","label":"Consumer Initiated Slashing","href":"/interchain-security/features/slashing","docId":"features/slashing","unlisted":false},{"type":"link","label":"Democracy modules","href":"/interchain-security/features/democracy-modules","docId":"features/democracy-modules","unlisted":false},{"type":"link","label":"Partial Set Security","href":"/interchain-security/features/partial-set-security","docId":"features/partial-set-security","unlisted":false},{"type":"link","label":"Power Shaping","href":"/interchain-security/features/power-shaping","docId":"features/power-shaping","unlisted":false}]},{"type":"category","label":"Consumer Guide","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Developing an ICS consumer chain","href":"/interchain-security/consumer-development/app-integration","docId":"consumer-development/app-integration","unlisted":false},{"type":"link","label":"Consumer Chain Governance","href":"/interchain-security/consumer-development/consumer-chain-governance","docId":"consumer-development/consumer-chain-governance","unlisted":false},{"type":"link","label":"Onboarding Checklist","href":"/interchain-security/consumer-development/onboarding","docId":"consumer-development/onboarding","unlisted":false},{"type":"link","label":"Offboarding Checklist","href":"/interchain-security/consumer-development/offboarding","docId":"consumer-development/offboarding","unlisted":false},{"type":"link","label":"Changeover Procedure","href":"/interchain-security/consumer-development/changeover-procedure","docId":"consumer-development/changeover-procedure","unlisted":false},{"type":"link","label":"Consumer Genesis Transformation","href":"/interchain-security/consumer-development/consumer-genesis-transformation","docId":"consumer-development/consumer-genesis-transformation","unlisted":false}]},{"type":"category","label":"Validators Guide","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Overview","href":"/interchain-security/validators/overview","docId":"validators/overview","unlisted":false},{"type":"link","label":"Joining Interchain Security testnet","href":"/interchain-security/validators/joining-testnet","docId":"validators/joining-testnet","unlisted":false},{"type":"link","label":"Consumer chain validator rewards","href":"/interchain-security/validators/withdraw_rewards","docId":"validators/withdraw_rewards","unlisted":false},{"type":"link","label":"Validator Instructions for Changeover Procedure","href":"/interchain-security/validators/changeover-procedure","docId":"validators/changeover-procedure","unlisted":false},{"type":"link","label":"Joining Neutron","href":"/interchain-security/validators/joining-neutron","docId":"validators/joining-neutron","unlisted":false},{"type":"link","label":"Joining Stride","href":"/interchain-security/validators/joining-stride","docId":"validators/joining-stride","unlisted":false},{"type":"link","label":"Partial Set Security","href":"/interchain-security/validators/partial-set-security-for-validators","docId":"validators/partial-set-security-for-validators","unlisted":false}]},{"type":"link","label":"Frequently Asked Questions","href":"/interchain-security/faq","docId":"frequently-asked-questions","unlisted":false},{"type":"category","label":"ADRs","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Overview","href":"/interchain-security/adrs/intro","docId":"adrs/intro","unlisted":false},{"type":"link","label":"Denom DOS fixes","href":"/interchain-security/adrs/adr-004-denom-dos-fixes","docId":"adrs/adr-004-denom-dos-fixes","unlisted":false},{"type":"link","label":"Pause validator unbonding during equivocation proposal","href":"/interchain-security/adrs/adr-007-pause-unbonding-on-eqv-prop","docId":"adrs/adr-007-pause-unbonding-on-eqv-prop","unlisted":false},{"type":"link","label":"Key Assignment","href":"/interchain-security/adrs/adr-001-key-assignment","docId":"adrs/adr-001-key-assignment","unlisted":false},{"type":"link","label":"Jail Throttling","href":"/interchain-security/adrs/adr-002-throttle","docId":"adrs/adr-002-throttle","unlisted":false},{"type":"link","label":"Equivocation governance proposal","href":"/interchain-security/adrs/adr-003-equivocation-gov-proposal","docId":"adrs/adr-003-equivocation-gov-proposal","unlisted":false},{"type":"link","label":"Cryptographic verification of equivocation evidence","href":"/interchain-security/adrs/adr-005-cryptographic-equivocation-verification","docId":"adrs/adr-005-cryptographic-equivocation-verification","unlisted":false},{"type":"link","label":"Throttle with retries","href":"/interchain-security/adrs/adr-008-throttle-retries","docId":"adrs/adr-008-throttle-retries","unlisted":false},{"type":"link","label":"Soft Opt-Out","href":"/interchain-security/adrs/adr-009-soft-opt-out","docId":"adrs/adr-009-soft-opt-out","unlisted":false},{"type":"link","label":"Standalone to Consumer Changeover","href":"/interchain-security/adrs/adr-010-standalone-changeover","docId":"adrs/adr-010-standalone-changeover","unlisted":false},{"type":"link","label":"Improving testing and increasing confidence","href":"/interchain-security/adrs/adr-011-improving-test-confidence","docId":"adrs/adr-011-improving-test-confidence","unlisted":false},{"type":"link","label":"Separate Releasing","href":"/interchain-security/adrs/adr-012-separate-releasing","docId":"adrs/adr-012-separate-releasing","unlisted":false},{"type":"link","label":"Slashing on the provider for consumer equivocation","href":"/interchain-security/adrs/adr-013-equivocation-slashing","docId":"adrs/adr-013-equivocation-slashing","unlisted":false},{"type":"link","label":"Epochs","href":"/interchain-security/adrs/adr-014-epochs","docId":"adrs/adr-014-epochs","unlisted":false},{"type":"link","label":"Partial Set Security","href":"/interchain-security/adrs/adr-015-partial-set-security","docId":"adrs/adr-015-partial-set-security","unlisted":false},{"type":"link","label":"Security aggregation","href":"/interchain-security/adrs/adr-016-securityaggregation","docId":"adrs/adr-016-securityaggregation","unlisted":false},{"type":"link","label":"ICS with Inactive Provider Validators","href":"/interchain-security/adrs/adr-017-allowing-inactive-validators","docId":"adrs/adr-017-allowing-inactive-validators","unlisted":false}]}]},"docs":{"adrs/adr-001-key-assignment":{"id":"adrs/adr-001-key-assignment","title":"Key Assignment","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-002-throttle":{"id":"adrs/adr-002-throttle","title":"Jail Throttling","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-003-equivocation-gov-proposal":{"id":"adrs/adr-003-equivocation-gov-proposal","title":"Equivocation governance proposal","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-004-denom-dos-fixes":{"id":"adrs/adr-004-denom-dos-fixes","title":"Denom DOS fixes","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-005-cryptographic-equivocation-verification":{"id":"adrs/adr-005-cryptographic-equivocation-verification","title":"Cryptographic verification of equivocation evidence","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-007-pause-unbonding-on-eqv-prop":{"id":"adrs/adr-007-pause-unbonding-on-eqv-prop","title":"Pause validator unbonding during equivocation proposal","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-008-throttle-retries":{"id":"adrs/adr-008-throttle-retries","title":"Throttle with retries","description":"ADR 008: Throttle with retries","sidebar":"tutorialSidebar"},"adrs/adr-009-soft-opt-out":{"id":"adrs/adr-009-soft-opt-out","title":"Soft Opt-Out","description":"ADR 009: Soft Opt-Out","sidebar":"tutorialSidebar"},"adrs/adr-010-standalone-changeover":{"id":"adrs/adr-010-standalone-changeover","title":"Standalone to Consumer Changeover","description":"ADR 010: Standalone to Consumer Changeover","sidebar":"tutorialSidebar"},"adrs/adr-011-improving-test-confidence":{"id":"adrs/adr-011-improving-test-confidence","title":"Improving testing and increasing confidence","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-012-separate-releasing":{"id":"adrs/adr-012-separate-releasing","title":"Separate Releasing","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-013-equivocation-slashing":{"id":"adrs/adr-013-equivocation-slashing","title":"Slashing on the provider for consumer equivocation","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-014-epochs":{"id":"adrs/adr-014-epochs","title":"Epochs","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-015-partial-set-security":{"id":"adrs/adr-015-partial-set-security","title":"Partial Set Security","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-016-securityaggregation":{"id":"adrs/adr-016-securityaggregation","title":"Security aggregation","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-017-allowing-inactive-validators":{"id":"adrs/adr-017-allowing-inactive-validators","title":"ICS with Inactive Provider Validators","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/intro":{"id":"adrs/intro","title":"Overview","description":"This is a location to record all high-level architecture decisions in the Interchain Security project.","sidebar":"tutorialSidebar"},"consumer-development/app-integration":{"id":"consumer-development/app-integration","title":"Developing an ICS consumer chain","description":"When developing an ICS consumer chain, besides just focusing on your chain\'s logic you should aim to allocate time to ensure that your chain is compatible with the ICS protocol.","sidebar":"tutorialSidebar"},"consumer-development/changeover-procedure":{"id":"consumer-development/changeover-procedure","title":"Changeover Procedure","description":"Chains that were not initially launched as consumers of Interchain Security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the changeover procedure and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain.","sidebar":"tutorialSidebar"},"consumer-development/consumer-chain-governance":{"id":"consumer-development/consumer-chain-governance","title":"Consumer Chain Governance","description":"Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We\'ll cover what these are in the \\"Whitelist\\" section below.","sidebar":"tutorialSidebar"},"consumer-development/consumer-genesis-transformation":{"id":"consumer-development/consumer-genesis-transformation","title":"Consumer Genesis Transformation","description":"Preparing a consumer chain for onboarding requires some information explaining how to run your chain. This includes a genesis file with CCV data where the CCV data is exported from the provider chain and added to the consumers genesis file (for more details check the documentation on Onboarding and Changeover).","sidebar":"tutorialSidebar"},"consumer-development/offboarding":{"id":"consumer-development/offboarding","title":"Offboarding Checklist","description":"To offboard a consumer chain simply submit a ConsumerRemovalProposal governance proposal listing a stop_time. After stop time passes, the provider chain will remove the chain from the ICS protocol (it will stop sending validator set updates).","sidebar":"tutorialSidebar"},"consumer-development/onboarding":{"id":"consumer-development/onboarding","title":"Onboarding Checklist","description":"The following checklists will aid in onboarding a new consumer chain to interchain security.","sidebar":"tutorialSidebar"},"features/democracy-modules":{"id":"features/democracy-modules","title":"Democracy modules","description":"This section is relevant for chains transitioning from a standalone chain and new consumer chains that require some functionality from the x/staking module.","sidebar":"tutorialSidebar"},"features/key-assignment":{"id":"features/key-assignment","title":"Key Assignment","description":"Key Assignment (aka. as key delegation) allows validator operators to use different consensus keys for each consumer chain validator node that they operate.","sidebar":"tutorialSidebar"},"features/partial-set-security":{"id":"features/partial-set-security","title":"Partial Set Security","description":"Partial Set Security (PSS) allows consumer chains to leverage only a subset of validators from the provider chain, which offers more flexibility than the traditional Replicated Security model. By introducing the top_N parameter, each consumer chain can choose the extent of security needed:","sidebar":"tutorialSidebar"},"features/power-shaping":{"id":"features/power-shaping","title":"Power Shaping","description":"To give consumer chains more flexibility in choosing their validator set, Interchain Security offers","sidebar":"tutorialSidebar"},"features/proposals":{"id":"features/proposals","title":"ICS Provider Proposals","description":"Interchain security module introduces new proposal types to the provider.","sidebar":"tutorialSidebar"},"features/reward-distribution":{"id":"features/reward-distribution","title":"Reward Distribution","description":"Sending and distributing rewards from consumer chains to the provider chain is handled by the Reward Distribution sub-protocol.","sidebar":"tutorialSidebar"},"features/slashing":{"id":"features/slashing","title":"Consumer Initiated Slashing","description":"A consumer chain is essentially a regular Cosmos-SDK based chain that uses the Interchain Security module to achieve economic security by stake deposited on the provider chain, instead of its own chain.","sidebar":"tutorialSidebar"},"frequently-asked-questions":{"id":"frequently-asked-questions","title":"Frequently Asked Questions","description":"What is a consumer chain?","sidebar":"tutorialSidebar"},"index":{"id":"index","title":"Interchain Security Docs","description":"Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains.","sidebar":"tutorialSidebar"},"introduction/overview":{"id":"introduction/overview","title":"Overview","description":"Interchain Security is an open sourced IBC application which allows cosmos blockchains to lease their proof-of-stake security to one another.","sidebar":"tutorialSidebar"},"introduction/params":{"id":"introduction/params","title":"Interchain Security Parameters","description":"The parameters necessary for Interchain Security (ICS) are defined in","sidebar":"tutorialSidebar"},"introduction/technical-specification":{"id":"introduction/technical-specification","title":"Technical Specification","description":"For a technical deep dive into the replicated security protocol, see the specification.","sidebar":"tutorialSidebar"},"introduction/terminology":{"id":"introduction/terminology","title":"Terminology","description":"You may have heard of one or multiple buzzwords thrown around in the cosmos and wider crypto ecosystem such shared security, interchain security, replicated security, cross chain validation, and mesh security. These terms will be clarified below, before diving into any introductions.","sidebar":"tutorialSidebar"},"upgrading/migrate_v4_v5":{"id":"upgrading/migrate_v4_v5","title":"Upgrading to ICS v5.0.0","description":"This ICS version uses cosmos-sdk v0.50.x and ibc-go v8.x.","sidebar":"tutorialSidebar"},"validators/changeover-procedure":{"id":"validators/changeover-procedure","title":"Validator Instructions for Changeover Procedure","description":"More details available in Changeover Procedure documentation.","sidebar":"tutorialSidebar"},"validators/joining-neutron":{"id":"validators/joining-neutron","title":"Joining Neutron","description":"Neutron is the first consumer chain to implement ICS.","sidebar":"tutorialSidebar"},"validators/joining-stride":{"id":"validators/joining-stride","title":"Joining Stride","description":"Stride is the first consumer chain to perform the standalone to consumer changeover procedure and transition from a standalone validator set to using cosmoshub-4 validator set.","sidebar":"tutorialSidebar"},"validators/joining-testnet":{"id":"validators/joining-testnet","title":"Joining Interchain Security testnet","description":"Introduction","sidebar":"tutorialSidebar"},"validators/overview":{"id":"validators/overview","title":"Overview","description":"We advise that you join the Interchain Security testnet to gain hands-on experience with running consumer chains.","sidebar":"tutorialSidebar"},"validators/partial-set-security-for-validators":{"id":"validators/partial-set-security-for-validators","title":"Partial Set Security","description":"Partial Set Security allows consumer chains to join as Opt-In or Top N.","sidebar":"tutorialSidebar"},"validators/withdraw_rewards":{"id":"validators/withdraw_rewards","title":"Consumer chain validator rewards","description":"A validator can only receive rewards from a consumer chain if the validator has been validating the consumer chain","sidebar":"tutorialSidebar"}}}')}}]);
\ No newline at end of file
diff --git a/assets/js/94b74966.577b76d7.js b/assets/js/94b74966.577b76d7.js
new file mode 100644
index 0000000000..ada9cf20fc
--- /dev/null
+++ b/assets/js/94b74966.577b76d7.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6673],{2546:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>d});var s=i(5893),t=i(1151);const o={sidebar_position:5},a="Changeover Procedure",r={id:"consumer-development/changeover-procedure",title:"Changeover Procedure",description:"Chains that were not initially launched as consumers of replicated security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the changeover procedure and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain.",source:"@site/versioned_docs/version-v4.2.0-docs/consumer-development/changeover-procedure.md",sourceDirName:"consumer-development",slug:"/consumer-development/changeover-procedure",permalink:"/interchain-security/v4.2.0/consumer-development/changeover-procedure",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"tutorialSidebar",previous:{title:"Offboarding Checklist",permalink:"/interchain-security/v4.2.0/consumer-development/offboarding"},next:{title:"Consumer Genesis Transformation",permalink:"/interchain-security/v4.2.0/consumer-development/consumer-genesis-transformation"}},c={},d=[{value:"Overview",id:"overview",level:2},{value:"1. ConsumerAddition proposal submitted to the provider chain",id:"1-consumeraddition-proposal-submitted-to-the-provider-chain",level:3},{value:"2. upgrade proposal on standalone chain",id:"2-upgrade-proposal-on-standalone-chain",level:3},{value:"3. spawn time is reached",id:"3-spawn-time-is-reached",level:3},{value:"4. standalone chain upgrade",id:"4-standalone-chain-upgrade",level:3},{value:"Notes",id:"notes",level:4},{value:"Onboarding Checklist",id:"onboarding-checklist",level:2},{value:"1. Complete testing & integration",id:"1-complete-testing--integration",level:2},{value:"2. Create an Onboarding Repository",id:"2-create-an-onboarding-repository",level:2},{value:"3. Submit a ConsumerChainAddition Governance Proposal to the provider",id:"3-submit-a-consumerchainaddition-governance-proposal-to-the-provider",level:2},{value:"3. Submit an Upgrade Proposal & Prepare for Changeover",id:"3-submit-an-upgrade-proposal--prepare-for-changeover",level:2},{value:"4. Upgrade time \ud83d\ude80",id:"4-upgrade-time-",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",input:"input",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"changeover-procedure",children:"Changeover Procedure"}),"\n",(0,s.jsxs)(n.p,{children:["Chains that were not initially launched as consumers of replicated security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the ",(0,s.jsx)(n.strong,{children:"changeover procedure"})," and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain."]}),"\n",(0,s.jsx)(n.p,{children:"The relevant protocol specifications are available below:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/overview_and_basic_concepts.md#channel-initialization-existing-chains",children:"ICS-28 with existing chains"}),"."]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-010-standalone-changeover",children:"ADR in ICS repo"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(n.p,{children:"Standalone to consumer changeover procedure can roughly be separated into 4 parts:"}),"\n",(0,s.jsxs)(n.h3,{id:"1-consumeraddition-proposal-submitted-to-the-provider-chain",children:["1. ConsumerAddition proposal submitted to the ",(0,s.jsx)(n.code,{children:"provider"})," chain"]}),"\n",(0,s.jsx)(n.p,{children:'The proposal is equivalent to the "normal" ConsumerAddition proposal submitted by new consumer chains.'}),"\n",(0,s.jsx)(n.p,{children:"However, here are the most important notes and differences between a new consumer chain and a standalone chain performing a changeover:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"chain_id"})," must be equal to the standalone chain id"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"initial_height"})," field has additional rules to abide by:"]}),"\n"]}),"\n",(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'{\n...\n "initial_height" : {\n // must correspond to current revision number of standalone chain\n // e.g. stride-1 => "revision_number": 1\n "revision_number": 1,\n\n // must correspond to a height that is at least 1 block after the upgrade\n // that will add the `consumer` module to the standalone chain\n // e.g. "upgrade_height": 100 => "revision_height": 101\n "revision_height": 1,\n },\n...\n}\n'})}),(0,s.jsx)(n.p,{children:"RevisionNumber: 0, RevisionHeight: 111"})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"genesis_hash"})," can be safely ignored because the chain is already running. A hash of the standalone chain's initial genesis may be used"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"binary_hash"})," may not be available ahead of time. All chains performing the changeover go through rigorous testing - if bugs are caught and fixed the hash listed in the proposal may not be the most recent one."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"spawn_time"})," listed in the proposal MUST be before the ",(0,s.jsx)(n.code,{children:"upgrade_height"})," listed in the upgrade proposal on the standalone chain."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"spawn_time"})," must occur before the ",(0,s.jsx)(n.code,{children:"upgrade_height"})," on the standalone chain is reached because the ",(0,s.jsx)(n.code,{children:"provider"})," chain must generate the ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," that contains the ",(0,s.jsx)(n.strong,{children:"validator set"})," that will be used after the changeover."]})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"unbonding_period"})," must correspond to the value used on the standalone chain. Otherwise, the clients used for the ccv protocol may be incorrectly initialized."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"distribution_transmission_channel"})," ",(0,s.jsx)(n.strong,{children:"should be set"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.admonition,{type:"note",children:[(0,s.jsxs)(n.p,{children:["Populating ",(0,s.jsx)(n.code,{children:"distribution_transmission_channel"})," will enable the standalone chain to reuse one of the existing channels to the provider for consumer chain rewards distribution. This will preserve the ",(0,s.jsx)(n.code,{children:"ibc denom"})," that may already be in use."]}),(0,s.jsx)(n.p,{children:"If the parameter is not set, a new channel will be created."})]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"ccv_timeout_period"})," has no important notes"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"transfer_timeout_period"})," has no important notes"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"consumer_redistribution_fraction"})," has no important notes"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"blocks_per_distribution_transmission"})," has no important notes"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"historical_entries"})," has no important notes"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"2-upgrade-proposal-on-standalone-chain",children:"2. upgrade proposal on standalone chain"}),"\n",(0,s.jsxs)(n.p,{children:["The standalone chain creates an upgrade proposal to include the ",(0,s.jsx)(n.code,{children:"interchain-security/x/ccv/consumer"})," module."]}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["The upgrade height in the proposal should correspond to a height that is after the ",(0,s.jsx)(n.code,{children:"spawn_time"})," in the consumer addition proposal submitted to the ",(0,s.jsx)(n.code,{children:"provider"})," chain."]})}),"\n",(0,s.jsx)(n.p,{children:"Otherwise, the upgrade is indistinguishable from a regular on-chain upgrade proposal."}),"\n",(0,s.jsx)(n.h3,{id:"3-spawn-time-is-reached",children:"3. spawn time is reached"}),"\n",(0,s.jsxs)(n.p,{children:["When the ",(0,s.jsx)(n.code,{children:"spawn_time"})," is reached on the ",(0,s.jsx)(n.code,{children:"provider"})," it will generate a ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," that contains the validator set that will supersede the ",(0,s.jsx)(n.code,{children:"standalone"})," validator set."]}),"\n",(0,s.jsxs)(n.p,{children:["This ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," must be available on the standalone chain during the on-chain upgrade."]}),"\n",(0,s.jsx)(n.h3,{id:"4-standalone-chain-upgrade",children:"4. standalone chain upgrade"}),"\n",(0,s.jsxs)(n.p,{children:["Performing the on-chain upgrade on the standalone chain will add the ",(0,s.jsx)(n.code,{children:"ccv/consumer"})," module and allow the chain to become a ",(0,s.jsx)(n.code,{children:"consumer"})," of replicated security."]}),"\n",(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," must be exported to a file and placed in the correct folder on the standalone chain before the upgrade."]}),(0,s.jsx)(n.p,{children:"The file must be placed at the exact specified location, otherwise the upgrade will not be executed correctly."}),(0,s.jsxs)(n.p,{children:["Usually the file is placed in ",(0,s.jsx)(n.code,{children:"$NODE_HOME/config"}),", but the file name and the exact directory is dictated by the upgrade code on the ",(0,s.jsx)(n.code,{children:"standalone"})," chain."]}),(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["please check exact instructions provided by the ",(0,s.jsx)(n.code,{children:"standalone"})," chain team"]}),"\n"]})]}),"\n",(0,s.jsxs)(n.p,{children:["After the ",(0,s.jsx)(n.code,{children:"genesis.json"})," file has been made available, the process is equivalent to a normal on-chain upgrade. The standalone validator set will sign the next couple of blocks before transferring control to ",(0,s.jsx)(n.code,{children:"provider"})," validator set."]}),"\n",(0,s.jsxs)(n.p,{children:["The standalone validator set can still be slashed for any infractions if evidence is submitted within the ",(0,s.jsx)(n.code,{children:"unboding_period"}),"."]}),"\n",(0,s.jsx)(n.h4,{id:"notes",children:"Notes"}),"\n",(0,s.jsx)(n.p,{children:"The changeover procedure may be updated in the future to create a seamless way of providing the validator set information to the standalone chain."}),"\n",(0,s.jsx)(n.h2,{id:"onboarding-checklist",children:"Onboarding Checklist"}),"\n",(0,s.jsxs)(n.p,{children:["This onboarding checklist is slightly different from the one under ",(0,s.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/onboarding",children:"Onboarding"})]}),"\n",(0,s.jsxs)(n.p,{children:["Additionally, you can check the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md",children:"testnet repo"})," for a comprehensive guide on preparing and launching consumer chains."]}),"\n",(0,s.jsx)(n.h2,{id:"1-complete-testing--integration",children:"1. Complete testing & integration"}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test integration with gaia"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test your protocol with supported relayer versions (minimum hermes 1.4.1)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test the changeover procedure"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","reach out to the ICS team if you are facing issues"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"2-create-an-onboarding-repository",children:"2. Create an Onboarding Repository"}),"\n",(0,s.jsx)(n.p,{children:"To help validators and other node runners onboard onto your chain, please prepare a repository with information on how to run your chain."}),"\n",(0,s.jsx)(n.p,{children:"This should include (at minimum):"}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json with CCV data (after spawn time passes). Check if CCV data needs to be transformed (see ",(0,s.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/consumer-genesis-transformation",children:"Transform Consumer Genesis"}),")"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","information about relevant seed/peer nodes you are running"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","relayer information (compatible versions)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","copy of your governance proposal (as JSON)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","a script showing how to start your chain and connect to peers (optional)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take feedback from other developers, validators and community regarding your onboarding repo and make improvements where applicable"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Example of such a repository can be found ",(0,s.jsx)(n.a,{href:"https://github.com/hyphacoop/ics-testnets/tree/main/game-of-chains-2022/sputnik",children:"here"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"3-submit-a-consumerchainaddition-governance-proposal-to-the-provider",children:"3. Submit a ConsumerChainAddition Governance Proposal to the provider"}),"\n",(0,s.jsxs)(n.p,{children:["Before you submit a ",(0,s.jsx)(n.code,{children:"ConsumerChainAddition"})," proposal, please provide a ",(0,s.jsx)(n.code,{children:"spawn_time"})," that is ",(0,s.jsx)(n.strong,{children:"before"})," the ",(0,s.jsx)(n.code,{children:"upgrade_height"})," of the upgrade that will introduce the ",(0,s.jsx)(n.code,{children:"ccv module"})," to your chain."]}),"\n",(0,s.jsx)(n.admonition,{type:"danger",children:(0,s.jsxs)(n.p,{children:["If the ",(0,s.jsx)(n.code,{children:"spawn_time"})," happens after your ",(0,s.jsx)(n.code,{children:"upgrade_height"})," the provider will not be able to communicate the new validator set to be used after the changeover."]})}),"\n",(0,s.jsxs)(n.p,{children:["Additionally, reach out to the community via the ",(0,s.jsx)(n.a,{href:"https://forum.cosmos.network/",children:"forum"})," to formalize your intention to become an ICS consumer, gather community support and accept feedback from the community, validators and developers."]}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine your chain's spawn time"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine consumer chain parameters to be put in the proposal"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take note to include a link to your onboarding repository"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Example of a consumer chain addition proposal (compare with the ",(0,s.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/onboarding#3-submit-a-governance-proposal",children:"ConsumerAdditionProposal"})," in the ICS Provider Proposals section for chains that ",(0,s.jsx)(n.em,{children:"launch"})," as consumers):"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:'// ConsumerAdditionProposal is a governance proposal on the provider chain to spawn a new consumer chain or add a standalone chain.\n// If it passes, then all validators on the provider chain are expected to validate the consumer chain at spawn time.\n// It is recommended that spawn time occurs after the proposal end time and that it is scheduled to happen before the standalone chain upgrade\n// that sill introduce the ccv module.\n{\n // Title of the proposal\n "title": "Changeover Standalone chain",\n // Description of the proposal\n // format the text as a .md file and include the file in your onboarding repository\n "description": ".md description of your chain and all other relevant information",\n // Proposed chain-id of the new consumer chain.\n // Must be unique from all other consumer chain ids of the executing provider chain.\n "chain_id": "standalone-1",\n // Initial height of new consumer chain.\n "initial_height" : {\n // must correspond to current revision number of standalone chain\n // e.g. standalone-1 => "revision_number": 1\n "revision_number": 1,\n\n // must correspond to a height that is at least 1 block after the upgrade\n // that will add the `consumer` module to the standalone chain\n // e.g. "upgrade_height": 100 => "revision_height": 101\n "revision_number": 1,\n },\n // Hash of the consumer chain genesis state without the consumer CCV module genesis params.\n // => not relevant for changeover procedure\n "genesis_hash": "d86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0",\n // Hash of the consumer chain binary that should be run by validators on standalone chain upgrade\n // => not relevant for changeover procedure as it may become stale\n "binary_hash": "376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1",\n // Time on the provider chain at which the consumer chain genesis is finalized and all validators\n // will be responsible for starting their consumer chain validator node.\n "spawn_time": "2023-02-28T20:40:00.000000Z",\n // Unbonding period for the consumer chain.\n // It should should be smaller than that of the provider.\n "unbonding_period": 86400000000000,\n // Timeout period for CCV related IBC packets.\n // Packets are considered timed-out after this interval elapses.\n "ccv_timeout_period": 259200000000000,\n // IBC transfer packets will timeout after this interval elapses.\n "transfer_timeout_period": 1800000000000,\n // The fraction of tokens allocated to the consumer redistribution address during distribution events.\n // The fraction is a string representing a decimal number. For example "0.75" would represent 75%.\n // The reward amount distributed to the provider is calculated as: 1 - consumer_redistribution_fraction.\n "consumer_redistribution_fraction": "0.75",\n // BlocksPerDistributionTransmission is the number of blocks between IBC token transfers from the consumer chain to the provider chain.\n // eg. send rewards to the provider every 1000 blocks\n "blocks_per_distribution_transmission": 1000,\n // The number of historical info entries to persist in store.\n // This param is a part of the cosmos sdk staking module. In the case of\n // a ccv enabled consumer chain, the ccv module acts as the staking module.\n "historical_entries": 10000,\n // The ID of a token transfer channel used for the Reward Distribution\n\t// sub-protocol. If DistributionTransmissionChannel == "", a new transfer\n\t// channel is created on top of the same connection as the CCV channel.\n\t// Note that transfer_channel_id is the ID of the channel end on the consumer chain.\n // it is most relevant for chains performing a standalone to consumer changeover\n // in order to maintain the existing ibc transfer channel\n "distribution_transmission_channel": "channel-123" // NOTE: use existing transfer channel if available\n}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"3-submit-an-upgrade-proposal--prepare-for-changeover",children:"3. Submit an Upgrade Proposal & Prepare for Changeover"}),"\n",(0,s.jsxs)(n.p,{children:["This proposal should add the ccv ",(0,s.jsx)(n.code,{children:"consumer"})," module to your chain."]}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","proposal ",(0,s.jsx)(n.code,{children:"upgrade_height"})," must happen after ",(0,s.jsx)(n.code,{children:"spawn_time"})," in the ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","advise validators about the exact procedure for your chain and point them to your onboarding repository"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"4-upgrade-time-",children:"4. Upgrade time \ud83d\ude80"}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","after ",(0,s.jsx)(n.code,{children:"spawn_time"}),", request ",(0,s.jsx)(n.code,{children:"ConsumerGenesis"})," from the ",(0,s.jsx)(n.code,{children:"provider"})," and place it in ",(0,s.jsx)(n.code,{children:"/.sovereign/config/genesis.json"})]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","upgrade the binary to the one listed in your ",(0,s.jsx)(n.code,{children:"UpgradeProposal"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:['The chain starts after at least 66.67% of standalone voting power comes online. The consumer chain is considered interchain secured once the "old" validator set signs a couple of blocks and transfers control to the ',(0,s.jsx)(n.code,{children:"provider"})," validator set."]}),"\n",(0,s.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","provide a repo with onboarding instructions for validators (it should already be listed in the proposal)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json after ",(0,s.jsx)(n.code,{children:"spawn_time"})," obtained from ",(0,s.jsx)(n.code,{children:"provider"})," (MUST contain the initial validator set)"]}),"\n",(0,s.jsxs)(n.li,{className:"task-list-item",children:[(0,s.jsx)(n.input,{type:"checkbox",disabled:!0})," ","maintenance & emergency contact info (relevant discord, telegram, slack or other communication channels)"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>a});var s=i(7294);const t={},o=s.createContext(t);function a(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/95875ea0.a97a223d.js b/assets/js/95875ea0.a97a223d.js
new file mode 100644
index 0000000000..903c081201
--- /dev/null
+++ b/assets/js/95875ea0.a97a223d.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3813],{2180:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>d,frontMatter:()=>s,metadata:()=>r,toc:()=>l});var i=t(5893),a=t(1151);const s={sidebar_position:3,title:"Onboarding Checklist"},o="Consumer Onboarding Checklist",r={id:"consumer-development/onboarding",title:"Onboarding Checklist",description:"The following checklists will aid in onboarding a new consumer chain to interchain security.",source:"@site/docs/consumer-development/onboarding.md",sourceDirName:"consumer-development",slug:"/consumer-development/onboarding",permalink:"/interchain-security/consumer-development/onboarding",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Onboarding Checklist"},sidebar:"tutorialSidebar",previous:{title:"Consumer Chain Governance",permalink:"/interchain-security/consumer-development/consumer-chain-governance"},next:{title:"Offboarding Checklist",permalink:"/interchain-security/consumer-development/offboarding"}},c={},l=[{value:"1. Complete testing & integration",id:"1-complete-testing--integration",level:2},{value:"2. Create an Onboarding Repository",id:"2-create-an-onboarding-repository",level:2},{value:"3. Submit a Governance Proposal",id:"3-submit-a-governance-proposal",level:2},{value:"4. Launch",id:"4-launch",level:2}];function h(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",input:"input",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"consumer-onboarding-checklist",children:"Consumer Onboarding Checklist"}),"\n",(0,i.jsx)(n.p,{children:"The following checklists will aid in onboarding a new consumer chain to interchain security."}),"\n",(0,i.jsxs)(n.p,{children:["Additionally, you can check the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md",children:"testnet repo"})," for a comprehensive guide on preparing and launching consumer chains."]}),"\n",(0,i.jsx)(n.h2,{id:"1-complete-testing--integration",children:"1. Complete testing & integration"}),"\n",(0,i.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test integration with gaia"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test your protocol with supported relayer versions (minimum hermes 1.4.1)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","reach out to the ICS team if you are facing issues"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"2-create-an-onboarding-repository",children:"2. Create an Onboarding Repository"}),"\n",(0,i.jsx)(n.p,{children:"To help validators and other node runners onboard onto your chain, please prepare a repository with information on how to run your chain."}),"\n",(0,i.jsx)(n.p,{children:"This should include (at minimum):"}),"\n",(0,i.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json without CCV data (before the proposal passes)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json with CCV data (after spawn time passes). Check if CCV data needs to be transformed (see ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/consumer-genesis-transformation",children:"Transform Consumer Genesis"}),")"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","information about relevant seed/peer nodes you are running"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","relayer information (compatible versions)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","copy of your governance proposal (as JSON)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","a script showing how to start your chain and connect to peers (optional)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take feedback from other developers, validators and community regarding your onboarding repo and make improvements where applicable"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Example of such a repository can be found ",(0,i.jsx)(n.a,{href:"https://github.com/hyphacoop/ics-testnets/tree/main/game-of-chains-2022/sputnik",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"3-submit-a-governance-proposal",children:"3. Submit a Governance Proposal"}),"\n",(0,i.jsxs)(n.p,{children:["Before you submit a ",(0,i.jsx)(n.code,{children:"ConsumerChainAddition"})," proposal, please consider allowing at least a day between your proposal passing and the chain spawn time. This will allow the validators, other node operators and the community to prepare for the chain launch.\nIf possible, please set your spawn time so people from different parts of the globe can be available in case of emergencies. Ideally, you should set your spawn time to be between 12:00 UTC and 20:00 UTC so most validator operators are available and ready to respond to any issues."]}),"\n",(0,i.jsxs)(n.p,{children:["Additionally, reach out to the community via the ",(0,i.jsx)(n.a,{href:"https://forum.cosmos.network/",children:"forum"})," to formalize your intention to become an ICS consumer, gather community support and accept feedback from the community, validators and developers."]}),"\n",(0,i.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine your chain's spawn time"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine consumer chain parameters to be put in the proposal"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take note to include a link to your onboarding repository"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","describe the purpose and benefits of running your chain"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine whether your chain should be an Opt-In chain or a Top N chain (see ",(0,i.jsx)(n.a,{href:"/interchain-security/features/partial-set-security",children:"Partial Set Security"}),")"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","if desired, decide on power-shaping parameters (see ",(0,i.jsx)(n.a,{href:"/interchain-security/features/power-shaping",children:"Power Shaping"}),")"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Example of a consumer chain addition proposal."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",children:'// ConsumerAdditionProposal is a governance proposal on the provider chain to spawn a new consumer chain.\n// If it passes, if the top_N parameter is not equal to 0, the top N% of validators by voting power on the provider chain are expected to validate the consumer chain at spawn time.\n// Otherwise, only validators that opted in during the proposal period are expected to validate the consumer chain at spawn time.\n// It is recommended that spawn time occurs after the proposal end time.\n{\n // Title of the proposal\n "title": "Add consumer chain",\n // Description of the proposal\n // format the text as a .md file and include the file in your onboarding repository\n "description": ".md description of your chain and all other relevant information",\n // Proposed chain-id of the new consumer chain.\n // Must be unique from all other consumer chain ids of the executing provider chain.\n "chain_id": "newchain-1",\n // Initial height of new consumer chain.\n // For a completely new chain, this will be {0,1}.\n "initial_height" : {\n "revision_height": 0,\n "revision_number": 1,\n },\n // Hash of the consumer chain genesis state without the consumer CCV module genesis params.\n // It is used for off-chain confirmation of genesis.json validity by validators and other parties.\n "genesis_hash": "d86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0",\n // Hash of the consumer chain binary that should be run by validators on chain initialization.\n // It is used for off-chain confirmation of binary validity by validators and other parties.\n "binary_hash": "376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1",\n // Time on the provider chain at which the consumer chain genesis is finalized and validators\n // will be responsible for starting their consumer chain validator node.\n "spawn_time": "2023-02-28T20:40:00.000000Z",\n // Unbonding period for the consumer chain.\n // It should be smaller than that of the provider.\n "unbonding_period": 86400000000000,\n // Timeout period for CCV related IBC packets.\n // Packets are considered timed-out after this interval elapses.\n "ccv_timeout_period": 259200000000000,\n // IBC transfer packets will timeout after this interval elapses.\n "transfer_timeout_period": 1800000000000,\n // The fraction of tokens allocated to the consumer redistribution address during distribution events.\n // The fraction is a string representing a decimal number. For example "0.75" would represent 75%.\n // The reward amount distributed to the provider is calculated as: 1 - consumer_redistribution_fraction.\n "consumer_redistribution_fraction": "0.75",\n // BlocksPerDistributionTransmission is the number of blocks between IBC token transfers from the consumer chain to the provider chain.\n // eg. send rewards to the provider every 1000 blocks\n "blocks_per_distribution_transmission": 1000,\n // The number of historical info entries to persist in store.\n // This param is a part of the cosmos sdk staking module. In the case of\n // a ccv enabled consumer chain, the ccv module acts as the staking module.\n "historical_entries": 10000,\n // The ID of a token transfer channel used for the Reward Distribution\n\t// sub-protocol. If DistributionTransmissionChannel == "", a new transfer\n\t// channel is created on top of the same connection as the CCV channel.\n\t// Note that transfer_channel_id is the ID of the channel end on the consumer chain.\n // it is most relevant for chains performing a standalone to consumer changeover\n // in order to maintain the existing ibc transfer channel\n "distribution_transmission_channel": "channel-123",\n // Corresponds to the percentage of validators that have to validate the chain under the Top N case.\n // For example, 53 corresponds to a Top 53% chain, meaning that the top 53% provider validators by voting power\n // have to validate the proposed consumer chain. top_N can either be 0 or any value in [50, 100].\n // A chain can join with top_N == 0 as an Opt In chain, or with top_N \u2208 [50, 100] as a Top N chain.\n "top_N": 95,\n // Corresponds to the maximum power (percentage-wise) a validator can have on the consumer chain. For instance, if\n // `validators_power_cap` is set to 32, it means that no validator can have more than 32% of the voting power on the\n // consumer chain. Note that this might not be feasible. For example, think of a consumer chain with only\n // 5 validators and with `validators_power_cap` set to 10%. In such a scenario, at least one validator would need\n // to have more than 20% of the total voting power. Therefore, `validators_power_cap` operates on a best-effort basis.\n "validators_power_cap": 0,\n // Corresponds to the maximum number of validators that can validate a consumer chain.\n // Only applicable to Opt In chains. Setting `validator_set_cap` on a Top N chain is a no-op.\n "validator_set_cap": 0,\n // Corresponds to a list of provider consensus addresses of validators that are the ONLY ones that can validate\n // the consumer chain.\n "allowlist": [],\n // Corresponds to a list of provider consensus addresses of validators that CANNOT validate the consumer chain.\n "denylist": []\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"4-launch",children:"4. Launch"}),"\n",(0,i.jsxs)(n.p,{children:["The consumer chain starts after at least 66.67% of its voting power comes online.\nNote that this means 66.67% of the voting power in the ",(0,i.jsx)(n.em,{children:"consumer"})," validator set, which will be comprised of all validators that either opted in to the chain or are part of the top N% of the provider chain (and are thus automatically opted in).\nThe consumer chain is considered interchain secured once the appropriate CCV channels are established and the first validator set update is propagated from the provider to the consumer"]}),"\n",(0,i.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","provide a repo with onboarding instructions for validators (it should already be listed in the proposal)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json with ccv data populated (MUST contain the initial validator set)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","maintenance & emergency contact info (relevant discord, telegram, slack or other communication channels)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","have a block explorer in place to track chain activity & health"]}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>r,a:()=>o});var i=t(7294);const a={},s=i.createContext(a);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/97662a95.fa11ce6a.js b/assets/js/97662a95.fa11ce6a.js
new file mode 100644
index 0000000000..654f393379
--- /dev/null
+++ b/assets/js/97662a95.fa11ce6a.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3859],{9541:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>t,default:()=>h,frontMatter:()=>s,metadata:()=>d,toc:()=>c});var a=n(5893),i=n(1151);const s={sidebar_position:3},t="Withdrawing consumer chain validator rewards",d={id:"validators/withdraw_rewards",title:"Withdrawing consumer chain validator rewards",description:"Here are example steps for withdrawing rewards from consumer chains in the provider chain",source:"@site/versioned_docs/version-v4.2.0-docs/validators/withdraw_rewards.md",sourceDirName:"validators",slug:"/validators/withdraw_rewards",permalink:"/interchain-security/v4.2.0/validators/withdraw_rewards",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"tutorialSidebar",previous:{title:"Joining Interchain Security testnet",permalink:"/interchain-security/v4.2.0/validators/joining-testnet"},next:{title:"Validator Instructions for Changeover Procedure",permalink:"/interchain-security/v4.2.0/validators/changeover-procedure"}},o={},c=[{value:"Querying validator rewards",id:"querying-validator-rewards",level:2},{value:"Withdrawing rewards and commission",id:"withdrawing-rewards-and-commission",level:2},{value:"1. Withdraw rewards",id:"1-withdraw-rewards",level:3},{value:"2. Confirm withdrawal",id:"2-confirm-withdrawal",level:3}];function l(e){const r={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(r.h1,{id:"withdrawing-consumer-chain-validator-rewards",children:"Withdrawing consumer chain validator rewards"}),"\n",(0,a.jsx)(r.p,{children:"Here are example steps for withdrawing rewards from consumer chains in the provider chain"}),"\n",(0,a.jsxs)(r.admonition,{type:"info",children:[(0,a.jsxs)(r.p,{children:["The examples used are from ",(0,a.jsx)(r.code,{children:"rs-testnet"}),", the replicated security persistent testnet."]}),(0,a.jsxs)(r.p,{children:["Validator operator address: ",(0,a.jsx)(r.code,{children:"cosmosvaloper1e5yfpc8l6g4808fclmlyd38tjgxuwshnmjkrq6"}),"\nSelf-delegation address: ",(0,a.jsx)(r.code,{children:"cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf"})]})]}),"\n",(0,a.jsx)(r.p,{children:"Prior to withdrawing rewards, query balances for self-delegation address:"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:'gaiad q bank balances cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf\n\nbalances:\n- amount: "1000000000000"\n denom: uatom\npagination:\n next_key: null\n total: "0"\n'})}),"\n",(0,a.jsx)(r.h2,{id:"querying-validator-rewards",children:"Querying validator rewards"}),"\n",(0,a.jsx)(r.p,{children:"Query rewards for the validator address:"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:'gaiad q distribution rewards cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf cosmosvaloper1e5yfpc8l6g4808fclmlyd38tjgxuwshnmjkrq6\n\nrewards:\n- amount: "158.069895000000000000"\n denom: ibc/2CB0E87E2A742166FEC0A18D6FBF0F6AD4AA1ADE694792C1BD6F5E99088D67FD\n- amount: "841842390516.072526500000000000"\n denom: uatom\n'})}),"\n",(0,a.jsxs)(r.p,{children:["The ",(0,a.jsx)(r.code,{children:"ibc/2CB0E87E2A742166FEC0A18D6FBF0F6AD4AA1ADE694792C1BD6F5E99088D67FD"})," denom represents rewards from a consumer chain."]}),"\n",(0,a.jsx)(r.h2,{id:"withdrawing-rewards-and-commission",children:"Withdrawing rewards and commission"}),"\n",(0,a.jsx)(r.h3,{id:"1-withdraw-rewards",children:"1. Withdraw rewards"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:"gaiad tx distribution withdraw-rewards cosmosvaloper1e5yfpc8l6g4808fclmlyd38tjgxuwshnmjkrq6 --from cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf --commission --chain-id provider --gas auto --fees 500uatom -b block -y\n\ntxhash: A7E384FB1958211B43B7C06527FC7D4471FB6B491EE56FDEA9C5634D76FF1B9A\n"})}),"\n",(0,a.jsx)(r.h3,{id:"2-confirm-withdrawal",children:"2. Confirm withdrawal"}),"\n",(0,a.jsx)(r.p,{children:"After withdrawing rewards self-delegation address balance to confirm rewards were withdrawn:"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:'gaiad q bank balances cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf\n\nbalances:\n- amount: "216"\n denom: ibc/2CB0E87E2A742166FEC0A18D6FBF0F6AD4AA1ADE694792C1BD6F5E99088D67FD\n- amount: "2233766225342"\n denom: uatom\npagination:\n next_key: null\n total: "0"\n'})})]})}function h(e={}){const{wrapper:r}={...(0,i.a)(),...e.components};return r?(0,a.jsx)(r,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},1151:(e,r,n)=>{n.d(r,{Z:()=>d,a:()=>t});var a=n(7294);const i={},s=a.createContext(i);function t(e){const r=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function d(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),a.createElement(s.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/98891868.9f022861.js b/assets/js/98891868.9f022861.js
new file mode 100644
index 0000000000..7483a9017f
--- /dev/null
+++ b/assets/js/98891868.9f022861.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4964],{2177:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>i,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var r=s(5893),t=s(1151);const a={sidebar_position:3,title:"Key Assignment"},i="ADR 001: Key Assignment",o={id:"adrs/adr-001-key-assignment",title:"Key Assignment",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-001-key-assignment.md",sourceDirName:"adrs",slug:"/adrs/adr-001-key-assignment",permalink:"/interchain-security/v4.2.0/adrs/adr-001-key-assignment",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Key Assignment"},sidebar:"tutorialSidebar",previous:{title:"ADR Template",permalink:"/interchain-security/v4.2.0/adrs/adr-template"},next:{title:"Jail Throttling",permalink:"/interchain-security/v4.2.0/adrs/adr-002-throttle"}},d={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"State required",id:"state-required",level:3},{value:"Protocol overview",id:"protocol-overview",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"adr-001-key-assignment",children:"ADR 001: Key Assignment"}),"\n",(0,r.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"2022-12-01: Initial Draft"}),"\n",(0,r.jsx)(n.li,{children:"2024-03-01: Updated to take into account they key-assigment-replacement deprecation."}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,r.jsx)(n.p,{children:"Accepted"}),"\n",(0,r.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,r.jsx)(n.p,{children:"KeyAssignment is the name of the feature that allows validator operators to use different consensus keys for each consumer chain validator node that they operate."}),"\n",(0,r.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,r.jsxs)(n.p,{children:["It is possible to change the keys at any time by submitting a transaction (i.e., ",(0,r.jsx)(n.code,{children:"MsgAssignConsumerKey"}),")."]}),"\n",(0,r.jsx)(n.h3,{id:"state-required",children:"State required"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ValidatorConsumerPubKey"})," - Stores the validator assigned keys for every consumer chain."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"ConsumerValidatorsBytePrefix | len(chainID) | chainID | providerConsAddress -> consumerKey\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ValidatorByConsumerAddr"})," - Stores the mapping from validator addresses on consumer chains to validator addresses on the provider chain. Needed for the consumer initiated slashing sub-protocol."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"ValidatorsByConsumerAddrBytePrefix | len(chainID) | chainID | consumerConsAddress -> providerConsAddress\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ConsumerAddrsToPrune"})," - Stores the mapping from VSC ids to consumer validators addresses. Needed for pruning ",(0,r.jsx)(n.code,{children:"ValidatorByConsumerAddr"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"ConsumerAddrsToPruneBytePrefix | len(chainID) | chainID | vscID -> []consumerConsAddresses\n"})}),"\n",(0,r.jsx)(n.h3,{id:"protocol-overview",children:"Protocol overview"}),"\n",(0,r.jsxs)(n.p,{children:["On receiving a ",(0,r.jsx)(n.code,{children:"MsgAssignConsumerKey(chainID, providerAddr, consumerKey)"})," message:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"// get validator from staking module \nvalidator, found := stakingKeeper.GetValidator(providerAddr)\nif !found {\n return ErrNoValidatorFound\n}\nproviderConsAddr := validator.GetConsAddr()\n\n// make sure consumer key is not in use\nconsumerAddr := utils.TMCryptoPublicKeyToConsAddr(consumerKey)\nif _, found := GetValidatorByConsumerAddr(ChainID, consumerAddr); found {\n return ErrInvalidConsumerConsensusPubKey\n}\n\n// check whether the consumer chain is already registered\n// i.e., a client to the consumer was already created\nif _, consumerRegistered := GetConsumerClientId(chainID); consumerRegistered {\n // get the previous key assigned for this validator on this consumer chain\n oldConsumerKey, found := GetValidatorConsumerPubKey(chainID, providerConsAddr)\n if found {\n // mark this old consumer key as prunable once the VSCMaturedPacket\n // for the current VSC ID is received\n oldConsumerAddr := utils.TMCryptoPublicKeyToConsAddr(oldConsumerKey)\n vscID := GetValidatorSetUpdateId()\n AppendConsumerAddrsToPrune(chainID, vscID, oldConsumerAddr)\n }\n} else {\n // if the consumer chain is not registered, then remove the previous reverse mapping\n if oldConsumerKey, found := GetValidatorConsumerPubKey(chainID, providerConsAddr); found {\n oldConsumerAddr := utils.TMCryptoPublicKeyToConsAddr(oldConsumerKey)\n DeleteValidatorByConsumerAddr(chainID, oldConsumerAddr)\n }\n}\n\n\n// set the mapping from this validator's provider address to the new consumer key\nSetValidatorConsumerPubKey(chainID, providerConsAddr, consumerKey)\n\n// set the reverse mapping: from this validator's new consensus address \n// on the consumer to its consensus address on the provider\nSetValidatorByConsumerAddr(chainID, consumerAddr, providerConsAddr)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["When a new consumer chain is registered, i.e., a client to the consumer chain is created, the provider constructs the consumer CCV module part of the genesis state (see ",(0,r.jsx)(n.code,{children:"MakeConsumerGenesis"}),")."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func (k Keeper) MakeConsumerGenesis(chainID string) (gen consumertypes.GenesisState, nextValidatorsHash []byte, err error) {\n // ...\n // get initial valset from the staking module\n var updates []abci.ValidatorUpdate{}\n stakingKeeper.IterateLastValidatorPowers(func(providerAddr sdk.ValAddress, power int64) (stop bool) {\n validator := stakingKeeper.GetValidator(providerAddr)\n providerKey := validator.TmConsPublicKey()\n\t\tupdates = append(updates, abci.ValidatorUpdate{PubKey: providerKey, Power: power})\n\t\treturn false\n\t})\n\n // applies the key assignment to the initial validator\n\tfor i, update := range updates {\n\t\tproviderAddr := utils.TMCryptoPublicKeyToConsAddr(update.PubKey)\n\t\tif consumerKey, found := GetValidatorConsumerPubKey(chainID, providerAddr); found {\n\t\t\tupdates[i].PubKey = consumerKey\n\t\t}\n\t}\n gen.InitialValSet = updates\n\n // get a hash of the consumer validator set from the update\n\tupdatesAsValSet := tendermint.PB2TM.ValidatorUpdates(updates)\n\thash := tendermint.NewValidatorSet(updatesAsValSet).Hash()\n\n\treturn gen, hash, nil\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Note that key assignment works hand-in-hand with ",(0,r.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-014-epochs.md",children:"epochs"}),".\nFor each consumer chain, we store the consumer validator set that is currently (i.e., in this epoch) validating the consumer chain.\nSpecifically, for each validator in the set we store among others, the public key that it is using on the consumer chain during the current (i.e., ongoing) epoch.\nAt the end of every epoch, if there were validator set changes on the provider, then for every consumer chain, we construct a ",(0,r.jsx)(n.code,{children:"VSCPacket"}),"\nwith all the validator updates and add it to the list of ",(0,r.jsx)(n.code,{children:"PendingVSCPacket"}),"s. We compute the validator updates needed by a consumer chain by\ncomparing the stored list of consumer validators with the current bonded validators on the provider, with something similar to this:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"// get the valset that has been validating the consumer chain during this epoch \ncurrentValidators := GetConsumerValSet(consumerChain)\n// generate the validator updates needed to be sent through a `VSCPacket` by comparing the current validators \n// in the epoch with the latest bonded validators\nvalUpdates := DiffValidators(currentValidators, stakingmodule.GetBondedValidators())\n// update the current validators set for the upcoming epoch to be the latest bonded validators instead\nSetConsumerValSet(stakingmodule.GetBondedValidators())\n"})}),"\n",(0,r.jsxs)(n.p,{children:["where ",(0,r.jsx)(n.code,{children:"DiffValidators"})," internally checks if the consumer public key for a validator has changed since the last\nepoch and if so generates a validator update. This way, a validator can change its consumer public key for a consumer\nchain an arbitrary amount of times and only the last set consumer public key would be taken into account."]}),"\n",(0,r.jsxs)(n.p,{children:["On receiving a ",(0,r.jsx)(n.code,{children:"SlashPacket"})," from a consumer chain with id ",(0,r.jsx)(n.code,{children:"chainID"})," for a infraction of a validator ",(0,r.jsx)(n.code,{children:"data.Validator"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func HandleSlashPacket(chainID string, data ccv.SlashPacketData) (success bool, err error) {\n // ...\n // the slash packet validator address may be known only on the consumer chain;\n\t// in this case, it must be mapped back to the consensus address on the provider chain\n consumerAddr := sdk.ConsAddress(data.Validator.Address)\n providerAddr, found := GetValidatorByConsumerAddr(chainID, consumerAddr)\n if !found {\n // the validator has the same key on the consumer as on the provider\n providerAddr = consumerAddr\n }\n // ...\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["On receiving a ",(0,r.jsx)(n.code,{children:"VSCMatured"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func OnRecvVSCMaturedPacket(packet channeltypes.Packet, data ccv.VSCMaturedPacketData) exported.Acknowledgement {\n // ...\n // prune previous consumer validator address that are no longer needed\n consumerAddrs := GetConsumerAddrsToPrune(chainID, data.ValsetUpdateId)\n\tfor _, addr := range consumerAddrs {\n\t\tDeleteValidatorByConsumerAddr(chainID, addr)\n\t}\n\tDeleteConsumerAddrsToPrune(chainID, data.ValsetUpdateId)\n // ...\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"On stopping a consumer chain:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan bool) (err error) {\n // ...\n // deletes all the state needed for key assignments on this consumer chain\n // ...\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,r.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Validators can use different consensus keys on the consumer chains."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"None"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The consensus state necessary to create a client to the consumer chain must use the hash returned by the ",(0,r.jsx)(n.code,{children:"MakeConsumerGenesis"})," method as the ",(0,r.jsx)(n.code,{children:"nextValsHash"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The consumer chain can no longer check the initial validator set against the consensus state on ",(0,r.jsx)(n.code,{children:"InitGenesis"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/26",children:"Key assignment issue"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>o,a:()=>i});var r=s(7294);const t={},a=r.createContext(t);function i(e){const n=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),r.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/99394557.c883f412.js b/assets/js/99394557.c883f412.js
new file mode 100644
index 0000000000..c9f6935628
--- /dev/null
+++ b/assets/js/99394557.c883f412.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9897],{3347:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>u,contentTitle:()=>c,default:()=>m,frontMatter:()=>a,metadata:()=>d,toc:()=>h});var t=n(5893),i=n(1151),s=n(2307),o=n(8758);const a={sidebar_position:1},c="Interchain Security Docs",d={id:"index",title:"Interchain Security Docs",description:"Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains.",source:"@site/versioned_docs/version-v4.2.0-docs/index.mdx",sourceDirName:".",slug:"/",permalink:"/interchain-security/v4.2.0/",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",next:{title:"Overview",permalink:"/interchain-security/v4.2.0/introduction/overview"}},u={},h=[];function l(e){const r={h1:"h1",p:"p",...(0,i.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.h1,{id:"interchain-security-docs",children:"Interchain Security Docs"}),"\n",(0,t.jsx)(r.p,{children:"Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains."}),"\n",(0,t.jsx)(r.p,{children:"Here you can find information about replicated security, consumer chain development and instructions for validator onboarding."}),"\n",(0,t.jsx)(s.Z,{cards:o.Z})]})}function m(e={}){const{wrapper:r}={...(0,i.a)(),...e.components};return r?(0,t.jsx)(r,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},2307:(e,r,n)=>{n.d(r,{Z:()=>s});n(7294);var t=n(5893);const i=function(e){return(0,t.jsx)("a",{href:e.href,className:"border shadow rounded-sm border-stone-200 dark:border-stone-800 dark:bg-neutral-900 hover:border-stone-300 hover:shadow-lg dark:hover:border-stone-200 transition-all duration-200 no-underline",children:(0,t.jsxs)("div",{className:"p-6",children:[(0,t.jsx)("h2",{className:"",children:e.header}),(0,t.jsx)("p",{className:"",children:e.summary})]})})};const s=function(e){return(0,t.jsx)("div",{className:"card-section grid grid-cols-1 lg:grid-cols-2 gap-4 no-underline",children:e.cards.map(((e,r)=>(0,t.jsx)(i,{href:e.href,header:e.header,summary:e.summary},r)))})}},8758:(e,r,n)=>{n.d(r,{Z:()=>t});const t=[{href:"/interchain-security/introduction/overview",header:"Basic concepts",summary:"Get started with the basic concepts and ideas."},{href:"/interchain-security/consumer-development/app-integration",header:"Start building",summary:"Click here to start building with Interchain security"},{href:"/interchain-security/features/key-assignment",header:"Feature: Key Assignment",summary:"Learn about the key assignment feature"},{href:"/interchain-security/features/reward-distribution",header:"Feature: Reward Distribution",summary:"Learn about consumer chain rewards distribution"},{href:"/interchain-security/consumer-development/onboarding",header:"Onboarding Checklist",summary:"Checklist to help you integrate Interchain Security, get support and onboard validators"},{href:"/interchain-security/faq",header:"FAQ",summary:"Frequently asked questions about the protocol and its implications"}]},1151:(e,r,n)=>{n.d(r,{Z:()=>a,a:()=>o});var t=n(7294);const i={},s=t.createContext(i);function o(e){const r=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),t.createElement(s.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/99c91eb8.ebba5ec5.js b/assets/js/99c91eb8.ebba5ec5.js
new file mode 100644
index 0000000000..949c64f126
--- /dev/null
+++ b/assets/js/99c91eb8.ebba5ec5.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5112],{9697:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var i=s(5893),t=s(1151);const r={sidebar_position:2,title:"Joining Interchain Security testnet"},o=void 0,a={id:"validators/joining-testnet",title:"Joining Interchain Security testnet",description:"Introduction",source:"@site/versioned_docs/version-v5.0.0/validators/joining-testnet.md",sourceDirName:"validators",slug:"/validators/joining-testnet",permalink:"/interchain-security/v5.0.0/validators/joining-testnet",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"Joining Interchain Security testnet"},sidebar:"tutorialSidebar",previous:{title:"Overview",permalink:"/interchain-security/v5.0.0/validators/overview"},next:{title:"Withdrawing consumer chain validator rewards",permalink:"/interchain-security/v5.0.0/validators/withdraw_rewards"}},c={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Joining the provider chain",id:"joining-the-provider-chain",level:2},{value:"Initialization",id:"initialization",level:2},{value:"Joining consumer chains",id:"joining-consumer-chains",level:2},{value:"Re-using consensus key",id:"re-using-consensus-key",level:2},{value:"Assigning consensus keys",id:"assigning-consensus-keys",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(n.p,{children:["This short guide will teach you how to join the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security",children:"Interchain Security testnet"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The experience gained in the testnet will prepare you for validating interchain secured chains."}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"Provider and consumer chain represent distinct networks and infrastructures operated by the same validator set."}),(0,i.jsxs)(n.p,{children:["For general information about running cosmos-sdk based chains check out the ",(0,i.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup",children:"validator basics"})," and ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/main/run-node/run-node",children:"Running a Node section"})," of Cosmos SDK docs"]})]}),"\n",(0,i.jsx)(n.h2,{id:"joining-the-provider-chain",children:"Joining the provider chain"}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsx)(n.p,{children:"At present, all validators of the provider chain must also validate all governance approved consumer chains. The consumer chains cannot have a validator set different than the provider, which means they cannot introduce validators that are not also validating the provider chain."})}),"\n",(0,i.jsxs)(n.p,{children:["A comprehensive guide is available ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security/provider",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"initialization",children:"Initialization"}),"\n",(0,i.jsxs)(n.p,{children:["First, initialize your ",(0,i.jsx)(n.code,{children:"$NODE_HOME"})," using the ",(0,i.jsx)(n.code,{children:"provider"})," chain binary."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"NODE_MONIKER=\nCHAIN_ID=provider\nNODE_HOME=\n\ngaiad init $NODE_MONIKER --chain-id $CHAIN_ID --home $NODE_HOME\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Add your key to the keyring - more details available ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/main/run-node/keyring",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["In this example we will use the ",(0,i.jsx)(n.code,{children:"test"})," keyring-backend. This option is not safe to use in production."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad keys add --keyring-backend test\n\n# save the address as variable for later use\nMY_VALIDATOR_ADDRESS=$(gaiad keys show my_validator -a --keyring-backend test)\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Before issuing any transactions, use the ",(0,i.jsx)(n.code,{children:"provider"})," testnet faucet to add funds to your address."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'curl https://faucet.rs-testnet.polypore.xyz/request?address=$MY_VALIDATOR_ADDRESS&chain=provider\n\n# example output:\n{\n "address": "cosmos17p3erf5gv2436fd4vyjwmudakts563a497syuz",\n "amount": "10000000uatom",\n "chain": "provider",\n "hash": "10BFEC53C80C9B649B66549FD88A0B6BCF09E8FCE468A73B4C4243422E724985",\n "status": "success"\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Then, use the account associated with the keyring to issue a ",(0,i.jsx)(n.code,{children:"create-validator"})," transaction which will register your validator on chain."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'gaiad tx staking create-validator \\\n --amount=1000000uatom \\\n --pubkey=$(gaiad tendermint show-validator) \\\n --moniker="choose a moniker" \\\n --chain-id=$CHAIN_ID" \\\n --commission-rate="0.10" \\\n --commission-max-rate="0.20" \\\n --commission-max-change-rate="0.01" \\\n --min-self-delegation="1000000" \\\n --gas="auto" \\\n --gas-prices="0.0025uatom" \\\n --from=\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Check this ",(0,i.jsx)(n.a,{href:"https://hub.cosmos.network/validators/validator-setup#edit-validator-description",children:"guide"})," to edit your validator."]})}),"\n",(0,i.jsxs)(n.p,{children:["After this step, your validator is created and you can start your node and catch up to the rest of the network. It is recommended that you use ",(0,i.jsx)(n.code,{children:"statesync"})," to catch up to the rest of the network."]}),"\n",(0,i.jsxs)(n.p,{children:["You can use this script to modify your ",(0,i.jsx)(n.code,{children:"config.toml"})," with the required statesync parameters."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# create the statesync script\n$: cd $NODE_HOME\n$: touch statesync.sh\n$ chmod 700 statesync.sh # make executable\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Paste the following instructions into the ",(0,i.jsx)(n.code,{children:"statesync.sh"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'#!/bin/bash\n\nSNAP_RPC="https://rpc.provider-state-sync-01.rs-testnet.polypore.xyz:443"\n\nLATEST_HEIGHT=$(curl -s $SNAP_RPC/block | jq -r .result.block.header.height); \\\nBLOCK_HEIGHT=$((LATEST_HEIGHT - 2000)); \\\nTRUST_HASH=$(curl -s "$SNAP_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash)\n\nsed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\\1true| ; \\\ns|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\\1\\"$SNAP_RPC,$SNAP_RPC\\"| ; \\\ns|^(trust_height[[:space:]]+=[[:space:]]+).*$|\\1$BLOCK_HEIGHT| ; \\\ns|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\\1\\"$TRUST_HASH\\"|" $NODE_HOME/config/config.toml\n'})}),"\n",(0,i.jsx)(n.p,{children:"Then, you can execute the script:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"$: ./statesync.sh # setup config.toml for statesync\n"})}),"\n",(0,i.jsx)(n.p,{children:"Finally, copy the provider genesis and start your node:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'$: GENESIS_URL=https://github.com/cosmos/testnets/raw/master/interchain-security/provider/provider-genesis.json\n$: wget $GENESIS_URL -O genesis.json\n$: genesis.json $NODE_HOME/config/genesis.json\n# start the service\n$: gaiad start --x-crisis-skip-assert-invariants --home $NODE_HOME --p2p.seeds="08ec17e86dac67b9da70deb20177655495a55407@provider-seed-01.rs-testnet.polypore.xyz:26656,4ea6e56300a2f37b90e58de5ee27d1c9065cf871@provider-seed-02.rs-testnet.polypore.xyz:26656"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Additional scripts to setup your nodes are available ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/provider/join-ics-provider.sh",children:"here"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/provider/join-ics-provider-cv.sh",children:"here"}),". The scripts will configure your node and create the required services - the scripts only work in linux environments."]}),"\n",(0,i.jsx)(n.h2,{id:"joining-consumer-chains",children:"Joining consumer chains"}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsx)(n.p,{children:"Once you reach the active set on the provider chain, you will be required to validate all available consumer chains."}),(0,i.jsxs)(n.p,{children:["You can use the same consensus key on all consumer chains, or opt to use a different key on each consumer chain.\nCheck out this ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/features/key-assignment",children:"guide"})," to learn more about key assignment in interchain security."]})]}),"\n",(0,i.jsx)(n.p,{children:"To join consumer chains, simply replicate the steps above for each consumer using the correct consumer chain binaries."}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:["When running the provider chain and consumers on the same machine please update the ",(0,i.jsx)(n.code,{children:"PORT"})," numbers for each of them and make sure they do not overlap (otherwise the binaries will not start)."]}),(0,i.jsx)(n.p,{children:"Important ports to re-configure:"}),(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--rpc.laddr"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--p2p.laddr"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--api.address"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--grpc.address"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"--grpc-web.address"})}),"\n"]})]}),"\n",(0,i.jsx)(n.h2,{id:"re-using-consensus-key",children:"Re-using consensus key"}),"\n",(0,i.jsxs)(n.p,{children:["To reuse the key on the provider and consumer chains, simply initialize your consumer chain and place the ",(0,i.jsx)(n.code,{children:"priv_validator_key.json"})," into the home directory of your consumer chain (",(0,i.jsx)(n.code,{children:"/config/priv_validator_key.json"}),")."]}),"\n",(0,i.jsx)(n.p,{children:"When you start the chain, the consensus key will be the same on the provider and the consumer chain."}),"\n",(0,i.jsx)(n.h2,{id:"assigning-consensus-keys",children:"Assigning consensus keys"}),"\n",(0,i.jsx)(n.p,{children:"Whenever you initialize a new node, it will be configured with a consensus key you can use."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'# machine running consumer chain\nconsumerd init --home --chain-id consumer-1\n\n# use the output of this command to get the consumer chain consensus key\nconsumerd tendermint show-validator\n# output: {"@type":"/cosmos.crypto.ed25519.PubKey","key":""}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Then, let the provider know which key you will be using for the consumer chain:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# machine running the provider chain\ngaiad tx provider assign-consensus-key consumer-1 '' --from --home $NODE_HOME --gas 900000 -b sync -y -o json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["After this step, you are ready to copy the consumer genesis into your nodes's ",(0,i.jsx)(n.code,{children:"/config"})," folder, start your consumer chain node and catch up to the network."]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>a,a:()=>o});var i=s(7294);const t={},r=i.createContext(t);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/9b334c7f.4eb2d589.js b/assets/js/9b334c7f.4eb2d589.js
new file mode 100644
index 0000000000..ed2d3d2e9a
--- /dev/null
+++ b/assets/js/9b334c7f.4eb2d589.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5118],{9651:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var t=o(5893),i=o(1151);const r={sidebar_position:4,title:"Offboarding Checklist"},s="Consumer Offboarding",a={id:"consumer-development/offboarding",title:"Offboarding Checklist",description:"To offboard a consumer chain simply submit a ConsumerRemovalProposal governance proposal listing a stop_time. After stop time passes, the provider chain will remove the chain from the ICS protocol (it will stop sending validator set updates).",source:"@site/versioned_docs/version-v5.0.0/consumer-development/offboarding.md",sourceDirName:"consumer-development",slug:"/consumer-development/offboarding",permalink:"/interchain-security/v5.0.0/consumer-development/offboarding",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Offboarding Checklist"},sidebar:"tutorialSidebar",previous:{title:"Onboarding Checklist",permalink:"/interchain-security/v5.0.0/consumer-development/onboarding"},next:{title:"Changeover Procedure",permalink:"/interchain-security/v5.0.0/consumer-development/changeover-procedure"}},c={},d=[];function l(e){const n={code:"code",h1:"h1",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"consumer-offboarding",children:"Consumer Offboarding"}),"\n",(0,t.jsxs)(n.p,{children:["To offboard a consumer chain simply submit a ",(0,t.jsx)(n.code,{children:"ConsumerRemovalProposal"})," governance proposal listing a ",(0,t.jsx)(n.code,{children:"stop_time"}),". After stop time passes, the provider chain will remove the chain from the ICS protocol (it will stop sending validator set updates)."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'// ConsumerRemovalProposal is a governance proposal on the provider chain to remove (and stop) a consumer chain.\n// If it passes, all the consumer chain\'s state is removed from the provider chain. The outstanding unbonding\n// operation funds are released.\n{\n // the title of the proposal\n "title": "This was a great chain",\n "description": "Here is a .md formatted string specifying removal details",\n // the chain-id of the consumer chain to be stopped\n "chain_id": "consumerchain-1",\n // the time on the provider chain at which all validators are responsible to stop their consumer chain validator node\n "stop_time": "2023-03-07T12:40:00.000000Z",\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"More information will be listed in a future version of this document."})]})}function p(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>a,a:()=>s});var t=o(7294);const i={},r=t.createContext(i);function s(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/9be59c75.cfc66a57.js b/assets/js/9be59c75.cfc66a57.js
new file mode 100644
index 0000000000..c814ffbf35
--- /dev/null
+++ b/assets/js/9be59c75.cfc66a57.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6420],{4408:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>h,contentTitle:()=>s,default:()=>d,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var n=i(5893),a=i(1151);const o={sidebar_position:7},s="Power Shaping",r={id:"features/power-shaping",title:"Power Shaping",description:"To give consumer chains more flexibility in choosing their validator set, Interchain Security offers",source:"@site/docs/features/power-shaping.md",sourceDirName:"features",slug:"/features/power-shaping",permalink:"/interchain-security/features/power-shaping",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:7,frontMatter:{sidebar_position:7},sidebar:"tutorialSidebar",previous:{title:"Partial Set Security",permalink:"/interchain-security/features/partial-set-security"},next:{title:"Developing an ICS consumer chain",permalink:"/interchain-security/consumer-development/app-integration"}},h={},l=[{value:"Guidelines for setting power shaping parameters",id:"guidelines-for-setting-power-shaping-parameters",level:2}];function c(e){const t={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"power-shaping",children:"Power Shaping"}),"\n",(0,n.jsx)(t.p,{children:'To give consumer chains more flexibility in choosing their validator set, Interchain Security offers\nseveral "power shaping" mechanisms for consumer chains.'}),"\n",(0,n.jsx)(t.p,{children:"These are:"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Capping the size of the validator set"}),": The consumer chain can specify a maximum number of validators it\nwants to have in its validator set. This can be used to limit the number of validators in the set, which can\nbe useful for chains that want to have a smaller validator set for faster blocks or lower overhead. If more validators\nthan the maximum size have opted in on a consumer chain, only the validators with the highest power, up to the specified\nmaximum, will validate the consumer chain."]}),"\n"]}),"\n",(0,n.jsx)(t.admonition,{type:"info",children:(0,n.jsx)(t.p,{children:"This is only applicable to Opt In chains (chains with Top N = 0)."})}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Capping the fraction of power any single validator can have"}),": The consumer chain can specify a maximum fraction\nof the total voting power that any single validator in its validator set should have.\nThis is a security measure with the intention of making it harder for a single large validator to take over a consumer chain. This mitigates the risk of an Opt In chain with only a few validators being dominated by a validator with a large amount of stake opting in.\nFor example, setting this fraction to e.g. 33% would mean that no single validator can have more than 33% of the total voting power,\nand thus there is no single validator who would stop the chain by going offline."]}),"\n"]}),"\n",(0,n.jsx)(t.admonition,{type:"info",children:(0,n.jsx)(t.p,{children:"This is a soft cap, and the actual power of a validator can exceed this fraction if the validator set is small (e.g. there are only 3 validators and the cap is 20%)."})}),"\n",(0,n.jsx)(t.admonition,{type:"info",children:(0,n.jsx)(t.p,{children:"Rewards are distributed proportionally to validators with respect to their capped voting power on the consumer,\nnot their total voting power on the provider."})}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Allowlist and denylist"}),": The consumer chain can specify a list of validators that are allowed or disallowed from participating in the validator set. If an allowlist is set, all validators not on the allowlist cannot validate the consumer chain. If a validator is on both lists, the denylist takes precedence, that is, they cannot validate the consumer chain. If neither list is set, all validators are able to validate the consumer chain."]}),"\n"]}),"\n",(0,n.jsx)(t.admonition,{type:"warning",children:(0,n.jsxs)(t.p,{children:["Note that if denylisting is used in a Top N consumer chain, then the chain might not be secured by N% of the total provider's\npower. For example, consider that the top validator ",(0,n.jsx)(t.code,{children:"V"})," on the provider chain has 10% of the voting power, and we have a Top 50% consumer chain,\nthen if ",(0,n.jsx)(t.code,{children:"V"})," is denylisted, the consumer chain would only be secured by at least 40% of the provider's power."]})}),"\n",(0,n.jsxs)(t.p,{children:["All these mechanisms are set by the consumer chain in the ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"}),". They operate ",(0,n.jsx)(t.em,{children:"solely on the provider chain"}),", meaning the consumer chain simply receives the validator set after these rules have been applied and does not have any knowledge about whether they are applied."]}),"\n",(0,n.jsxs)(t.p,{children:["Each of these mechanisms is ",(0,n.jsx)(t.em,{children:"set during the consumer addition proposal"})," (see ",(0,n.jsx)(t.a,{href:"/interchain-security/consumer-development/onboarding#3-submit-a-governance-proposal",children:"Onboarding"}),"), and is currently ",(0,n.jsx)(t.em,{children:"immutable"})," after the chain has been added."]}),"\n",(0,n.jsx)(t.p,{children:"The values can be seen by querying the list of consumer chains:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"interchain-security-pd query provider list-consumer-chains\n"})}),"\n",(0,n.jsx)(t.h2,{id:"guidelines-for-setting-power-shaping-parameters",children:"Guidelines for setting power shaping parameters"}),"\n",(0,n.jsx)(t.p,{children:"When setting power shaping parameters, please consider the following guidelines:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Do not cap the validator set size too low: Notice that this number is the *",(0,n.jsx)(t.em,{children:"maximum"})," number of validators that will ever validate the consumer chain. If this number is too low, the chain will be very limited in the\namount of stake that secures it. The validator set size cap should only be used if there are strong reasons to prefer fewer validators. Consider that setting the cap will mean that\neven if the whole validator set of the provider wants to validate on the chain, some validators will simply not be able to."]}),"\n",(0,n.jsx)(t.li,{children:"Capping the fraction of power any single validator can have is a decent security measure, but it's good to be aware of the interactions with the size of the validator set.\nFor example, if there are only 3 validators, and the cap is 20%, this will not be possible (since even splitting the power fairly would mean that each validator has 33% of the power, so is above the cap).\nHowever, the cap can be a good measure to prevent a single large validator from essentially taking over the chain.\nIn general, values under 33% make sense (since a validator that has 33% of the chains power would halt the chain if they go offline).\nNotice that the smaller this value is, the more the original voting power gets distorted, which could discourage large validators from deciding to opt in to the chain."}),"\n",(0,n.jsxs)(t.li,{children:["If the allowlist is ",(0,n.jsx)(t.em,{children:"empty"}),", all validators can validate the chain. If it is ",(0,n.jsx)(t.em,{children:"non empty"}),", then ",(0,n.jsx)(t.em,{children:"only"})," validators on the allowlist can validate the chain.\nThus, an allowlist containing too few validators is a security risk. In particular, consider that if the validators on the allowlist lose a lot of stake or stop being validators,\nan allowlist that is too short can very quickly become outdated and leave too few validators, or validators with too little stake, to secure the chain in a decentralized way."]}),"\n",(0,n.jsx)(t.li,{children:"If the denylist is too full, this can likewise be problematic. If too many large validators are denylisted, the chain might not be secured by a large enough fraction of the provider's power, in particular when\nthe power distribution on the provider shifts and the denylisted validators gain more power."}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"In general, when setting these parameters, consider that the voting power distribution in the future might be very different from the one right now,\nand that the chain should be secure even if the power distribution changes significantly."}),"\n",(0,n.jsx)(t.admonition,{type:"tip",children:(0,n.jsxs)(t.p,{children:["The power shaping parameters of a running consumer chain can be changed through a ",(0,n.jsx)(t.a,{href:"/interchain-security/features/proposals#consumermodificationproposal",children:(0,n.jsx)(t.code,{children:"ConsumerModificationProposal"})}),"."]})})]})}function d(e={}){const{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},1151:(e,t,i)=>{i.d(t,{Z:()=>r,a:()=>s});var n=i(7294);const a={},o=n.createContext(a);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/9c202c81.4de6f0b5.js b/assets/js/9c202c81.4de6f0b5.js
new file mode 100644
index 0000000000..ee46d08e9e
--- /dev/null
+++ b/assets/js/9c202c81.4de6f0b5.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6625],{5626:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>l,frontMatter:()=>t,metadata:()=>a,toc:()=>c});var i=r(5893),s=r(1151);const t={sidebar_position:2},o="Reward Distribution",a={id:"features/reward-distribution",title:"Reward Distribution",description:"Sending and distributing rewards from consumer chains to the provider chain is handled by the Reward Distribution sub-protocol.",source:"@site/versioned_docs/version-v5.0.0/features/reward-distribution.md",sourceDirName:"features",slug:"/features/reward-distribution",permalink:"/interchain-security/v5.0.0/features/reward-distribution",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Key Assignment",permalink:"/interchain-security/v5.0.0/features/key-assignment"},next:{title:"ICS Provider Proposals",permalink:"/interchain-security/v5.0.0/features/proposals"}},d={},c=[{value:"Whitelisting Reward Denoms",id:"whitelisting-reward-denoms",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"reward-distribution",children:"Reward Distribution"}),"\n",(0,i.jsxs)(n.p,{children:["Sending and distributing rewards from consumer chains to the provider chain is handled by the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/overview_and_basic_concepts.md#reward-distribution",children:"Reward Distribution sub-protocol"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Consumer chains have the option of sharing (a portion of) their block rewards (inflation tokens and fees) with the provider chain validators and delegators.\nIn replicated security, block rewards are periodically sent from the consumer to the provider according to consumer chain parameters using an IBC transfer channel.\nThis channel is created during consumer chain initialization, unless it is provided via the ",(0,i.jsx)(n.code,{children:"ConsumerAdditionProposal"})," when adding a new consumer chain.\nFor more details, see the ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/introduction/params#reward-distribution-parameters",children:"reward distribution parameters"}),"."]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Providing an IBC transfer channel (see ",(0,i.jsx)(n.code,{children:"DistributionTransmissionChannel"}),") enables a consumer chain to re-use one of the existing channels to the provider for consumer chain rewards distribution. This will preserve the ",(0,i.jsx)(n.code,{children:"ibc denom"})," that may already be in use.\nThis is especially important for standalone chains transitioning to become consumer chains.\nFor more details, see the ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/changeover-procedure",children:"changeover procedure"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Reward distribution on the provider is handled by the distribution module."}),"\n",(0,i.jsx)(n.h2,{id:"whitelisting-reward-denoms",children:"Whitelisting Reward Denoms"}),"\n",(0,i.jsxs)(n.p,{children:["The ICS distribution system works by allowing consumer chains to send rewards to a module address on the provider called the ",(0,i.jsx)(n.code,{children:"ConsumerRewardsPool"}),".\nTo avoid spam, the provider must whitelist denoms before accepting them as ICS rewards.\nOnly whitelisted denoms are transferred from the ",(0,i.jsx)(n.code,{children:"ConsumerRewardsPool"})," to the ",(0,i.jsx)(n.code,{children:"FeePoolAddress"}),", to be distributed to delegators and validators.\nThe whitelisted denoms can be adjusted through governance by sending a ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/features/proposals#changerewarddenomproposal",children:(0,i.jsx)(n.code,{children:"ChangeRewardDenomProposal"})}),"."]}),"\n",(0,i.jsx)(n.p,{children:"To query the list of whitelisted reward denoms on the Cosmos Hub, use the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"> gaiad q provider registered-consumer-reward-denoms\ndenoms:\n- ibc/0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5\n- ibc/6B8A3F5C2AD51CD6171FA41A7E8C35AD594AB69226438DB94450436EA57B3A89\n- uatom\n"})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsxs)(n.p,{children:["Use the following command to get a human readable denom from the ",(0,i.jsx)(n.code,{children:"ibc/*"})," denom trace format:"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"> gaiad query ibc-transfer denom-trace ibc/0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5\ndenom_trace:\n base_denom: untrn\n path: transfer/channel-569\n"})})]})]})}function l(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>o});var i=r(7294);const s={},t=i.createContext(s);function o(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/9fa21ee5.9bb946f7.js b/assets/js/9fa21ee5.9bb946f7.js
new file mode 100644
index 0000000000..ca6d148617
--- /dev/null
+++ b/assets/js/9fa21ee5.9bb946f7.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3500],{7809:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var i=a(5893),t=a(1151);const s={sidebar_position:4},o="Validator Instructions for Changeover Procedure",r={id:"validators/changeover-procedure",title:"Validator Instructions for Changeover Procedure",description:"More details available in Changeover Procedure documentation.",source:"@site/versioned_docs/version-v5.0.0/validators/changeover-procedure.md",sourceDirName:"validators",slug:"/validators/changeover-procedure",permalink:"/interchain-security/v5.0.0/validators/changeover-procedure",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"Withdrawing consumer chain validator rewards",permalink:"/interchain-security/v5.0.0/validators/withdraw_rewards"},next:{title:"Joining Neutron",permalink:"/interchain-security/v5.0.0/validators/joining-neutron"}},d={},c=[{value:"Timeline",id:"timeline",level:2},{value:"1. ConsumerAdditionProposal on provider chain",id:"1-consumeradditionproposal-on-provider-chain",level:3},{value:"2. SoftwareUpgradeProposal on the standalone/consumer chain",id:"2-softwareupgradeproposal-on-the-standaloneconsumer-chain",level:3},{value:"3. Assigning a consumer key",id:"3-assigning-a-consumer-key",level:3},{value:"4. Perform the software upgrade on standalone chain",id:"4-perform-the-software-upgrade-on-standalone-chain",level:3},{value:"FAQ",id:"faq",level:2},{value:"Can I reuse the same validator key for the consumer chain that I am already using on the standalone chain? Will I need to perform a AssignConsumerKey tx with this key before spawn time?",id:"can-i-reuse-the-same-validator-key-for-the-consumer-chain-that-i-am-already-using-on-the-standalone-chain-will-i-need-to-perform-a-assignconsumerkey-tx-with-this-key-before-spawn-time",level:3},{value:"Can I continue using the same node that was validating the standalone chain?",id:"can-i-continue-using-the-same-node-that-was-validating-the-standalone-chain",level:3},{value:"Can I set up a new node to validate the standalone/consumer chain after it transitions to replicated security?",id:"can-i-set-up-a-new-node-to-validate-the-standaloneconsumer-chain-after-it-transitions-to-replicated-security",level:3},{value:"What happens to the standalone validator set after it transitions to replicated security?",id:"what-happens-to-the-standalone-validator-set-after-it-transitions-to-replicated-security",level:3},{value:"Credits",id:"credits",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"validator-instructions-for-changeover-procedure",children:"Validator Instructions for Changeover Procedure"}),"\n",(0,i.jsxs)(n.p,{children:["More details available in ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/changeover-procedure",children:"Changeover Procedure documentation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A major difference between launching a new consumer chain vs. onboarding a standalone chain to ICS is that there is no consumer genesis available for the standalone chain. Since a standalone chain already exists, its state must be preserved once it transitions to being a consumer chain."}),"\n",(0,i.jsx)(n.h2,{id:"timeline",children:"Timeline"}),"\n",(0,i.jsxs)(n.p,{children:["Upgrading standalone chains can be best visualised using a timeline, such as the one available ",(0,i.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Excalidraw graphic by Stride"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"There is some flexibility with regards to how the changeover procedure is executed, so please make sure to follow the guides provided by the team doing the changeover."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Standalone to consumer transition timeline",src:a(7509).Z+"",width:"5307",height:"2157"})}),"\n",(0,i.jsxs)(n.h3,{id:"1-consumeradditionproposal-on-provider-chain",children:["1. ",(0,i.jsx)(n.code,{children:"ConsumerAdditionProposal"})," on provider chain"]}),"\n",(0,i.jsxs)(n.p,{children:["This step will add the standalone chain to the list of consumer chains secured by the provider.\nThis step dictates the ",(0,i.jsx)(n.code,{children:"spawn_time"}),". After ",(0,i.jsx)(n.code,{children:"spawn_time"})," the CCV state (initial validator set of the provider) will be available to the consumer."]}),"\n",(0,i.jsx)(n.p,{children:"To obtain it from the provider use:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad q provider consumer-genesis stride-1 -o json > ccv-state.json\njq -s '.[0].app_state.ccvconsumer = .[1] | .[0]' genesis.json ccv-state.json > ccv.json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Transformation of the exported consumer genesis state to the target version of the consumer might be needed in case the provider and consumer formats are incompatible.\nRefer to the compatibility notes ",(0,i.jsx)(n.a,{href:"../../../RELEASES.md#backwards-compatibility",children:"here"})," to check if data transformation is needed for your case.\nInstructions on how to transform the exported CCV genesis state (",(0,i.jsx)(n.code,{children:"ccv-state.json"})," in the example above) to the required target version can be found ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/consumer-genesis-transformation",children:"here"})]}),"\n",(0,i.jsxs)(n.h3,{id:"2-softwareupgradeproposal-on-the-standaloneconsumer-chain",children:["2. ",(0,i.jsx)(n.code,{children:"SoftwareUpgradeProposal"})," on the standalone/consumer chain"]}),"\n",(0,i.jsx)(n.p,{children:"This upgrade proposal will introduce ICS to the standalone chain, making it a consumer."}),"\n",(0,i.jsx)(n.h3,{id:"3-assigning-a-consumer-key",children:"3. Assigning a consumer key"}),"\n",(0,i.jsxs)(n.p,{children:["After ",(0,i.jsx)(n.code,{children:"spawn_time"}),", make sure to assign a consumer key if you intend to use one."]}),"\n",(0,i.jsxs)(n.p,{children:["Instructions are available ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/features/key-assignment",children:"here"})]}),"\n",(0,i.jsx)(n.h3,{id:"4-perform-the-software-upgrade-on-standalone-chain",children:"4. Perform the software upgrade on standalone chain"}),"\n",(0,i.jsx)(n.p,{children:"Please use instructions provided by the standalone chain team and make sure to reach out if you are facing issues.\nThe upgrade preparation depends on your setup, so please make sure you prepare ahead of time."}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"ccv.json"})," from step 1. must be made available on the machine running the standalone/consumer chain at standalone chain ",(0,i.jsx)(n.code,{children:"upgrade_height"}),". This file contains the initial validator set and parameters required for normal ICS operation."]}),(0,i.jsxs)(n.p,{children:["Usually, the file is placed in ",(0,i.jsx)(n.code,{children:"$NODE_HOME/config"})," but this is not a strict requirement. The exact details are available in the upgrade code of the standalone/consumer chain."]})]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Performing this upgrade will transition the standalone chain to be a consumer chain."})}),"\n",(0,i.jsxs)(n.p,{children:['After 3 blocks, the standalone chain will stop using the "old" validator set and begin using the ',(0,i.jsx)(n.code,{children:"provider"})," validator set."]}),"\n",(0,i.jsx)(n.h2,{id:"faq",children:"FAQ"}),"\n",(0,i.jsxs)(n.h3,{id:"can-i-reuse-the-same-validator-key-for-the-consumer-chain-that-i-am-already-using-on-the-standalone-chain-will-i-need-to-perform-a-assignconsumerkey-tx-with-this-key-before-spawn-time",children:["Can I reuse the same validator key for the ",(0,i.jsx)(n.code,{children:"consumer"})," chain that I am already using on the ",(0,i.jsx)(n.code,{children:"standalone"})," chain? Will I need to perform a ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx with this key before spawn time?"]}),"\n",(0,i.jsxs)(n.p,{children:["Validators must either assign a key or use the same key as on the ",(0,i.jsx)(n.code,{children:"provider"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["If you are validating both the ",(0,i.jsx)(n.code,{children:"standalone"})," and the ",(0,i.jsx)(n.code,{children:"provider"}),", you ",(0,i.jsx)(n.strong,{children:"can"})," use your current ",(0,i.jsx)(n.code,{children:"standalone"})," key with some caveats:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["you must submit an ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx with your current ",(0,i.jsx)(n.code,{children:"standalone"})," validator key"]}),"\n",(0,i.jsxs)(n.li,{children:["it is best to submit ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx before ",(0,i.jsx)(n.code,{children:"spawn_time"})]}),"\n",(0,i.jsxs)(n.li,{children:["if you do not submit the Tx, it is assumed that you will be re-using your ",(0,i.jsx)(n.code,{children:"provider"})," key to validate the ",(0,i.jsx)(n.code,{children:"standalone/consumer"})," chain"]}),"\n"]}),"\n",(0,i.jsxs)(n.h3,{id:"can-i-continue-using-the-same-node-that-was-validating-the-standalone-chain",children:["Can I continue using the same node that was validating the ",(0,i.jsx)(n.code,{children:"standalone"})," chain?"]}),"\n",(0,i.jsx)(n.p,{children:"Yes."}),"\n",(0,i.jsx)(n.p,{children:"Please assign your consensus key as stated above."}),"\n",(0,i.jsxs)(n.h3,{id:"can-i-set-up-a-new-node-to-validate-the-standaloneconsumer-chain-after-it-transitions-to-replicated-security",children:["Can I set up a new node to validate the ",(0,i.jsx)(n.code,{children:"standalone/consumer"})," chain after it transitions to replicated security?"]}),"\n",(0,i.jsx)(n.p,{children:"Yes."}),"\n",(0,i.jsxs)(n.p,{children:["If you are planning to do this please make sure that the node is synced with ",(0,i.jsx)(n.code,{children:"standalone"})," network and to submit ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx before ",(0,i.jsx)(n.code,{children:"spawn_time"}),"."]}),"\n",(0,i.jsxs)(n.h3,{id:"what-happens-to-the-standalone-validator-set-after-it-transitions-to-replicated-security",children:["What happens to the ",(0,i.jsx)(n.code,{children:"standalone"})," validator set after it transitions to replicated security?"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"standalone"})," chain validators will stop being validators after the first 3 blocks are created while using replicated security. The ",(0,i.jsx)(n.code,{children:"standalone"})," validators will become ",(0,i.jsx)(n.strong,{children:"governors"})," and still can receive delegations if the ",(0,i.jsx)(n.code,{children:"consumer"})," chain is using the ",(0,i.jsx)(n.code,{children:"consumer-democracy"})," module."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Governors DO NOT VALIDATE BLOCKS"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Instead, they can participate in the governance process and take on other chain-specific roles."}),"\n",(0,i.jsx)(n.h2,{id:"credits",children:"Credits"}),"\n",(0,i.jsx)(n.p,{children:"Thank you Stride team for providing detailed instructions about the changeover procedure."})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},7509:(e,n,a)=>{a.d(n,{Z:()=>i});const i=a.p+"assets/images/ics_changeover_timeline_stride-9bcad1834fef24a0fea7f2c80c9ccd71.png"},1151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var i=a(7294);const t={},s=i.createContext(t);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/a088363e.e8d00cce.js b/assets/js/a088363e.e8d00cce.js
new file mode 100644
index 0000000000..b7ec44f91c
--- /dev/null
+++ b/assets/js/a088363e.e8d00cce.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6530],{6682:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>s,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>c});var r=o(5893),i=o(1151);const t={sidebar_position:3},s="ICS Provider Proposals",a={id:"features/proposals",title:"ICS Provider Proposals",description:"Interchain security module introduces 3 new proposal types to the provider.",source:"@site/versioned_docs/version-v4.2.0-docs/features/proposals.md",sourceDirName:"features",slug:"/features/proposals",permalink:"/interchain-security/v4.2.0/features/proposals",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"tutorialSidebar",previous:{title:"Reward Distribution",permalink:"/interchain-security/v4.2.0/features/reward-distribution"},next:{title:"Consumer Initiated Slashing",permalink:"/interchain-security/v4.2.0/features/slashing"}},d={},c=[{value:"ConsumerAdditionProposal",id:"consumeradditionproposal",level:2},{value:"ConsumerRemovalProposal",id:"consumerremovalproposal",level:2},{value:"ChangeRewardDenomProposal",id:"changerewarddenomproposal",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"ics-provider-proposals",children:"ICS Provider Proposals"}),"\n",(0,r.jsx)(n.p,{children:"Interchain security module introduces 3 new proposal types to the provider."}),"\n",(0,r.jsx)(n.p,{children:"The proposals are used to propose upcoming interchain security events through governance."}),"\n",(0,r.jsx)(n.h2,{id:"consumeradditionproposal",children:(0,r.jsx)(n.code,{children:"ConsumerAdditionProposal"})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["If you are preparing a ",(0,r.jsx)(n.code,{children:"ConsumerAdditionProposal"})," you can find more information in the ",(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/onboarding",children:"consumer onboarding checklist"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Proposal type used to suggest adding a new consumer chain."}),"\n",(0,r.jsxs)(n.p,{children:["When proposals of this type are passed and the ",(0,r.jsx)(n.code,{children:"spawn_time"})," specified in the proposal is reached, all provider chain validators are expected to run infrastructure (validator nodes) for the proposed consumer chain."]}),"\n",(0,r.jsx)(n.p,{children:"Minimal example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:'{\n // Time on the provider chain at which the consumer chain genesis is finalized and all validators\n // will be responsible for starting their consumer chain validator node.\n "spawn_time": "2023-02-28T20:40:00.000000Z",\n "title": "Add consumer chain",\n "description": ".md description of your chain and all other relevant information",\n "chain_id": "newchain-1",\n "initial_height" : {\n "revision_height": 0,\n "revision_number": 1,\n },\n // Unbonding period for the consumer chain.\n // It should be smaller than that of the provider.\n "unbonding_period": 86400000000000,\n // Timeout period for CCV related IBC packets.\n // Packets are considered timed-out after this interval elapses.\n "ccv_timeout_period": 259200000000000,\n "transfer_timeout_period": 1800000000000,\n "consumer_redistribution_fraction": "0.75",\n "blocks_per_distribution_transmission": 1000,\n "historical_entries": 10000,\n "genesis_hash": "d86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0",\n "binary_hash": "376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1",\n "distribution_transmission_channel": "channel-123",\n "top_N": 95,\n "validators_power_cap": 0,\n "validator_set_cap": 0,\n "allowlist": [],\n "denylist": []\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["More examples can be found in the interchain security testnet repository ",(0,r.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/stopped/baryon-1/proposal-baryon-1.json",children:"here"})," and ",(0,r.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/stopped/noble-1/start-proposal-noble-1.json",children:"here"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"consumerremovalproposal",children:(0,r.jsx)(n.code,{children:"ConsumerRemovalProposal"})}),"\n",(0,r.jsx)(n.p,{children:"Proposal type used to suggest removing an existing consumer chain."}),"\n",(0,r.jsx)(n.p,{children:"When proposals of this type are passed, the consumer chain in question will be gracefully removed from interchain security and validators will no longer be required to run infrastructure for the specified chain.\nAfter the consumer chain removal, the chain in question will no longer be secured by the provider's validator set."}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["The chain in question my continue to produce blocks, but the validator set can no longer be slashed for any infractions committed on that chain.\nAdditional steps are required to completely offboard a consumer chain, such as re-introducing the staking module and removing the provider's validators from the active set.\nMore information will be made available in the ",(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/offboarding",children:"Consumer Offboarding Checklist"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Minimal example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:'{\n // the time on the provider chain at which all validators are responsible to stop their consumer chain validator node\n "stop_time": "2023-03-07T12:40:00.000000Z",\n // the chain-id of the consumer chain to be stopped\n "chain_id": "consumerchain-1",\n "title": "This was a great chain",\n "description": "Here is a .md formatted string specifying removal details"\n}\n'})}),"\n",(0,r.jsx)(n.admonition,{type:"warning",children:(0,r.jsx)(n.p,{children:'Before the introduction of Partial Set Security, consumer chains typically included a "soft opt-out mechanism"\nwhich allows the bottom N% of the provider\'s validators to not validate the consumer chain, without being jailed for downtime on the provider.\nAfter the introduction of Partial Set Security, the use of the soft opt-out mechanism is discouraged, and consumer chains are\nencouraged to use the topN parameter to not force validators with little stake to validate the chain.'})}),"\n",(0,r.jsx)(n.h2,{id:"changerewarddenomproposal",children:"ChangeRewardDenomProposal"}),"\n",(0,r.jsx)(n.p,{children:"Proposal type used to mutate the set of denoms accepted by the provider as rewards."}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsxs)(n.p,{children:["A ",(0,r.jsx)(n.code,{children:"ChangeRewardDenomProposal"})," will only be accepted on the provider chain if at least one of the ",(0,r.jsx)(n.code,{children:"denomsToAdd"})," or ",(0,r.jsx)(n.code,{children:"denomsToRemove"})," fields is populated with at least one denom. Also, a denom cannot be repeated in both sets."]})}),"\n",(0,r.jsx)(n.p,{children:"Minimal example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:'{\n "title": "Add uatom as a reward denom",\n "description": "Here is more information about the proposal",\n "denomsToAdd": ["uatom"],\n "denomsToRemove": []\n}\n'})}),"\n",(0,r.jsxs)(n.admonition,{type:"tip",children:[(0,r.jsxs)(n.p,{children:["Besides native provider denoms (e.g., ",(0,r.jsx)(n.code,{children:"uatom"})," for the Cosmos Hub), please use the ",(0,r.jsx)(n.code,{children:"ibc/*"})," denom trace format.\nFor example, for ",(0,r.jsx)(n.code,{children:"untrn"})," transferred over the path ",(0,r.jsx)(n.code,{children:"transfer/channel-569"}),", the denom trace\ncan be queried using the following command:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"> gaiad query ibc-transfer denom-hash transfer/channel-569/untrn\nhash: 0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5\n"})}),(0,r.jsxs)(n.p,{children:["Then use the resulting hash in the ",(0,r.jsx)(n.code,{children:"ChangeRewardDenomProposal"}),", e.g.,"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:'{\n "title": "Add untrn as a reward denom",\n "description": "Here is more information about the proposal",\n "denomsToAdd": ["ibc/0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5"],\n "denomsToRemove": []\n}\n'})})]})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>a,a:()=>s});var r=o(7294);const i={},t=r.createContext(i);function s(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/a09d3327.4f88cf6f.js b/assets/js/a09d3327.4f88cf6f.js
new file mode 100644
index 0000000000..2e36b2e63a
--- /dev/null
+++ b/assets/js/a09d3327.4f88cf6f.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8270],{3696:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>h});var i=t(5893),s=t(1151);const r={sidebar_position:15,title:"Epochs"},o="ADR 014: Epochs",a={id:"adrs/adr-014-epochs",title:"Epochs",description:"Changelog",source:"@site/docs/adrs/adr-014-epochs.md",sourceDirName:"adrs",slug:"/adrs/adr-014-epochs",permalink:"/interchain-security/adrs/adr-014-epochs",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:15,frontMatter:{sidebar_position:15,title:"Epochs"},sidebar:"tutorialSidebar",previous:{title:"Slashing on the provider for consumer equivocation",permalink:"/interchain-security/adrs/adr-013-equivocation-slashing"},next:{title:"Partial Set Security",permalink:"/interchain-security/adrs/adr-015-partial-set-security"}},c={},h=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-014-epochs",children:"ADR 014: Epochs"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2024-01-05: Proposed, first draft of ADR."}),"\n",(0,i.jsx)(n.li,{children:"2024-02-29: Updated so that it describes the implementation where we store the whole consumer validator set."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Accepted"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsxs)(n.p,{children:["In every block that the provider valset changes, a ",(0,i.jsx)(n.code,{children:"VSCPacket"})," must be sent to every consumer and a corresponding ",(0,i.jsx)(n.code,{children:"VSCMaturedPacket"})," sent back.\nGiven that the validator powers may change very often on the provider chain (e.g., the Cosmos Hub), this approach results in a large workload for the relayers.\nAlthough the validator powers may change very often, these changes are usually small and have an insignificant impact on the chain's security.\nIn other words, the valset on the consumers can be slightly outdated without affecting security.\nAs a matter of fact, this already happens due to relaying delays."]}),"\n",(0,i.jsxs)(n.p,{children:["As a solution, this ADR introduces the concept of ",(0,i.jsx)(n.em,{children:"epochs"}),".\nAn epoch consists of multiple blocks.\nThe provider sends ",(0,i.jsx)(n.code,{children:"VSCPacket"}),"s once per epoch.\nA ",(0,i.jsx)(n.code,{children:"VSCPacket"})," contains all the validator updates that are needed by a consumer chain."]}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.p,{children:"The implementation of epochs requires the following changes:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"For each consumer chain, we store the consumer validator set that is currently (i.e., in this epoch) validating the\nconsumer chain. For each validator in the set we store i) its voting power, and ii) the public key that it is\nusing on the consumer chain during the current (i.e., ongoing) epoch.\nThe initial consumer validator set for a chain is set during the creation of the consumer genesis."}),"\n",(0,i.jsxs)(n.li,{children:["We introduce the ",(0,i.jsx)(n.code,{children:"BlocksPerEpoch"})," param that sets the number of blocks in an epoch. By default, ",(0,i.jsx)(n.code,{children:"BlocksPerEpoch"})," is\nset to be 600 which corresponds to 1 hour, assuming 6 seconds per block. This param can be changed through\na ",(0,i.jsx)(n.em,{children:"governance proposal"}),". In the provider ",(0,i.jsx)(n.code,{children:"EndBlock"})," we check ",(0,i.jsx)(n.code,{children:"BlockHeight() % BlocksPerEpoch() == 0"}),"\nto decide when an epoch has ended."]}),"\n",(0,i.jsxs)(n.li,{children:["At the end of every epoch, if there were validator set changes on the provider, then for every consumer chain, we\nconstruct a ",(0,i.jsx)(n.code,{children:"VSCPacket"})," with all the validator updates and add it to the list of ",(0,i.jsx)(n.code,{children:"PendingVSCPackets"}),". We compute the\nvalidator updates needed by a consumer chain by comparing the stored list of consumer validators with the current\nbonded validators on the provider, with something similar to this:"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:"// get the valset that has been validating the consumer chain during this epoch \ncurrentValidators := GetConsumerValSet(consumerChain)\n// generate the validator updates needed to be sent through a `VSCPacket` by comparing the current validators \n// in the epoch with the latest bonded validators\nvalUpdates := DiffValidators(currentValidators, stakingmodule.GetBondedValidators())\n// update the current validators set for the upcoming epoch to be the latest bonded validators instead\nSetConsumerValSet(stakingmodule.GetBondedValidators())\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that a validator can change its consumer public key for a specific consumer chain an arbitrary amount of times during\na block and during an epoch. Then, when we generate the validator updates in ",(0,i.jsx)(n.code,{children:"DiffValidators"}),", we have to check whether\nthe current consumer public key (retrieved by calling ",(0,i.jsx)(n.code,{children:"GetValidatorConsumerPubKey"}),") is different from the consumer public\nkey the validator was using in the current epoch."]}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Reduce the cost of relaying."}),"\n",(0,i.jsx)(n.li,{children:"Reduce the amount of IBC packets needed for ICS."}),"\n",(0,i.jsxs)(n.li,{children:["Simplifies ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-001-key-assignment.md",children:"key-assignment code"})," because\nwe only need to check if the ",(0,i.jsx)(n.code,{children:"consumer_public_key"})," has been modified since the last epoch to generate an update."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Increase the delay in the propagation of validator set changes (but for reasonable epoch lengths on the order of ~hours or less, this is unlikely to be significant)."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsx)(n.p,{children:"N/A"}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/1087",children:"EPIC"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>o});var i=t(7294);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/a2707102.27890462.js b/assets/js/a2707102.27890462.js
new file mode 100644
index 0000000000..3836677406
--- /dev/null
+++ b/assets/js/a2707102.27890462.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[457],{5077:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var r=i(5893),t=i(1151);const s={sidebar_position:1,title:"Overview"},c="Overview",a={id:"adrs/intro",title:"Overview",description:"This is a location to record all high-level architecture decisions in the Interchain Security project.",source:"@site/docs/adrs/intro.md",sourceDirName:"adrs",slug:"/adrs/intro",permalink:"/interchain-security/adrs/intro",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1,title:"Overview"},sidebar:"tutorialSidebar",previous:{title:"Frequently Asked Questions",permalink:"/interchain-security/faq"},next:{title:"Denom DOS fixes",permalink:"/interchain-security/adrs/adr-004-denom-dos-fixes"}},o={},d=[{value:"Table of Contents",id:"table-of-contents",level:2},{value:"Accepted",id:"accepted",level:3},{value:"Proposed",id:"proposed",level:3},{value:"Rejected",id:"rejected",level:3},{value:"Deprecated",id:"deprecated",level:3}];function h(e){const n={a:"a",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,t.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"overview",children:"Overview"}),"\n",(0,r.jsx)(n.p,{children:"This is a location to record all high-level architecture decisions in the Interchain Security project."}),"\n",(0,r.jsxs)(n.p,{children:["You can read more about the Architecture Decision Record (ADR) concept in this ",(0,r.jsx)(n.a,{href:"https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0#.78xhdix6t",children:"blog post"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"An ADR should provide:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Context on the relevant goals and the current state"}),"\n",(0,r.jsx)(n.li,{children:"Proposed changes to achieve the goals"}),"\n",(0,r.jsx)(n.li,{children:"Summary of pros and cons"}),"\n",(0,r.jsx)(n.li,{children:"References"}),"\n",(0,r.jsx)(n.li,{children:"Changelog"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Note the distinction between an ADR and a spec. The ADR provides the context, intuition, reasoning, and\njustification for a change in architecture, or for the architecture of something\nnew. The spec is much more compressed and streamlined summary of everything as\nit is or should be."}),"\n",(0,r.jsx)(n.p,{children:"If recorded decisions turned out to be lacking, convene a discussion, record the new decisions here, and then modify the code to match."}),"\n",(0,r.jsx)(n.p,{children:"Note the context/background should be written in the present tense."}),"\n",(0,r.jsxs)(n.p,{children:["To suggest an ADR, please make use of the ",(0,r.jsx)(n.a,{href:"./templates/adr-template.md",children:"ADR template"})," provided."]}),"\n",(0,r.jsx)(n.h2,{id:"table-of-contents",children:"Table of Contents"}),"\n",(0,r.jsx)(n.h3,{id:"accepted",children:"Accepted"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-001-key-assignment",children:"ADR 001: Key Assignment"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-002-throttle",children:"ADR 002: Jail Throttling"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-004-denom-dos-fixes",children:"ADR 004: Denom DOS fixes"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR 005: Cryptographic verification of equivocation evidence"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-008-throttle-retries",children:"ADR 008: Throttle with retries"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-010-standalone-changeover",children:"ADR 010: Standalone to Consumer Changeover"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-013-equivocation-slashing",children:"ADR 013: Slashing on the provider for consumer equivocation"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-014-epochs",children:"ADR 014: Epochs"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-015-partial-set-security",children:"ADR 015: Partial Set Security"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"proposed",children:"Proposed"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-011-improving-test-confidence",children:"ADR 011: Improving testing and increasing confidence"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-016-securityaggregation",children:"ADR 016: Security aggregation"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-017-allowing-inactive-validators",children:"ADR 017: ICS with Inactive Provider Validators"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"rejected",children:"Rejected"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-007-pause-unbonding-on-eqv-prop",children:"ADR 007: Pause validator unbonding during equivocation proposal"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-012-separate-releasing",children:"ADR 012: Separate Releasing"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"deprecated",children:"Deprecated"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-003-equivocation-gov-proposal",children:"ADR 003: Equivocation governance proposal"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/adrs/adr-009-soft-opt-out",children:"ADR 009: Soft Opt-Out"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>a,a:()=>c});var r=i(7294);const t={},s=r.createContext(t);function c(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:c(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/a6888f58.4bb14d96.js b/assets/js/a6888f58.4bb14d96.js
new file mode 100644
index 0000000000..25da85fecd
--- /dev/null
+++ b/assets/js/a6888f58.4bb14d96.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7487],{4753:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>i,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var r=s(5893),t=s(1151);const a={sidebar_position:3,title:"Key Assignment"},i="ADR 001: Key Assignment",o={id:"adrs/adr-001-key-assignment",title:"Key Assignment",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-001-key-assignment.md",sourceDirName:"adrs",slug:"/adrs/adr-001-key-assignment",permalink:"/interchain-security/v5.0.0/adrs/adr-001-key-assignment",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Key Assignment"},sidebar:"tutorialSidebar",previous:{title:"ADR Template",permalink:"/interchain-security/v5.0.0/adrs/adr-template"},next:{title:"Jail Throttling",permalink:"/interchain-security/v5.0.0/adrs/adr-002-throttle"}},d={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"State required",id:"state-required",level:3},{value:"Protocol overview",id:"protocol-overview",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"adr-001-key-assignment",children:"ADR 001: Key Assignment"}),"\n",(0,r.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"2022-12-01: Initial Draft"}),"\n",(0,r.jsx)(n.li,{children:"2024-03-01: Updated to take into account they key-assigment-replacement deprecation."}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,r.jsx)(n.p,{children:"Accepted"}),"\n",(0,r.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,r.jsx)(n.p,{children:"KeyAssignment is the name of the feature that allows validator operators to use different consensus keys for each consumer chain validator node that they operate."}),"\n",(0,r.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,r.jsxs)(n.p,{children:["It is possible to change the keys at any time by submitting a transaction (i.e., ",(0,r.jsx)(n.code,{children:"MsgAssignConsumerKey"}),")."]}),"\n",(0,r.jsx)(n.h3,{id:"state-required",children:"State required"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ValidatorConsumerPubKey"})," - Stores the validator assigned keys for every consumer chain."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"ConsumerValidatorsBytePrefix | len(chainID) | chainID | providerConsAddress -> consumerKey\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ValidatorByConsumerAddr"})," - Stores the mapping from validator addresses on consumer chains to validator addresses on the provider chain. Needed for the consumer initiated slashing sub-protocol."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"ValidatorsByConsumerAddrBytePrefix | len(chainID) | chainID | consumerConsAddress -> providerConsAddress\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ConsumerAddrsToPrune"})," - Stores the mapping from VSC ids to consumer validators addresses. Needed for pruning ",(0,r.jsx)(n.code,{children:"ValidatorByConsumerAddr"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"ConsumerAddrsToPruneBytePrefix | len(chainID) | chainID | vscID -> []consumerConsAddresses\n"})}),"\n",(0,r.jsx)(n.h3,{id:"protocol-overview",children:"Protocol overview"}),"\n",(0,r.jsxs)(n.p,{children:["On receiving a ",(0,r.jsx)(n.code,{children:"MsgAssignConsumerKey(chainID, providerAddr, consumerKey)"})," message:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"// get validator from staking module \nvalidator, found := stakingKeeper.GetValidator(providerAddr)\nif !found {\n return ErrNoValidatorFound\n}\nproviderConsAddr := validator.GetConsAddr()\n\n// make sure consumer key is not in use\nconsumerAddr := utils.TMCryptoPublicKeyToConsAddr(consumerKey)\nif _, found := GetValidatorByConsumerAddr(ChainID, consumerAddr); found {\n return ErrInvalidConsumerConsensusPubKey\n}\n\n// check whether the consumer chain is already registered\n// i.e., a client to the consumer was already created\nif _, consumerRegistered := GetConsumerClientId(chainID); consumerRegistered {\n // get the previous key assigned for this validator on this consumer chain\n oldConsumerKey, found := GetValidatorConsumerPubKey(chainID, providerConsAddr)\n if found {\n // mark this old consumer key as prunable once the VSCMaturedPacket\n // for the current VSC ID is received\n oldConsumerAddr := utils.TMCryptoPublicKeyToConsAddr(oldConsumerKey)\n vscID := GetValidatorSetUpdateId()\n AppendConsumerAddrsToPrune(chainID, vscID, oldConsumerAddr)\n }\n} else {\n // if the consumer chain is not registered, then remove the previous reverse mapping\n if oldConsumerKey, found := GetValidatorConsumerPubKey(chainID, providerConsAddr); found {\n oldConsumerAddr := utils.TMCryptoPublicKeyToConsAddr(oldConsumerKey)\n DeleteValidatorByConsumerAddr(chainID, oldConsumerAddr)\n }\n}\n\n\n// set the mapping from this validator's provider address to the new consumer key\nSetValidatorConsumerPubKey(chainID, providerConsAddr, consumerKey)\n\n// set the reverse mapping: from this validator's new consensus address \n// on the consumer to its consensus address on the provider\nSetValidatorByConsumerAddr(chainID, consumerAddr, providerConsAddr)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["When a new consumer chain is registered, i.e., a client to the consumer chain is created, the provider constructs the consumer CCV module part of the genesis state (see ",(0,r.jsx)(n.code,{children:"MakeConsumerGenesis"}),")."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func (k Keeper) MakeConsumerGenesis(chainID string) (gen consumertypes.GenesisState, nextValidatorsHash []byte, err error) {\n // ...\n // get initial valset from the staking module\n var updates []abci.ValidatorUpdate{}\n stakingKeeper.IterateLastValidatorPowers(func(providerAddr sdk.ValAddress, power int64) (stop bool) {\n validator := stakingKeeper.GetValidator(providerAddr)\n providerKey := validator.TmConsPublicKey()\n\t\tupdates = append(updates, abci.ValidatorUpdate{PubKey: providerKey, Power: power})\n\t\treturn false\n\t})\n\n // applies the key assignment to the initial validator\n\tfor i, update := range updates {\n\t\tproviderAddr := utils.TMCryptoPublicKeyToConsAddr(update.PubKey)\n\t\tif consumerKey, found := GetValidatorConsumerPubKey(chainID, providerAddr); found {\n\t\t\tupdates[i].PubKey = consumerKey\n\t\t}\n\t}\n gen.InitialValSet = updates\n\n // get a hash of the consumer validator set from the update\n\tupdatesAsValSet := tendermint.PB2TM.ValidatorUpdates(updates)\n\thash := tendermint.NewValidatorSet(updatesAsValSet).Hash()\n\n\treturn gen, hash, nil\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Note that key assignment works hand-in-hand with ",(0,r.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-014-epochs.md",children:"epochs"}),".\nFor each consumer chain, we store the consumer validator set that is currently (i.e., in this epoch) validating the consumer chain.\nSpecifically, for each validator in the set we store among others, the public key that it is using on the consumer chain during the current (i.e., ongoing) epoch.\nAt the end of every epoch, if there were validator set changes on the provider, then for every consumer chain, we construct a ",(0,r.jsx)(n.code,{children:"VSCPacket"}),"\nwith all the validator updates and add it to the list of ",(0,r.jsx)(n.code,{children:"PendingVSCPacket"}),"s. We compute the validator updates needed by a consumer chain by\ncomparing the stored list of consumer validators with the current bonded validators on the provider, with something similar to this:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"// get the valset that has been validating the consumer chain during this epoch \ncurrentValidators := GetConsumerValSet(consumerChain)\n// generate the validator updates needed to be sent through a `VSCPacket` by comparing the current validators \n// in the epoch with the latest bonded validators\nvalUpdates := DiffValidators(currentValidators, stakingmodule.GetBondedValidators())\n// update the current validators set for the upcoming epoch to be the latest bonded validators instead\nSetConsumerValSet(stakingmodule.GetBondedValidators())\n"})}),"\n",(0,r.jsxs)(n.p,{children:["where ",(0,r.jsx)(n.code,{children:"DiffValidators"})," internally checks if the consumer public key for a validator has changed since the last\nepoch and if so generates a validator update. This way, a validator can change its consumer public key for a consumer\nchain an arbitrary amount of times and only the last set consumer public key would be taken into account."]}),"\n",(0,r.jsxs)(n.p,{children:["On receiving a ",(0,r.jsx)(n.code,{children:"SlashPacket"})," from a consumer chain with id ",(0,r.jsx)(n.code,{children:"chainID"})," for a infraction of a validator ",(0,r.jsx)(n.code,{children:"data.Validator"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func HandleSlashPacket(chainID string, data ccv.SlashPacketData) (success bool, err error) {\n // ...\n // the slash packet validator address may be known only on the consumer chain;\n\t// in this case, it must be mapped back to the consensus address on the provider chain\n consumerAddr := sdk.ConsAddress(data.Validator.Address)\n providerAddr, found := GetValidatorByConsumerAddr(chainID, consumerAddr)\n if !found {\n // the validator has the same key on the consumer as on the provider\n providerAddr = consumerAddr\n }\n // ...\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["On receiving a ",(0,r.jsx)(n.code,{children:"VSCMatured"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func OnRecvVSCMaturedPacket(packet channeltypes.Packet, data ccv.VSCMaturedPacketData) exported.Acknowledgement {\n // ...\n // prune previous consumer validator address that are no longer needed\n consumerAddrs := GetConsumerAddrsToPrune(chainID, data.ValsetUpdateId)\n\tfor _, addr := range consumerAddrs {\n\t\tDeleteValidatorByConsumerAddr(chainID, addr)\n\t}\n\tDeleteConsumerAddrsToPrune(chainID, data.ValsetUpdateId)\n // ...\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"On stopping a consumer chain:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-golang",children:"func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan bool) (err error) {\n // ...\n // deletes all the state needed for key assignments on this consumer chain\n // ...\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,r.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Validators can use different consensus keys on the consumer chains."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"None"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The consensus state necessary to create a client to the consumer chain must use the hash returned by the ",(0,r.jsx)(n.code,{children:"MakeConsumerGenesis"})," method as the ",(0,r.jsx)(n.code,{children:"nextValsHash"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The consumer chain can no longer check the initial validator set against the consensus state on ",(0,r.jsx)(n.code,{children:"InitGenesis"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/26",children:"Key assignment issue"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>o,a:()=>i});var r=s(7294);const t={},a=r.createContext(t);function i(e){const n=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),r.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/a7bd4aaa.687d6c08.js b/assets/js/a7bd4aaa.687d6c08.js
new file mode 100644
index 0000000000..74fed2fec3
--- /dev/null
+++ b/assets/js/a7bd4aaa.687d6c08.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8518],{8564:(e,n,s)=>{s.r(n),s.d(n,{default:()=>d});s(7294);var r=s(1944),o=s(3320),t=s(4477),i=s(8790),c=s(197),u=s(5893);function a(e){const{version:n}=e;return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(c.Z,{version:n.version,tag:(0,o.os)(n.pluginId,n.version)}),(0,u.jsx)(r.d,{children:n.noIndex&&(0,u.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})]})}function l(e){const{version:n,route:s}=e;return(0,u.jsx)(r.FG,{className:n.className,children:(0,u.jsx)(t.q,{version:n,children:(0,i.H)(s.routes)})})}function d(e){return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(a,{...e}),(0,u.jsx)(l,{...e})]})}}}]);
\ No newline at end of file
diff --git a/assets/js/a8cc50aa.4e815e71.js b/assets/js/a8cc50aa.4e815e71.js
new file mode 100644
index 0000000000..9c8b19919d
--- /dev/null
+++ b/assets/js/a8cc50aa.4e815e71.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[787],{2973:(s,e,a)=>{a.r(e),a.d(e,{assets:()=>h,contentTitle:()=>l,default:()=>d,frontMatter:()=>t,metadata:()=>r,toc:()=>c});var i=a(5893),n=a(1151);const t={sidebar_position:3,title:"Jail Throttling"},l="ADR 002: Jail Throttling",r={id:"adrs/adr-002-throttle",title:"Jail Throttling",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-002-throttle.md",sourceDirName:"adrs",slug:"/adrs/adr-002-throttle",permalink:"/interchain-security/v5.0.0/adrs/adr-002-throttle",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Jail Throttling"},sidebar:"tutorialSidebar",previous:{title:"Key Assignment",permalink:"/interchain-security/v5.0.0/adrs/adr-001-key-assignment"},next:{title:"Equivocation governance proposal",permalink:"/interchain-security/v5.0.0/adrs/adr-003-equivocation-gov-proposal"}},h={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Required State",id:"required-state",level:3},{value:"Params",id:"params",level:3},{value:"Protocol Overview",id:"protocol-overview",level:3},{value:"OnRecvSlashPacket",id:"onrecvslashpacket",level:4},{value:"OnRecvVSCMaturedPacket",id:"onrecvvscmaturedpacket",level:4},{value:"Endblocker",id:"endblocker",level:4},{value:"Slash Meter Replenishment",id:"slash-meter-replenishment",level:5},{value:"Handle Leading VSCMaturedPackets",id:"handle-leading-vscmaturedpackets",level:5},{value:"Handle Throttle Queues",id:"handle-throttle-queues",level:5},{value:"System Properties",id:"system-properties",level:3},{value:"Main Throttling Property",id:"main-throttling-property",level:3},{value:"How Unjailing Affects the Main Throttling Property",id:"how-unjailing-affects-the-main-throttling-property",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function m(s){const e={a:"a",annotation:"annotation",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",li:"li",math:"math",mfrac:"mfrac",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",msub:"msub",ol:"ol",p:"p",pre:"pre",semantics:"semantics",span:"span",strong:"strong",ul:"ul",...(0,n.a)(),...s.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"adr-002-jail-throttling",children:"ADR 002: Jail Throttling"}),"\n",(0,i.jsx)(e.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"2023-01-26: Initial Draft"}),"\n",(0,i.jsx)(e.li,{children:"2023-02-07: Property refined, ADR ready to review/merge"}),"\n",(0,i.jsx)(e.li,{children:"2023-11-22: Refactor for better understanding"}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(e.p,{children:"Accepted"}),"\n",(0,i.jsx)(e.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(e.p,{children:"The CCV spec is based around the assumption that the provider binary and all consumers binaries are non-malicious, and follow the defined protocols.\nIn practice, this assumption may not hold.\nA malicious consumer binary could potentially include code which is able to send many slash/jail packets at once to the provider."}),"\n",(0,i.jsx)(e.p,{children:"Before the throttling feature was implemented, the following attack was possible.\nAttacker(s) would create provider validators just below the provider's active set.\nUsing a malicious consumer binary, slash packets would be relayed to the provider, that would slash/jail a significant portion (or all) of honest validator at once.\nControl of the provider would then pass over to the attackers' validators.\nThis enables the attacker(s) to halt the provider.\nOr even worse, commit arbitrary state on the provider, potentially stealing all tokens bridged to the provider over IBC."}),"\n",(0,i.jsx)(e.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(e.p,{children:"The throttling feature was designed to slow down the mentioned attack from above, allowing validators and the community to appropriately respond to the attack,\ni.e., this feature limits (enforced by on-chain params) the rate that the provider validator set can be jailed over time."}),"\n",(0,i.jsx)(e.h3,{id:"required-state",children:"Required State"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Slash meter:"})," There exists one slash meter on the provider which stores an amount of voting power (integer), corresponding to an allowance of validators that can be jailed over time.\nThis meter is initialized to a certain value on genesis, decremented by the amount of voting power jailed whenever a slash packet is handled, and periodically replenished as decided by on-chain params."]}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Global entry queue:"}),' There exists a single queue which stores "global slash entries".\nThese entries allow the provider to appropriately handle slash packets sent from any consumer in FIFO ordering.\nThis queue is responsible for coordinating the order that slash packets (from multiple chains) are handled over time.']}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Per-chain data queue:"}),' For each established consumer, there exists a queue which stores "throttled packet data",\ni.e.,pending slash packet data is queued together with pending VSC matured packet data in FIFO ordering.\nOrder is enforced by IBC sequence number.\nThese "per-chain" queues are responsible for coordinating the order that slash packets are handled in relation to VSC matured packets from the same chain.']}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.em,{children:"Note:"})," The reason for a multiple-queue design is the ",(0,i.jsx)(e.em,{children:"VSC Maturity and Slashing Order"})," property (see ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#consumer-initiated-slashing",children:"spec"}),").\nThere are other ways to ensure such a property (like a queue of linked lists, etc.), but the proposed approach seemed to be the most understandable and easiest to implement with a KV store."]}),"\n",(0,i.jsx)(e.h3,{id:"params",children:"Params"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishPeriod"})," -- the period after which the slash meter is replenished."]}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," -- the portion (in range [0, 1]) of total voting power that is replenished to the slash meter when a replenishment occurs. This param also serves as a maximum fraction of total voting power that the slash meter can hold."]}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.code,{children:"MaxThrottledPackets"})," -- the maximum amount of throttled slash or vsc matured packets that can be queued from a single consumer before the provider chain halts, it should be set to a large value.\nThis param would allow provider binaries to panic deterministically in the event that packet throttling results in a large amount of state-bloat. In such a scenario, packet throttling could prevent a violation of safety caused by a malicious consumer, at the cost of provider liveness."]}),"\n",(0,i.jsx)(e.h3,{id:"protocol-overview",children:"Protocol Overview"}),"\n",(0,i.jsx)(e.h4,{id:"onrecvslashpacket",children:"OnRecvSlashPacket"}),"\n",(0,i.jsx)(e.p,{children:"Upon the provider receiving a slash packet from any of the established consumers during block execution, two things occur:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsx)(e.li,{children:"A global slash entry is queued."}),"\n",(0,i.jsx)(e.li,{children:"The data of such a packet is added to the per-chain queue."}),"\n"]}),"\n",(0,i.jsx)(e.h4,{id:"onrecvvscmaturedpacket",children:"OnRecvVSCMaturedPacket"}),"\n",(0,i.jsx)(e.p,{children:"Upon the provider receiving a VSCMatured packet from any of the established consumers during block execution, the VSCMatured packet data is added to the per-chain queue."}),"\n",(0,i.jsx)(e.h4,{id:"endblocker",children:"Endblocker"}),"\n",(0,i.jsxs)(e.p,{children:["In the ",(0,i.jsx)(e.code,{children:"EndBlock"})," of the provider CCV module, there are three actions performed:"]}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"replenish the slash meter;"}),"\n",(0,i.jsxs)(e.li,{children:["handle the leading ",(0,i.jsx)(e.code,{children:"VSCMaturedPackets"}),";"]}),"\n",(0,i.jsx)(e.li,{children:"and handle the throttle queues."}),"\n"]}),"\n",(0,i.jsx)(e.h5,{id:"slash-meter-replenishment",children:"Slash Meter Replenishment"}),"\n",(0,i.jsxs)(e.p,{children:["Once the slash meter becomes not full, it'll be replenished after ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishPeriod"})," by incrementing the meter with its allowance for the replenishment block, where ",(0,i.jsx)(e.code,{children:"allowance"})," = ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," * ",(0,i.jsx)(e.code,{children:"currentTotalVotingPower"}),".\nThe slash meter will never exceed its current allowance (function of the total voting power for the block) in value."]}),"\n",(0,i.jsx)(e.p,{children:"Note a few things:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsx)(e.li,{children:"The slash meter can go negative in value, and will do so when handling a single slash packet that jails a validator with significant voting power.\nIn such a scenario, the slash meter may take multiple replenishment periods to once again reach a positive value (or 0), meaning no other slash packets may be handled for multiple replenishment periods."}),"\n",(0,i.jsx)(e.li,{children:"Total voting power of a chain changes over time, especially as validators are jailed.\nAs validators are jailed, total voting power decreases, and so does the jailing allowance.\nSee below for more detailed throttling property discussion."}),"\n",(0,i.jsxs)(e.li,{children:["The voting power allowance added to the slash meter during replenishment will always be greater than or equal to 1.\nIf the ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," is set too low, integer rounding will put this minimum value into effect.\nThat is, if ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," * ",(0,i.jsx)(e.code,{children:"currentTotalVotingPower"})," < 1, then the effective allowance would be 1.\nThis min value of allowance ensures that there's some packets handled over time, even if that is a very long time.\nIt's a crude solution to an edge case caused by too small of a replenishment fraction."]}),"\n"]}),"\n",(0,i.jsxs)(e.p,{children:["The behavior described above is achieved by executing ",(0,i.jsx)(e.code,{children:"CheckForSlashMeterReplenishment()"})," every ",(0,i.jsx)(e.code,{children:"EndBlock"}),", BEFORE ",(0,i.jsx)(e.code,{children:"HandleThrottleQueues()"})," is executed."]}),"\n",(0,i.jsx)(e.h5,{id:"handle-leading-vscmaturedpackets",children:"Handle Leading VSCMaturedPackets"}),"\n",(0,i.jsxs)(e.p,{children:["In every block, it is possible that ",(0,i.jsx)(e.code,{children:"VSCMaturedPacket"}),' data was queued before any slash packet data.\nSince this "leading" VSCMatured packet data does not have to be throttled (see ',(0,i.jsx)(e.em,{children:"VSC Maturity and Slashing Order"}),"), we can handle all VSCMatured packet data at the head of the queue, before the any throttling or packet data handling logic executes."]}),"\n",(0,i.jsx)(e.h5,{id:"handle-throttle-queues",children:"Handle Throttle Queues"}),"\n",(0,i.jsxs)(e.p,{children:["In every ",(0,i.jsx)(e.code,{children:"EndBlock"}),", the following logic is executed to handle data from the throttle queues."]}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-typescript",children:"meter := getSlashMeter()\n\n// Keep iterating as long as the meter has a positive (or 0) value, and global slash entries exist \nwhile meter.IsPositiveOrZero() && entriesExist() {\n // Get next entry in queue\n entry := getNextGlobalSlashEntry()\n // Decrement slash meter by the voting power that will be removed from the valset from handling this slash packet\n valPower := entry.getValPower()\n meter = meter - valPower\n // Using the per-chain queue, handle the single slash packet using its queued data,\n // then handle all trailing VSCMatured packets for this consumer\n handleSlashPacketAndTrailingVSCMaturedPackets(entry)\n // Delete entry in global queue, delete handled data\n entry.Delete()\n deleteThrottledSlashPacketData()\n deleteTrailingVSCMaturedPacketData()\n}\n"})}),"\n",(0,i.jsx)(e.h3,{id:"system-properties",children:"System Properties"}),"\n",(0,i.jsxs)(e.p,{children:["All CCV system properties should be maintained by implementing this feature, see ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#consumer-initiated-slashing",children:"CCV spec - Consumer Initiated Slashing"}),"."]}),"\n",(0,i.jsxs)(e.p,{children:["One implementation-specific property introduced is that if any of the chain-specific packet data queues become larger than ",(0,i.jsx)(e.code,{children:"MaxThrottledPackets"}),", then the provider binary will panic, and the provider chain will halt.\nTherefore this param should be set carefully. See ",(0,i.jsx)(e.code,{children:"SetThrottledPacketDataSize"}),".\nThis behavior ensures that if the provider binaries are queuing up more packet data than machines can handle, the provider chain halts deterministically between validators."]}),"\n",(0,i.jsx)(e.h3,{id:"main-throttling-property",children:"Main Throttling Property"}),"\n",(0,i.jsx)(e.p,{children:"Using on-chain params and the sub protocol defined, slash packet throttling is implemented such that the following property holds under some conditions."}),"\n",(0,i.jsx)(e.p,{children:"First, we introduce the following definitions:"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:'A consumer initiated slash attack "starts" when the first slash packet from such an attack is received by the provider.'}),"\n",(0,i.jsx)(e.li,{children:'The "initial validator set" for the attack is the validator set that existed on the provider when the attack started.'}),"\n",(0,i.jsxs)(e.li,{children:["There is a list of honest validators such that if they are jailed, ",(0,i.jsx)(e.code,{children:"X"}),"% of the initial validator set will be jailed."]}),"\n"]}),"\n",(0,i.jsx)(e.p,{children:"For the Throttling Property to hold, the following assumptions must be true:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsx)(e.li,{children:"We assume the total voting power of the chain (as a function of delegations) does not increase over the course of the attack."}),"\n",(0,i.jsxs)(e.li,{children:["No validator has more than ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," of total voting power on the provider."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," is large enough that ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," * ",(0,i.jsx)(e.code,{children:"currentTotalVotingPower"})," > 1,\ni.e., the replenish fraction is set high enough that we can ignore the effects of rounding."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishPeriod"})," is sufficiently longer than the time it takes to produce a block."]}),"\n"]}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.em,{children:"Note if these assumptions do not hold, throttling will still slow down the described attack in most cases, just not in a way that can be succinctly described. It's possible that more complex properties can be defined."})}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Throttling Property"}),": The time it takes to jail/tombstone ",(0,i.jsx)(e.code,{children:"X"}),"% of the initial validator set will be greater than or equal to\n",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"d"})]}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"c"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"n"})]})]}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"d"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathit{SlashMeterReplenishPeriod} \\cdot \\frac{X}{\\mathit{SlashMeterReplenishFraction}} - 2 \\cdot \\mathit{SlashMeterReplenishPeriod}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishPeriod"})}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.3534em",verticalAlign:"-0.4811em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8723em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"SlashMeterReplenishFraction"})})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.394em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"})})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.4811em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,i.jsx)(e.span,{className:"mord",children:"2"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishPeriod"})})]})]})]}),"."]}),"\n",(0,i.jsxs)(e.blockquote,{children:["\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"Intuition"})}),"\n",(0,i.jsx)(e.p,{children:"Let's use the following notation:"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"C"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"})]})})]}),": Number of replenishment cycles"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"P"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"P"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})})]}),": ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"d"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathit{SlashMeterReplenishPeriod}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishPeriod"})})]})})]})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"F"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"F"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})})]}),": ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"c"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"n"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathit{SlashMeterReplenishFraction}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishFraction"})})]})})]})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"V_{\\mathit{max}}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]}),": Max power of a validator as a fraction of total voting power"]}),"\n"]}),"\n",(0,i.jsxs)(e.p,{children:["In ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"C"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"})]})})]})," number of replenishment cycles, the fraction of total voting power that can be removed, ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"a"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"a"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",children:"a"})]})})]}),", is ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mo,{children:"\u2264"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"+"}),(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"a \\leq F \\cdot C + V_{\\mathit{max}}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7719em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",children:"a"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2264"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"+"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})]})]})," (where ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"V_{\\mathit{max}}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]})," is there to account for the power fraction of the last validator removed, one which pushes the meter to the negative value)."]}),"\n",(0,i.jsxs)(e.p,{children:["So, we need at least ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u2265"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})]}),(0,i.jsx)(e.mi,{children:"F"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\geq \\frac{a - V_{\\mathit{max}}}{F}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8193em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.2334em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8884em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.4101em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",children:"a"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1645em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.357em",marginLeft:"-0.2222em",marginRight:"0.0714em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.5em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size3 size1 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.143em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})," cycles to remove ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"a"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"a"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",children:"a"})]})})]})," fraction of the total voting power."]}),"\n",(0,i.jsxs)(e.p,{children:["Since we defined the start of the attack to be the moment when the first slash request arrives, then ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"F"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"F"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})})]})," fraction of the initial validator set can be jailed immediately. For the remaining ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"X - F"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})]})]})," fraction of the initial validator set to be jailed, it takes at least ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u2265"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mo,{stretchy:"false",children:"("}),(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mo,{stretchy:"false",children:")"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})]}),(0,i.jsx)(e.mi,{children:"F"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\geq \\frac{(X - F) - V_{\\mathit{max}}}{F}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8193em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.355em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"1.01em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.485em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mopen mtight",children:"("}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"}),(0,i.jsx)(e.span,{className:"mclose mtight",children:")"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1645em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.357em",marginLeft:"-0.2222em",marginRight:"0.0714em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.5em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size3 size1 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.143em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})," cycles. Using the assumption that ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]}),(0,i.jsx)(e.mo,{children:"\u2264"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"V_{\\mathit{max}} \\leq F"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2264"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})]})]})," (assumption 2), we get ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u2265"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.mi,{children:"F"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\geq \\frac{X - 2F}{F}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8193em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.2173em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8723em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.394em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mord mtight",children:"2"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})," cycles."]}),"\n",(0,i.jsxs)(e.p,{children:["In order to execute ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"C"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"})]})})]})," cycles, we need ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mi,{children:"P"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\cdot P"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})]})]})," time."]}),"\n",(0,i.jsxs)(e.p,{children:["Thus, jailing the remaining ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"X - F"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})]})]})," fraction of the initial validator set corresponds to ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mo,{stretchy:"false",children:"("}),(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,i.jsx)(e.mi,{children:"F"})]})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\frac{P \\cdot (X - 2F)}{F}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.355em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"1.01em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.485em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"P"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mopen mtight",children:"("}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mord mtight",children:"2"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"}),(0,i.jsx)(e.span,{className:"mclose mtight",children:")"})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})})]})," time."]}),"\n",(0,i.jsxs)(e.p,{children:["In other words, the attack must take at least ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mi,{children:"X"})]}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mi,{children:"P"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\frac{P \\cdot X}{F} - 2P"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.2173em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8723em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.394em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"P"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord",children:"2"}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})]})]})," time (in the units of replenish period ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"P"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"P"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})})]}),")."]}),"\n"]}),"\n",(0,i.jsxs)(e.p,{children:["This property is useful because it allows us to reason about the time it takes to jail a certain percentage of the initial provider validator set from consumer initiated slash requests.\nFor example, if ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," is set to ",(0,i.jsx)(e.code,{children:"0.06"}),", then it takes no less than 4 replenishment periods to jail 33% of the initial provider validator set on the Cosmos Hub.\nNote that as of writing this on 11/29/22, the Cosmos Hub does not have a validator with more than 6% of total voting power."]}),"\n",(0,i.jsx)(e.p,{children:"Note also that 4 replenishment period is a worst case scenario that depends on well crafted attack timings."}),"\n",(0,i.jsx)(e.h3,{id:"how-unjailing-affects-the-main-throttling-property",children:"How Unjailing Affects the Main Throttling Property"}),"\n",(0,i.jsx)(e.p,{children:"Note that the jailing allowance is directly proportional to the current total voting power of the provider chain. Therefore, if honest validators don't unjail themselves during the attack, the total voting power of the provider chain will decrease over the course of the attack, and the attack will be slowed down, main throttling property is maintained."}),"\n",(0,i.jsx)(e.p,{children:"If honest validators do unjail themselves, the total voting power of the provider chain will still not become higher than when the attack started (unless new token delegations happen), therefore the main property is still maintained. Moreover, honest validators unjailing themselves helps prevent the attacking validators from gaining control of the provider."}),"\n",(0,i.jsx)(e.p,{children:"In summary, the throttling mechanism as designed has desirable properties whether or not honest validators unjail themselves over the course of the attack."}),"\n",(0,i.jsx)(e.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(e.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"The described attack is slowed down in seemingly all cases."}),"\n",(0,i.jsx)(e.li,{children:"If certain assumptions hold, the described attack is slowed down in a way that can be precisely time-bounded."}),"\n"]}),"\n",(0,i.jsx)(e.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["Throttling introduces a vector for a malicious consumer chain to halt the provider, see issue below.\nHowever, this is sacrificing liveness in a edge case scenario for the sake of security.\nAs an improvement, ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/713",children:"using retries"})," would fully prevent this attack vector."]}),"\n"]}),"\n",(0,i.jsx)(e.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"Additional state is introduced to the provider chain."}),"\n",(0,i.jsx)(e.li,{children:"VSCMatured and slash packet data is not always handled in the same block that it is received."}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/404",children:"Original issue inspiring throttling feature"})}),"\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/594",children:"Issue on DOS vector"})}),"\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/685",children:"Consideration of another attack vector"})}),"\n"]})]})}function d(s={}){const{wrapper:e}={...(0,n.a)(),...s.components};return e?(0,i.jsx)(e,{...s,children:(0,i.jsx)(m,{...s})}):m(s)}},1151:(s,e,a)=>{a.d(e,{Z:()=>r,a:()=>l});var i=a(7294);const n={},t=i.createContext(n);function l(s){const e=i.useContext(t);return i.useMemo((function(){return"function"==typeof s?s(e):{...e,...s}}),[e,s])}function r(s){let e;return e=s.disableParentContext?"function"==typeof s.components?s.components(n):s.components||n:l(s.components),i.createElement(t.Provider,{value:e},s.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/a94703ab.3856b628.js b/assets/js/a94703ab.3856b628.js
new file mode 100644
index 0000000000..e887c1dcf3
--- /dev/null
+++ b/assets/js/a94703ab.3856b628.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4368],{2674:(e,t,n)=>{n.r(t),n.d(t,{default:()=>be});var a=n(7294),o=n(512),i=n(1944),s=n(5281),l=n(2802),r=n(1116),c=n(5999),d=n(2466),u=n(5936);const m={backToTopButton:"backToTopButton_sjWU",backToTopButtonShow:"backToTopButtonShow_xfvO"};var b=n(5893);function h(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,o]=(0,a.useState)(!1),i=(0,a.useRef)(!1),{startScroll:s,cancelScroll:l}=(0,d.Ct)();return(0,d.RF)(((e,n)=>{let{scrollY:a}=e;const s=n?.scrollY;s&&(i.current?i.current=!1:a>=s?(l(),o(!1)):a{e.location.hash&&(i.current=!0,o(!1))})),{shown:n,scrollToTop:()=>s(0)}}({threshold:300});return(0,b.jsx)("button",{"aria-label":(0,c.I)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,o.Z)("clean-btn",s.k.common.backToTopButton,m.backToTopButton,e&&m.backToTopButtonShow),type:"button",onClick:t})}var p=n(1442),x=n(6550),f=n(7524),j=n(6668),k=n(1327);function _(e){return(0,b.jsx)("svg",{width:"20",height:"20","aria-hidden":"true",...e,children:(0,b.jsxs)("g",{fill:"#7a7a7a",children:[(0,b.jsx)("path",{d:"M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"}),(0,b.jsx)("path",{d:"M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"})]})})}const v={collapseSidebarButton:"collapseSidebarButton_PEFL",collapseSidebarButtonIcon:"collapseSidebarButtonIcon_kv0_"};function g(e){let{onClick:t}=e;return(0,b.jsx)("button",{type:"button",title:(0,c.I)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,c.I)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,o.Z)("button button--secondary button--outline",v.collapseSidebarButton),onClick:t,children:(0,b.jsx)(_,{className:v.collapseSidebarButtonIcon})})}var C=n(9689),S=n(902);const I=Symbol("EmptyContext"),N=a.createContext(I);function T(e){let{children:t}=e;const[n,o]=(0,a.useState)(null),i=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:o})),[n]);return(0,b.jsx)(N.Provider,{value:i,children:t})}var B=n(6043),Z=n(8596),A=n(9960),L=n(2389);function y(e){let{collapsed:t,categoryLabel:n,onClick:a}=e;return(0,b.jsx)("button",{"aria-label":t?(0,c.I)({id:"theme.DocSidebarItem.expandCategoryAriaLabel",message:"Expand sidebar category '{label}'",description:"The ARIA label to expand the sidebar category"},{label:n}):(0,c.I)({id:"theme.DocSidebarItem.collapseCategoryAriaLabel",message:"Collapse sidebar category '{label}'",description:"The ARIA label to collapse the sidebar category"},{label:n}),type:"button",className:"clean-btn menu__caret",onClick:a})}function w(e){let{item:t,onItemClick:n,activePath:i,level:r,index:c,...d}=e;const{items:u,label:m,collapsible:h,className:p,href:x}=t,{docs:{sidebar:{autoCollapseCategories:f}}}=(0,j.L)(),k=function(e){const t=(0,L.Z)();return(0,a.useMemo)((()=>e.href&&!e.linkUnlisted?e.href:!t&&e.collapsible?(0,l.LM)(e):void 0),[e,t])}(t),_=(0,l._F)(t,i),v=(0,Z.Mg)(x,i),{collapsed:g,setCollapsed:C}=(0,B.u)({initialState:()=>!!h&&(!_&&t.collapsed)}),{expandedItem:T,setExpandedItem:w}=function(){const e=(0,a.useContext)(N);if(e===I)throw new S.i6("DocSidebarItemsExpandedStateProvider");return e}(),E=function(e){void 0===e&&(e=!g),w(e?null:c),C(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:o}=e;const i=(0,S.D9)(t);(0,a.useEffect)((()=>{t&&!i&&n&&o(!1)}),[t,i,n,o])}({isActive:_,collapsed:g,updateCollapsed:E}),(0,a.useEffect)((()=>{h&&null!=T&&T!==c&&f&&C(!0)}),[h,T,c,C,f]),(0,b.jsxs)("li",{className:(0,o.Z)(s.k.docs.docSidebarItemCategory,s.k.docs.docSidebarItemCategoryLevel(r),"menu__list-item",{"menu__list-item--collapsed":g},p),children:[(0,b.jsxs)("div",{className:(0,o.Z)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":v}),children:[(0,b.jsx)(A.Z,{className:(0,o.Z)("menu__link",{"menu__link--sublist":h,"menu__link--sublist-caret":!x&&h,"menu__link--active":_}),onClick:h?e=>{n?.(t),x?E(!1):(e.preventDefault(),E())}:()=>{n?.(t)},"aria-current":v?"page":void 0,"aria-expanded":h?!g:void 0,href:h?k??"#":k,...d,children:m}),x&&h&&(0,b.jsx)(y,{collapsed:g,categoryLabel:m,onClick:e=>{e.preventDefault(),E()}})]}),(0,b.jsx)(B.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:g,children:(0,b.jsx)(V,{items:u,tabIndex:g?-1:0,onItemClick:n,activePath:i,level:r+1})})]})}var E=n(3919),H=n(9471);const M={menuExternalLink:"menuExternalLink_NmtK"};function R(e){let{item:t,onItemClick:n,activePath:a,level:i,index:r,...c}=e;const{href:d,label:u,className:m,autoAddBaseUrl:h}=t,p=(0,l._F)(t,a),x=(0,E.Z)(d);return(0,b.jsx)("li",{className:(0,o.Z)(s.k.docs.docSidebarItemLink,s.k.docs.docSidebarItemLinkLevel(i),"menu__list-item",m),children:(0,b.jsxs)(A.Z,{className:(0,o.Z)("menu__link",!x&&M.menuExternalLink,{"menu__link--active":p}),autoAddBaseUrl:h,"aria-current":p?"page":void 0,to:d,...x&&{onClick:n?()=>n(t):void 0},...c,children:[u,!x&&(0,b.jsx)(H.Z,{})]})},u)}const W={menuHtmlItem:"menuHtmlItem_M9Kj"};function F(e){let{item:t,level:n,index:a}=e;const{value:i,defaultStyle:l,className:r}=t;return(0,b.jsx)("li",{className:(0,o.Z)(s.k.docs.docSidebarItemLink,s.k.docs.docSidebarItemLinkLevel(n),l&&[W.menuHtmlItem,"menu__list-item"],r),dangerouslySetInnerHTML:{__html:i}},a)}function P(e){let{item:t,...n}=e;switch(t.type){case"category":return(0,b.jsx)(w,{item:t,...n});case"html":return(0,b.jsx)(F,{item:t,...n});default:return(0,b.jsx)(R,{item:t,...n})}}function D(e){let{items:t,...n}=e;const a=(0,l.f)(t,n.activePath);return(0,b.jsx)(T,{children:a.map(((e,t)=>(0,b.jsx)(P,{item:e,index:t,...n},t)))})}const V=(0,a.memo)(D),U={menu:"menu_SIkG",menuWithAnnouncementBar:"menuWithAnnouncementBar_GW3s"};function K(e){let{path:t,sidebar:n,className:i}=e;const l=function(){const{isActive:e}=(0,C.nT)(),[t,n]=(0,a.useState)(e);return(0,d.RF)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return(0,b.jsx)("nav",{"aria-label":(0,c.I)({id:"theme.docs.sidebar.navAriaLabel",message:"Docs sidebar",description:"The ARIA label for the sidebar navigation"}),className:(0,o.Z)("menu thin-scrollbar",U.menu,l&&U.menuWithAnnouncementBar,i),children:(0,b.jsx)("ul",{className:(0,o.Z)(s.k.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(V,{items:n,activePath:t,level:1})})})}const Y="sidebar_njMd",z="sidebarWithHideableNavbar_wUlq",G="sidebarHidden_VK0M",O="sidebarLogo_isFc";function q(e){let{path:t,sidebar:n,onCollapse:a,isHidden:i}=e;const{navbar:{hideOnScroll:s},docs:{sidebar:{hideable:l}}}=(0,j.L)();return(0,b.jsxs)("div",{className:(0,o.Z)(Y,s&&z,i&&G),children:[s&&(0,b.jsx)(k.Z,{tabIndex:-1,className:O}),(0,b.jsx)(K,{path:t,sidebar:n}),l&&(0,b.jsx)(g,{onClick:a})]})}const J=a.memo(q);var Q=n(3102),X=n(2961);const $=e=>{let{sidebar:t,path:n}=e;const a=(0,X.e)();return(0,b.jsx)("ul",{className:(0,o.Z)(s.k.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(V,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&a.toggle(),"link"===e.type&&a.toggle()},level:1})})};function ee(e){return(0,b.jsx)(Q.Zo,{component:$,props:e})}const te=a.memo(ee);function ne(e){const t=(0,f.i)(),n="desktop"===t||"ssr"===t,a="mobile"===t;return(0,b.jsxs)(b.Fragment,{children:[n&&(0,b.jsx)(J,{...e}),a&&(0,b.jsx)(te,{...e})]})}const ae={expandButton:"expandButton_TmdG",expandButtonIcon:"expandButtonIcon_i1dp"};function oe(e){let{toggleSidebar:t}=e;return(0,b.jsx)("div",{className:ae.expandButton,title:(0,c.I)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,c.I)({id:"theme.docs.sidebar.expandButtonAriaLabel",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),tabIndex:0,role:"button",onKeyDown:t,onClick:t,children:(0,b.jsx)(_,{className:ae.expandButtonIcon})})}const ie={docSidebarContainer:"docSidebarContainer_YfHR",docSidebarContainerHidden:"docSidebarContainerHidden_DPk8",sidebarViewport:"sidebarViewport_aRkj"};function se(e){let{children:t}=e;const n=(0,r.V)();return(0,b.jsx)(a.Fragment,{children:t},n?.name??"noSidebar")}function le(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:i}=e;const{pathname:l}=(0,x.TH)(),[r,c]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{r&&c(!1),!r&&(0,p.n)()&&c(!0),i((e=>!e))}),[i,r]);return(0,b.jsx)("aside",{className:(0,o.Z)(s.k.docs.docSidebarContainer,ie.docSidebarContainer,n&&ie.docSidebarContainerHidden),onTransitionEnd:e=>{e.currentTarget.classList.contains(ie.docSidebarContainer)&&n&&c(!0)},children:(0,b.jsx)(se,{children:(0,b.jsxs)("div",{className:(0,o.Z)(ie.sidebarViewport,r&&ie.sidebarViewportHidden),children:[(0,b.jsx)(ne,{sidebar:t,path:l,onCollapse:d,isHidden:r}),r&&(0,b.jsx)(oe,{toggleSidebar:d})]})})})}const re={docMainContainer:"docMainContainer_TBSr",docMainContainerEnhanced:"docMainContainerEnhanced_lQrH",docItemWrapperEnhanced:"docItemWrapperEnhanced_JWYK"};function ce(e){let{hiddenSidebarContainer:t,children:n}=e;const a=(0,r.V)();return(0,b.jsx)("main",{className:(0,o.Z)(re.docMainContainer,(t||!a)&&re.docMainContainerEnhanced),children:(0,b.jsx)("div",{className:(0,o.Z)("container padding-top--md padding-bottom--lg",re.docItemWrapper,t&&re.docItemWrapperEnhanced),children:n})})}const de={docRoot:"docRoot_UBD9",docsWrapper:"docsWrapper_hBAB"};function ue(e){let{children:t}=e;const n=(0,r.V)(),[o,i]=(0,a.useState)(!1);return(0,b.jsxs)("div",{className:de.docsWrapper,children:[(0,b.jsx)(h,{}),(0,b.jsxs)("div",{className:de.docRoot,children:[n&&(0,b.jsx)(le,{sidebar:n.items,hiddenSidebarContainer:o,setHiddenSidebarContainer:i}),(0,b.jsx)(ce,{hiddenSidebarContainer:o,children:t})]})]})}var me=n(5658);function be(e){const t=(0,l.SN)(e);if(!t)return(0,b.jsx)(me.Z,{});const{docElement:n,sidebarName:a,sidebarItems:c}=t;return(0,b.jsx)(i.FG,{className:(0,o.Z)(s.k.page.docsDocPage),children:(0,b.jsx)(r.b,{name:a,items:c,children:(0,b.jsx)(ue,{children:n})})})}},5658:(e,t,n)=>{n.d(t,{Z:()=>l});n(7294);var a=n(512),o=n(5999),i=n(2503),s=n(5893);function l(e){let{className:t}=e;return(0,s.jsx)("main",{className:(0,a.Z)("container margin-vert--xl",t),children:(0,s.jsx)("div",{className:"row",children:(0,s.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,s.jsx)(i.Z,{as:"h1",className:"hero__title",children:(0,s.jsx)(o.Z,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}}}]);
\ No newline at end of file
diff --git a/assets/js/a95292b9.5acfbcd2.js b/assets/js/a95292b9.5acfbcd2.js
new file mode 100644
index 0000000000..492fa13b08
--- /dev/null
+++ b/assets/js/a95292b9.5acfbcd2.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5474],{3623:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>s,contentTitle:()=>c,default:()=>l,frontMatter:()=>a,metadata:()=>r,toc:()=>h});var i=o(5893),t=o(1151);const a={sidebar_position:1},c="Developing an ICS consumer chain",r={id:"consumer-development/app-integration",title:"Developing an ICS consumer chain",description:"When developing an ICS consumer chain, besides just focusing on your chain's logic you should aim to allocate time to ensure that your chain is compatible with the ICS protocol.",source:"@site/versioned_docs/version-v4.2.0-docs/consumer-development/app-integration.md",sourceDirName:"consumer-development",slug:"/consumer-development/app-integration",permalink:"/interchain-security/v4.2.0/consumer-development/app-integration",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Power Shaping",permalink:"/interchain-security/v4.2.0/features/power-shaping"},next:{title:"Consumer Chain Governance",permalink:"/interchain-security/v4.2.0/consumer-development/consumer-chain-governance"}},s={},h=[{value:"Basic consumer chain",id:"basic-consumer-chain",level:2},{value:"Democracy consumer chain",id:"democracy-consumer-chain",level:2},{value:"Standalone chain to consumer chain changeover",id:"standalone-chain-to-consumer-chain-changeover",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"developing-an-ics-consumer-chain",children:"Developing an ICS consumer chain"}),"\n",(0,i.jsx)(n.p,{children:"When developing an ICS consumer chain, besides just focusing on your chain's logic you should aim to allocate time to ensure that your chain is compatible with the ICS protocol.\nTo help you on your journey, the ICS team has provided multiple examples of a minimum viable consumer chain applications."}),"\n",(0,i.jsx)(n.h2,{id:"basic-consumer-chain",children:"Basic consumer chain"}),"\n",(0,i.jsxs)(n.p,{children:["The source code for the example app can be found ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/main/app/consumer",children:"here"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Please note that consumer chains do not implement the staking module - the validator set is replicated from the provider, meaning that the provider and the consumer use the same validator set and their stake on the provider directly determines their stake on the consumer.\nAt present there is no opt-in mechanism available, so all validators of the provider must also validate on the provider chain."}),"\n",(0,i.jsxs)(n.p,{children:["Your chain should import the consumer module from ",(0,i.jsx)(n.code,{children:"x/consumer"})," and register it in the correct places in your ",(0,i.jsx)(n.code,{children:"app.go"}),".\nThe ",(0,i.jsx)(n.code,{children:"x/consumer"})," module will allow your chain to communicate with the provider using the ICS protocol. The module handles all IBC communication with the provider, and it is a simple drop-in.\nYou should not need to manage or override any code from the ",(0,i.jsx)(n.code,{children:"x/consumer"})," module."]}),"\n",(0,i.jsx)(n.h2,{id:"democracy-consumer-chain",children:"Democracy consumer chain"}),"\n",(0,i.jsxs)(n.p,{children:["The source code for the example app can be found ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/main/app/consumer-democracy",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This type of consumer chain wraps the basic CosmosSDK ",(0,i.jsx)(n.code,{children:"x/distribution"}),", ",(0,i.jsx)(n.code,{children:"x/staking"})," and ",(0,i.jsx)(n.code,{children:"x/governance"})," modules allowing the consumer chain to perform democratic actions such as participating and voting within the chain's governance system."]}),"\n",(0,i.jsxs)(n.p,{children:["This allows the consumer chain to leverage those modules while also using the ",(0,i.jsx)(n.code,{children:"x/consumer"})," module."]}),"\n",(0,i.jsx)(n.p,{children:'With these modules enabled, the consumer chain can mint its own governance tokens, which can then be delegated to prominent community members which are referred to as "representatives" (as opposed to "validators" in standalone chains). The token may have different use cases besides just voting on governance proposals.'}),"\n",(0,i.jsx)(n.h2,{id:"standalone-chain-to-consumer-chain-changeover",children:"Standalone chain to consumer chain changeover"}),"\n",(0,i.jsxs)(n.p,{children:["See the ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/changeover-procedure",children:"standalone chain to consumer chain changeover guide"})," for more information on how to transition your standalone chain to a consumer chain."]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>r,a:()=>c});var i=o(7294);const t={},a=i.createContext(t);function c(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:c(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/aa5e9d52.e1985f6a.js b/assets/js/aa5e9d52.e1985f6a.js
new file mode 100644
index 0000000000..312af43e02
--- /dev/null
+++ b/assets/js/aa5e9d52.e1985f6a.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4244],{9950:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>h});var s=t(5893),o=t(1151);const a={sidebar_position:11,title:"Standalone to Consumer Changeover"},r=void 0,i={id:"adrs/adr-010-standalone-changeover",title:"Standalone to Consumer Changeover",description:"ADR 010: Standalone to Consumer Changeover",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-010-standalone-changeover.md",sourceDirName:"adrs",slug:"/adrs/adr-010-standalone-changeover",permalink:"/interchain-security/v5.0.0/adrs/adr-010-standalone-changeover",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:11,frontMatter:{sidebar_position:11,title:"Standalone to Consumer Changeover"},sidebar:"tutorialSidebar",previous:{title:"Soft Opt-Out",permalink:"/interchain-security/v5.0.0/adrs/adr-009-soft-opt-out"},next:{title:"Improving testing and increasing confidence",permalink:"/interchain-security/v5.0.0/adrs/adr-011-improving-test-confidence"}},c={},h=[{value:"ADR 010: Standalone to Consumer Changeover",id:"adr-010-standalone-to-consumer-changeover",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Process",id:"process",level:3},{value:"Changes to CCV Protocol",id:"changes-to-ccv-protocol",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"adr-010-standalone-to-consumer-changeover",children:"ADR 010: Standalone to Consumer Changeover"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"6/30/23: Feature completed, first draft of ADR."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsx)(n.p,{children:"Implemented"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://github.com/Stride-Labs/stride",children:"Stride"}),' will be the first consumer to "changeover" from a standalone cosmos blockchain, to a consumer chain secured by the Cosmos Hub. This document will outline the changes made to the replicated security protocol to support this changeover process.']}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsx)(n.h3,{id:"process",children:"Process"}),"\n",(0,s.jsx)(n.p,{children:'Prior to the changeover, the consumer chain will have an existing staking keeper and validator set, these may be referred to as the "standalone staking keeper" and "standalone validator set" respectively.'}),"\n",(0,s.jsx)(n.p,{children:"The first step in the changeover process is to submit a ConsumerAdditionProposal. If the proposal passes, the provider will create a new IBC client for the consumer at spawn time, with the provider's validator set. A consumer genesis will also be constructed by the provider for validators to query. Within this consumer genesis contains the initial validator set for the consumer to apply after the changeover."}),"\n",(0,s.jsx)(n.p,{children:"Next, the standalone consumer chain runs an upgrade which adds the CCV module, and is properly setup to execute changeover logic."}),"\n",(0,s.jsx)(n.p,{children:"The consumer upgrade height must be reached after the provider has created the new IBC client. Any replicated security validators who will run the consumer, but are not a part of the sovereign validator set, must sync up a full node before the consumer upgrade height is reached. The disk state of said full node will be used to run the consumer chain after the changeover has completed."}),"\n",(0,s.jsxs)(n.p,{children:["The meat of the changeover logic is that the consumer chain validator set is updated to that which was specified by the provider via the queried consumer genesis. Validators which were a part of the old set, but not the new set, are given zero voting power. Once these validator updates are given to Comet, the set is committed, and in effect 2 blocks later (see ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/f10e780df182158d95a30f7cf94588b2d0479309/x/ccv/consumer/keeper/changeover.go#L19",children:"FirstConsumerHeight"}),")."]}),"\n",(0,s.jsx)(n.p,{children:"A relayer then establishes the new IBC connection between the provider and consumer. The CCV channel handshake is started on top of this connection. Once the CCV channel is established and VSC packets are being relayed, the consumer chain is secured by the provider."}),"\n",(0,s.jsx)(n.h3,{id:"changes-to-ccv-protocol",children:"Changes to CCV Protocol"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Consumer Genesis state is updated to include a ",(0,s.jsx)(n.code,{children:"PreCCV"})," boolean. When this boolean is set true in the consumer genesis JSON, ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/f10e780df182158d95a30f7cf94588b2d0479309/x/ccv/consumer/keeper/changeover.go",children:"special logic"})," is executed on InitGenesis to trigger the changeover process on the consumer's first endblocker after the upgrade which adds the CCV module. Note that InitGenesis is not automatically called during chain upgrades, so the consumer must manually call the consumer's InitGenesis method in an upgrade handler."]}),"\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})," type is updated to include a ",(0,s.jsx)(n.code,{children:"DistributionTransmissionChannel"})," field. This field allows the consumer to use an existing IBC transfer channel to send rewards as a part of the CCV protocol. Consumers that're not changing over from a standalone chain will leave this field blank, indicating that a new transfer channel should be created on top of the same connection as the CCV channel."]}),"\n",(0,s.jsx)(n.li,{children:"The CCV consumer keeper is updated to contain an optional reference to the standalone staking keeper. The standalone staking keeper is used to slash for infractions that happened before the changeover was completed. Ie. any infraction from a block height before the changeover, that is submitted after the changeover, will call the standalone staking keeper's slash method. Note that a changeover consumer's standalone staking keeper becomes a democracy module keeper, so it is possible for a governance token to be slashed."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Existing cosmos chains are now able to onboard over to a consumer chain secured by a provider."}),"\n",(0,s.jsx)(n.li,{children:"The previous staking keepers for such chains can be transitioned to democracy staking module keepers."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The delineation between different types of consumers in this repo becomes less clear. Ie. there is code in the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/f10e780df182158d95a30f7cf94588b2d0479309/app/consumer-democracy/app.go",children:"democracy consumer's app.go"})," that only applies to a previously standalone chain, but that file also serves as the base for a normal democracy consumer launched with RS from genesis."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["EPIC: Standalone to Consumer Changeover ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/756",children:"#756"})]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Changeover diagram from Stride"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>i,a:()=>r});var s=t(7294);const o={},a=s.createContext(o);function r(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/ab367a53.c91aaa68.js b/assets/js/ab367a53.c91aaa68.js
new file mode 100644
index 0000000000..8b58cb5500
--- /dev/null
+++ b/assets/js/ab367a53.c91aaa68.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3784],{5003:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v4.2.0-docs","label":"v4.2.0","banner":null,"badge":true,"noIndex":false,"className":"docs-version-v4.2.0-docs","isLast":true,"docsSidebars":{"tutorialSidebar":[{"type":"link","label":"Interchain Security Docs","href":"/interchain-security/v4.2.0/","docId":"index","unlisted":false},{"type":"category","label":"Introduction","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Overview","href":"/interchain-security/v4.2.0/introduction/overview","docId":"introduction/overview","unlisted":false},{"type":"link","label":"Terminology","href":"/interchain-security/v4.2.0/introduction/terminology","docId":"introduction/terminology","unlisted":false},{"type":"link","label":"Interchain Security Parameters","href":"/interchain-security/v4.2.0/introduction/params","docId":"introduction/params","unlisted":false},{"type":"link","label":"Technical Specification","href":"/interchain-security/v4.2.0/introduction/technical-specification","docId":"introduction/technical-specification","unlisted":false}]},{"type":"category","label":"Features","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Key Assignment","href":"/interchain-security/v4.2.0/features/key-assignment","docId":"features/key-assignment","unlisted":false},{"type":"link","label":"Reward Distribution","href":"/interchain-security/v4.2.0/features/reward-distribution","docId":"features/reward-distribution","unlisted":false},{"type":"link","label":"ICS Provider Proposals","href":"/interchain-security/v4.2.0/features/proposals","docId":"features/proposals","unlisted":false},{"type":"link","label":"Consumer Initiated Slashing","href":"/interchain-security/v4.2.0/features/slashing","docId":"features/slashing","unlisted":false},{"type":"link","label":"Partial Set Security","href":"/interchain-security/v4.2.0/features/partial-set-security","docId":"features/partial-set-security","unlisted":false},{"type":"link","label":"Power Shaping","href":"/interchain-security/v4.2.0/features/power-shaping","docId":"features/power-shaping","unlisted":false}]},{"type":"category","label":"Consumer Guide","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Developing an ICS consumer chain","href":"/interchain-security/v4.2.0/consumer-development/app-integration","docId":"consumer-development/app-integration","unlisted":false},{"type":"link","label":"Consumer Chain Governance","href":"/interchain-security/v4.2.0/consumer-development/consumer-chain-governance","docId":"consumer-development/consumer-chain-governance","unlisted":false},{"type":"link","label":"Onboarding Checklist","href":"/interchain-security/v4.2.0/consumer-development/onboarding","docId":"consumer-development/onboarding","unlisted":false},{"type":"link","label":"Offboarding Checklist","href":"/interchain-security/v4.2.0/consumer-development/offboarding","docId":"consumer-development/offboarding","unlisted":false},{"type":"link","label":"Changeover Procedure","href":"/interchain-security/v4.2.0/consumer-development/changeover-procedure","docId":"consumer-development/changeover-procedure","unlisted":false},{"type":"link","label":"Consumer Genesis Transformation","href":"/interchain-security/v4.2.0/consumer-development/consumer-genesis-transformation","docId":"consumer-development/consumer-genesis-transformation","unlisted":false}]},{"type":"category","label":"Validators Guide","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Overview","href":"/interchain-security/v4.2.0/validators/overview","docId":"validators/overview","unlisted":false},{"type":"link","label":"Joining Interchain Security testnet","href":"/interchain-security/v4.2.0/validators/joining-testnet","docId":"validators/joining-testnet","unlisted":false},{"type":"link","label":"Withdrawing consumer chain validator rewards","href":"/interchain-security/v4.2.0/validators/withdraw_rewards","docId":"validators/withdraw_rewards","unlisted":false},{"type":"link","label":"Validator Instructions for Changeover Procedure","href":"/interchain-security/v4.2.0/validators/changeover-procedure","docId":"validators/changeover-procedure","unlisted":false},{"type":"link","label":"Joining Neutron","href":"/interchain-security/v4.2.0/validators/joining-neutron","docId":"validators/joining-neutron","unlisted":false},{"type":"link","label":"Joining Stride","href":"/interchain-security/v4.2.0/validators/joining-stride","docId":"validators/joining-stride","unlisted":false},{"type":"link","label":"Partial Set Security","href":"/interchain-security/v4.2.0/validators/partial-set-security-for-validators","docId":"validators/partial-set-security-for-validators","unlisted":false}]},{"type":"link","label":"Frequently Asked Questions","href":"/interchain-security/v4.2.0/faq","docId":"frequently-asked-questions","unlisted":false},{"type":"category","label":"ADRs","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"ADRs","href":"/interchain-security/v4.2.0/adrs/intro","docId":"adrs/intro","unlisted":false},{"type":"link","label":"ADR Template","href":"/interchain-security/v4.2.0/adrs/adr-004-denom-dos-fixes","docId":"adrs/adr-004-denom-dos-fixes","unlisted":false},{"type":"link","label":"ADR Template","href":"/interchain-security/v4.2.0/adrs/adr-007-pause-unbonding-on-eqv-prop","docId":"adrs/adr-007-pause-unbonding-on-eqv-prop","unlisted":false},{"type":"link","label":"ADR Template","href":"/interchain-security/v4.2.0/adrs/adr-template","docId":"adrs/adr-template","unlisted":false},{"type":"link","label":"Key Assignment","href":"/interchain-security/v4.2.0/adrs/adr-001-key-assignment","docId":"adrs/adr-001-key-assignment","unlisted":false},{"type":"link","label":"Jail Throttling","href":"/interchain-security/v4.2.0/adrs/adr-002-throttle","docId":"adrs/adr-002-throttle","unlisted":false},{"type":"link","label":"Equivocation governance proposal","href":"/interchain-security/v4.2.0/adrs/adr-003-equivocation-gov-proposal","docId":"adrs/adr-003-equivocation-gov-proposal","unlisted":false},{"type":"link","label":"Cryptographic verification of equivocation evidence","href":"/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification","docId":"adrs/adr-005-cryptographic-equivocation-verification","unlisted":false},{"type":"link","label":"Throttle with retries","href":"/interchain-security/v4.2.0/adrs/adr-008-throttle-retries","docId":"adrs/adr-008-throttle-retries","unlisted":false},{"type":"link","label":"Soft Opt-Out","href":"/interchain-security/v4.2.0/adrs/adr-009-soft-opt-out","docId":"adrs/adr-009-soft-opt-out","unlisted":false},{"type":"link","label":"Standalone to Consumer Changeover","href":"/interchain-security/v4.2.0/adrs/adr-010-standalone-changeover","docId":"adrs/adr-010-standalone-changeover","unlisted":false},{"type":"link","label":"Improving testing and increasing confidence","href":"/interchain-security/v4.2.0/adrs/adr-011-improving-test-confidence","docId":"adrs/adr-011-improving-test-confidence","unlisted":false},{"type":"link","label":"Separate Releasing","href":"/interchain-security/v4.2.0/adrs/adr-012-separate-releasing","docId":"adrs/adr-012-separate-releasing","unlisted":false},{"type":"link","label":"Slashing on the provider for consumer equivocation","href":"/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing","docId":"adrs/adr-013-equivocation-slashing","unlisted":false},{"type":"link","label":"Epochs","href":"/interchain-security/v4.2.0/adrs/adr-014-epochs","docId":"adrs/adr-014-epochs","unlisted":false},{"type":"link","label":"Partial Set Security","href":"/interchain-security/v4.2.0/adrs/adr-015-partial-set-security","docId":"adrs/adr-015-partial-set-security","unlisted":false}]}]},"docs":{"adrs/adr-001-key-assignment":{"id":"adrs/adr-001-key-assignment","title":"Key Assignment","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-002-throttle":{"id":"adrs/adr-002-throttle","title":"Jail Throttling","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-003-equivocation-gov-proposal":{"id":"adrs/adr-003-equivocation-gov-proposal","title":"Equivocation governance proposal","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-004-denom-dos-fixes":{"id":"adrs/adr-004-denom-dos-fixes","title":"ADR Template","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-005-cryptographic-equivocation-verification":{"id":"adrs/adr-005-cryptographic-equivocation-verification","title":"Cryptographic verification of equivocation evidence","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-007-pause-unbonding-on-eqv-prop":{"id":"adrs/adr-007-pause-unbonding-on-eqv-prop","title":"ADR Template","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-008-throttle-retries":{"id":"adrs/adr-008-throttle-retries","title":"Throttle with retries","description":"ADR 008: Throttle with retries","sidebar":"tutorialSidebar"},"adrs/adr-009-soft-opt-out":{"id":"adrs/adr-009-soft-opt-out","title":"Soft Opt-Out","description":"ADR 009: Soft Opt-Out","sidebar":"tutorialSidebar"},"adrs/adr-010-standalone-changeover":{"id":"adrs/adr-010-standalone-changeover","title":"Standalone to Consumer Changeover","description":"ADR 010: Standalone to Consumer Changeover","sidebar":"tutorialSidebar"},"adrs/adr-011-improving-test-confidence":{"id":"adrs/adr-011-improving-test-confidence","title":"Improving testing and increasing confidence","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-012-separate-releasing":{"id":"adrs/adr-012-separate-releasing","title":"Separate Releasing","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-013-equivocation-slashing":{"id":"adrs/adr-013-equivocation-slashing","title":"Slashing on the provider for consumer equivocation","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-014-epochs":{"id":"adrs/adr-014-epochs","title":"Epochs","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-015-partial-set-security":{"id":"adrs/adr-015-partial-set-security","title":"Partial Set Security","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/adr-template":{"id":"adrs/adr-template","title":"ADR Template","description":"Changelog","sidebar":"tutorialSidebar"},"adrs/intro":{"id":"adrs/intro","title":"ADRs","description":"This is a location to record all high-level architecture decisions in the Interchain Security project.","sidebar":"tutorialSidebar"},"consumer-development/app-integration":{"id":"consumer-development/app-integration","title":"Developing an ICS consumer chain","description":"When developing an ICS consumer chain, besides just focusing on your chain\'s logic you should aim to allocate time to ensure that your chain is compatible with the ICS protocol.","sidebar":"tutorialSidebar"},"consumer-development/changeover-procedure":{"id":"consumer-development/changeover-procedure","title":"Changeover Procedure","description":"Chains that were not initially launched as consumers of replicated security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the changeover procedure and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain.","sidebar":"tutorialSidebar"},"consumer-development/consumer-chain-governance":{"id":"consumer-development/consumer-chain-governance","title":"Consumer Chain Governance","description":"Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We\'ll cover what these are in the \\"Whitelist\\" section below.","sidebar":"tutorialSidebar"},"consumer-development/consumer-genesis-transformation":{"id":"consumer-development/consumer-genesis-transformation","title":"Consumer Genesis Transformation","description":"Preparing a consumer chain for onboarding requires some information explaining how to run your chain. This includes a genesis file with CCV data where the CCV data is exported from the provider chain and added to the consumers genesis file (for more details check the documentation on Onboarding and Changeover).","sidebar":"tutorialSidebar"},"consumer-development/offboarding":{"id":"consumer-development/offboarding","title":"Offboarding Checklist","description":"To offboard a consumer chain simply submit a ConsumerRemovalProposal governance proposal listing a stop_time. After stop time passes, the provider chain will remove the chain from the ICS protocol (it will stop sending validator set updates).","sidebar":"tutorialSidebar"},"consumer-development/onboarding":{"id":"consumer-development/onboarding","title":"Onboarding Checklist","description":"The following checklists will aid in onboarding a new consumer chain to interchain security.","sidebar":"tutorialSidebar"},"features/key-assignment":{"id":"features/key-assignment","title":"Key Assignment","description":"Key Assignment (aka. as key delegation) allows validator operators to use different consensus keys for each consumer chain validator node that they operate.","sidebar":"tutorialSidebar"},"features/partial-set-security":{"id":"features/partial-set-security","title":"Partial Set Security","description":"Partial Set Security (PSS) allows consumer chains to leverage only a subset of validators from the provider chain, which offers more flexibility than the traditional Replicated Security model. By introducing the top_N parameter, each consumer chain can choose the extent of security needed:","sidebar":"tutorialSidebar"},"features/power-shaping":{"id":"features/power-shaping","title":"Power Shaping","description":"To give consumer chains more flexibility in choosing their validator set, Interchain Security offers","sidebar":"tutorialSidebar"},"features/proposals":{"id":"features/proposals","title":"ICS Provider Proposals","description":"Interchain security module introduces 3 new proposal types to the provider.","sidebar":"tutorialSidebar"},"features/reward-distribution":{"id":"features/reward-distribution","title":"Reward Distribution","description":"Sending and distributing rewards from consumer chains to the provider chain is handled by the Reward Distribution sub-protocol.","sidebar":"tutorialSidebar"},"features/slashing":{"id":"features/slashing","title":"Consumer Initiated Slashing","description":"A consumer chain is essentially a regular Cosmos-SDK based chain that uses the Interchain Security module to achieve economic security by stake deposited on the provider chain, instead of its own chain.","sidebar":"tutorialSidebar"},"frequently-asked-questions":{"id":"frequently-asked-questions","title":"Frequently Asked Questions","description":"What is a consumer chain?","sidebar":"tutorialSidebar"},"index":{"id":"index","title":"Interchain Security Docs","description":"Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains.","sidebar":"tutorialSidebar"},"introduction/overview":{"id":"introduction/overview","title":"Overview","description":"Interchain Security is an open sourced IBC application which allows cosmos blockchains to lease their proof-of-stake security to one another.","sidebar":"tutorialSidebar"},"introduction/params":{"id":"introduction/params","title":"Interchain Security Parameters","description":"The parameters necessary for Interchain Security (ICS) are defined in","sidebar":"tutorialSidebar"},"introduction/technical-specification":{"id":"introduction/technical-specification","title":"Technical Specification","description":"For a technical deep dive into the replicated security protocol, see the specification.","sidebar":"tutorialSidebar"},"introduction/terminology":{"id":"introduction/terminology","title":"Terminology","description":"You may have heard of one or multiple buzzwords thrown around in the cosmos and wider crypto ecosystem such shared security, interchain security, replicated security, cross chain validation, and mesh security. These terms will be clarified below, before diving into any introductions.","sidebar":"tutorialSidebar"},"validators/changeover-procedure":{"id":"validators/changeover-procedure","title":"Validator Instructions for Changeover Procedure","description":"More details available in Changeover Procedure documentation.","sidebar":"tutorialSidebar"},"validators/joining-neutron":{"id":"validators/joining-neutron","title":"Joining Neutron","description":"Neutron is the first consumer chain to implement ICS.","sidebar":"tutorialSidebar"},"validators/joining-stride":{"id":"validators/joining-stride","title":"Joining Stride","description":"Stride is the first consumer chain to perform the standalone to consumer changeover procedure and transition from a standalone validator set to using cosmoshub-4 validator set.","sidebar":"tutorialSidebar"},"validators/joining-testnet":{"id":"validators/joining-testnet","title":"Joining Interchain Security testnet","description":"Introduction","sidebar":"tutorialSidebar"},"validators/overview":{"id":"validators/overview","title":"Overview","description":"We advise that you join the Replicated Security testnet to gain hands-on experience with running consumer chains.","sidebar":"tutorialSidebar"},"validators/partial-set-security-for-validators":{"id":"validators/partial-set-security-for-validators","title":"Partial Set Security","description":"Partial Set Security allows consumer chains to join as Opt-In or Top N.","sidebar":"tutorialSidebar"},"validators/withdraw_rewards":{"id":"validators/withdraw_rewards","title":"Withdrawing consumer chain validator rewards","description":"Here are example steps for withdrawing rewards from consumer chains in the provider chain","sidebar":"tutorialSidebar"}}}')}}]);
\ No newline at end of file
diff --git a/assets/js/ac4ec955.d4051eb8.js b/assets/js/ac4ec955.d4051eb8.js
new file mode 100644
index 0000000000..f819ba1855
--- /dev/null
+++ b/assets/js/ac4ec955.d4051eb8.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3297],{6114:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>d,toc:()=>l});var s=i(5893),o=i(1151);const r={sidebar_position:2,title:"Denom DOS fixes"},t="ADR 004: Denom DOS fixes",d={id:"adrs/adr-004-denom-dos-fixes",title:"Denom DOS fixes",description:"Changelog",source:"@site/docs/adrs/adr-004-denom-dos-fixes.md",sourceDirName:"adrs",slug:"/adrs/adr-004-denom-dos-fixes",permalink:"/interchain-security/adrs/adr-004-denom-dos-fixes",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"Denom DOS fixes"},sidebar:"tutorialSidebar",previous:{title:"Overview",permalink:"/interchain-security/adrs/intro"},next:{title:"Pause validator unbonding during equivocation proposal",permalink:"/interchain-security/adrs/adr-007-pause-unbonding-on-eqv-prop"}},a={},l=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Provider",id:"provider",level:3},{value:"Consumer",id:"consumer",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3}];function c(e){const n={h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"adr-004-denom-dos-fixes",children:"ADR 004: Denom DOS fixes"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"5/9/2023: ADR created"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsx)(n.p,{children:"Accepted"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsx)(n.p,{children:"The provider and consumer modules are vulnerable to similar issues involving an attacker sending millions of denoms to certain addresses and causing the chain to halt. This ADR outlines both fixes since they are similar. Both fixes involve processing only denoms that are on a whitelist to avoid iterating over millions of junk denoms but have different requirements and are implemented in different ways."}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsx)(n.h3,{id:"provider",children:"Provider"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Put the distribution module's FeePoolAddress back on the blocklist so that it cannot receive funds from users."}),"\n",(0,s.jsx)(n.li,{children:"Create a new address called ConsumerRewardPool and unblock it, allowing funds to be sent to it."}),"\n",(0,s.jsx)(n.li,{children:"Create a set of strings in the store for allowed ConsumerRewardDenoms."}),"\n",(0,s.jsx)(n.li,{children:"Create an endpoint called RegisterConsumerRewardDenom which deducts a fee from the sender's account, sends it to the community pool and adds a string to the ConsumerRewardDenoms set."}),"\n",(0,s.jsx)(n.li,{children:"Create a parameter called ConsumerRewardDenomRegistrationFee which determines the fee which is charged to register a consumer reward denom in the step above."}),"\n",(0,s.jsxs)(n.li,{children:["Create a function called TransferRewardsToFeeCollector which gets the entire ConsumerRewardDenoms set from the store, iterates over it, and for each entry:","\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Gets the balance of this denom for the ConsumerRewardPool account"}),"\n",(0,s.jsx)(n.li,{children:"Sends the entire balance out to the FeePoolAddress using SendCoinsFromModuleToModule which is not affected by the blocklist."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:"Run TransferRewardsToFeeCollector in the endblock"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Now, nobody can send millions of junk denoms to the FeePoolAddress because it is on the block list. If they send millions of junk denoms to the ConsumerRewardPool, this does not matter because all balances are not iterated over, only those which are in the ConsumerRewardDenoms set."}),"\n",(0,s.jsx)(n.p,{children:"We also add a new tx: register-consumer-reward-denom, and a new query: registered-consumer-reward-denoms"}),"\n",(0,s.jsx)(n.h3,{id:"consumer",children:"Consumer"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Create a new param RewardDenoms with a list of strings"}),"\n",(0,s.jsx)(n.li,{children:"Create a new param ProviderRewardDenoms with a list of strings"}),"\n",(0,s.jsx)(n.li,{children:"Create a function AllowedRewardDenoms which iterates over ProviderRewardDenoms and converts each denom to its ibc-prefixed denom using the provider chain's ibc channel information, then concatenates the RewardDenoms list and returns the combined list of allowed denoms."}),"\n",(0,s.jsx)(n.li,{children:"In SendRewardsToProvider, instead of iterating over the balances of all denoms in the ToSendToProvider address, iterate over AllowedRewardDenoms"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Now, if somebody sends millions of junk denoms to ToSendToProvider, they will not be iterated over. Only the RewardDenoms and ProviderRewardDenoms will be iterated over. Since we do not require this feature to be permissionless on the consumer, the registration fee process is not needed."}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Denom DOS is no longer possible on either provider or consumer."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Consumer chain teams must pay a fee to register a denom for distribution on the provider, and add some extra parameters in their genesis file."}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>d,a:()=>t});var s=i(7294);const o={},r=s.createContext(o);function t(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:t(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/ae015673.fbf9e71e.js b/assets/js/ae015673.fbf9e71e.js
new file mode 100644
index 0000000000..4dbeab3a6f
--- /dev/null
+++ b/assets/js/ae015673.fbf9e71e.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2108],{2165:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var i=t(5893),r=t(1151);const s={sidebar_position:6},o="Joining Stride",a={id:"validators/joining-stride",title:"Joining Stride",description:"Stride is the first consumer chain to perform the standalone to consumer changeover procedure and transition from a standalone validator set to using cosmoshub-4 validator set.",source:"@site/versioned_docs/version-v4.2.0-docs/validators/joining-stride.md",sourceDirName:"validators",slug:"/validators/joining-stride",permalink:"/interchain-security/v4.2.0/validators/joining-stride",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Joining Neutron",permalink:"/interchain-security/v4.2.0/validators/joining-neutron"},next:{title:"Partial Set Security",permalink:"/interchain-security/v4.2.0/validators/partial-set-security-for-validators"}},c={},d=[{value:"Note",id:"note",level:2},{value:"Resources",id:"resources",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"joining-stride",children:"Joining Stride"}),"\n",(0,i.jsxs)(n.p,{children:["Stride is the first consumer chain to perform the standalone to consumer changeover procedure and transition from a standalone validator set to using ",(0,i.jsx)(n.code,{children:"cosmoshub-4"})," validator set."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"stride-1"})," network (mainnet) will perform a software upgrade and at height ",(0,i.jsx)(n.code,{children:"4616678"})," that will transition the network to using the Cosmos Hub's (",(0,i.jsx)(n.code,{children:"cosmoshub-4"}),") validator set."]}),"\n",(0,i.jsxs)(n.p,{children:["You can find instructions about the Stride consumer chain launch and joining the mainnet ",(0,i.jsx)(n.a,{href:"https://github.com/Stride-Labs/mainnet/tree/main/ics-instructions",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This ",(0,i.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Excalidraw graphic"})," explains the timeline of Stride's changeover procedure."]}),"\n",(0,i.jsx)(n.h2,{id:"note",children:"Note"}),"\n",(0,i.jsxs)(n.p,{children:["Stride re-uses an existing ",(0,i.jsx)(n.code,{children:"transfer"})," channel to send consumer rewards to the provider chain, in order to preserve existing transfer IBC denom between ",(0,i.jsx)(n.code,{children:"stride-1"})," and ",(0,i.jsx)(n.code,{children:"cosmoshub-4"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"resources",children:"Resources"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.stride.zone/docs",children:"Stride docs"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Changeover procedure timeline"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/Stride-Labs/mainnet/tree/main/ics-instructions",children:"Changeover upgrade docs"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>o});var i=t(7294);const r={},s=i.createContext(r);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/ae63551b.40097d02.js b/assets/js/ae63551b.40097d02.js
new file mode 100644
index 0000000000..2fc88b5029
--- /dev/null
+++ b/assets/js/ae63551b.40097d02.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5056],{6873:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var i=t(5893),r=t(1151);const s={sidebar_position:6},o="Joining Stride",a={id:"validators/joining-stride",title:"Joining Stride",description:"Stride is the first consumer chain to perform the standalone to consumer changeover procedure and transition from a standalone validator set to using cosmoshub-4 validator set.",source:"@site/docs/validators/joining-stride.md",sourceDirName:"validators",slug:"/validators/joining-stride",permalink:"/interchain-security/validators/joining-stride",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Joining Neutron",permalink:"/interchain-security/validators/joining-neutron"},next:{title:"Partial Set Security",permalink:"/interchain-security/validators/partial-set-security-for-validators"}},c={},d=[{value:"Note",id:"note",level:2},{value:"Resources",id:"resources",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"joining-stride",children:"Joining Stride"}),"\n",(0,i.jsxs)(n.p,{children:["Stride is the first consumer chain to perform the standalone to consumer changeover procedure and transition from a standalone validator set to using ",(0,i.jsx)(n.code,{children:"cosmoshub-4"})," validator set."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"stride-1"})," network (mainnet) will perform a software upgrade and at height ",(0,i.jsx)(n.code,{children:"4616678"})," that will transition the network to using the Cosmos Hub's (",(0,i.jsx)(n.code,{children:"cosmoshub-4"}),") validator set."]}),"\n",(0,i.jsxs)(n.p,{children:["You can find instructions about the Stride consumer chain launch and joining the mainnet ",(0,i.jsx)(n.a,{href:"https://github.com/Stride-Labs/mainnet/tree/main/ics-instructions",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This ",(0,i.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Excalidraw graphic"})," explains the timeline of Stride's changeover procedure."]}),"\n",(0,i.jsx)(n.h2,{id:"note",children:"Note"}),"\n",(0,i.jsxs)(n.p,{children:["Stride re-uses an existing ",(0,i.jsx)(n.code,{children:"transfer"})," channel to send consumer rewards to the provider chain, in order to preserve existing transfer IBC denom between ",(0,i.jsx)(n.code,{children:"stride-1"})," and ",(0,i.jsx)(n.code,{children:"cosmoshub-4"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"resources",children:"Resources"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.stride.zone/docs",children:"Stride docs"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Changeover procedure timeline"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/Stride-Labs/mainnet/tree/main/ics-instructions",children:"Changeover upgrade docs"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>o});var i=t(7294);const r={},s=i.createContext(r);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/af3e09f2.5eacecf7.js b/assets/js/af3e09f2.5eacecf7.js
new file mode 100644
index 0000000000..b9e249de3a
--- /dev/null
+++ b/assets/js/af3e09f2.5eacecf7.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4440],{8501:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var i=s(5893),o=s(1151);const r={sidebar_position:13,title:"Separate Releasing"},t="ADR 012: Separate Releasing",a={id:"adrs/adr-012-separate-releasing",title:"Separate Releasing",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-012-separate-releasing.md",sourceDirName:"adrs",slug:"/adrs/adr-012-separate-releasing",permalink:"/interchain-security/v4.2.0/adrs/adr-012-separate-releasing",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:13,frontMatter:{sidebar_position:13,title:"Separate Releasing"},sidebar:"tutorialSidebar",previous:{title:"Improving testing and increasing confidence",permalink:"/interchain-security/v4.2.0/adrs/adr-011-improving-test-confidence"},next:{title:"Slashing on the provider for consumer equivocation",permalink:"/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing"}},l={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Spike results",id:"spike-results",level:3},{value:"Why go.mod split is not the way to go",id:"why-gomod-split-is-not-the-way-to-go",level:3},{value:"Why separate repos is cool but also not the way to go",id:"why-separate-repos-is-cool-but-also-not-the-way-to-go",level:3},{value:"Decision",id:"decision",level:2},{value:"Example release flow",id:"example-release-flow",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function c(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-012-separate-releasing",children:"ADR 012: Separate Releasing"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[8/18/22,": Initial draft of idea in ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801",children:"#801"})]}),"\n",(0,i.jsxs)(n.li,{children:[8/22/22,": Put idea in this ADR"]}),"\n",(0,i.jsxs)(n.li,{children:[.05,": Reject this ADR"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Rejected"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.h3,{id:"spike-results",children:"Spike results"}),"\n",(0,i.jsxs)(n.p,{children:["I explored the idea of ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801",children:"#801"})," with this ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/shawn%2Fgo-mod-split-aug-spike",children:"spike branch"}),". Here's my conclusions:"]}),"\n",(0,i.jsxs)(n.p,{children:["Splitting this repo to have multiple go.mods is possible. However there are various intricacies involved in decoupling the package hierarchy to have ",(0,i.jsx)(n.code,{children:"x/ccv/types"})," as the lowest level dep, with ",(0,i.jsx)(n.code,{children:"x/ccv/consumer"})," and ",(0,i.jsx)(n.code,{children:"x/ccv/provider"})," being one dep layer above, with high-level tests depending on all three of the mentioned packages. I'd estimate this decoupling would take 2-5 workdays to finish, and require significant review effort."]}),"\n",(0,i.jsx)(n.h3,{id:"why-gomod-split-is-not-the-way-to-go",children:"Why go.mod split is not the way to go"}),"\n",(0,i.jsxs)(n.p,{children:["Let's take a step back and remember the issue we're trying to solve - ",(0,i.jsx)(n.strong,{children:"We need a clean way to decouple semver/releasing for the consumer and provider modules"}),". After more consideration, splitting up go.mods gives us little benefit in achieving this. Reasons:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The ",(0,i.jsx)(n.code,{children:"go.mod"})," dependency system is tied to git tags for the entire repo (ex: ",(0,i.jsx)(n.code,{children:"require github.com/cometbft/cometbft v0.37.2"})," refers to a historical tag for the entire cometbft repo)."]}),"\n",(0,i.jsx)(n.li,{children:"It'd be an odd dev experience to allow modules to reference past releases of other modules in the same repo. When would we ever want the consumer module to reference a past release of the types module for example?"}),"\n",(0,i.jsxs)(n.li,{children:["If we allow for ",(0,i.jsx)(n.code,{children:"go.mod"})," replace statements to build from local source code, why split up the package deps at all?"]}),"\n",(0,i.jsxs)(n.li,{children:["Splitting go.mods adds a bunch of complexity with ",(0,i.jsx)(n.code,{children:"go.work"})," files and all that shiz. VSCode does not play well with multiple module repos either."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"why-separate-repos-is-cool-but-also-not-the-way-to-go",children:"Why separate repos is cool but also not the way to go"}),"\n",(0,i.jsxs)(n.p,{children:["All this considered, the cleanest solution to decoupling semver/releasing for the consumer and provider modules would be to have multiple repos, each with their own go.mod (3-4 repos total including high level tests). With this scheme we could separately tag each repo as changes are merged, they could share some code from ",(0,i.jsx)(n.code,{children:"types"})," being an external dep, etc."]}),"\n",(0,i.jsx)(n.p,{children:"I don't think any of us want to split up the monorepo, that's a lot of work and seems like bikeshedding. There's another solution that's very simple.."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsxs)(n.p,{children:["Slightly adapting ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/cca008d856e3ffc60ec1a486871d0faa702abe26/CONTRIBUTING.md#semantic-versioning",children:"the current semver ruleset"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"A library API breaking change to EITHER the provider or consumer module will result in an increase of the MAJOR version number for BOTH modules (X.y.z-provider AND X.y.z-consumer)."}),"\n",(0,i.jsx)(n.li,{children:"A state breaking change (change requiring coordinated upgrade and/or state migration) will result in an increase of the MINOR version number for the AFFECTED module(s) (x.Y.z-provider AND/OR x.Y.z-consumer)."}),"\n",(0,i.jsx)(n.li,{children:"Any other changes (including node API breaking changes) will result in an increase of the PATCH version number for the AFFECTED module(s) (x.y.Z-provider AND/OR x.y.Z-consumer)."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"example-release-flow",children:"Example release flow"}),"\n",(0,i.jsxs)(n.p,{children:["We upgrade ",(0,i.jsx)(n.code,{children:"main"})," to use a new version of SDK. This is a major version bump, triggering a new release for both the provider and consumer modules, ",(0,i.jsx)(n.code,{children:"v5.0.0-provider"})," and ",(0,i.jsx)(n.code,{children:"v5.0.0-consumer"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["A state breaking change is merged to ",(0,i.jsx)(n.code,{children:"main"})," for the provider module. We release only a ",(0,i.jsx)(n.code,{children:"v5.1.0-provider"})," off main."]}),"\n",(0,i.jsxs)(n.li,{children:["Another state breaking change is merged to ",(0,i.jsx)(n.code,{children:"main"})," for the provider module. We release only a ",(0,i.jsx)(n.code,{children:"v5.2.0-provider"})," off main."]}),"\n",(0,i.jsxs)(n.li,{children:["At this point, the latest consumer version is still ",(0,i.jsx)(n.code,{children:"v5.0.0-consumer"}),". We now merge a state breaking change for the consumer module to ",(0,i.jsx)(n.code,{children:"main"}),", and consequently release ",(0,i.jsx)(n.code,{children:"v5.1.0-consumer"}),". Note that ",(0,i.jsx)(n.code,{children:"v5.1.0-consumer"})," is tagged off a LATER commit from main than ",(0,i.jsx)(n.code,{children:"v5.2.0-provider"}),". This is fine, as the consumer module should not be affected by the provider module's state breaking changes."]}),"\n",(0,i.jsxs)(n.li,{children:["Once either module sees a library API breaking change, we bump the major version for both modules. For example, we merge a library API breaking change to ",(0,i.jsx)(n.code,{children:"main"})," for the provider module. We release ",(0,i.jsx)(n.code,{children:"v6.0.0-provider"})," and ",(0,i.jsx)(n.code,{children:"v6.0.0-consumer"})," off main. Note that most often, a library API breaking change will affect both modules simultaneously (example being bumping sdk version)."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Consumer repos have clear communication of what tagged versions are relevant to them. Consumer devs should know to never reference an ICS version that starts with ",(0,i.jsx)(n.code,{children:"provider"}),", even if it'd technically build."]}),"\n",(0,i.jsx)(n.li,{children:"Consumer and provider modules do not deviate as long as we continually release off a shared main branch. Backporting remains relatively unchanged besides being explicit about what module(s) your changes should affect."}),"\n",(0,i.jsx)(n.li,{children:"No code changes, just changes in process. Very simple."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"~~Slightly more complexity.~~Considerably more complex to manage the ICS library.\nThis is because ICS needs to support multiple versions of SDK (e.g., 0.45, 0.47, 0.50).\nIn addition, ICS needs to support a special fork of SDK (with LSM included) for the Cosmos Hub.\nThis means that instead of focusing on main the development team needs to manage multiple release\nbranches with different dependency trees."}),"\n",(0,i.jsx)(n.li,{children:"This solution does not allow having provider and consumer on separate versions of e.g. the Cosmos SDK."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801",children:"#801"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801#issuecomment-1683349298",children:"#801 comment"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>a,a:()=>t});var i=s(7294);const o={},r=i.createContext(o);function t(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:t(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/b22483fb.fc7b3cc6.js b/assets/js/b22483fb.fc7b3cc6.js
new file mode 100644
index 0000000000..bc40bf4e8a
--- /dev/null
+++ b/assets/js/b22483fb.fc7b3cc6.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4533],{4875:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>r,toc:()=>p});var n=i(5893),c=i(1151);const o={sidebar_position:4},s="Technical Specification",r={id:"introduction/technical-specification",title:"Technical Specification",description:"For a technical deep dive into the replicated security protocol, see the specification.",source:"@site/versioned_docs/version-v4.2.0-docs/introduction/technical-specification.md",sourceDirName:"introduction",slug:"/introduction/technical-specification",permalink:"/interchain-security/v4.2.0/introduction/technical-specification",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"Interchain Security Parameters",permalink:"/interchain-security/v4.2.0/introduction/params"},next:{title:"Key Assignment",permalink:"/interchain-security/v4.2.0/features/key-assignment"}},a={},p=[];function d(e){const t={a:"a",h1:"h1",p:"p",...(0,c.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"technical-specification",children:"Technical Specification"}),"\n",(0,n.jsxs)(t.p,{children:["For a technical deep dive into the replicated security protocol, see the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/README.md",children:"specification"}),"."]})]})}function u(e={}){const{wrapper:t}={...(0,c.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},1151:(e,t,i)=>{i.d(t,{Z:()=>r,a:()=>s});var n=i(7294);const c={},o=n.createContext(c);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/b2a29569.d74a382c.js b/assets/js/b2a29569.d74a382c.js
new file mode 100644
index 0000000000..82ac346324
--- /dev/null
+++ b/assets/js/b2a29569.d74a382c.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8864],{3567:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>h,contentTitle:()=>a,default:()=>l,frontMatter:()=>t,metadata:()=>r,toc:()=>d});var i=o(5893),s=o(1151);const t={sidebar_position:14,title:"Slashing on the provider for consumer equivocation"},a="ADR 013: Slashing on the provider for consumer equivocation",r={id:"adrs/adr-013-equivocation-slashing",title:"Slashing on the provider for consumer equivocation",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-013-equivocation-slashing.md",sourceDirName:"adrs",slug:"/adrs/adr-013-equivocation-slashing",permalink:"/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:14,frontMatter:{sidebar_position:14,title:"Slashing on the provider for consumer equivocation"},sidebar:"tutorialSidebar",previous:{title:"Separate Releasing",permalink:"/interchain-security/v4.2.0/adrs/adr-012-separate-releasing"},next:{title:"Epochs",permalink:"/interchain-security/v4.2.0/adrs/adr-014-epochs"}},h={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Single-chain slashing",id:"single-chain-slashing",level:3},{value:"Slashing undelegations and redelegations",id:"slashing-undelegations-and-redelegations",level:4},{value:"Slashing delegations",id:"slashing-delegations",level:4},{value:"Old evidence",id:"old-evidence",level:4},{value:"Slashing for equivocation on the consumer",id:"slashing-for-equivocation-on-the-consumer",level:3},{value:"Proposed solution",id:"proposed-solution",level:2},{value:"Implementation",id:"implementation",level:3},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function c(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-013-slashing-on-the-provider-for-consumer-equivocation",children:"ADR 013: Slashing on the provider for consumer equivocation"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"1st Sept. 2023: Initial draft"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Accepted"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsxs)(n.p,{children:["This ADR presents some approaches on how to slash on the provider chain validators that performed equivocations on consumer chains.\nCurrently, the provider chain can ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"receive and verify evidence of equivocation"}),", but it cannot slash the misbehaving validator."]}),"\n",(0,i.jsx)(n.p,{children:"In the remainder of this section, we explain how slashing is performed on a single chain and show why slashing on the provider for equivocation on the consumer is challenging."}),"\n",(0,i.jsxs)(n.p,{children:["Note that future versions of the Cosmos SDK, CometBFT, and ibc-go could modify the way we slash, etc. Therefore, a future reader of this ADR, should note that when we refer to Cosmos SDK, CometBFT, and ibc-go we specifically refer to their ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/intro/overview",children:"v0.47"}),", ",(0,i.jsx)(n.a,{href:"https://docs.cometbft.com/v0.37/",children:"v0.37"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc-go/blob/v7.3.0",children:"v7.3.0"})," versions respectively."]}),"\n",(0,i.jsx)(n.h3,{id:"single-chain-slashing",children:"Single-chain slashing"}),"\n",(0,i.jsxs)(n.p,{children:["Slashing is implemented across the ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/slashing",children:"slashing"}),"\nand ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/staking",children:"staking"})," modules.\nThe slashing module's keeper calls the staking module's ",(0,i.jsx)(n.code,{children:"Slash()"})," method, passing among others, the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," (i.e., the height when the equivocation occurred), the validator's ",(0,i.jsx)(n.code,{children:"power"})," at the infraction height, and the ",(0,i.jsx)(n.code,{children:"slashFactor"})," (currently set to ",(0,i.jsx)(n.code,{children:"5%"})," in case of equivocation on the Cosmos Hub)."]}),"\n",(0,i.jsx)(n.h4,{id:"slashing-undelegations-and-redelegations",children:"Slashing undelegations and redelegations"}),"\n",(0,i.jsxs)(n.p,{children:["To slash undelegations, ",(0,i.jsx)(n.code,{children:"Slash"})," goes through all undelegations and checks whether they started before or after the infraction occurred. If an undelegation started before the ",(0,i.jsx)(n.code,{children:"infractionHeight"}),", then it is ",(0,i.jsx)(n.strong,{children:"not"})," slashed, otherwise it is slashed by ",(0,i.jsx)(n.code,{children:"slashFactor"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The slashing of redelegations happens in a similar way, meaning that ",(0,i.jsx)(n.code,{children:"Slash"})," goes through all redelegations and checks whether the redelegations started before or after the ",(0,i.jsx)(n.code,{children:"infractionHeight"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"slashing-delegations",children:"Slashing delegations"}),"\n",(0,i.jsxs)(n.p,{children:["Besides undelegations and redelegations, the validator's delegations need to also be slashed.\nThis is performed by deducting the appropriate amount of tokens from the validator. Note that this deduction is computed based on the voting ",(0,i.jsx)(n.code,{children:"power"})," the misbehaving validator had at the height of the equivocation. As a result of the tokens deduction,\nthe ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/staking#delegator-shares",children:"tokens per share"}),"\nreduce and hence later on, when delegators undelegate or redelegate, the delegators retrieve back less\ntokens, effectively having their tokens slashed. The rationale behind this slashing mechanism, as mentioned in the ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/staking#delegator-shares",children:"Cosmos SDK documentation"})]}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"[...] is to simplify the accounting around slashing. Rather than iteratively slashing the tokens of every delegation entry, instead the Validators total bonded tokens can be slashed, effectively reducing the value of each issued delegator share."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["This approach of slashing delegations does not utilize the\n",(0,i.jsx)(n.code,{children:"infractionHeight"})," in any way and hence the following scenario could occur:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["a validator ",(0,i.jsx)(n.code,{children:"V"})," performs an equivocation at a height ",(0,i.jsx)(n.code,{children:"Hi"})]}),"\n",(0,i.jsxs)(n.li,{children:["a new delegator ",(0,i.jsx)(n.code,{children:"D"})," delegates to ",(0,i.jsx)(n.code,{children:"V"})," after height ",(0,i.jsx)(n.code,{children:"Hi"})]}),"\n",(0,i.jsxs)(n.li,{children:["evidence of the equivocation by validator ",(0,i.jsx)(n.code,{children:"V"})," is received"]}),"\n",(0,i.jsxs)(n.li,{children:["the tokens of delegator ",(0,i.jsx)(n.code,{children:"D"})," are slashed"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["In the above scenario, delegator ",(0,i.jsx)(n.code,{children:"D"})," is slashed, even though ",(0,i.jsx)(n.code,{children:"D"}),"'s voting power did not contribute to the infraction."]}),"\n",(0,i.jsx)(n.h4,{id:"old-evidence",children:"Old evidence"}),"\n",(0,i.jsxs)(n.p,{children:["In the single-chain case, old evidence (e.g., from 3 years ago) is ignored. This is achieved through\n",(0,i.jsx)(n.a,{href:"https://docs.cometbft.com/v0.37/spec/consensus/evidence",children:"CometBFT"})," that ignores old evidence based on the parameters ",(0,i.jsx)(n.code,{children:"MaxAgeNumBlocks"})," and ",(0,i.jsx)(n.code,{children:"MaxAgeDuration"})," (see ",(0,i.jsx)(n.a,{href:"https://github.com/cometbft/cometbft/blob/v0.37.0/evidence/pool.go#271",children:"here"}),").\nAdditionally, note that when the evidence is sent by CometBFT to the application, the evidence is rechecked in the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/evidence/keeper/infraction.go#L54",children:"evidence module"})," of Cosmos SDK and if it is old, the evidence is ignored.\nIn Cosmos Hub, the ",(0,i.jsx)(n.code,{children:"MaxAgeNumBlocks"})," is set to 1000000 (i.e., ~70 days if we assume we need ~6 sec per block) and ",(0,i.jsx)(n.code,{children:"MaxAgeDuration"})," is set to 172800000000000 ns (i.e., 2 days). Because of this check, we can easily exclude old evidence."]}),"\n",(0,i.jsx)(n.h3,{id:"slashing-for-equivocation-on-the-consumer",children:"Slashing for equivocation on the consumer"}),"\n",(0,i.jsxs)(n.p,{children:["In the single-chain case, slashing requires both the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and the voting ",(0,i.jsx)(n.code,{children:"power"}),".\nIn order to slash on the provider for an equivocation on a consumer, we need to have both the provider's ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and voting ",(0,i.jsx)(n.code,{children:"power"}),".\nNote that the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," on the consumer chain must be mapped to a height on the provider chain.\nUnless we have a way to find the corresponding ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and ",(0,i.jsx)(n.code,{children:"power"})," on the provider chain, we cannot slash for equivocation on the consumer in the same way as we would slash in the single-chain case."]}),"\n",(0,i.jsxs)(n.p,{children:["The challenge of figuring out the corresponding ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and ",(0,i.jsx)(n.code,{children:"power"})," values on the provider chain is due to the following trust assumption:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["We trust the consensus layer and validator set of the consumer chains, ",(0,i.jsx)(n.em,{children:"but we do not trust the application layer"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["As a result, we cannot trust anything that stems from the ",(0,i.jsx)(n.em,{children:"application state"})," of a consumer chain."]}),"\n",(0,i.jsxs)(n.p,{children:["Note that when a relayer or a user sends evidence through a ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"MsgSubmitConsumerDoubleVoting"})," message, the provider gets access to ",(0,i.jsx)(n.a,{href:"https://github.com/cometbft/cometbft/blob/v0.37.0/types/evidence.go#L35",children:"DuplicateVoteEvidence"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-protobuf",children:'type DuplicateVoteEvidence struct {\n\tVoteA *Vote `json:"vote_a"`\n\tVoteB *Vote `json:"vote_b"`\n\n\t// abci specific information\n\tTotalVotingPower int64\n\tValidatorPower int64\n\tTimestamp time.Time\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:['The "abci specific information" fields cannot be trusted because they are not signed. Therefore,\nwe can use neither ',(0,i.jsx)(n.code,{children:"ValidatorPower"})," for slashing on the provider chain, nor the ",(0,i.jsx)(n.code,{children:"Timestamp"})," to check the evidence age. We can get the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," from the votes, but this ",(0,i.jsx)(n.code,{children:"infractionHeight"})," corresponds to the infraction height on the consumer and ",(0,i.jsx)(n.strong,{children:"not"})," on the provider chain.\nSimilarly, when a relayer or a user sends evidence through a ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/826",children:"MsgSubmitConsumerMisbehaviour"})," message, the provider gets access to ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc-go/blob/v7.3.0/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L79",children:"Misbehaviour"})," that we cannot use to extract the infraction height, power, or the time on the provider chain."]}),"\n",(0,i.jsx)(n.h2,{id:"proposed-solution",children:"Proposed solution"}),"\n",(0,i.jsx)(n.p,{children:"As a first iteration, we propose the following approach. At the moment the provider receives evidence of equivocation on a consumer:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["slash all the undelegations and redelegations using ",(0,i.jsx)(n.code,{children:"slashFactor"}),";"]}),"\n",(0,i.jsxs)(n.li,{children:["slash all delegations using as voting ",(0,i.jsx)(n.code,{children:"power"})," the sum of the voting power of the misbehaving validator and the power of all the ongoing undelegations and redelegations."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Evidence expiration:"})," Additionally, because we cannot infer the actual time of the evidence (i.e., the timestamp of the evidence cannot be trusted), we do not consider ",(0,i.jsx)(n.em,{children:"evidence expiration"})," and hence old evidence is never ignored (e.g., the provider would act on 3 year-old evidence of equivocation on a consumer).\nAdditionally, we do not need to store equivocation evidence to avoid slashing a validator more than once, because we ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/evidence/keeper/infraction.go#L94",children:"do not slash"})," tombstoned validators and we ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/evidence/keeper/infraction.go#L138",children:"tombstone"})," a validator when slashed."]}),"\n",(0,i.jsxs)(n.p,{children:["We do not act on evidence that was signed by a validator ",(0,i.jsx)(n.a,{href:"https://tutorials.cosmos.network/tutorials/9-path-to-prod/3-keys.html#what-validator-keys",children:"consensus key"})," that is ",(0,i.jsx)(n.em,{children:"pruned"})," when we receive the evidence. We prune a validator's consensus key if the validator has assigned a new consumer key (using ",(0,i.jsx)(n.code,{children:"MsgAssignConsumerKey"}),") and an unbonding period on the consumer chain has elapsed (see ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-001-key-assignment.md",children:"key assignment ADR"}),"). Note that the provider chain is informed that the unbonding period has elapsed on the consumer when the provider receives a ",(0,i.jsx)(n.code,{children:"VSCMaturedPacket"})," and because of this, if the consumer delays the sending of a ",(0,i.jsx)(n.code,{children:"VSCMaturedPacket"}),", we would delay the pruning of the key as well."]}),"\n",(0,i.jsx)(n.h3,{id:"implementation",children:"Implementation"}),"\n",(0,i.jsxs)(n.p,{children:["The following logic needs to be added to the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"HandleConsumerDoubleVoting"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/826",children:"HandleConsumerMisbehaviour"})," methods:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:"undelegationsInTokens := sdk.NewInt(0)\nfor _, v := range k.stakingKeeper.GetUnbondingDelegationsFromValidator(ctx, validatorAddress) {\n for _, entry := range v.Entries {\n if entry.IsMature(now) && !entry.OnHold() {\n // undelegation no longer eligible for slashing, skip it\n continue\n }\n undelegationsInTokens = undelegationsInTokens.Add(entry.InitialBalance)\n }\n}\n\nredelegationsInTokens := sdk.NewInt(0)\nfor _, v := range k.stakingKeeper.GetRedelegationsFromSrcValidator(ctx, validatorAddress) {\n for _, entry := range v.Entries {\n if entry.IsMature(now) && !entry.OnHold() {\n // redelegation no longer eligible for slashing, skip it\n continue\n }\n redelegationsInTokens = redelegationsInTokens.Add(entry.InitialBalance)\n }\n}\n\ninfractionHeight := 0\nundelegationsAndRedelegationsInPower = sdk.TokensToConsensusPower(undelegationsInTokens.Add(redelegationsInTokens))\ntotalPower := validator's voting power + undelegationsAndRedelegationsInPower\nslashFraction := k.slashingKeeper.SlashFractionDoubleSign(ctx)\n\nk.stakingKeeper.Slash(ctx, validatorConsAddress, infractionHeight, totalPower, slashFraction, DoubleSign)\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Infraction height:"})," We provide a zero ",(0,i.jsx)(n.code,{children:"infractionHeight"})," to the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L33",children:"Slash"})," method in order to slash all ongoing undelegations and redelegations (see checks in ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L92",children:"Slash"}),", ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L195",children:"SlashUnbondingDelegation"}),", and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L249",children:"SlashRedelegation"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Power:"})," We pass the sum of the voting power of the misbehaving validator when the evidence was received (i.e., at evidence height) and the power of all the ongoing undelegations and redelegations.\nIf we assume that the ",(0,i.jsx)(n.code,{children:"slashFactor"})," is ",(0,i.jsx)(n.code,{children:"5%"}),", then the voting power we pass is ",(0,i.jsx)(n.code,{children:"power + totalPower(undelegations) + totalPower(redelegations)"}),".\nHence, when the ",(0,i.jsx)(n.code,{children:"Slash"})," method slashes all the undelegations and redelegations it would end up with ",(0,i.jsx)(n.code,{children:"0.05 * power + 0.05 * totalPower(undelegations) + 0.05 * totalPower(redelegations) - 0.05 * totalPower(undelegations) - 0.05 * totalPower(redelegations) = 0.05 * power"})," and hence it would slash ",(0,i.jsx)(n.code,{children:"5%"})," of the validator's power when the evidence is received."]}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsx)(n.p,{children:"With the proposed approach we can quickly implement slashing functionality on the provider chain for consumer chain equivocations.\nThis approach does not need to change the staking module and therefore does not change in any way how slashing is performed today for a single chain."}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["We ",(0,i.jsx)(n.em,{children:"definitely"})," slash more when it comes to undelegations and redelegations because we slash for all of them without considering an ",(0,i.jsx)(n.code,{children:"infractionHeight"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["We ",(0,i.jsx)(n.em,{children:"potentially"})," slash more than what we would have slashed if we knew the voting ",(0,i.jsx)(n.code,{children:"power"})," at the corresponding ",(0,i.jsx)(n.code,{children:"infractionHeight"})," in the provider chain."]}),"\n",(0,i.jsx)(n.li,{children:"We slash on old evidence of equivocation on a consumer."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-005-cryptographic-equivocation-verification.md",children:"ADR 005: Cryptographic verification of equivocation evidence"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/732",children:"EPIC tracking cryptographic equivocation feature"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://forum.cosmos.network/t/cryptographic-equivocation-slashing-design/11400",children:"Cosmos Hub Forum discussion on cryptographic equivocation slashing"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>r,a:()=>a});var i=o(7294);const s={},t=i.createContext(s);function a(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/b8d345cd.3f23582b.js b/assets/js/b8d345cd.3f23582b.js
new file mode 100644
index 0000000000..4c688a65f5
--- /dev/null
+++ b/assets/js/b8d345cd.3f23582b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4341],{186:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>d,toc:()=>c});var i=t(5893),s=t(1151);const r={sidebar_position:12,title:"Improving testing and increasing confidence"},o="ADR 011: Improving testing and increasing confidence",d={id:"adrs/adr-011-improving-test-confidence",title:"Improving testing and increasing confidence",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-011-improving-test-confidence.md",sourceDirName:"adrs",slug:"/adrs/adr-011-improving-test-confidence",permalink:"/interchain-security/v4.2.0/adrs/adr-011-improving-test-confidence",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:12,frontMatter:{sidebar_position:12,title:"Improving testing and increasing confidence"},sidebar:"tutorialSidebar",previous:{title:"Standalone to Consumer Changeover",permalink:"/interchain-security/v4.2.0/adrs/adr-010-standalone-changeover"},next:{title:"Separate Releasing",permalink:"/interchain-security/v4.2.0/adrs/adr-012-separate-releasing"}},a={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Current state of testing",id:"current-state-of-testing",level:4},{value:"Unit testing",id:"unit-testing",level:3},{value:"Integration testing",id:"integration-testing",level:3},{value:"End-to-end testing",id:"end-to-end-testing",level:3},{value:"Decision",id:"decision",level:2},{value:"1. Connect specifications to code and tooling",id:"1-connect-specifications-to-code-and-tooling",level:3},{value:"Decision context and hypothesis",id:"decision-context-and-hypothesis",level:4},{value:"Main benefit",id:"main-benefit",level:4},{value:"2. Improve e2e tooling",id:"2-improve-e2e-tooling",level:3},{value:"Matrix tests",id:"matrix-tests",level:4},{value:"Introducing e2e regression testing",id:"introducing-e2e-regression-testing",level:4},{value:"Introducing e2e CometMock tests",id:"introducing-e2e-cometmock-tests",level:4},{value:"3. Introduce innovative testing approaches",id:"3-introduce-innovative-testing-approaches",level:3},{value:"Model",id:"model",level:4},{value:"Driver",id:"driver",level:4},{value:"Harness",id:"harness",level:4},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-011-improving-testing-and-increasing-confidence",children:"ADR 011: Improving testing and increasing confidence"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2023-08-11: Proposed, first draft of ADR."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Proposed"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.p,{children:"Testing, QA, and maintenance of interchain-security libraries is an ever-evolving area of software engineering we have to keep incrementally improving. The purpose of the QA process is to catch bugs as early as possible. In an ideal development workflow a bug should never reach production. A bug found in the specification stage is a lot cheaper to resolve than a bug discovered in production (or even in testnet). Ideally, all bugs should be found during the CI execution, and we hope that no bugs will ever even reach the testnet (although nothing can replace actual system stress test under load interacting with users)."}),"\n",(0,i.jsx)(n.p,{children:"During development and testnet operation the following types of bugs were the most commonly found:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"improper iterator usage"}),"\n",(0,i.jsx)(n.li,{children:"unbounded array access/iteration"}),"\n",(0,i.jsx)(n.li,{children:"improper input handling and validation"}),"\n",(0,i.jsx)(n.li,{children:"improper cached context usage"}),"\n",(0,i.jsx)(n.li,{children:"non-determinism check (improper use of maps in go, relying on random values)"}),"\n",(0,i.jsx)(n.li,{children:"KV store management and/or how keys are defined"}),"\n",(0,i.jsx)(n.li,{children:"deserialization issues arising from consumer/provider versioning mismatch"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Such bugs can be discovered earlier with better tooling. Some of these bugs can induce increases in block times, chain halts, state corruption, or introduce an attack surface which is difficult to remove if other systems have started depending on that behavior."}),"\n",(0,i.jsx)(n.h4,{id:"current-state-of-testing",children:"Current state of testing"}),"\n",(0,i.jsx)(n.p,{children:"Our testing suites consist of multiple parts, each with their own trade-offs and benefits with regards to code coverage, complexity and confidence they provide."}),"\n",(0,i.jsx)(n.h3,{id:"unit-testing",children:"Unit testing"}),"\n",(0,i.jsxs)(n.p,{children:["Unit testing is employed mostly for testing single-module functionality. It is the first step in testing and often the most practical. While highly important, unit tests often ",(0,i.jsx)(n.strong,{children:"test a single piece of code"})," and don't test relationships between different moving parts, this makes them less valuable when dealing with multi-module interactions."]}),"\n",(0,i.jsx)(n.p,{children:"Unit tests often employ mocks to abstract parts of the system that are not under test. Mocks are not equivalent to actual models and should not be treated as such."}),"\n",(0,i.jsx)(n.p,{children:"Out of all the approaches used, unit testing has the most tools available and the coverage can simply be displayed as % of code lines tested. Although this is a very nice and very easy to understand metric, it does not speak about the quality of the test coverage."}),"\n",(0,i.jsx)(n.p,{children:"Since distributed systems testing is a lot more involved, unit tests are oftentimes not sufficient to cover complex interactions. Unit tests are still necessary and helpful, but in cases where unit tests are not helpful e2e or integration tests should be favored."}),"\n",(0,i.jsx)(n.h3,{id:"integration-testing",children:"Integration testing"}),"\n",(0,i.jsxs)(n.p,{children:["With integration testing we ",(0,i.jsx)(n.strong,{children:"test the multi-module interactions"})," while isolating them from the remainder of the system.\nIntegration tests can uncover bugs that are often missed by unit tests."]}),"\n",(0,i.jsxs)(n.p,{children:["It is very difficult to gauge the actual test coverage imparted by integration tests and the available tooling is limited.\nIn interchain-security we employ the ",(0,i.jsx)(n.code,{children:"ibc-go/testing"})," framework to test interactions in-memory."]}),"\n",(0,i.jsx)(n.p,{children:"At present, integration testing does not involve the consensus layer - it is only concerned with application level state and logic."}),"\n",(0,i.jsx)(n.h3,{id:"end-to-end-testing",children:"End-to-end testing"}),"\n",(0,i.jsx)(n.p,{children:"In our context end-to-end testing comprises of tests that use the actual application binaries in an isolated environment (e.g. docker container). During test execution the inputs are meant to simulate actual user interaction, either by submitting transactions/queries using the command line or using gRPC/REST APIs and checking for state changes after an action has been performed. With this testing strategy we also include the consensus layer in all of our runs. This is the closest we can get to testing user interactions without starting a full testnet."}),"\n",(0,i.jsx)(n.p,{children:"End-to-end testing strategies vary between different teams and projects and we strive to unify our approach to the best of our ability (at least for ICS and gaia)."}),"\n",(0,i.jsx)(n.p,{children:"The available tooling does not give us significant (or relevant) line of code coverage information since most of the tools are geared towards analyzing unit tests and simple code branch evaluation."}),"\n",(0,i.jsx)(n.p,{children:"We aim to adapt our best practices by learning from other similar systems and projects such as cosmos-sdk, ibc-go and CometBFT."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.h3,{id:"1-connect-specifications-to-code-and-tooling",children:"1. Connect specifications to code and tooling"}),"\n",(0,i.jsx)(n.p,{children:"Oftentimes, specifications are disconnected from the development and QA processes. This gives rise to problems where the specification does not reflect the actual state of the system and vice-versa.\nUsually specifications are just text files that are rarely used and go unmaintained after a while, resulting in consistency issues and misleading instructions/expectations about system behavior."}),"\n",(0,i.jsx)(n.h4,{id:"decision-context-and-hypothesis",children:"Decision context and hypothesis"}),"\n",(0,i.jsx)(n.p,{children:"Specifications written in a dedicated and executable specification language are easier to maintain than the ones written entirely in text.\nAdditionally, we can create models based on the specification OR make the model equivalent to a specification."}),"\n",(0,i.jsxs)(n.p,{children:["Models do not care about the intricacies of implementation and neither do specifications. Since both models and specifications care about concisely and accurately describing a system (such as a finite state machine), we see a benefit of adding model based tools (such as ",(0,i.jsx)(n.a,{href:"https://github.com/informalsystems/quint",children:"quint"}),") to our testing and development workflows."]}),"\n",(0,i.jsx)(n.h4,{id:"main-benefit",children:"Main benefit"}),"\n",(0,i.jsx)(n.p,{children:"MBT tooling can be used to generate test traces that can be executed by multiple different testing setups."}),"\n",(0,i.jsx)(n.h3,{id:"2-improve-e2e-tooling",children:"2. Improve e2e tooling"}),"\n",(0,i.jsx)(n.h4,{id:"matrix-tests",children:"Matrix tests"}),"\n",(0,i.jsxs)(n.p,{children:["Instead of only running tests against current ",(0,i.jsx)(n.code,{children:"main"})," branch we should adopt an approach where we also:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"run regression tests against different released software versions"})," (",(0,i.jsx)(n.code,{children:"ICS v1 vs v2 vs v3"}),")"]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.strong,{children:"run non-determinism tests to uncover issues quickly"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Matrix tests can be implemented using ",(0,i.jsx)(n.a,{href:"https://github.com/informalsystems/CometMock",children:"CometMock"})," and refactoring our current e2e CI setup."]}),"\n",(0,i.jsx)(n.h4,{id:"introducing-e2e-regression-testing",children:"Introducing e2e regression testing"}),"\n",(0,i.jsx)(n.p,{children:"This e2e test suite would execute using a cronjob in our CI (nightly, multiple times a day etc.)"}),"\n",(0,i.jsxs)(n.p,{children:["Briefly, the same set of traces is run against different ",(0,i.jsx)(n.strong,{children:"maintained"})," versions of the software and the ",(0,i.jsx)(n.code,{children:"main"})," branch.\nThis would allow us to discover potential issues during development instead of in a testnet scenarios."]}),"\n",(0,i.jsxs)(n.p,{children:["The most valuable issues that can be discovered in this way are ",(0,i.jsx)(n.strong,{children:"state breaking changes"}),", ",(0,i.jsx)(n.strong,{children:"regressions"})," and ",(0,i.jsx)(n.strong,{children:"version incompatibilities"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The setup is illustrated by the image below.\n",(0,i.jsx)(n.img,{alt:"e2e matrix tests",src:t(4023).Z+"",width:"2170",height:"1624"})]}),"\n",(0,i.jsx)(n.p,{children:"This table explains which versions are tested against each other for the same set of test traces:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\u2705 marks a passing test"}),"\n",(0,i.jsx)(n.li,{children:"\u274c marks a failing test"}),"\n"]}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"USES: ICS v1 PROVIDER"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"start chain"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"add key"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"delegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"undelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"redelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"downtime"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"equivocation"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"stop chain"})})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v1 consumer (sdk45,ibc4.3)"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v2 consumer (sdk45, ibc4.4)"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v3 consumer (sdk47, ibc7)"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"main consumer"})}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"neutron"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"stride"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"})]})]})]}),"\n",(0,i.jsx)(n.h4,{id:"introducing-e2e-cometmock-tests",children:"Introducing e2e CometMock tests"}),"\n",(0,i.jsxs)(n.p,{children:["CometMock is a mock implementation of the ",(0,i.jsx)(n.a,{href:"https://github.com/cometbft/cometbft",children:"CometBFT"})," consensus engine. It supports most operations performed by CometBFT while also being lightweight and relatively easy to use."]}),"\n",(0,i.jsxs)(n.p,{children:['CometMock tests allow more nuanced control of test scenarios because CometMock can "fool" the blockchain app into thinking that a certain number of blocks had passed.\n',(0,i.jsx)(n.strong,{children:"This allows us to test very nuanced scenarios, difficult edge cases and long-running operations (such as unbonding operations)."})]}),"\n",(0,i.jsx)(n.p,{children:"Examples of tests made easier with CometMock are listed below:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"regression tests"}),"\n",(0,i.jsx)(n.li,{children:"non-determinism tests"}),"\n",(0,i.jsx)(n.li,{children:"upgrade tests"}),"\n",(0,i.jsx)(n.li,{children:"state-breaking changes"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["With CometMock, the ",(0,i.jsx)(n.strong,{children:"matrix test"})," approach can also be used. The image below illustrates a CometMock setup that can be used to discover non-deterministic behavior and state-breaking changes.\n",(0,i.jsx)(n.img,{alt:"e2e matrix tests",src:t(3146).Z+"",width:"3714",height:"2082"})]}),"\n",(0,i.jsx)(n.p,{children:"This table explains which versions are tested against each other for the same set of test traces:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\u2705 marks a passing test"}),"\n",(0,i.jsx)(n.li,{children:"\u274c marks a failing test"}),"\n"]}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"SCENARIO"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"start chain"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"add key"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"delegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"undelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"redelegate"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"downtime"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"equivocation"})}),(0,i.jsx)(n.th,{children:(0,i.jsx)(n.strong,{children:"stop chain"})})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"v3 provi + v3 consu"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"main provi + main consu"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"commit provi + commit consu"})}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u2705"}),(0,i.jsx)(n.td,{children:"\u274c"}),(0,i.jsx)(n.td,{children:"\u274c"})]})]})]}),"\n",(0,i.jsxs)(n.p,{children:["Briefly; multiple versions of the application are run against the same CometMock instance and any deviations in app behavior would result in ",(0,i.jsx)(n.code,{children:"app hash"})," errors (the apps would be in different states after performing the same set of actions)."]}),"\n",(0,i.jsx)(n.h3,{id:"3-introduce-innovative-testing-approaches",children:"3. Introduce innovative testing approaches"}),"\n",(0,i.jsx)(n.p,{children:"When discussing e2e testing, some very important patterns emerge - especially if test traces are used instead of ad-hoc tests written by hand."}),"\n",(0,i.jsx)(n.p,{children:"We see a unique opportunity to clearly identify concerns and modularize the testing architecture."}),"\n",(0,i.jsxs)(n.p,{children:["The e2e testing frameworks can be split into a ",(0,i.jsx)(n.strong,{children:"pipeline consisting of 3 parts: model, driver and harness"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"model",children:"Model"}),"\n",(0,i.jsx)(n.p,{children:"Model is the part of the system that can emulate the behavior of the system under test.\nIdeally, it is very close to the specification and is written in a specification language such as quint, TLA+ or similar.\nOne of the purposes of the model is that it can be used to generate test traces."}),"\n",(0,i.jsx)(n.h4,{id:"driver",children:"Driver"}),"\n",(0,i.jsx)(n.p,{children:"The purpose of the driver is to accept test traces (generated by the model or written by hand), process them and provide inputs to the next part of the pipeline."}),"\n",(0,i.jsx)(n.p,{children:"Basically, the driver sits between the model and the actual infrastructure on which the test traces are being executed on."}),"\n",(0,i.jsx)(n.h4,{id:"harness",children:"Harness"}),"\n",(0,i.jsx)(n.p,{children:"Harness is the infrastructure layer of the pipeline that accepts inputs from the driver."}),"\n",(0,i.jsx)(n.p,{children:"There can be multiple harnesses as long as they can perform four things:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"bootstrap a test execution environment (local, docker, k8s\u2026)"}),"\n",(0,i.jsx)(n.li,{children:"accept inputs from drivers"}),"\n",(0,i.jsx)(n.li,{children:"perform the action specified by the driver"}),"\n",(0,i.jsx)(n.li,{children:"report results after performing actions"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.p,{children:"The procedure outlined in this ADR is not an all-or-nothing approach. Concepts introduced here do not rely on each other, so this ADR may only be applied partially without negative impact on test coverage and code confidence."}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"introduction of maintainable MBT solutions"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:'improvement over the current "difftest" setup that relies on an opinionated typescript model and go driver'}),"\n"]}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsx)(n.li,{children:"increased code coverage and confidence"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"using CometMock allows us to run more tests in less time"}),"\n",(0,i.jsx)(n.li,{children:"adding matrix e2e tests allows us to quickly pinpoint differences between code versions"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsx)(n.p,{children:"It might be easier to forgo the MBT tooling and instead focus on pure property based testing"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/667",children:"PBT proof of concept"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/flyingmutant/rapid",children:"property based testing in go"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:'The solutions are potentially expensive if we increase usage of the CI pipeline - this is fixed by running "expensive" tests using a cronjob, instead of running them on every commit.'}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsx)(n.p,{children:"The process of changing development and testing process is not something that can be thought of and delivered quickly. Luckily, the changes can be rolled out incrementally without impacting existing workflows."}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/gaia/issues/2427",children:"https://github.com/cosmos/gaia/issues/2427"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/gaia/issues/2420",children:"https://github.com/cosmos/gaia/issues/2420"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc-go/tree/main/e2e",children:"ibc-go e2e tests"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},3146:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/cometmock_matrix_test-714f36252aff9df4214823e3145d0ef5.png"},4023:(e,n,t)=>{t.d(n,{Z:()=>i});const i=t.p+"assets/images/matrix_e2e_tests-30681305077301daaf3097e1952b54bb.png"},1151:(e,n,t)=>{t.d(n,{Z:()=>d,a:()=>o});var i=t(7294);const s={},r=i.createContext(s);function o(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/b8e16dc5.a2560616.js b/assets/js/b8e16dc5.a2560616.js
new file mode 100644
index 0000000000..bbefab6d34
--- /dev/null
+++ b/assets/js/b8e16dc5.a2560616.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6705],{1528:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>h});var s=t(5893),o=t(1151);const a={sidebar_position:11,title:"Standalone to Consumer Changeover"},r=void 0,i={id:"adrs/adr-010-standalone-changeover",title:"Standalone to Consumer Changeover",description:"ADR 010: Standalone to Consumer Changeover",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-010-standalone-changeover.md",sourceDirName:"adrs",slug:"/adrs/adr-010-standalone-changeover",permalink:"/interchain-security/v4.2.0/adrs/adr-010-standalone-changeover",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:11,frontMatter:{sidebar_position:11,title:"Standalone to Consumer Changeover"},sidebar:"tutorialSidebar",previous:{title:"Soft Opt-Out",permalink:"/interchain-security/v4.2.0/adrs/adr-009-soft-opt-out"},next:{title:"Improving testing and increasing confidence",permalink:"/interchain-security/v4.2.0/adrs/adr-011-improving-test-confidence"}},c={},h=[{value:"ADR 010: Standalone to Consumer Changeover",id:"adr-010-standalone-to-consumer-changeover",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Process",id:"process",level:3},{value:"Changes to CCV Protocol",id:"changes-to-ccv-protocol",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"adr-010-standalone-to-consumer-changeover",children:"ADR 010: Standalone to Consumer Changeover"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"6/30/23: Feature completed, first draft of ADR."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsx)(n.p,{children:"Implemented"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://github.com/Stride-Labs/stride",children:"Stride"}),' will be the first consumer to "changeover" from a standalone cosmos blockchain, to a consumer chain secured by the Cosmos Hub. This document will outline the changes made to the replicated security protocol to support this changeover process.']}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsx)(n.h3,{id:"process",children:"Process"}),"\n",(0,s.jsx)(n.p,{children:'Prior to the changeover, the consumer chain will have an existing staking keeper and validator set, these may be referred to as the "standalone staking keeper" and "standalone validator set" respectively.'}),"\n",(0,s.jsx)(n.p,{children:"The first step in the changeover process is to submit a ConsumerAdditionProposal. If the proposal passes, the provider will create a new IBC client for the consumer at spawn time, with the provider's validator set. A consumer genesis will also be constructed by the provider for validators to query. Within this consumer genesis contains the initial validator set for the consumer to apply after the changeover."}),"\n",(0,s.jsx)(n.p,{children:"Next, the standalone consumer chain runs an upgrade which adds the CCV module, and is properly setup to execute changeover logic."}),"\n",(0,s.jsx)(n.p,{children:"The consumer upgrade height must be reached after the provider has created the new IBC client. Any replicated security validators who will run the consumer, but are not a part of the sovereign validator set, must sync up a full node before the consumer upgrade height is reached. The disk state of said full node will be used to run the consumer chain after the changeover has completed."}),"\n",(0,s.jsxs)(n.p,{children:["The meat of the changeover logic is that the consumer chain validator set is updated to that which was specified by the provider via the queried consumer genesis. Validators which were a part of the old set, but not the new set, are given zero voting power. Once these validator updates are given to Comet, the set is committed, and in effect 2 blocks later (see ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/f10e780df182158d95a30f7cf94588b2d0479309/x/ccv/consumer/keeper/changeover.go#L19",children:"FirstConsumerHeight"}),")."]}),"\n",(0,s.jsx)(n.p,{children:"A relayer then establishes the new IBC connection between the provider and consumer. The CCV channel handshake is started on top of this connection. Once the CCV channel is established and VSC packets are being relayed, the consumer chain is secured by the provider."}),"\n",(0,s.jsx)(n.h3,{id:"changes-to-ccv-protocol",children:"Changes to CCV Protocol"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Consumer Genesis state is updated to include a ",(0,s.jsx)(n.code,{children:"PreCCV"})," boolean. When this boolean is set true in the consumer genesis JSON, ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/f10e780df182158d95a30f7cf94588b2d0479309/x/ccv/consumer/keeper/changeover.go",children:"special logic"})," is executed on InitGenesis to trigger the changeover process on the consumer's first endblocker after the upgrade which adds the CCV module. Note that InitGenesis is not automatically called during chain upgrades, so the consumer must manually call the consumer's InitGenesis method in an upgrade handler."]}),"\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})," type is updated to include a ",(0,s.jsx)(n.code,{children:"DistributionTransmissionChannel"})," field. This field allows the consumer to use an existing IBC transfer channel to send rewards as a part of the CCV protocol. Consumers that're not changing over from a standalone chain will leave this field blank, indicating that a new transfer channel should be created on top of the same connection as the CCV channel."]}),"\n",(0,s.jsx)(n.li,{children:"The CCV consumer keeper is updated to contain an optional reference to the standalone staking keeper. The standalone staking keeper is used to slash for infractions that happened before the changeover was completed. Ie. any infraction from a block height before the changeover, that is submitted after the changeover, will call the standalone staking keeper's slash method. Note that a changeover consumer's standalone staking keeper becomes a democracy module keeper, so it is possible for a governance token to be slashed."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Existing cosmos chains are now able to onboard over to a consumer chain secured by a provider."}),"\n",(0,s.jsx)(n.li,{children:"The previous staking keepers for such chains can be transitioned to democracy staking module keepers."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The delineation between different types of consumers in this repo becomes less clear. Ie. there is code in the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/f10e780df182158d95a30f7cf94588b2d0479309/app/consumer-democracy/app.go",children:"democracy consumer's app.go"})," that only applies to a previously standalone chain, but that file also serves as the base for a normal democracy consumer launched with RS from genesis."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["EPIC: Standalone to Consumer Changeover ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/756",children:"#756"})]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Changeover diagram from Stride"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>i,a:()=>r});var s=t(7294);const o={},a=s.createContext(o);function r(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/b93225b7.6c538bb2.js b/assets/js/b93225b7.6c538bb2.js
new file mode 100644
index 0000000000..e646d8e18e
--- /dev/null
+++ b/assets/js/b93225b7.6c538bb2.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7144],{8304:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>l,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var n=o(5893),i=o(1151);const s={sidebar_position:16,title:"Partial Set Security"},a="ADR 015: Partial Set Security",r={id:"adrs/adr-015-partial-set-security",title:"Partial Set Security",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-015-partial-set-security.md",sourceDirName:"adrs",slug:"/adrs/adr-015-partial-set-security",permalink:"/interchain-security/v4.2.0/adrs/adr-015-partial-set-security",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:16,frontMatter:{sidebar_position:16,title:"Partial Set Security"},sidebar:"tutorialSidebar",previous:{title:"Epochs",permalink:"/interchain-security/v4.2.0/adrs/adr-014-epochs"}},d={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"How do consumer chains join?",id:"how-do-consumer-chains-join",level:3},{value:"State & Query",id:"state--query",level:4},{value:"How do validators opt in?",id:"how-do-validators-opt-in",level:3},{value:"State & Query",id:"state--query-1",level:4},{value:"When do validators opt in?",id:"when-do-validators-opt-in",level:4},{value:"How do validators opt out?",id:"how-do-validators-opt-out",level:3},{value:"State & Query",id:"state--query-2",level:4},{value:"When does a consumer chain start?",id:"when-does-a-consumer-chain-start",level:3},{value:"How do we send the partial validator sets to the consumer chains?",id:"how-do-we-send-the-partial-validator-sets-to-the-consumer-chains",level:3},{value:"How do we distribute rewards?",id:"how-do-we-distribute-rewards",level:3},{value:"Misbehaviour",id:"misbehaviour",level:3},{value:"Fraud votes",id:"fraud-votes",level:4},{value:"Double signing",id:"double-signing",level:4},{value:"Downtime",id:"downtime",level:4},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function h(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"adr-015-partial-set-security",children:"ADR 015: Partial Set Security"}),"\n",(0,n.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"2024-01-22: Proposed, first draft of ADR."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,n.jsx)(t.p,{children:"Proposed"}),"\n",(0,n.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,n.jsxs)(t.p,{children:["Currently, in ",(0,n.jsx)(t.em,{children:"Replicated Security"}),", the entire validator set of the provider chain is used to secure consumer chains. There are at least three concerns with this approach.\nFirst, a large number of validators might be forced to validate consumer chains they are not interested in securing.\nSecond, it is costly for small validators to secure additional chains. This concern is only partially addressed through ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-009-soft-opt-out.md",children:"soft opt-out"})," that allows small validators to opt out from validating consumer chains.\nThird and for the above reasons, it is challenging for a new consumer chain to join Replicated Security."]}),"\n",(0,n.jsxs)(t.p,{children:["As a solution, we present ",(0,n.jsx)(t.em,{children:"Partial Set Security"})," (PSS). As the name suggests, PSS allows for every consumer chain to be secured by only a subset of the provider validator set.\nIn what follows we propose the exact steps we need to take to implement PSS. This is a first iteration of PSS, and therefore we present the most minimal solution that make PSS possible."]}),"\n",(0,n.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,n.jsxs)(t.p,{children:["In Replicated Security, all the provider validators have to secure every consumer chain (with the exception of those validators allowed to opt out through the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-009-soft-opt-out.md",children:"soft opt-out"})," feature)."]}),"\n",(0,n.jsxs)(t.p,{children:["In PSS, we allow validators to opt in and out of validating any given consumer chain.\nThis has one exception: we introduce a parameter ",(0,n.jsx)(t.code,{children:"N"})," for each consumer chain and require that the validators in top ",(0,n.jsx)(t.code,{children:"N%"})," of the provider's voting power have to secure the consumer chain.\nValidators outside of the top ",(0,n.jsx)(t.code,{children:"N%"})," can dynamically opt in if they want to validate on the consumer chain."]}),"\n",(0,n.jsxs)(t.p,{children:["For example, if a consumer chain has ",(0,n.jsx)(t.code,{children:"N = 95%"}),", then it ultimately receives the same security it receives today with Replicated Security (with a default ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-009-soft-opt-out.md",children:"SoftOptOutThreshold"})," of 5%).\nOn the other hand, if a consumer chain has ",(0,n.jsx)(t.code,{children:"N = 0%"}),", then no validator is forced to validate the chain, but validators can opt in to do so instead."]}),"\n",(0,n.jsxs)(t.p,{children:["For the remainder of this ADR, we call a consumer chain ",(0,n.jsx)(t.em,{children:"Top N"})," if it has joined as a Top N chain with ",(0,n.jsx)(t.code,{children:"N > 0"})," and ",(0,n.jsx)(t.em,{children:"Opt In"})," chain otherwise. An Opt In consumer chain is secured only by the validators that have opted in to secure that chain."]}),"\n",(0,n.jsxs)(t.p,{children:["We intend to implement PSS using a feature branch off ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/tree/v4.0.0",children:"v4.0.0 interchain security"}),"."]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-consumer-chains-join",children:"How do consumer chains join?"}),"\n",(0,n.jsxs)(t.p,{children:["As a simplification and to avoid ",(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/pss-permissionless-vs-premissioned-lite-opt-in-consumer-chains/12984/17",children:"chain id squatting"}),", a consumer chain can only join PSS through a governance proposal and not in a permissionless way."]}),"\n",(0,n.jsx)(t.p,{children:'However, this proposal type will be modified so that it requires a lower quorum percentage than normal proposal, and every validator who voted "YES" on the proposal will form the consumer chain\'s initial validator set.'}),"\n",(0,n.jsxs)(t.p,{children:["Consumer chains join PSS the same way chains now join Replicated Security, namely through a ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})," proposal.\nWe extend ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/proto/interchain_security/ccv/provider/v1/provider.proto#L27",children:(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})})," with one optional field:"]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.code,{children:"uint32 top_N"}),": Corresponds to the percentage of validators that join under the Top N case.\nFor example, ",(0,n.jsx)(t.code,{children:"53"})," corresponds to a Top 53% chain, meaning that the top ",(0,n.jsx)(t.code,{children:"53%"})," provider validators have to validate the proposed consumer chain.\n",(0,n.jsx)(t.code,{children:"top_N"})," can be ",(0,n.jsx)(t.code,{children:"0"})," or include any value in ",(0,n.jsx)(t.code,{children:"[50, 100]"}),". A chain can join with ",(0,n.jsx)(t.code,{children:"top_N == 0"})," as an Opt In, or with ",(0,n.jsx)(t.code,{children:"top_N \u2208 [50, 100]"})," as a Top N chain."]}),"\n",(0,n.jsxs)(t.p,{children:["In case of a Top N chain, we restrict the possible values of ",(0,n.jsx)(t.code,{children:"top_N"})," from ",(0,n.jsx)(t.code,{children:"(0, 100]"})," to ",(0,n.jsx)(t.code,{children:"[50, 100]"}),".\nBy having ",(0,n.jsx)(t.code,{children:"top_N >= 50"})," we can guarantee that we cannot have a successful attack, assuming that at most ",(0,n.jsx)(t.code,{children:"1/3"})," of provider validators can be malicious.\nThis is because, a Top N chain with ",(0,n.jsx)(t.code,{children:"N >= 50%"})," would have at least ",(0,n.jsx)(t.code,{children:"1/3"})," honest validators, which is sufficient to stop attacks.\nAdditionally, by having ",(0,n.jsx)(t.code,{children:"N >= 50%"})," (and hence ",(0,n.jsx)(t.code,{children:"N > (VetoThreshold = 33.4%)"}),") we enable the top N validators to ",(0,n.jsx)(t.code,{children:"Veto"})," any ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})," for consumer chains they do not want to validate."]}),"\n",(0,n.jsxs)(t.p,{children:["If a proposal has the ",(0,n.jsx)(t.code,{children:"top_N"})," argument wrongly set, it should get rejected in [ValidateBasic] (",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/proposal.go#L86",children:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/proposal.go#L86"}),")."]}),"\n",(0,n.jsxs)(t.p,{children:["In the code, we distinguish whether a chain is ",(0,n.jsx)(t.em,{children:"Top N"})," or ",(0,n.jsx)(t.em,{children:"Opt In"})," by checking whether ",(0,n.jsx)(t.code,{children:"top_N"})," is zero or not."]}),"\n",(0,n.jsxs)(t.p,{children:["In a future version of PSS, we intend to introduce a ",(0,n.jsx)(t.code,{children:"ConsumerModificationProposal"})," so that we can modify the parameters of a consumer chain, e.g, a chain that is ",(0,n.jsx)(t.em,{children:"Opt In"})," to become ",(0,n.jsx)(t.em,{children:"Top N"}),", etc."]}),"\n",(0,n.jsx)(t.h4,{id:"state--query",children:"State & Query"}),"\n",(0,n.jsxs)(t.p,{children:["We augment the provider module\u2019s state to keep track of the ",(0,n.jsx)(t.code,{children:"top_N"})," value for each consumer chain. The key to store this information would be:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"topNBytePrefix | len(chainID) | chainID\n"})}),"\n",(0,n.jsxs)(t.p,{children:["To create the above key, we can use ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/keys.go#L418",children:(0,n.jsx)(t.code,{children:"ChainIdWithLenKey"})}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["Then in the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/keeper.go",children:"keeper"})," we introduce methods as follows:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-golang",children:"func (k Keeper) SetTopN(ctx sdk.Context, chainID string, topN uint32)\nfunc (k Keeper) IsTopN(ctx sdk.Context, chainID string) bool\nfunc (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool\n\n// returns the N if Top N chain, otherwise an error\nfunc (k Keeper) GetTopN(ctx sdk.Context, chainID string) (uint32, error)\n"})}),"\n",(0,n.jsxs)(t.p,{children:["We also extend the ",(0,n.jsx)(t.code,{children:"interchain-security-pd query provider list-consumer-chains"}),' query to return information on whether a consumer chain is an Opt In or a Top N chain and with what N.\nThis way, block explorers can present informative messages such as "This chain is secured by N% of the provider chain" for consumer chains.']}),"\n",(0,n.jsx)(t.h3,{id:"how-do-validators-opt-in",children:"How do validators opt in?"}),"\n",(0,n.jsxs)(t.p,{children:["A validator can opt in by sending a new type of message that we introduce in ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/proto/interchain_security/ccv/provider/v1/tx.proto#L1",children:"tx.proto"}),"."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-protobuf",children:"message MsgOptIn {\n // the chain id of the consumer chain to opt in to\n string chainID = 1;\n // the provider address of the validator\n string providerAddr = 2;\n // (optional) the consensus public key to use on the consumer\n optional string consumerKey = 3;\n}\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Note that in a Top N consumer chain, the top ",(0,n.jsx)(t.code,{children:"N%"})," provider validators have to validate the consumer chain.\nNevertheless, validators in the bottom ",(0,n.jsx)(t.code,{children:"(100 - N)%"})," can opt in to validate as well.\nProvider validators that belong or enter the top ",(0,n.jsx)(t.code,{children:"N%"})," validators are ",(0,n.jsx)(t.em,{children:"automatically"})," opted in to validate a Top N consumer chain.\nThis means that if a validator ",(0,n.jsx)(t.code,{children:"V"})," belongs to the top ",(0,n.jsx)(t.code,{children:"N%"})," validators but later falls (e.g., due to undelegations) to the bottom ",(0,n.jsx)(t.code,{children:"(100 - N)%"}),", ",(0,n.jsx)(t.code,{children:"V"})," is still considered opted in and has to validate unless ",(0,n.jsx)(t.code,{children:"V"})," sends a ",(0,n.jsx)(t.code,{children:"MsgOptOut"})," message (see below).\nBy automatically opting in validators when they enter the top ",(0,n.jsx)(t.code,{children:"N%"})," validators and by forcing top ",(0,n.jsx)(t.code,{children:"N%"})," validators to explicitly opt out in case they fall to the ",(0,n.jsx)(t.code,{children:"(100 - N)%"})," bottom validators we simplify the design of PSS."]}),"\n",(0,n.jsxs)(t.p,{children:["Note that a validator can send a ",(0,n.jsx)(t.code,{children:"MsgOptIn"})," message even if the consumer chain is not yet running. To do this we reuse the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/key_assignment.go#L644",children:(0,n.jsx)(t.code,{children:"IsConsumerProposedOrRegistered"})}),". If the ",(0,n.jsx)(t.code,{children:"chainID"})," does not exist, the ",(0,n.jsx)(t.code,{children:"MsgOptIn"})," should fail, as well as if the provider address does not exist."]}),"\n",(0,n.jsxs)(t.p,{children:["Optionally, a validator that opts in can provide a ",(0,n.jsx)(t.code,{children:"consumerKey"})," so that it assigns a different consumer key (from the provider) to the consumer chain.\nNaturally, a validator can always change the consumer key on a consumer chain by sending a ",(0,n.jsx)(t.code,{children:"MsgAssignConsumerKey"})," message at a later point in time, as is done in Replicated Security."]}),"\n",(0,n.jsx)(t.h4,{id:"state--query-1",children:"State & Query"}),"\n",(0,n.jsxs)(t.p,{children:["For each validator, we store a pair ",(0,n.jsx)(t.code,{children:"(blockHeight, isOptedIn)"})," that contains the block height the validator opted in and whether the validator is currently opted in or not, under the key:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"optedInBytePrefix | len(chainID) | chainID | addr\n"})}),"\n",(0,n.jsxs)(t.p,{children:["By using a prefix iterator on ",(0,n.jsx)(t.code,{children:"optedInBytePrefix | len(chainID) | chainID"})," we retrieve all the opted in validators."]}),"\n",(0,n.jsxs)(t.p,{children:["We introduce the following ",(0,n.jsx)(t.code,{children:"Keeper"})," methods."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-golang",children:"// returns all the validators that have opted in on chain `chainID`\nfunc (k Keeper) GetOptedInValidators(ctx sdk.Context, chainID string) []Validators\n\nfunc (k Keeper) IsValidatorOptedIn(ctx sdk.Context, chainID string, val Validator) bool\n"})}),"\n",(0,n.jsx)(t.p,{children:"We introduce the following two queries:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"interchain-security-pd query provider optedInValidators $chainID\ninterchain-security-pd query provider hasToValidate $providerAddr\n"})}),"\n",(0,n.jsx)(t.p,{children:"One query to retrieve the validators that are opted in and hence the validators that need to validate the consumer chain and one query that given a validator's address returns all the chains this validator has to validate."}),"\n",(0,n.jsx)(t.h4,{id:"when-do-validators-opt-in",children:"When do validators opt in?"}),"\n",(0,n.jsxs)(t.p,{children:["As described earlier, validators can manually opt in by sending a ",(0,n.jsx)(t.code,{children:"MsgOptIn"})," message.\nAdditionally, in a Top N chain, a validator is automatically opted in when it moves from the bottom ",(0,n.jsx)(t.code,{children:"(100 - N)%"})," to the top ",(0,n.jsx)(t.code,{children:"N%"})," validators."]}),"\n",(0,n.jsxs)(t.p,{children:["Lastly, validators can also opt in if they vote ",(0,n.jsx)(t.code,{children:"Yes"})," during the ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})," that introduces a consumer chain.\nThis simplifies validators operations because they do not have to send an additional message to opt in."]}),"\n",(0,n.jsxs)(t.p,{children:["Because the ",(0,n.jsx)(t.code,{children:"Tally"})," method ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.7/x/gov/keeper/tally.go#L71",children:"deletes the votes"})," after reading them, we cannot check the votes of the validators after the votes have been tallied.\nTo circumvent this, we introduce a hook for ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.7/x/gov/keeper/vote.go#L35",children:(0,n.jsx)(t.code,{children:"AfterProposalVote"})})," and keep track of all the votes cast by a validator.\nIf a validator casts more than one vote, we only consider the latest vote.\nFinally, we only consider a validator has opted in if it casts a 100% ",(0,n.jsx)(t.code,{children:"Yes"})," vote in case of a ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-037-gov-split-vote.md",children:"weighted vote"}),"."]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-validators-opt-out",children:"How do validators opt out?"}),"\n",(0,n.jsx)(t.p,{children:"Validators that have opted in on a chain can opt out by sending the following message:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-protobuf",children:"message MsgOptOut {\n // the chain id of the consumer chain to opt out from\n string chainID = 1;\n // the provider address of the validator\n string providerAddr = 2;\n}\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Validators can only opt out after a consumer chain has started and hence the above message returns an error if the chain with ",(0,n.jsx)(t.code,{children:"chainID"})," is not running.\nAdditionally, a validator that belongs to the top ",(0,n.jsx)(t.code,{children:"N%"})," validators cannot opt out from a Top N chain and hence a ",(0,n.jsx)(t.code,{children:"MsgOptOut"})," would error in such a case."]}),"\n",(0,n.jsx)(t.h4,{id:"state--query-2",children:"State & Query"}),"\n",(0,n.jsx)(t.p,{children:"We also update the state of the opted-in validators when a validator has opted out by removing the opted-out validator."}),"\n",(0,n.jsxs)(t.p,{children:["Note that only opted-in validators can be punished for downtime on a consumer chain.\nFor this, we use historical info of all the validators that have opted in; We can examine the ",(0,n.jsx)(t.code,{children:"blockHeight"})," stored under the key ",(0,n.jsx)(t.code,{children:"optedInBytePrefix | len(chainID) | chainID | addr"})," to see if a validator was opted in.\nThis way we can jail validators for downtime knowing that indeed the validators have opted in at some point in the past.\nOtherwise, we can think of a scenario where a validator ",(0,n.jsx)(t.code,{children:"V"})," is down for a period of time, but before ",(0,n.jsx)(t.code,{children:"V"})," gets punished for downtime, validator ",(0,n.jsx)(t.code,{children:"V"})," opts out, and then we do not know whether ",(0,n.jsx)(t.code,{children:"V"})," should be punished or not."]}),"\n",(0,n.jsx)(t.h3,{id:"when-does-a-consumer-chain-start",children:"When does a consumer chain start?"}),"\n",(0,n.jsxs)(t.p,{children:["A Top N consumer chain always starts at the specified date (",(0,n.jsx)(t.code,{children:"spawn_time"}),") if the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/proto/interchain_security/ccv/provider/v1/provider.proto#L27",children:(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})})," has passed.\nAn Opt In consumer chain only starts if at least one validator has opted in. We check this in ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/proposal.go#L357",children:"BeginBlockInit"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-golang",children:'func (k Keeper) BeginBlockInit(ctx sdk.Context) {\n propsToExecute := k.GetConsumerAdditionPropsToExecute(ctx)\n\n for _, prop := range propsToExecute {\n chainID := prop.ChainId\n if !k.IsTopN(ctx, chainID) && len(k.GetOptedInValidators(ctx, chainID)) == 0 {\n // drop the proposal\n ctx.Logger().Info("could not start chain because no validator has opted in")\n continue\n } \n ...\n'})}),"\n",(0,n.jsx)(t.h3,{id:"how-do-we-send-the-partial-validator-sets-to-the-consumer-chains",children:"How do we send the partial validator sets to the consumer chains?"}),"\n",(0,n.jsxs)(t.p,{children:["A consumer chain should only be validated by opted in validators.\nWe introduce logic to do this when we ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/relay.go#L213",children:"queue"})," the ",(0,n.jsx)(t.code,{children:"VSCPacket"}),"s.\nThe logic behind this, is not as straightforward as it seems because CometBFT does not receive the validator set that has to validate a chain, but rather a delta of ",(0,n.jsx)(t.a,{href:"https://docs.cometbft.com/v0.37/spec/abci/abci++_methods#validatorupdate",children:"validator updates"}),".\nFor example, to remove an opted-out validator from a consumer chain, we have to send a validator update with a ",(0,n.jsx)(t.code,{children:"power"})," of ",(0,n.jsx)(t.code,{children:"0"}),", similarly to what is done in the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/key_assignment.go#L525",children:"assignment of consumer keys"}),".\nWe intend to update this ADR at a later stage on how exactly we intend to implement this logic."]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-we-distribute-rewards",children:"How do we distribute rewards?"}),"\n",(0,n.jsxs)(t.p,{children:["Currently, rewards are distributed as follows: The consumer ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/consumer/keeper/distribution.go#L148",children:"periodically sends rewards"})," on the provider ",(0,n.jsx)(t.code,{children:"ConsumerRewardsPool"})," address.\nThe provider then ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/distribution.go#L77",children:"transfers those rewards to the fee collector address"})," and those transferred rewards are distributed to validators and delegators."]}),"\n",(0,n.jsx)(t.p,{children:"In PSS, we distribute rewards only to validators that actually validate the consumer chain.\nTo do this, we have a pool associated with each consumer chain and consumers IBC transfer the rewards to this pool.\nWe then extract the rewards from each consumer pool and distribute them to the opted in validators."}),"\n",(0,n.jsx)(t.p,{children:"Note that we only distribute rewards to validators that have been opted in for some time (e.g., 10000 blocks) to avoid cases where validators opt in just to receive rewards and then opt out immediately afterward."}),"\n",(0,n.jsx)(t.h3,{id:"misbehaviour",children:"Misbehaviour"}),"\n",(0,n.jsx)(t.h4,{id:"fraud-votes",children:"Fraud votes"}),"\n",(0,n.jsxs)(t.p,{children:["In an Opt In chain, a set of validators might attempt to perform an attack. To deter such potential attacks, PSS allows for the use of fraud votes.\nA ",(0,n.jsx)(t.em,{children:"fraud vote"})," is a governance proposal that enables the slashing of validators that performed an attack.\nDue to their inherent complexity, we intend to introduce fraud votes in a different ADR and at a future iteration of PSS."]}),"\n",(0,n.jsx)(t.h4,{id:"double-signing",children:"Double signing"}),"\n",(0,n.jsx)(t.p,{children:"We do not change the way slashing for double signing and light client attacks functions.\nIf a validator misbehaves on a consumer, then we slash that validator on the provider."}),"\n",(0,n.jsx)(t.h4,{id:"downtime",children:"Downtime"}),"\n",(0,n.jsx)(t.p,{children:"We do not change the way downtime jailing functions.\nIf a validator is down on a consumer chain for an adequate amount of time, we jail this validator on the provider but only if the validator was opted in on this consumer chain in the recent past."}),"\n",(0,n.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,n.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Easier for new consumer chains to consume the provider's chain economic security because proposals are more likely to pass if not everyone is forced to validate."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Smaller validators are not forced to validate chains anymore if they do not want to."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"We can deprecate the soft opt-out implementation."}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["A consumer chain does not receive the same economic security as with Replicated Security (assuming the value of ",(0,n.jsx)(t.code,{children:"SoftOptOutThreshold"})," is ",(0,n.jsx)(t.code,{children:"5%"}),"), unless it is a Top N chain with ",(0,n.jsx)(t.code,{children:"N >= 95%"}),"."]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/pss-permissionless-vs-premissioned-lite-opt-in-consumer-chains/12984",children:"PSS: Permissionless vs premissioned-lite opt-in consumer chains"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/chips-discussion-phase-partial-set-security-updated/11775",children:"CHIPs discussion phase: Partial Set Security (updated)"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/pss-exclusive-vs-inclusive-top-n/13058",children:"PSS: Exclusive vs Inclusive Top-N"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1518",children:"Initial PSS ADR and notes #1518"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://informal.systems/blog/replicated-vs-mesh-security",children:"Replicated vs. Mesh Security"})}),"\n"]})]})}function l(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},1151:(e,t,o)=>{o.d(t,{Z:()=>r,a:()=>a});var n=o(7294);const i={},s=n.createContext(i);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/bbea31d2.43863e88.js b/assets/js/bbea31d2.43863e88.js
new file mode 100644
index 0000000000..640b9d87de
--- /dev/null
+++ b/assets/js/bbea31d2.43863e88.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[109],{662:(s,e,a)=>{a.r(e),a.d(e,{assets:()=>h,contentTitle:()=>l,default:()=>d,frontMatter:()=>t,metadata:()=>r,toc:()=>c});var i=a(5893),n=a(1151);const t={sidebar_position:3,title:"Jail Throttling"},l="ADR 002: Jail Throttling",r={id:"adrs/adr-002-throttle",title:"Jail Throttling",description:"Changelog",source:"@site/docs/adrs/adr-002-throttle.md",sourceDirName:"adrs",slug:"/adrs/adr-002-throttle",permalink:"/interchain-security/adrs/adr-002-throttle",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Jail Throttling"},sidebar:"tutorialSidebar",previous:{title:"Key Assignment",permalink:"/interchain-security/adrs/adr-001-key-assignment"},next:{title:"Equivocation governance proposal",permalink:"/interchain-security/adrs/adr-003-equivocation-gov-proposal"}},h={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Required State",id:"required-state",level:3},{value:"Params",id:"params",level:3},{value:"Protocol Overview",id:"protocol-overview",level:3},{value:"OnRecvSlashPacket",id:"onrecvslashpacket",level:4},{value:"OnRecvVSCMaturedPacket",id:"onrecvvscmaturedpacket",level:4},{value:"Endblocker",id:"endblocker",level:4},{value:"Slash Meter Replenishment",id:"slash-meter-replenishment",level:5},{value:"Handle Leading VSCMaturedPackets",id:"handle-leading-vscmaturedpackets",level:5},{value:"Handle Throttle Queues",id:"handle-throttle-queues",level:5},{value:"System Properties",id:"system-properties",level:3},{value:"Main Throttling Property",id:"main-throttling-property",level:3},{value:"How Unjailing Affects the Main Throttling Property",id:"how-unjailing-affects-the-main-throttling-property",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function m(s){const e={a:"a",annotation:"annotation",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",li:"li",math:"math",mfrac:"mfrac",mi:"mi",mn:"mn",mo:"mo",mrow:"mrow",msub:"msub",ol:"ol",p:"p",pre:"pre",semantics:"semantics",span:"span",strong:"strong",ul:"ul",...(0,n.a)(),...s.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"adr-002-jail-throttling",children:"ADR 002: Jail Throttling"}),"\n",(0,i.jsx)(e.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"2023-01-26: Initial Draft"}),"\n",(0,i.jsx)(e.li,{children:"2023-02-07: Property refined, ADR ready to review/merge"}),"\n",(0,i.jsx)(e.li,{children:"2023-11-22: Refactor for better understanding"}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(e.p,{children:"Accepted"}),"\n",(0,i.jsx)(e.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(e.p,{children:"The CCV spec is based around the assumption that the provider binary and all consumers binaries are non-malicious, and follow the defined protocols.\nIn practice, this assumption may not hold.\nA malicious consumer binary could potentially include code which is able to send many slash/jail packets at once to the provider."}),"\n",(0,i.jsx)(e.p,{children:"Before the throttling feature was implemented, the following attack was possible.\nAttacker(s) would create provider validators just below the provider's active set.\nUsing a malicious consumer binary, slash packets would be relayed to the provider, that would slash/jail a significant portion (or all) of honest validator at once.\nControl of the provider would then pass over to the attackers' validators.\nThis enables the attacker(s) to halt the provider.\nOr even worse, commit arbitrary state on the provider, potentially stealing all tokens bridged to the provider over IBC."}),"\n",(0,i.jsx)(e.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(e.p,{children:"The throttling feature was designed to slow down the mentioned attack from above, allowing validators and the community to appropriately respond to the attack,\ni.e., this feature limits (enforced by on-chain params) the rate that the provider validator set can be jailed over time."}),"\n",(0,i.jsx)(e.h3,{id:"required-state",children:"Required State"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Slash meter:"})," There exists one slash meter on the provider which stores an amount of voting power (integer), corresponding to an allowance of validators that can be jailed over time.\nThis meter is initialized to a certain value on genesis, decremented by the amount of voting power jailed whenever a slash packet is handled, and periodically replenished as decided by on-chain params."]}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Global entry queue:"}),' There exists a single queue which stores "global slash entries".\nThese entries allow the provider to appropriately handle slash packets sent from any consumer in FIFO ordering.\nThis queue is responsible for coordinating the order that slash packets (from multiple chains) are handled over time.']}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Per-chain data queue:"}),' For each established consumer, there exists a queue which stores "throttled packet data",\ni.e.,pending slash packet data is queued together with pending VSC matured packet data in FIFO ordering.\nOrder is enforced by IBC sequence number.\nThese "per-chain" queues are responsible for coordinating the order that slash packets are handled in relation to VSC matured packets from the same chain.']}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.em,{children:"Note:"})," The reason for a multiple-queue design is the ",(0,i.jsx)(e.em,{children:"VSC Maturity and Slashing Order"})," property (see ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#consumer-initiated-slashing",children:"spec"}),").\nThere are other ways to ensure such a property (like a queue of linked lists, etc.), but the proposed approach seemed to be the most understandable and easiest to implement with a KV store."]}),"\n",(0,i.jsx)(e.h3,{id:"params",children:"Params"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishPeriod"})," -- the period after which the slash meter is replenished."]}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," -- the portion (in range [0, 1]) of total voting power that is replenished to the slash meter when a replenishment occurs. This param also serves as a maximum fraction of total voting power that the slash meter can hold."]}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.code,{children:"MaxThrottledPackets"})," -- the maximum amount of throttled slash or vsc matured packets that can be queued from a single consumer before the provider chain halts, it should be set to a large value.\nThis param would allow provider binaries to panic deterministically in the event that packet throttling results in a large amount of state-bloat. In such a scenario, packet throttling could prevent a violation of safety caused by a malicious consumer, at the cost of provider liveness."]}),"\n",(0,i.jsx)(e.h3,{id:"protocol-overview",children:"Protocol Overview"}),"\n",(0,i.jsx)(e.h4,{id:"onrecvslashpacket",children:"OnRecvSlashPacket"}),"\n",(0,i.jsx)(e.p,{children:"Upon the provider receiving a slash packet from any of the established consumers during block execution, two things occur:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsx)(e.li,{children:"A global slash entry is queued."}),"\n",(0,i.jsx)(e.li,{children:"The data of such a packet is added to the per-chain queue."}),"\n"]}),"\n",(0,i.jsx)(e.h4,{id:"onrecvvscmaturedpacket",children:"OnRecvVSCMaturedPacket"}),"\n",(0,i.jsx)(e.p,{children:"Upon the provider receiving a VSCMatured packet from any of the established consumers during block execution, the VSCMatured packet data is added to the per-chain queue."}),"\n",(0,i.jsx)(e.h4,{id:"endblocker",children:"Endblocker"}),"\n",(0,i.jsxs)(e.p,{children:["In the ",(0,i.jsx)(e.code,{children:"EndBlock"})," of the provider CCV module, there are three actions performed:"]}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"replenish the slash meter;"}),"\n",(0,i.jsxs)(e.li,{children:["handle the leading ",(0,i.jsx)(e.code,{children:"VSCMaturedPackets"}),";"]}),"\n",(0,i.jsx)(e.li,{children:"and handle the throttle queues."}),"\n"]}),"\n",(0,i.jsx)(e.h5,{id:"slash-meter-replenishment",children:"Slash Meter Replenishment"}),"\n",(0,i.jsxs)(e.p,{children:["Once the slash meter becomes not full, it'll be replenished after ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishPeriod"})," by incrementing the meter with its allowance for the replenishment block, where ",(0,i.jsx)(e.code,{children:"allowance"})," = ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," * ",(0,i.jsx)(e.code,{children:"currentTotalVotingPower"}),".\nThe slash meter will never exceed its current allowance (function of the total voting power for the block) in value."]}),"\n",(0,i.jsx)(e.p,{children:"Note a few things:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsx)(e.li,{children:"The slash meter can go negative in value, and will do so when handling a single slash packet that jails a validator with significant voting power.\nIn such a scenario, the slash meter may take multiple replenishment periods to once again reach a positive value (or 0), meaning no other slash packets may be handled for multiple replenishment periods."}),"\n",(0,i.jsx)(e.li,{children:"Total voting power of a chain changes over time, especially as validators are jailed.\nAs validators are jailed, total voting power decreases, and so does the jailing allowance.\nSee below for more detailed throttling property discussion."}),"\n",(0,i.jsxs)(e.li,{children:["The voting power allowance added to the slash meter during replenishment will always be greater than or equal to 1.\nIf the ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," is set too low, integer rounding will put this minimum value into effect.\nThat is, if ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," * ",(0,i.jsx)(e.code,{children:"currentTotalVotingPower"})," < 1, then the effective allowance would be 1.\nThis min value of allowance ensures that there's some packets handled over time, even if that is a very long time.\nIt's a crude solution to an edge case caused by too small of a replenishment fraction."]}),"\n"]}),"\n",(0,i.jsxs)(e.p,{children:["The behavior described above is achieved by executing ",(0,i.jsx)(e.code,{children:"CheckForSlashMeterReplenishment()"})," every ",(0,i.jsx)(e.code,{children:"EndBlock"}),", BEFORE ",(0,i.jsx)(e.code,{children:"HandleThrottleQueues()"})," is executed."]}),"\n",(0,i.jsx)(e.h5,{id:"handle-leading-vscmaturedpackets",children:"Handle Leading VSCMaturedPackets"}),"\n",(0,i.jsxs)(e.p,{children:["In every block, it is possible that ",(0,i.jsx)(e.code,{children:"VSCMaturedPacket"}),' data was queued before any slash packet data.\nSince this "leading" VSCMatured packet data does not have to be throttled (see ',(0,i.jsx)(e.em,{children:"VSC Maturity and Slashing Order"}),"), we can handle all VSCMatured packet data at the head of the queue, before the any throttling or packet data handling logic executes."]}),"\n",(0,i.jsx)(e.h5,{id:"handle-throttle-queues",children:"Handle Throttle Queues"}),"\n",(0,i.jsxs)(e.p,{children:["In every ",(0,i.jsx)(e.code,{children:"EndBlock"}),", the following logic is executed to handle data from the throttle queues."]}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-typescript",children:"meter := getSlashMeter()\n\n// Keep iterating as long as the meter has a positive (or 0) value, and global slash entries exist \nwhile meter.IsPositiveOrZero() && entriesExist() {\n // Get next entry in queue\n entry := getNextGlobalSlashEntry()\n // Decrement slash meter by the voting power that will be removed from the valset from handling this slash packet\n valPower := entry.getValPower()\n meter = meter - valPower\n // Using the per-chain queue, handle the single slash packet using its queued data,\n // then handle all trailing VSCMatured packets for this consumer\n handleSlashPacketAndTrailingVSCMaturedPackets(entry)\n // Delete entry in global queue, delete handled data\n entry.Delete()\n deleteThrottledSlashPacketData()\n deleteTrailingVSCMaturedPacketData()\n}\n"})}),"\n",(0,i.jsx)(e.h3,{id:"system-properties",children:"System Properties"}),"\n",(0,i.jsxs)(e.p,{children:["All CCV system properties should be maintained by implementing this feature, see ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#consumer-initiated-slashing",children:"CCV spec - Consumer Initiated Slashing"}),"."]}),"\n",(0,i.jsxs)(e.p,{children:["One implementation-specific property introduced is that if any of the chain-specific packet data queues become larger than ",(0,i.jsx)(e.code,{children:"MaxThrottledPackets"}),", then the provider binary will panic, and the provider chain will halt.\nTherefore this param should be set carefully. See ",(0,i.jsx)(e.code,{children:"SetThrottledPacketDataSize"}),".\nThis behavior ensures that if the provider binaries are queuing up more packet data than machines can handle, the provider chain halts deterministically between validators."]}),"\n",(0,i.jsx)(e.h3,{id:"main-throttling-property",children:"Main Throttling Property"}),"\n",(0,i.jsx)(e.p,{children:"Using on-chain params and the sub protocol defined, slash packet throttling is implemented such that the following property holds under some conditions."}),"\n",(0,i.jsx)(e.p,{children:"First, we introduce the following definitions:"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:'A consumer initiated slash attack "starts" when the first slash packet from such an attack is received by the provider.'}),"\n",(0,i.jsx)(e.li,{children:'The "initial validator set" for the attack is the validator set that existed on the provider when the attack started.'}),"\n",(0,i.jsxs)(e.li,{children:["There is a list of honest validators such that if they are jailed, ",(0,i.jsx)(e.code,{children:"X"}),"% of the initial validator set will be jailed."]}),"\n"]}),"\n",(0,i.jsx)(e.p,{children:"For the Throttling Property to hold, the following assumptions must be true:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsx)(e.li,{children:"We assume the total voting power of the chain (as a function of delegations) does not increase over the course of the attack."}),"\n",(0,i.jsxs)(e.li,{children:["No validator has more than ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," of total voting power on the provider."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," is large enough that ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," * ",(0,i.jsx)(e.code,{children:"currentTotalVotingPower"})," > 1,\ni.e., the replenish fraction is set high enough that we can ignore the effects of rounding."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.code,{children:"SlashMeterReplenishPeriod"})," is sufficiently longer than the time it takes to produce a block."]}),"\n"]}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.em,{children:"Note if these assumptions do not hold, throttling will still slow down the described attack in most cases, just not in a way that can be succinctly described. It's possible that more complex properties can be defined."})}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.strong,{children:"Throttling Property"}),": The time it takes to jail/tombstone ",(0,i.jsx)(e.code,{children:"X"}),"% of the initial validator set will be greater than or equal to\n",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"d"})]}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"c"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"n"})]})]}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"d"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathit{SlashMeterReplenishPeriod} \\cdot \\frac{X}{\\mathit{SlashMeterReplenishFraction}} - 2 \\cdot \\mathit{SlashMeterReplenishPeriod}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishPeriod"})}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.3534em",verticalAlign:"-0.4811em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8723em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"SlashMeterReplenishFraction"})})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.394em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"})})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.4811em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6444em"}}),(0,i.jsx)(e.span,{className:"mord",children:"2"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishPeriod"})})]})]})]}),"."]}),"\n",(0,i.jsxs)(e.blockquote,{children:["\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"Intuition"})}),"\n",(0,i.jsx)(e.p,{children:"Let's use the following notation:"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"C"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"})]})})]}),": Number of replenishment cycles"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"P"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"P"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})})]}),": ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"d"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathit{SlashMeterReplenishPeriod}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishPeriod"})})]})})]})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"F"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"F"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})})]}),": ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"S"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"M"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"R"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"p"}),(0,i.jsx)(e.mi,{children:"l"}),(0,i.jsx)(e.mi,{children:"e"}),(0,i.jsx)(e.mi,{children:"n"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"s"}),(0,i.jsx)(e.mi,{children:"h"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mi,{children:"r"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"c"}),(0,i.jsx)(e.mi,{children:"t"}),(0,i.jsx)(e.mi,{children:"i"}),(0,i.jsx)(e.mi,{children:"o"}),(0,i.jsx)(e.mi,{children:"n"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\mathit{SlashMeterReplenishFraction}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8889em",verticalAlign:"-0.1944em"}}),(0,i.jsx)(e.span,{className:"mord",children:(0,i.jsx)(e.span,{className:"mord mathit",children:"SlashMeterReplenishFraction"})})]})})]})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"V_{\\mathit{max}}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]}),": Max power of a validator as a fraction of total voting power"]}),"\n"]}),"\n",(0,i.jsxs)(e.p,{children:["In ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"C"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"})]})})]})," number of replenishment cycles, the fraction of total voting power that can be removed, ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"a"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"a"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",children:"a"})]})})]}),", is ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mo,{children:"\u2264"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"+"}),(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"a \\leq F \\cdot C + V_{\\mathit{max}}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7719em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",children:"a"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2264"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"+"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})]})]})," (where ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"V_{\\mathit{max}}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]})," is there to account for the power fraction of the last validator removed, one which pushes the meter to the negative value)."]}),"\n",(0,i.jsxs)(e.p,{children:["So, we need at least ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u2265"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})]}),(0,i.jsx)(e.mi,{children:"F"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\geq \\frac{a - V_{\\mathit{max}}}{F}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8193em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.2334em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8884em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.4101em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",children:"a"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1645em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.357em",marginLeft:"-0.2222em",marginRight:"0.0714em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.5em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size3 size1 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.143em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})," cycles to remove ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"a"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"a"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.4306em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",children:"a"})]})})]})," fraction of the total voting power."]}),"\n",(0,i.jsxs)(e.p,{children:["Since we defined the start of the attack to be the moment when the first slash request arrives, then ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"F"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"F"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})})]})," fraction of the initial validator set can be jailed immediately. For the remaining ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"X - F"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})]})]})," fraction of the initial validator set to be jailed, it takes at least ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u2265"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mo,{stretchy:"false",children:"("}),(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mo,{stretchy:"false",children:")"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]})]}),(0,i.jsx)(e.mi,{children:"F"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\geq \\frac{(X - F) - V_{\\mathit{max}}}{F}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8193em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.355em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"1.01em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.485em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mopen mtight",children:"("}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"}),(0,i.jsx)(e.span,{className:"mclose mtight",children:")"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1645em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.357em",marginLeft:"-0.2222em",marginRight:"0.0714em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.5em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size3 size1 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.143em"},children:(0,i.jsx)(e.span,{})})})]})})]})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})," cycles. Using the assumption that ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsxs)(e.msub,{children:[(0,i.jsx)(e.mi,{children:"V"}),(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"m"}),(0,i.jsx)(e.mi,{children:"a"}),(0,i.jsx)(e.mi,{children:"x"})]})]}),(0,i.jsx)(e.mo,{children:"\u2264"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"V_{\\mathit{max}} \\leq F"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8333em",verticalAlign:"-0.15em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.22222em"},children:"V"}),(0,i.jsx)(e.span,{className:"msupsub",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.1514em"},children:(0,i.jsxs)(e.span,{style:{top:"-2.55em",marginLeft:"-0.2222em",marginRight:"0.05em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"2.7em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathit mtight",children:"max"})})})})]})}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.15em"},children:(0,i.jsx)(e.span,{})})})]})})]}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2264"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})]})]})," (assumption 2), we get ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u2265"}),(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.mi,{children:"F"})]})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\geq \\frac{X - 2F}{F}"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.8193em",verticalAlign:"-0.136em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}}),(0,i.jsx)(e.span,{className:"mrel",children:"\u2265"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2778em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.2173em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8723em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.394em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mord mtight",children:"2"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})]})]})," cycles."]}),"\n",(0,i.jsxs)(e.p,{children:["In order to execute ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"C"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"})]})})]})," cycles, we need ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"C"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mi,{children:"P"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"C \\cdot P"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07153em"},children:"C"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})]})]})," time."]}),"\n",(0,i.jsxs)(e.p,{children:["Thus, jailing the remaining ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"X - F"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.7667em",verticalAlign:"-0.0833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"F"})]})]})]})," fraction of the initial validator set corresponds to ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mo,{stretchy:"false",children:"("}),(0,i.jsx)(e.mi,{children:"X"}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mi,{children:"F"}),(0,i.jsx)(e.mo,{stretchy:"false",children:")"})]}),(0,i.jsx)(e.mi,{children:"F"})]})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\frac{P \\cdot (X - 2F)}{F}"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.355em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"1.01em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.485em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"P"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mopen mtight",children:"("}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mord mtight",children:"2"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"}),(0,i.jsx)(e.span,{className:"mclose mtight",children:")"})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]})]})})]})," time."]}),"\n",(0,i.jsxs)(e.p,{children:["In other words, the attack must take at least ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsxs)(e.mfrac,{children:[(0,i.jsxs)(e.mrow,{children:[(0,i.jsx)(e.mi,{children:"P"}),(0,i.jsx)(e.mo,{children:"\u22c5"}),(0,i.jsx)(e.mi,{children:"X"})]}),(0,i.jsx)(e.mi,{children:"F"})]}),(0,i.jsx)(e.mo,{children:"\u2212"}),(0,i.jsx)(e.mn,{children:"2"}),(0,i.jsx)(e.mi,{children:"P"})]}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"\\frac{P \\cdot X}{F} - 2P"})]})})}),(0,i.jsxs)(e.span,{className:"katex-html","aria-hidden":"true",children:[(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"1.2173em",verticalAlign:"-0.345em"}}),(0,i.jsxs)(e.span,{className:"mord",children:[(0,i.jsx)(e.span,{className:"mopen nulldelimiter"}),(0,i.jsx)(e.span,{className:"mfrac",children:(0,i.jsxs)(e.span,{className:"vlist-t vlist-t2",children:[(0,i.jsxs)(e.span,{className:"vlist-r",children:[(0,i.jsxs)(e.span,{className:"vlist",style:{height:"0.8723em"},children:[(0,i.jsxs)(e.span,{style:{top:"-2.655em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsx)(e.span,{className:"mord mtight",children:(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"F"})})})]}),(0,i.jsxs)(e.span,{style:{top:"-3.23em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"frac-line",style:{borderBottomWidth:"0.04em"}})]}),(0,i.jsxs)(e.span,{style:{top:"-3.394em"},children:[(0,i.jsx)(e.span,{className:"pstrut",style:{height:"3em"}}),(0,i.jsx)(e.span,{className:"sizing reset-size6 size3 mtight",children:(0,i.jsxs)(e.span,{className:"mord mtight",children:[(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.13889em"},children:"P"}),(0,i.jsx)(e.span,{className:"mbin mtight",children:"\u22c5"}),(0,i.jsx)(e.span,{className:"mord mathnormal mtight",style:{marginRight:"0.07847em"},children:"X"})]})})]})]}),(0,i.jsx)(e.span,{className:"vlist-s",children:"\u200b"})]}),(0,i.jsx)(e.span,{className:"vlist-r",children:(0,i.jsx)(e.span,{className:"vlist",style:{height:"0.345em"},children:(0,i.jsx)(e.span,{})})})]})}),(0,i.jsx)(e.span,{className:"mclose nulldelimiter"})]}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}}),(0,i.jsx)(e.span,{className:"mbin",children:"\u2212"}),(0,i.jsx)(e.span,{className:"mspace",style:{marginRight:"0.2222em"}})]}),(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord",children:"2"}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})]})]})," time (in the units of replenish period ",(0,i.jsxs)(e.span,{className:"katex",children:[(0,i.jsx)(e.span,{className:"katex-mathml",children:(0,i.jsx)(e.math,{xmlns:"http://www.w3.org/1998/Math/MathML",children:(0,i.jsxs)(e.semantics,{children:[(0,i.jsx)(e.mrow,{children:(0,i.jsx)(e.mi,{children:"P"})}),(0,i.jsx)(e.annotation,{encoding:"application/x-tex",children:"P"})]})})}),(0,i.jsx)(e.span,{className:"katex-html","aria-hidden":"true",children:(0,i.jsxs)(e.span,{className:"base",children:[(0,i.jsx)(e.span,{className:"strut",style:{height:"0.6833em"}}),(0,i.jsx)(e.span,{className:"mord mathnormal",style:{marginRight:"0.13889em"},children:"P"})]})})]}),")."]}),"\n"]}),"\n",(0,i.jsxs)(e.p,{children:["This property is useful because it allows us to reason about the time it takes to jail a certain percentage of the initial provider validator set from consumer initiated slash requests.\nFor example, if ",(0,i.jsx)(e.code,{children:"SlashMeterReplenishFraction"})," is set to ",(0,i.jsx)(e.code,{children:"0.06"}),", then it takes no less than 4 replenishment periods to jail 33% of the initial provider validator set on the Cosmos Hub.\nNote that as of writing this on 11/29/22, the Cosmos Hub does not have a validator with more than 6% of total voting power."]}),"\n",(0,i.jsx)(e.p,{children:"Note also that 4 replenishment period is a worst case scenario that depends on well crafted attack timings."}),"\n",(0,i.jsx)(e.h3,{id:"how-unjailing-affects-the-main-throttling-property",children:"How Unjailing Affects the Main Throttling Property"}),"\n",(0,i.jsx)(e.p,{children:"Note that the jailing allowance is directly proportional to the current total voting power of the provider chain. Therefore, if honest validators don't unjail themselves during the attack, the total voting power of the provider chain will decrease over the course of the attack, and the attack will be slowed down, main throttling property is maintained."}),"\n",(0,i.jsx)(e.p,{children:"If honest validators do unjail themselves, the total voting power of the provider chain will still not become higher than when the attack started (unless new token delegations happen), therefore the main property is still maintained. Moreover, honest validators unjailing themselves helps prevent the attacking validators from gaining control of the provider."}),"\n",(0,i.jsx)(e.p,{children:"In summary, the throttling mechanism as designed has desirable properties whether or not honest validators unjail themselves over the course of the attack."}),"\n",(0,i.jsx)(e.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(e.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"The described attack is slowed down in seemingly all cases."}),"\n",(0,i.jsx)(e.li,{children:"If certain assumptions hold, the described attack is slowed down in a way that can be precisely time-bounded."}),"\n"]}),"\n",(0,i.jsx)(e.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["Throttling introduces a vector for a malicious consumer chain to halt the provider, see issue below.\nHowever, this is sacrificing liveness in a edge case scenario for the sake of security.\nAs an improvement, ",(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/713",children:"using retries"})," would fully prevent this attack vector."]}),"\n"]}),"\n",(0,i.jsx)(e.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:"Additional state is introduced to the provider chain."}),"\n",(0,i.jsx)(e.li,{children:"VSCMatured and slash packet data is not always handled in the same block that it is received."}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/404",children:"Original issue inspiring throttling feature"})}),"\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/594",children:"Issue on DOS vector"})}),"\n",(0,i.jsx)(e.li,{children:(0,i.jsx)(e.a,{href:"https://github.com/cosmos/interchain-security/issues/685",children:"Consideration of another attack vector"})}),"\n"]})]})}function d(s={}){const{wrapper:e}={...(0,n.a)(),...s.components};return e?(0,i.jsx)(e,{...s,children:(0,i.jsx)(m,{...s})}):m(s)}},1151:(s,e,a)=>{a.d(e,{Z:()=>r,a:()=>l});var i=a(7294);const n={},t=i.createContext(n);function l(s){const e=i.useContext(t);return i.useMemo((function(){return"function"==typeof s?s(e):{...e,...s}}),[e,s])}function r(s){let e;return e=s.disableParentContext?"function"==typeof s.components?s.components(n):s.components||n:l(s.components),i.createElement(t.Provider,{value:e},s.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/bc8b8418.63027b8e.js b/assets/js/bc8b8418.63027b8e.js
new file mode 100644
index 0000000000..705622721f
--- /dev/null
+++ b/assets/js/bc8b8418.63027b8e.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4704],{1824:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>c,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>l});var n=t(5893),r=t(1151);const a={sidebar_position:2},o="Terminology",s={id:"introduction/terminology",title:"Terminology",description:"You may have heard of one or multiple buzzwords thrown around in the cosmos and wider crypto ecosystem such shared security, interchain security, replicated security, cross chain validation, and mesh security. These terms will be clarified below, before diving into any introductions.",source:"@site/docs/introduction/terminology.md",sourceDirName:"introduction",slug:"/introduction/terminology",permalink:"/interchain-security/introduction/terminology",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Overview",permalink:"/interchain-security/introduction/overview"},next:{title:"Interchain Security Parameters",permalink:"/interchain-security/introduction/params"}},c={},l=[{value:"Shared Security",id:"shared-security",level:2},{value:"Interchain Security",id:"interchain-security",level:2},{value:"Replicated Security",id:"replicated-security",level:2},{value:"Partial Set Security",id:"partial-set-security",level:2},{value:"Mesh security",id:"mesh-security",level:2},{value:"Consumer Chain",id:"consumer-chain",level:2},{value:"Standalone Chain",id:"standalone-chain",level:2},{value:"Changeover Procedure",id:"changeover-procedure",level:2}];function h(e){const i={a:"a",h1:"h1",h2:"h2",p:"p",strong:"strong",...(0,r.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"terminology",children:"Terminology"}),"\n",(0,n.jsx)(i.p,{children:"You may have heard of one or multiple buzzwords thrown around in the cosmos and wider crypto ecosystem such shared security, interchain security, replicated security, cross chain validation, and mesh security. These terms will be clarified below, before diving into any introductions."}),"\n",(0,n.jsx)(i.h2,{id:"shared-security",children:"Shared Security"}),"\n",(0,n.jsx)(i.p,{children:"Shared security is a family of technologies that include optimistic rollups, zk-rollups, sharding and Interchain Security. Ie. any protocol or technology that can allow one blockchain to lend/share its proof-of-stake security with another blockchain or off-chain process."}),"\n",(0,n.jsx)(i.h2,{id:"interchain-security",children:"Interchain Security"}),"\n",(0,n.jsx)(i.p,{children:"Interchain Security is the Cosmos-specific category of Shared Security that uses IBC (Inter-Blockchain Communication), i.e. any shared security protocol built with IBC."}),"\n",(0,n.jsx)(i.h2,{id:"replicated-security",children:"Replicated Security"}),"\n",(0,n.jsx)(i.p,{children:'A particular protocol/implementation of Interchain Security that fully replicates the security and decentralization of a validator set across multiple blockchains. Replicated security has also been referred to as "Cross Chain Validation" or "Interchain Security V1", a legacy term for the same protocol. That is, a "provider chain" such as the Cosmos Hub can share its exact validator set with multiple consumer chains by communicating changes in its validator set over IBC.'}),"\n",(0,n.jsx)(i.h2,{id:"partial-set-security",children:"Partial Set Security"}),"\n",(0,n.jsx)(i.p,{children:'A major iteration of Interchain Security, also known as "Interchain Security V2". Partial Set Security allows a provider chain to share only a subset of its validator set with a consumer chain. This subset can be determined by the top N% validators by voting power, or by validators opting in to validate the consumer chain. Partial Set Security allows for more flexible security tradeoffs than Replicated Security.'}),"\n",(0,n.jsx)(i.h2,{id:"mesh-security",children:"Mesh security"}),"\n",(0,n.jsxs)(i.p,{children:["A protocol built on IBC that allows delegators on a cosmos chain to re-delegate their stake to validators in another chain's own validator set, using the original chain's token (which remains bonded on the original chain). For a deeper exploration of mesh security, see ",(0,n.jsx)(i.a,{href:"https://informal.systems/blog/replicated-vs-mesh-security",children:"Replicated vs. Mesh Security on the Informal Blog"}),"."]}),"\n",(0,n.jsx)(i.h2,{id:"consumer-chain",children:"Consumer Chain"}),"\n",(0,n.jsx)(i.p,{children:"Chain that is secured by the validator set of the provider, instead of its own.\nInterchain Security allows a subset of the provider chain's validator set to validate blocks on the consumer chain."}),"\n",(0,n.jsx)(i.h2,{id:"standalone-chain",children:"Standalone Chain"}),"\n",(0,n.jsx)(i.p,{children:"Chain that is secured by its own validator set. This chain does not participate in Interchain Security."}),"\n",(0,n.jsx)(i.p,{children:'Standalone chains may sometimes be called "sovereign" - the terms are synonymous.'}),"\n",(0,n.jsx)(i.h2,{id:"changeover-procedure",children:"Changeover Procedure"}),"\n",(0,n.jsxs)(i.p,{children:["Chains that were not initially launched as consumers of Interchain Security can still participate in the protocol and leverage the economic security of the provider chain. The process where a standalone chain transitions to being a replicated consumer chain is called the ",(0,n.jsx)(i.strong,{children:"changeover procedure"})," and is part of the interchain security protocol. After the changeover, the new consumer chain will retain all existing state, including the IBC clients, connections and channels already established by the chain."]})]})}function d(e={}){const{wrapper:i}={...(0,r.a)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},1151:(e,i,t)=>{t.d(i,{Z:()=>s,a:()=>o});var n=t(7294);const r={},a=n.createContext(r);function o(e){const i=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function s(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),n.createElement(a.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/bdf2101f.feae5bf3.js b/assets/js/bdf2101f.feae5bf3.js
new file mode 100644
index 0000000000..ca8253038b
--- /dev/null
+++ b/assets/js/bdf2101f.feae5bf3.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7943],{3644:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>t,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var r=o(5893),i=o(1151);const s={sidebar_position:3},t="ICS Provider Proposals",a={id:"features/proposals",title:"ICS Provider Proposals",description:"Interchain security module introduces 3 new proposal types to the provider.",source:"@site/versioned_docs/version-v5.0.0/features/proposals.md",sourceDirName:"features",slug:"/features/proposals",permalink:"/interchain-security/v5.0.0/features/proposals",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"tutorialSidebar",previous:{title:"Reward Distribution",permalink:"/interchain-security/v5.0.0/features/reward-distribution"},next:{title:"Consumer Initiated Slashing",permalink:"/interchain-security/v5.0.0/features/slashing"}},d={},c=[{value:"ConsumerAdditionProposal",id:"consumeradditionproposal",level:2},{value:"ConsumerRemovalProposal",id:"consumerremovalproposal",level:2},{value:"ChangeRewardDenomProposal",id:"changerewarddenomproposal",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"ics-provider-proposals",children:"ICS Provider Proposals"}),"\n",(0,r.jsx)(n.p,{children:"Interchain security module introduces 3 new proposal types to the provider."}),"\n",(0,r.jsx)(n.p,{children:"The proposals are used to propose upcoming interchain security events through governance."}),"\n",(0,r.jsx)(n.h2,{id:"consumeradditionproposal",children:(0,r.jsx)(n.code,{children:"ConsumerAdditionProposal"})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["If you are preparing a ",(0,r.jsx)(n.code,{children:"ConsumerAdditionProposal"})," you can find more information in the ",(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/onboarding",children:"consumer onboarding checklist"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Proposal type used to suggest adding a new consumer chain."}),"\n",(0,r.jsxs)(n.p,{children:["When proposals of this type are passed and the ",(0,r.jsx)(n.code,{children:"spawn_time"})," specified in the proposal is reached, all provider chain validators are expected to run infrastructure (validator nodes) for the proposed consumer chain."]}),"\n",(0,r.jsx)(n.p,{children:"Minimal example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:'{\n // Time on the provider chain at which the consumer chain genesis is finalized and all validators\n // will be responsible for starting their consumer chain validator node.\n "spawn_time": "2023-02-28T20:40:00.000000Z",\n "title": "Add consumer chain",\n "description": ".md description of your chain and all other relevant information",\n "chain_id": "newchain-1",\n "initial_height" : {\n "revision_height": 0,\n "revision_number": 1,\n },\n // Unbonding period for the consumer chain.\n // It should be smaller than that of the provider.\n "unbonding_period": 86400000000000,\n // Timeout period for CCV related IBC packets.\n // Packets are considered timed-out after this interval elapses.\n "ccv_timeout_period": 259200000000000,\n "transfer_timeout_period": 1800000000000,\n "consumer_redistribution_fraction": "0.75",\n "blocks_per_distribution_transmission": 1000,\n "historical_entries": 10000,\n "genesis_hash": "d86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0",\n "binary_hash": "376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1"\n // relevant for chains performing a standalone to consumer changeover\n // in order to maintain the existing ibc transfer channel\n "distribution_transmission_channel": "channel-123"\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["More examples can be found in the interchain security testnet repository ",(0,r.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/stopped/baryon-1/proposal-baryon-1.json",children:"here"})," and ",(0,r.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/stopped/noble-1/start-proposal-noble-1.json",children:"here"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"consumerremovalproposal",children:(0,r.jsx)(n.code,{children:"ConsumerRemovalProposal"})}),"\n",(0,r.jsx)(n.p,{children:"Proposal type used to suggest removing an existing consumer chain."}),"\n",(0,r.jsx)(n.p,{children:"When proposals of this type are passed, the consumer chain in question will be gracefully removed from interchain security and validators will no longer be required to run infrastructure for the specified chain.\nAfter the consumer chain removal, the chain in question will no longer be secured by the provider's validator set."}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["The chain in question my continue to produce blocks, but the validator set can no longer be slashed for any infractions committed on that chain.\nAdditional steps are required to completely offboard a consumer chain, such as re-introducing the staking module and removing the provider's validators from the active set.\nMore information will be made available in the ",(0,r.jsx)(n.a,{href:"/interchain-security/v5.0.0/consumer-development/offboarding",children:"Consumer Offboarding Checklist"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Minimal example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:'{\n // the time on the provider chain at which all validators are responsible to stop their consumer chain validator node\n "stop_time": "2023-03-07T12:40:00.000000Z",\n // the chain-id of the consumer chain to be stopped\n "chain_id": "consumerchain-1",\n "title": "This was a great chain",\n "description": "Here is a .md formatted string specifying removal details"\n}\n'})}),"\n",(0,r.jsx)(n.h2,{id:"changerewarddenomproposal",children:"ChangeRewardDenomProposal"}),"\n",(0,r.jsx)(n.p,{children:"Proposal type used to mutate the set of denoms accepted by the provider as rewards."}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsxs)(n.p,{children:["A ",(0,r.jsx)(n.code,{children:"ChangeRewardDenomProposal"})," will only be accepted on the provider chain if at least one of the ",(0,r.jsx)(n.code,{children:"denomsToAdd"})," or ",(0,r.jsx)(n.code,{children:"denomsToRemove"})," fields is populated with at least one denom. Also, a denom cannot be repeated in both sets."]})}),"\n",(0,r.jsx)(n.p,{children:"Minimal example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:'{\n "title": "Add uatom as a reward denom",\n "description": "Here is more information about the proposal",\n "denomsToAdd": ["uatom"],\n "denomsToRemove": []\n}\n'})}),"\n",(0,r.jsxs)(n.admonition,{type:"tip",children:[(0,r.jsxs)(n.p,{children:["Besides native provider denoms (e.g., ",(0,r.jsx)(n.code,{children:"uatom"})," for the Cosmos Hub), please use the ",(0,r.jsx)(n.code,{children:"ibc/*"})," denom trace format.\nFor example, for ",(0,r.jsx)(n.code,{children:"untrn"})," transferred over the path ",(0,r.jsx)(n.code,{children:"transfer/channel-569"}),", the denom trace\ncan be queried using the following command:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"> gaiad query ibc-transfer denom-hash transfer/channel-569/untrn\nhash: 0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5\n"})}),(0,r.jsxs)(n.p,{children:["Then use the resulting hash in the ",(0,r.jsx)(n.code,{children:"ChangeRewardDenomProposal"}),", e.g.,"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:'{\n "title": "Add untrn as a reward denom",\n "description": "Here is more information about the proposal",\n "denomsToAdd": ["ibc/0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5"],\n "denomsToRemove": []\n}\n'})})]})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>a,a:()=>t});var r=o(7294);const i={},s=r.createContext(i);function t(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/bfc97f30.ec5561cc.js b/assets/js/bfc97f30.ec5561cc.js
new file mode 100644
index 0000000000..dd3cc68fec
--- /dev/null
+++ b/assets/js/bfc97f30.ec5561cc.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9253],{3473:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>h});var n=i(5893),a=i(1151);const o={sidebar_position:6},r="Partial Set Security",s={id:"features/partial-set-security",title:"Partial Set Security",description:"Partial Set Security (PSS) allows consumer chains to leverage only a subset of validators from the provider chain, which offers more flexibility than the traditional Replicated Security model. By introducing the top_N parameter, each consumer chain can choose the extent of security needed:",source:"@site/docs/features/partial-set-security.md",sourceDirName:"features",slug:"/features/partial-set-security",permalink:"/interchain-security/features/partial-set-security",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:6,frontMatter:{sidebar_position:6},sidebar:"tutorialSidebar",previous:{title:"Democracy modules",permalink:"/interchain-security/features/democracy-modules"},next:{title:"Power Shaping",permalink:"/interchain-security/features/power-shaping"}},c={},h=[];function l(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",li:"li",p:"p",ul:"ul",...(0,a.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"partial-set-security",children:"Partial Set Security"}),"\n",(0,n.jsx)(t.p,{children:"Partial Set Security (PSS) allows consumer chains to leverage only a subset of validators from the provider chain, which offers more flexibility than the traditional Replicated Security model. By introducing the top_N parameter, each consumer chain can choose the extent of security needed:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Top N: Requires the top N% validators from the provider chain to secure the consumer chain. This guarantees that the validators with the most power on the provider will validate the consumer chain, while others can voluntarily opt in."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:["Opt-In: If the ",(0,n.jsx)(t.code,{children:"top_N"})," parameter is set to zero, no validator is mandated to secure the consumer chain. Instead, any validator from the provider chain can opt in using a dedicated transaction."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"An advantage of a Top N chain is that the consumer chain is guaranteed to receive at least a certain fraction of the market cap of the provider chain in security. In turn, this chain needs to be approved by governance, since validators will be forced to run the chain. Thus, Top N chains should typically expect to need to provide a strong case for why they should be added to the provider chain, and they should make sure they offer enough rewards to incentivize validators and delegators to vote for their proposal."}),"\n",(0,n.jsx)(t.p,{children:"Opt-In chains, on the other hand, are more flexible. While for technical reasons, they are also currently added via governance proposals, since validators are never forced to validate these chains and simply opt in if they want to, they should typically expect to get their proposals approved much more easily compared to Top N chains, since validators that do not want to validate the chain can simply choose not to opt in.\nHowever, opt in chains do not get a fixed amount of security as a relation of the market cap of the provider as top N chains do, so opt in chains might want to keep an eye on how many validators have opted in to validate their chain and adjust their reward emissions accordingly to incentivize validators."}),"\n",(0,n.jsx)(t.admonition,{type:"tip",children:(0,n.jsx)(t.p,{children:"Partial Set Security is handled only by the provider chain - the consumer chains are simply sent validator sets, and they are not aware that this represents only a subset of the provider chain's validator set."})}),"\n",(0,n.jsxs)(t.admonition,{type:"caution",children:[(0,n.jsx)(t.p,{children:"Both Opt In and Top N chains currently require a governance proposal to be added to the provider chain."}),(0,n.jsx)(t.p,{children:"For Top N chains, this is also the long term vision for how they are launched."}),(0,n.jsx)(t.p,{children:"For Opt In chains, this is a temporary measure to prevent issues around chain ID squatting, i.e. someone could spuriously register many desirable chain IDs of upcoming consumer chain and simply deny legitimate consumer chains from using them. Eventually, the plan is to allow launching Opt In chains permissionlessly without going through governance, with quality control being handled by the market of validators deciding which chains they would like to validate on."})]}),"\n",(0,n.jsx)(t.admonition,{type:"tip",children:(0,n.jsxs)(t.p,{children:["A running Top N consumer chain might want to become an Opt-In chain or vice versa. This can be achieved by issuing\na ",(0,n.jsx)(t.a,{href:"/interchain-security/features/proposals#consumermodificationproposal",children:(0,n.jsx)(t.code,{children:"ConsumerModificationProposal"})}),"."]})})]})}function d(e={}){const{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},1151:(e,t,i)=>{i.d(t,{Z:()=>s,a:()=>r});var n=i(7294);const a={},o=n.createContext(a);function r(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/c1444bce.54c826a6.js b/assets/js/c1444bce.54c826a6.js
new file mode 100644
index 0000000000..f85c821b01
--- /dev/null
+++ b/assets/js/c1444bce.54c826a6.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5776],{7258:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>l,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var n=o(5893),i=o(1151);const s={sidebar_position:16,title:"Partial Set Security"},a="ADR 015: Partial Set Security",r={id:"adrs/adr-015-partial-set-security",title:"Partial Set Security",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-015-partial-set-security.md",sourceDirName:"adrs",slug:"/adrs/adr-015-partial-set-security",permalink:"/interchain-security/v5.0.0/adrs/adr-015-partial-set-security",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:16,frontMatter:{sidebar_position:16,title:"Partial Set Security"},sidebar:"tutorialSidebar",previous:{title:"Epochs",permalink:"/interchain-security/v5.0.0/adrs/adr-014-epochs"}},d={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"How do consumer chains join?",id:"how-do-consumer-chains-join",level:3},{value:"State & Query",id:"state--query",level:4},{value:"How do validators opt in?",id:"how-do-validators-opt-in",level:3},{value:"State & Query",id:"state--query-1",level:4},{value:"When do validators opt in?",id:"when-do-validators-opt-in",level:4},{value:"How do validators opt out?",id:"how-do-validators-opt-out",level:3},{value:"State & Query",id:"state--query-2",level:4},{value:"When does a consumer chain start?",id:"when-does-a-consumer-chain-start",level:3},{value:"How do we send the partial validator sets to the consumer chains?",id:"how-do-we-send-the-partial-validator-sets-to-the-consumer-chains",level:3},{value:"How do we distribute rewards?",id:"how-do-we-distribute-rewards",level:3},{value:"Misbehaviour",id:"misbehaviour",level:3},{value:"Fraud votes",id:"fraud-votes",level:4},{value:"Double signing",id:"double-signing",level:4},{value:"Downtime",id:"downtime",level:4},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function h(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"adr-015-partial-set-security",children:"ADR 015: Partial Set Security"}),"\n",(0,n.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"2024-01-22: Proposed, first draft of ADR."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,n.jsx)(t.p,{children:"Proposed"}),"\n",(0,n.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,n.jsxs)(t.p,{children:["Currently, in ",(0,n.jsx)(t.em,{children:"Replicated Security"}),", the entire validator set of the provider chain is used to secure consumer chains. There are at least three concerns with this approach.\nFirst, a large number of validators might be forced to validate consumer chains they are not interested in securing.\nSecond, it is costly for small validators to secure additional chains. This concern is only partially addressed through ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-009-soft-opt-out.md",children:"soft opt-out"})," that allows small validators to opt out from validating consumer chains.\nThird and for the above reasons, it is challenging for a new consumer chain to join Replicated Security."]}),"\n",(0,n.jsxs)(t.p,{children:["As a solution, we present ",(0,n.jsx)(t.em,{children:"Partial Set Security"})," (PSS). As the name suggests, PSS allows for every consumer chain to be secured by only a subset of the provider validator set.\nIn what follows we propose the exact steps we need to take to implement PSS. This is a first iteration of PSS, and therefore we present the most minimal solution that make PSS possible."]}),"\n",(0,n.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,n.jsxs)(t.p,{children:["In Replicated Security, all the provider validators have to secure every consumer chain (with the exception of those validators allowed to opt out through the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-009-soft-opt-out.md",children:"soft opt-out"})," feature)."]}),"\n",(0,n.jsxs)(t.p,{children:["In PSS, we allow validators to opt in and out of validating any given consumer chain.\nThis has one exception: we introduce a parameter ",(0,n.jsx)(t.code,{children:"N"})," for each consumer chain and require that the validators in top ",(0,n.jsx)(t.code,{children:"N%"})," of the provider's voting power have to secure the consumer chain.\nValidators outside of the top ",(0,n.jsx)(t.code,{children:"N%"})," can dynamically opt in if they want to validate on the consumer chain."]}),"\n",(0,n.jsxs)(t.p,{children:["For example, if a consumer chain has ",(0,n.jsx)(t.code,{children:"N = 95%"}),", then it ultimately receives the same security it receives today with Replicated Security (with a default ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-009-soft-opt-out.md",children:"SoftOptOutThreshold"})," of 5%).\nOn the other hand, if a consumer chain has ",(0,n.jsx)(t.code,{children:"N = 0%"}),", then no validator is forced to validate the chain, but validators can opt in to do so instead."]}),"\n",(0,n.jsxs)(t.p,{children:["For the remainder of this ADR, we call a consumer chain ",(0,n.jsx)(t.em,{children:"Top N"})," if it has joined as a Top N chain with ",(0,n.jsx)(t.code,{children:"N > 0"})," and ",(0,n.jsx)(t.em,{children:"Opt In"})," chain otherwise. An Opt In consumer chain is secured only by the validators that have opted in to secure that chain."]}),"\n",(0,n.jsxs)(t.p,{children:["We intend to implement PSS using a feature branch off ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/tree/v4.0.0",children:"v4.0.0 interchain security"}),"."]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-consumer-chains-join",children:"How do consumer chains join?"}),"\n",(0,n.jsxs)(t.p,{children:["As a simplification and to avoid ",(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/pss-permissionless-vs-premissioned-lite-opt-in-consumer-chains/12984/17",children:"chain id squatting"}),", a consumer chain can only join PSS through a governance proposal and not in a permissionless way."]}),"\n",(0,n.jsx)(t.p,{children:'However, this proposal type will be modified so that it requires a lower quorum percentage than normal proposal, and every validator who voted "YES" on the proposal will form the consumer chain\'s initial validator set.'}),"\n",(0,n.jsxs)(t.p,{children:["Consumer chains join PSS the same way chains now join Replicated Security, namely through a ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})," proposal.\nWe extend ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/proto/interchain_security/ccv/provider/v1/provider.proto#L27",children:(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})})," with one optional field:"]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.code,{children:"uint32 top_N"}),": Corresponds to the percentage of validators that join under the Top N case.\nFor example, ",(0,n.jsx)(t.code,{children:"53"})," corresponds to a Top 53% chain, meaning that the top ",(0,n.jsx)(t.code,{children:"53%"})," provider validators have to validate the proposed consumer chain.\n",(0,n.jsx)(t.code,{children:"top_N"})," can be ",(0,n.jsx)(t.code,{children:"0"})," or include any value in ",(0,n.jsx)(t.code,{children:"[50, 100]"}),". A chain can join with ",(0,n.jsx)(t.code,{children:"top_N == 0"})," as an Opt In, or with ",(0,n.jsx)(t.code,{children:"top_N \u2208 [50, 100]"})," as a Top N chain."]}),"\n",(0,n.jsxs)(t.p,{children:["In case of a Top N chain, we restrict the possible values of ",(0,n.jsx)(t.code,{children:"top_N"})," from ",(0,n.jsx)(t.code,{children:"(0, 100]"})," to ",(0,n.jsx)(t.code,{children:"[50, 100]"}),".\nBy having ",(0,n.jsx)(t.code,{children:"top_N >= 50"})," we can guarantee that we cannot have a successful attack, assuming that at most ",(0,n.jsx)(t.code,{children:"1/3"})," of provider validators can be malicious.\nThis is because, a Top N chain with ",(0,n.jsx)(t.code,{children:"N >= 50%"})," would have at least ",(0,n.jsx)(t.code,{children:"1/3"})," honest validators, which is sufficient to stop attacks.\nAdditionally, by having ",(0,n.jsx)(t.code,{children:"N >= 50%"})," (and hence ",(0,n.jsx)(t.code,{children:"N > (VetoThreshold = 33.4%)"}),") we enable the top N validators to ",(0,n.jsx)(t.code,{children:"Veto"})," any ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})," for consumer chains they do not want to validate."]}),"\n",(0,n.jsxs)(t.p,{children:["If a proposal has the ",(0,n.jsx)(t.code,{children:"top_N"})," argument wrongly set, it should get rejected in [ValidateBasic] (",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/proposal.go#L86",children:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/proposal.go#L86"}),")."]}),"\n",(0,n.jsxs)(t.p,{children:["In the code, we distinguish whether a chain is ",(0,n.jsx)(t.em,{children:"Top N"})," or ",(0,n.jsx)(t.em,{children:"Opt In"})," by checking whether ",(0,n.jsx)(t.code,{children:"top_N"})," is zero or not."]}),"\n",(0,n.jsxs)(t.p,{children:["In a future version of PSS, we intend to introduce a ",(0,n.jsx)(t.code,{children:"ConsumerModificationProposal"})," so that we can modify the parameters of a consumer chain, e.g, a chain that is ",(0,n.jsx)(t.em,{children:"Opt In"})," to become ",(0,n.jsx)(t.em,{children:"Top N"}),", etc."]}),"\n",(0,n.jsx)(t.h4,{id:"state--query",children:"State & Query"}),"\n",(0,n.jsxs)(t.p,{children:["We augment the provider module\u2019s state to keep track of the ",(0,n.jsx)(t.code,{children:"top_N"})," value for each consumer chain. The key to store this information would be:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"topNBytePrefix | len(chainID) | chainID\n"})}),"\n",(0,n.jsxs)(t.p,{children:["To create the above key, we can use ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/types/keys.go#L418",children:(0,n.jsx)(t.code,{children:"ChainIdWithLenKey"})}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["Then in the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/keeper.go",children:"keeper"})," we introduce methods as follows:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-golang",children:"func (k Keeper) SetTopN(ctx sdk.Context, chainID string, topN uint32)\nfunc (k Keeper) IsTopN(ctx sdk.Context, chainID string) bool\nfunc (k Keeper) IsOptIn(ctx sdk.Context, chainID string) bool\n\n// returns the N if Top N chain, otherwise an error\nfunc (k Keeper) GetTopN(ctx sdk.Context, chainID string) (uint32, error)\n"})}),"\n",(0,n.jsxs)(t.p,{children:["We also extend the ",(0,n.jsx)(t.code,{children:"interchain-security-pd query provider list-consumer-chains"}),' query to return information on whether a consumer chain is an Opt In or a Top N chain and with what N.\nThis way, block explorers can present informative messages such as "This chain is secured by N% of the provider chain" for consumer chains.']}),"\n",(0,n.jsx)(t.h3,{id:"how-do-validators-opt-in",children:"How do validators opt in?"}),"\n",(0,n.jsxs)(t.p,{children:["A validator can opt in by sending a new type of message that we introduce in ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/proto/interchain_security/ccv/provider/v1/tx.proto#L1",children:"tx.proto"}),"."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-protobuf",children:"message MsgOptIn {\n // the chain id of the consumer chain to opt in to\n string chainID = 1;\n // the provider address of the validator\n string providerAddr = 2;\n // (optional) the consensus public key to use on the consumer\n optional string consumerKey = 3;\n}\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Note that in a Top N consumer chain, the top ",(0,n.jsx)(t.code,{children:"N%"})," provider validators have to validate the consumer chain.\nNevertheless, validators in the bottom ",(0,n.jsx)(t.code,{children:"(100 - N)%"})," can opt in to validate as well.\nProvider validators that belong or enter the top ",(0,n.jsx)(t.code,{children:"N%"})," validators are ",(0,n.jsx)(t.em,{children:"automatically"})," opted in to validate a Top N consumer chain.\nThis means that if a validator ",(0,n.jsx)(t.code,{children:"V"})," belongs to the top ",(0,n.jsx)(t.code,{children:"N%"})," validators but later falls (e.g., due to undelegations) to the bottom ",(0,n.jsx)(t.code,{children:"(100 - N)%"}),", ",(0,n.jsx)(t.code,{children:"V"})," is still considered opted in and has to validate unless ",(0,n.jsx)(t.code,{children:"V"})," sends a ",(0,n.jsx)(t.code,{children:"MsgOptOut"})," message (see below).\nBy automatically opting in validators when they enter the top ",(0,n.jsx)(t.code,{children:"N%"})," validators and by forcing top ",(0,n.jsx)(t.code,{children:"N%"})," validators to explicitly opt out in case they fall to the ",(0,n.jsx)(t.code,{children:"(100 - N)%"})," bottom validators we simplify the design of PSS."]}),"\n",(0,n.jsxs)(t.p,{children:["Note that a validator can send a ",(0,n.jsx)(t.code,{children:"MsgOptIn"})," message even if the consumer chain is not yet running. To do this we reuse the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/key_assignment.go#L644",children:(0,n.jsx)(t.code,{children:"IsConsumerProposedOrRegistered"})}),". If the ",(0,n.jsx)(t.code,{children:"chainID"})," does not exist, the ",(0,n.jsx)(t.code,{children:"MsgOptIn"})," should fail, as well as if the provider address does not exist."]}),"\n",(0,n.jsxs)(t.p,{children:["Optionally, a validator that opts in can provide a ",(0,n.jsx)(t.code,{children:"consumerKey"})," so that it assigns a different consumer key (from the provider) to the consumer chain.\nNaturally, a validator can always change the consumer key on a consumer chain by sending a ",(0,n.jsx)(t.code,{children:"MsgAssignConsumerKey"})," message at a later point in time, as is done in Replicated Security."]}),"\n",(0,n.jsx)(t.h4,{id:"state--query-1",children:"State & Query"}),"\n",(0,n.jsxs)(t.p,{children:["For each validator, we store a pair ",(0,n.jsx)(t.code,{children:"(blockHeight, isOptedIn)"})," that contains the block height the validator opted in and whether the validator is currently opted in or not, under the key:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"optedInBytePrefix | len(chainID) | chainID | addr\n"})}),"\n",(0,n.jsxs)(t.p,{children:["By using a prefix iterator on ",(0,n.jsx)(t.code,{children:"optedInBytePrefix | len(chainID) | chainID"})," we retrieve all the opted in validators."]}),"\n",(0,n.jsxs)(t.p,{children:["We introduce the following ",(0,n.jsx)(t.code,{children:"Keeper"})," methods."]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-golang",children:"// returns all the validators that have opted in on chain `chainID`\nfunc (k Keeper) GetOptedInValidators(ctx sdk.Context, chainID string) []Validators\n\nfunc (k Keeper) IsValidatorOptedIn(ctx sdk.Context, chainID string, val Validator) bool\n"})}),"\n",(0,n.jsx)(t.p,{children:"We introduce the following two queries:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"interchain-security-pd query provider optedInValidators $chainID\ninterchain-security-pd query provider hasToValidate $providerAddr\n"})}),"\n",(0,n.jsx)(t.p,{children:"One query to retrieve the validators that are opted in and hence the validators that need to validate the consumer chain and one query that given a validator's address returns all the chains this validator has to validate."}),"\n",(0,n.jsx)(t.h4,{id:"when-do-validators-opt-in",children:"When do validators opt in?"}),"\n",(0,n.jsxs)(t.p,{children:["As described earlier, validators can manually opt in by sending a ",(0,n.jsx)(t.code,{children:"MsgOptIn"})," message.\nAdditionally, in a Top N chain, a validator is automatically opted in when it moves from the bottom ",(0,n.jsx)(t.code,{children:"(100 - N)%"})," to the top ",(0,n.jsx)(t.code,{children:"N%"})," validators."]}),"\n",(0,n.jsxs)(t.p,{children:["Lastly, validators can also opt in if they vote ",(0,n.jsx)(t.code,{children:"Yes"})," during the ",(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})," that introduces a consumer chain.\nThis simplifies validators operations because they do not have to send an additional message to opt in."]}),"\n",(0,n.jsxs)(t.p,{children:["Because the ",(0,n.jsx)(t.code,{children:"Tally"})," method ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.7/x/gov/keeper/tally.go#L71",children:"deletes the votes"})," after reading them, we cannot check the votes of the validators after the votes have been tallied.\nTo circumvent this, we introduce a hook for ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.7/x/gov/keeper/vote.go#L35",children:(0,n.jsx)(t.code,{children:"AfterProposalVote"})})," and keep track of all the votes cast by a validator.\nIf a validator casts more than one vote, we only consider the latest vote.\nFinally, we only consider a validator has opted in if it casts a 100% ",(0,n.jsx)(t.code,{children:"Yes"})," vote in case of a ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-037-gov-split-vote.md",children:"weighted vote"}),"."]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-validators-opt-out",children:"How do validators opt out?"}),"\n",(0,n.jsx)(t.p,{children:"Validators that have opted in on a chain can opt out by sending the following message:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-protobuf",children:"message MsgOptOut {\n // the chain id of the consumer chain to opt out from\n string chainID = 1;\n // the provider address of the validator\n string providerAddr = 2;\n}\n"})}),"\n",(0,n.jsxs)(t.p,{children:["Validators can only opt out after a consumer chain has started and hence the above message returns an error if the chain with ",(0,n.jsx)(t.code,{children:"chainID"})," is not running.\nAdditionally, a validator that belongs to the top ",(0,n.jsx)(t.code,{children:"N%"})," validators cannot opt out from a Top N chain and hence a ",(0,n.jsx)(t.code,{children:"MsgOptOut"})," would error in such a case."]}),"\n",(0,n.jsx)(t.h4,{id:"state--query-2",children:"State & Query"}),"\n",(0,n.jsx)(t.p,{children:"We also update the state of the opted-in validators when a validator has opted out by removing the opted-out validator."}),"\n",(0,n.jsxs)(t.p,{children:["Note that only opted-in validators can be punished for downtime on a consumer chain.\nFor this, we use historical info of all the validators that have opted in; We can examine the ",(0,n.jsx)(t.code,{children:"blockHeight"})," stored under the key ",(0,n.jsx)(t.code,{children:"optedInBytePrefix | len(chainID) | chainID | addr"})," to see if a validator was opted in.\nThis way we can jail validators for downtime knowing that indeed the validators have opted in at some point in the past.\nOtherwise, we can think of a scenario where a validator ",(0,n.jsx)(t.code,{children:"V"})," is down for a period of time, but before ",(0,n.jsx)(t.code,{children:"V"})," gets punished for downtime, validator ",(0,n.jsx)(t.code,{children:"V"})," opts out, and then we do not know whether ",(0,n.jsx)(t.code,{children:"V"})," should be punished or not."]}),"\n",(0,n.jsx)(t.h3,{id:"when-does-a-consumer-chain-start",children:"When does a consumer chain start?"}),"\n",(0,n.jsxs)(t.p,{children:["A Top N consumer chain always starts at the specified date (",(0,n.jsx)(t.code,{children:"spawn_time"}),") if the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/proto/interchain_security/ccv/provider/v1/provider.proto#L27",children:(0,n.jsx)(t.code,{children:"ConsumerAdditionProposal"})})," has passed.\nAn Opt In consumer chain only starts if at least one validator has opted in. We check this in ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/proposal.go#L357",children:"BeginBlockInit"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-golang",children:'func (k Keeper) BeginBlockInit(ctx sdk.Context) {\n propsToExecute := k.GetConsumerAdditionPropsToExecute(ctx)\n\n for _, prop := range propsToExecute {\n chainID := prop.ChainId\n if !k.IsTopN(ctx, chainID) && len(k.GetOptedInValidators(ctx, chainID)) == 0 {\n // drop the proposal\n ctx.Logger().Info("could not start chain because no validator has opted in")\n continue\n } \n ...\n'})}),"\n",(0,n.jsx)(t.h3,{id:"how-do-we-send-the-partial-validator-sets-to-the-consumer-chains",children:"How do we send the partial validator sets to the consumer chains?"}),"\n",(0,n.jsxs)(t.p,{children:["A consumer chain should only be validated by opted in validators.\nWe introduce logic to do this when we ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/relay.go#L213",children:"queue"})," the ",(0,n.jsx)(t.code,{children:"VSCPacket"}),"s.\nThe logic behind this, is not as straightforward as it seems because CometBFT does not receive the validator set that has to validate a chain, but rather a delta of ",(0,n.jsx)(t.a,{href:"https://docs.cometbft.com/v0.37/spec/abci/abci++_methods#validatorupdate",children:"validator updates"}),".\nFor example, to remove an opted-out validator from a consumer chain, we have to send a validator update with a ",(0,n.jsx)(t.code,{children:"power"})," of ",(0,n.jsx)(t.code,{children:"0"}),", similarly to what is done in the ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/key_assignment.go#L525",children:"assignment of consumer keys"}),".\nWe intend to update this ADR at a later stage on how exactly we intend to implement this logic."]}),"\n",(0,n.jsx)(t.h3,{id:"how-do-we-distribute-rewards",children:"How do we distribute rewards?"}),"\n",(0,n.jsxs)(t.p,{children:["Currently, rewards are distributed as follows: The consumer ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/consumer/keeper/distribution.go#L148",children:"periodically sends rewards"})," on the provider ",(0,n.jsx)(t.code,{children:"ConsumerRewardsPool"})," address.\nThe provider then ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/blob/v4.0.0/x/ccv/provider/keeper/distribution.go#L77",children:"transfers those rewards to the fee collector address"})," and those transferred rewards are distributed to validators and delegators."]}),"\n",(0,n.jsx)(t.p,{children:"In PSS, we distribute rewards only to validators that actually validate the consumer chain.\nTo do this, we have a pool associated with each consumer chain and consumers IBC transfer the rewards to this pool.\nWe then extract the rewards from each consumer pool and distribute them to the opted in validators."}),"\n",(0,n.jsx)(t.p,{children:"Note that we only distribute rewards to validators that have been opted in for some time (e.g., 10000 blocks) to avoid cases where validators opt in just to receive rewards and then opt out immediately afterward."}),"\n",(0,n.jsx)(t.h3,{id:"misbehaviour",children:"Misbehaviour"}),"\n",(0,n.jsx)(t.h4,{id:"fraud-votes",children:"Fraud votes"}),"\n",(0,n.jsxs)(t.p,{children:["In an Opt In chain, a set of validators might attempt to perform an attack. To deter such potential attacks, PSS allows for the use of fraud votes.\nA ",(0,n.jsx)(t.em,{children:"fraud vote"})," is a governance proposal that enables the slashing of validators that performed an attack.\nDue to their inherent complexity, we intend to introduce fraud votes in a different ADR and at a future iteration of PSS."]}),"\n",(0,n.jsx)(t.h4,{id:"double-signing",children:"Double signing"}),"\n",(0,n.jsx)(t.p,{children:"We do not change the way slashing for double signing and light client attacks functions.\nIf a validator misbehaves on a consumer, then we slash that validator on the provider."}),"\n",(0,n.jsx)(t.h4,{id:"downtime",children:"Downtime"}),"\n",(0,n.jsx)(t.p,{children:"We do not change the way downtime jailing functions.\nIf a validator is down on a consumer chain for an adequate amount of time, we jail this validator on the provider but only if the validator was opted in on this consumer chain in the recent past."}),"\n",(0,n.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,n.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Easier for new consumer chains to consume the provider's chain economic security because proposals are more likely to pass if not everyone is forced to validate."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Smaller validators are not forced to validate chains anymore if they do not want to."}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"We can deprecate the soft opt-out implementation."}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["A consumer chain does not receive the same economic security as with Replicated Security (assuming the value of ",(0,n.jsx)(t.code,{children:"SoftOptOutThreshold"})," is ",(0,n.jsx)(t.code,{children:"5%"}),"), unless it is a Top N chain with ",(0,n.jsx)(t.code,{children:"N >= 95%"}),"."]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/pss-permissionless-vs-premissioned-lite-opt-in-consumer-chains/12984",children:"PSS: Permissionless vs premissioned-lite opt-in consumer chains"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/chips-discussion-phase-partial-set-security-updated/11775",children:"CHIPs discussion phase: Partial Set Security (updated)"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://forum.cosmos.network/t/pss-exclusive-vs-inclusive-top-n/13058",children:"PSS: Exclusive vs Inclusive Top-N"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/pull/1518",children:"Initial PSS ADR and notes #1518"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://informal.systems/blog/replicated-vs-mesh-security",children:"Replicated vs. Mesh Security"})}),"\n"]})]})}function l(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},1151:(e,t,o)=>{o.d(t,{Z:()=>r,a:()=>a});var n=o(7294);const i={},s=n.createContext(i);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/c2cfb320.3bf8a73b.js b/assets/js/c2cfb320.3bf8a73b.js
new file mode 100644
index 0000000000..a1efd25076
--- /dev/null
+++ b/assets/js/c2cfb320.3bf8a73b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1429],{6639:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>l,frontMatter:()=>s,metadata:()=>r,toc:()=>c});var i=a(5893),t=a(1151);const s={sidebar_position:4},o="Validator Instructions for Changeover Procedure",r={id:"validators/changeover-procedure",title:"Validator Instructions for Changeover Procedure",description:"More details available in Changeover Procedure documentation.",source:"@site/docs/validators/changeover-procedure.md",sourceDirName:"validators",slug:"/validators/changeover-procedure",permalink:"/interchain-security/validators/changeover-procedure",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"Consumer chain validator rewards",permalink:"/interchain-security/validators/withdraw_rewards"},next:{title:"Joining Neutron",permalink:"/interchain-security/validators/joining-neutron"}},d={},c=[{value:"Timeline",id:"timeline",level:2},{value:"1. ConsumerAdditionProposal on provider chain",id:"1-consumeradditionproposal-on-provider-chain",level:3},{value:"2. SoftwareUpgradeProposal on the standalone/consumer chain",id:"2-softwareupgradeproposal-on-the-standaloneconsumer-chain",level:3},{value:"3. Assigning a consumer key",id:"3-assigning-a-consumer-key",level:3},{value:"4. Perform the software upgrade on standalone chain",id:"4-perform-the-software-upgrade-on-standalone-chain",level:3},{value:"FAQ",id:"faq",level:2},{value:"Can I reuse the same validator key for the consumer chain that I am already using on the standalone chain? Will I need to perform a AssignConsumerKey tx with this key before spawn time?",id:"can-i-reuse-the-same-validator-key-for-the-consumer-chain-that-i-am-already-using-on-the-standalone-chain-will-i-need-to-perform-a-assignconsumerkey-tx-with-this-key-before-spawn-time",level:3},{value:"Can I continue using the same node that was validating the standalone chain?",id:"can-i-continue-using-the-same-node-that-was-validating-the-standalone-chain",level:3},{value:"Can I set up a new node to validate the standalone/consumer chain after it transitions to Interchain Security?",id:"can-i-set-up-a-new-node-to-validate-the-standaloneconsumer-chain-after-it-transitions-to-interchain-security",level:3},{value:"What happens to the standalone validator set after it transitions to Interchain Security?",id:"what-happens-to-the-standalone-validator-set-after-it-transitions-to-interchain-security",level:3},{value:"Credits",id:"credits",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"validator-instructions-for-changeover-procedure",children:"Validator Instructions for Changeover Procedure"}),"\n",(0,i.jsxs)(n.p,{children:["More details available in ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/changeover-procedure",children:"Changeover Procedure documentation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A major difference between launching a new consumer chain vs. onboarding a standalone chain to ICS is that there is no consumer genesis available for the standalone chain. Since a standalone chain already exists, its state must be preserved once it transitions to being a consumer chain."}),"\n",(0,i.jsx)(n.h2,{id:"timeline",children:"Timeline"}),"\n",(0,i.jsxs)(n.p,{children:["Upgrading standalone chains can be best visualised using a timeline, such as the one available ",(0,i.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Excalidraw graphic by Stride"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"There is some flexibility with regards to how the changeover procedure is executed, so please make sure to follow the guides provided by the team doing the changeover."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Standalone to consumer transition timeline",src:a(6038).Z+"",width:"5307",height:"2157"})}),"\n",(0,i.jsxs)(n.h3,{id:"1-consumeradditionproposal-on-provider-chain",children:["1. ",(0,i.jsx)(n.code,{children:"ConsumerAdditionProposal"})," on provider chain"]}),"\n",(0,i.jsxs)(n.p,{children:["This step will add the standalone chain to the list of consumer chains secured by the provider.\nThis step dictates the ",(0,i.jsx)(n.code,{children:"spawn_time"}),". After ",(0,i.jsx)(n.code,{children:"spawn_time"})," the CCV state (initial validator set of the provider) will be available to the consumer."]}),"\n",(0,i.jsx)(n.p,{children:"To obtain it from the provider use:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad q provider consumer-genesis stride-1 -o json > ccv-state.json\njq -s '.[0].app_state.ccvconsumer = .[1] | .[0]' genesis.json ccv-state.json > ccv.json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Transformation of the exported consumer genesis state to the target version of the consumer might be needed in case the provider and consumer formats are incompatible.\nRefer to the compatibility notes ",(0,i.jsx)(n.a,{href:"../../../RELEASES.md#backwards-compatibility",children:"here"})," to check if data transformation is needed for your case.\nInstructions on how to transform the exported CCV genesis state (",(0,i.jsx)(n.code,{children:"ccv-state.json"})," in the example above) to the required target version can be found ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/consumer-genesis-transformation",children:"here"})]}),"\n",(0,i.jsxs)(n.h3,{id:"2-softwareupgradeproposal-on-the-standaloneconsumer-chain",children:["2. ",(0,i.jsx)(n.code,{children:"SoftwareUpgradeProposal"})," on the standalone/consumer chain"]}),"\n",(0,i.jsx)(n.p,{children:"This upgrade proposal will introduce ICS to the standalone chain, making it a consumer."}),"\n",(0,i.jsx)(n.h3,{id:"3-assigning-a-consumer-key",children:"3. Assigning a consumer key"}),"\n",(0,i.jsxs)(n.p,{children:["After ",(0,i.jsx)(n.code,{children:"spawn_time"}),", make sure to assign a consumer key if you intend to use one."]}),"\n",(0,i.jsxs)(n.p,{children:["Instructions are available ",(0,i.jsx)(n.a,{href:"/interchain-security/features/key-assignment",children:"here"})]}),"\n",(0,i.jsx)(n.h3,{id:"4-perform-the-software-upgrade-on-standalone-chain",children:"4. Perform the software upgrade on standalone chain"}),"\n",(0,i.jsx)(n.p,{children:"Please use instructions provided by the standalone chain team and make sure to reach out if you are facing issues.\nThe upgrade preparation depends on your setup, so please make sure you prepare ahead of time."}),"\n",(0,i.jsxs)(n.admonition,{type:"danger",children:[(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"ccv.json"})," from step 1. must be made available on the machine running the standalone/consumer chain at standalone chain ",(0,i.jsx)(n.code,{children:"upgrade_height"}),". This file contains the initial validator set and parameters required for normal ICS operation."]}),(0,i.jsxs)(n.p,{children:["Usually, the file is placed in ",(0,i.jsx)(n.code,{children:"$NODE_HOME/config"})," but this is not a strict requirement. The exact details are available in the upgrade code of the standalone/consumer chain."]})]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Performing this upgrade will transition the standalone chain to be a consumer chain."})}),"\n",(0,i.jsxs)(n.p,{children:['After 3 blocks, the standalone chain will stop using the "old" validator set and begin using the ',(0,i.jsx)(n.code,{children:"provider"})," validator set."]}),"\n",(0,i.jsx)(n.h2,{id:"faq",children:"FAQ"}),"\n",(0,i.jsxs)(n.h3,{id:"can-i-reuse-the-same-validator-key-for-the-consumer-chain-that-i-am-already-using-on-the-standalone-chain-will-i-need-to-perform-a-assignconsumerkey-tx-with-this-key-before-spawn-time",children:["Can I reuse the same validator key for the ",(0,i.jsx)(n.code,{children:"consumer"})," chain that I am already using on the ",(0,i.jsx)(n.code,{children:"standalone"})," chain? Will I need to perform a ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx with this key before spawn time?"]}),"\n",(0,i.jsxs)(n.p,{children:["Validators must either assign a key or use the same key as on the ",(0,i.jsx)(n.code,{children:"provider"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["If you are validating both the ",(0,i.jsx)(n.code,{children:"standalone"})," and the ",(0,i.jsx)(n.code,{children:"provider"}),", you ",(0,i.jsx)(n.strong,{children:"can"})," use your current ",(0,i.jsx)(n.code,{children:"standalone"})," key with some caveats:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["you must submit an ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx with your current ",(0,i.jsx)(n.code,{children:"standalone"})," validator key"]}),"\n",(0,i.jsxs)(n.li,{children:["it is best to submit ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx before ",(0,i.jsx)(n.code,{children:"spawn_time"})]}),"\n",(0,i.jsxs)(n.li,{children:["if you do not submit the Tx, it is assumed that you will be re-using your ",(0,i.jsx)(n.code,{children:"provider"})," key to validate the ",(0,i.jsx)(n.code,{children:"standalone/consumer"})," chain"]}),"\n"]}),"\n",(0,i.jsxs)(n.h3,{id:"can-i-continue-using-the-same-node-that-was-validating-the-standalone-chain",children:["Can I continue using the same node that was validating the ",(0,i.jsx)(n.code,{children:"standalone"})," chain?"]}),"\n",(0,i.jsx)(n.p,{children:"Yes."}),"\n",(0,i.jsx)(n.p,{children:"Please assign your consensus key as stated above."}),"\n",(0,i.jsxs)(n.h3,{id:"can-i-set-up-a-new-node-to-validate-the-standaloneconsumer-chain-after-it-transitions-to-interchain-security",children:["Can I set up a new node to validate the ",(0,i.jsx)(n.code,{children:"standalone/consumer"})," chain after it transitions to Interchain Security?"]}),"\n",(0,i.jsx)(n.p,{children:"Yes."}),"\n",(0,i.jsxs)(n.p,{children:["If you are planning to do this please make sure that the node is synced with ",(0,i.jsx)(n.code,{children:"standalone"})," network and to submit ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," tx before ",(0,i.jsx)(n.code,{children:"spawn_time"}),"."]}),"\n",(0,i.jsxs)(n.h3,{id:"what-happens-to-the-standalone-validator-set-after-it-transitions-to-interchain-security",children:["What happens to the ",(0,i.jsx)(n.code,{children:"standalone"})," validator set after it transitions to Interchain Security?"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"standalone"})," chain validators will stop being validators after the first 3 blocks are created while using Interchain Security. The ",(0,i.jsx)(n.code,{children:"standalone"})," validators will become ",(0,i.jsx)(n.strong,{children:"governors"})," and still can receive delegations if the ",(0,i.jsx)(n.code,{children:"consumer"})," chain is using the ",(0,i.jsx)(n.code,{children:"consumer-democracy"})," module."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Governors DO NOT VALIDATE BLOCKS"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Instead, they can participate in the governance process and take on other chain-specific roles."}),"\n",(0,i.jsx)(n.h2,{id:"credits",children:"Credits"}),"\n",(0,i.jsx)(n.p,{children:"Thank you Stride team for providing detailed instructions about the changeover procedure."})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},6038:(e,n,a)=>{a.d(n,{Z:()=>i});const i=a.p+"assets/images/ics_changeover_timeline_stride-9bcad1834fef24a0fea7f2c80c9ccd71.png"},1151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>o});var i=a(7294);const t={},s=i.createContext(t);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/c3827980.f880929a.js b/assets/js/c3827980.f880929a.js
new file mode 100644
index 0000000000..3f5c7317da
--- /dev/null
+++ b/assets/js/c3827980.f880929a.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5032],{5082:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>m,frontMatter:()=>s,metadata:()=>i,toc:()=>h});var o=t(5893),a=t(1151);const s={sidebar_position:2},r="Consumer Chain Governance",i={id:"consumer-development/consumer-chain-governance",title:"Consumer Chain Governance",description:'Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We\'ll cover what these are in the "Whitelist" section below.',source:"@site/versioned_docs/version-v5.0.0/consumer-development/consumer-chain-governance.md",sourceDirName:"consumer-development",slug:"/consumer-development/consumer-chain-governance",permalink:"/interchain-security/v5.0.0/consumer-development/consumer-chain-governance",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Developing an ICS consumer chain",permalink:"/interchain-security/v5.0.0/consumer-development/app-integration"},next:{title:"Onboarding Checklist",permalink:"/interchain-security/v5.0.0/consumer-development/onboarding"}},c={},h=[{value:"Democracy module",id:"democracy-module",level:2},{value:"CosmWasm",id:"cosmwasm",level:2},{value:"The Whitelist",id:"the-whitelist",level:2}];function l(e){const n={a:"a",h1:"h1",h2:"h2",p:"p",...(0,a.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"consumer-chain-governance",children:"Consumer Chain Governance"}),"\n",(0,o.jsx)(n.p,{children:'Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We\'ll cover what these are in the "Whitelist" section below.'}),"\n",(0,o.jsx)(n.h2,{id:"democracy-module",children:"Democracy module"}),"\n",(0,o.jsx)(n.p,{children:"The democracy module provides a governance experience identical to what exists on a standalone Cosmos chain, with one small but important difference. On a standalone Cosmos chain validators can act as representatives for their delegators by voting with their stake, but only if the delegator themselves does not vote. This is a lightweight form of liquid democracy."}),"\n",(0,o.jsx)(n.p,{children:"Using the democracy module on a consumer chain is the exact same experience, except for the fact that it is not the actual validator set of the chain (since it is a consumer chain, these are the Cosmos Hub validators) acting as representatives. Instead, there is a separate representative role who token holders can delegate to and who can perform the functions that validators do in Cosmos governance, without participating in proof of stake consensus."}),"\n",(0,o.jsxs)(n.p,{children:["For an example, see the ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/main/app/consumer-democracy",children:"Democracy Consumer"})]}),"\n",(0,o.jsx)(n.h2,{id:"cosmwasm",children:"CosmWasm"}),"\n",(0,o.jsx)(n.p,{children:"There are several great DAO and governance frameworks written as CosmWasm contracts. These can be used as the main governance system for a consumer chain. Actions triggered by the CosmWasm governance contracts are able to affect parameters and trigger actions on the consumer chain."}),"\n",(0,o.jsxs)(n.p,{children:["For an example, see ",(0,o.jsx)(n.a,{href:"https://github.com/neutron-org/neutron/",children:"Neutron"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"the-whitelist",children:"The Whitelist"}),"\n",(0,o.jsxs)(n.p,{children:["Not everything on a consumer chain can be changed by the consumer's governance. Some settings having to do with consensus etc. can only be changed by the provider chain. Consumer chains include a whitelist of parameters that are allowed to be changed by the consumer chain governance. For an example, see ",(0,o.jsx)(n.a,{href:"https://github.com/neutron-org/neutron/blob/main/app/proposals_allowlisting.go",children:"Neutron's"})," whitelist."]})]})}function m(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>i,a:()=>r});var o=t(7294);const a={},s=o.createContext(a);function r(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/c551d695.fa70b161.js b/assets/js/c551d695.fa70b161.js
new file mode 100644
index 0000000000..6fbbf74312
--- /dev/null
+++ b/assets/js/c551d695.fa70b161.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4635],{5414:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>l,frontMatter:()=>a,metadata:()=>t,toc:()=>d});var i=s(5893),r=s(1151);const a={sidebar_position:1},o="Key Assignment",t={id:"features/key-assignment",title:"Key Assignment",description:"Key Assignment (aka. as key delegation) allows validator operators to use different consensus keys for each consumer chain validator node that they operate.",source:"@site/versioned_docs/version-v4.2.0-docs/features/key-assignment.md",sourceDirName:"features",slug:"/features/key-assignment",permalink:"/interchain-security/v4.2.0/features/key-assignment",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Technical Specification",permalink:"/interchain-security/v4.2.0/introduction/technical-specification"},next:{title:"Reward Distribution",permalink:"/interchain-security/v4.2.0/features/reward-distribution"}},c={},d=[{value:"Rules",id:"rules",level:2},{value:"Adding a key",id:"adding-a-key",level:2},{value:"Changing a key",id:"changing-a-key",level:2},{value:"Removing a key",id:"removing-a-key",level:2},{value:"Querying proposed consumer chains",id:"querying-proposed-consumer-chains",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"key-assignment",children:"Key Assignment"}),"\n",(0,i.jsx)(n.p,{children:"Key Assignment (aka. as key delegation) allows validator operators to use different consensus keys for each consumer chain validator node that they operate.\nThere are various reasons to use different consensus keys on different chains, but the main benefit is that validator's provider chain consensus key cannot be compromised if their consumer chain node (or other infrastructure) gets compromised. Interchain security module adds queries and transactions for assigning keys on consumer chains."}),"\n",(0,i.jsxs)(n.p,{children:["The feature is outlined in this ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-001-key-assignment",children:"ADR-001"})]}),"\n",(0,i.jsxs)(n.p,{children:["By sending an ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," transaction, validators are able to indicate which consensus key they will be using to validate a consumer chain. On receiving the transaction, if the key assignment is valid, the provider will use the assigned consensus key when it sends future voting power updates to the consumer that involve the validator."]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"Key assignment is handled only by the provider chain - the consumer chains are not aware of the fact that different consensus keys represent the same validator entity."})}),"\n",(0,i.jsx)(n.h2,{id:"rules",children:"Rules"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"a key can be assigned as soon as the consumer addition proposal is submitted to the provider"}),"\n",(0,i.jsx)(n.li,{children:"validator A cannot assign consumer key K to consumer chain X if there is already a validator B (B!=A) using K on the provider"}),"\n",(0,i.jsx)(n.li,{children:"validator A cannot assign consumer key K to consumer chain X if there is already a validator B using K on X"}),"\n",(0,i.jsx)(n.li,{children:"a new validator on the provider cannot use a consensus key K if K is already used by any validator on any consumer chain"}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"Validators can use a different key for each consumer chain."})}),"\n",(0,i.jsx)(n.h2,{id:"adding-a-key",children:"Adding a key"}),"\n",(0,i.jsx)(n.p,{children:"First, create a new node on the consumer chain using the equivalent:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"consumerd init \n"})}),"\n",(0,i.jsx)(n.p,{children:"Then query your node for the consensus key."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'consumerd tendermint show-validator # {"@type":"/cosmos.crypto.ed25519.PubKey","key":""}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Then, make an ",(0,i.jsx)(n.code,{children:"assign-consensus-key"})," transaction on the provider chain in order to inform the provider chain about the consensus key you will be using for a specific consumer chain."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad tx provider assign-consensus-key '' --from --home --gas 900000 -b sync -y -o json\n"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"consumer-chain-id"})," is the string identifier of the consumer chain, as assigned on the provider chain"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"consumer-pub-key"})," has the following format ",(0,i.jsx)(n.code,{children:'{"@type":"/cosmos.crypto.ed25519.PubKey","key":""}'})]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Check that the key was assigned correctly by querying the provider:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider validator-consumer-key cosmosvalcons1e....3xsj3ayzf4uv6\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You must use a ",(0,i.jsx)(n.code,{children:"valcons"})," address. You can obtain it by querying your node on the provider ",(0,i.jsx)(n.code,{children:"gaiad tendermint show-address"})]}),"\n",(0,i.jsx)(n.p,{children:"OR"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider validator-provider-key consumervalcons1e....123asdnoaisdao\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You must use a ",(0,i.jsx)(n.code,{children:"valcons"})," address. You can obtain it by querying your node on the consumer ",(0,i.jsx)(n.code,{children:"consumerd tendermint show-address"})]}),"\n",(0,i.jsx)(n.p,{children:"OR"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider all-pairs-valconsensus-address \n"})}),"\n",(0,i.jsxs)(n.p,{children:["You just need to use the ",(0,i.jsx)(n.code,{children:"chainId"})," of consumer to query all pairs valconsensus address with ",(0,i.jsx)(n.code,{children:"consumer-pub-key"})," for each of pair"]}),"\n",(0,i.jsx)(n.h2,{id:"changing-a-key",children:"Changing a key"}),"\n",(0,i.jsx)(n.p,{children:"To change your key, simply repeat all of the steps listed above. Take note that your old key will be remembered for at least the unbonding period of the consumer chain so any slashes can be correctly applied"}),"\n",(0,i.jsx)(n.h2,{id:"removing-a-key",children:"Removing a key"}),"\n",(0,i.jsxs)(n.p,{children:["To remove a key, simply switch it back to the consensus key you have assigned on the provider chain by following steps in the ",(0,i.jsx)(n.code,{children:"Adding a key"})," section and using your provider consensus key."]}),"\n",(0,i.jsx)(n.admonition,{type:"warning",children:(0,i.jsxs)(n.p,{children:["Validators are strongly recommended to assign a separate key for each consumer chain\nand ",(0,i.jsx)(n.strong,{children:"not"})," reuse the provider key across consumer chains for security reasons."]})}),"\n",(0,i.jsx)(n.h2,{id:"querying-proposed-consumer-chains",children:"Querying proposed consumer chains"}),"\n",(0,i.jsx)(n.p,{children:"To query the consumer addition proposals that are in the voting period, you can use the following command on the provider:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider list-proposed-consumer-chains\n"})}),"\n",(0,i.jsx)(n.p,{children:"This query is valuable for staying informed about when keys can be assigned to newly proposed consumer chains."})]})}function l(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>t,a:()=>o});var i=s(7294);const r={},a=i.createContext(r);function o(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/caea946b.e5a1de44.js b/assets/js/caea946b.e5a1de44.js
new file mode 100644
index 0000000000..1e88790507
--- /dev/null
+++ b/assets/js/caea946b.e5a1de44.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3713],{5483:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>t,metadata:()=>d,toc:()=>l});var i=s(5893),o=s(1151);const t={sidebar_position:2,title:"ADR Template"},r="ADR 004: Denom DOS fixes",d={id:"adrs/adr-004-denom-dos-fixes",title:"ADR Template",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-004-denom-dos-fixes.md",sourceDirName:"adrs",slug:"/adrs/adr-004-denom-dos-fixes",permalink:"/interchain-security/v5.0.0/adrs/adr-004-denom-dos-fixes",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"ADR Template"},sidebar:"tutorialSidebar",previous:{title:"ADRs",permalink:"/interchain-security/v5.0.0/adrs/intro"},next:{title:"ADR Template",permalink:"/interchain-security/v5.0.0/adrs/adr-007-pause-unbonding-on-eqv-prop"}},a={},l=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Provider",id:"provider",level:3},{value:"Consumer",id:"consumer",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3}];function c(e){const n={h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-004-denom-dos-fixes",children:"ADR 004: Denom DOS fixes"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"5/9/2023: ADR created"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Accepted"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.p,{children:"The provider and consumer modules are vulnerable to similar issues involving an attacker sending millions of denoms to certain addresses and causing the chain to halt. This ADR outlines both fixes since they are similar. Both fixes involve processing only denoms that are on a whitelist to avoid iterating over millions of junk denoms but have different requirements and are implemented in different ways."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.h3,{id:"provider",children:"Provider"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Put the distribution module's FeePoolAddress back on the blocklist so that it cannot receive funds from users."}),"\n",(0,i.jsx)(n.li,{children:"Create a new address called ConsumerRewardPool and unblock it, allowing funds to be sent to it."}),"\n",(0,i.jsx)(n.li,{children:"Create a set of strings in the store for allowed ConsumerRewardDenoms."}),"\n",(0,i.jsx)(n.li,{children:"Create an endpoint called RegisterConsumerRewardDenom which deducts a fee from the sender's account, sends it to the community pool and adds a string to the ConsumerRewardDenoms set."}),"\n",(0,i.jsx)(n.li,{children:"Create a parameter called ConsumerRewardDenomRegistrationFee which determines the fee which is charged to register a consumer reward denom in the step above."}),"\n",(0,i.jsxs)(n.li,{children:["Create a function called TransferRewardsToFeeCollector which gets the entire ConsumerRewardDenoms set from the store, iterates over it, and for each entry:","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Gets the balance of this denom for the ConsumerRewardPool account"}),"\n",(0,i.jsx)(n.li,{children:"Sends the entire balance out to the FeePoolAddress using SendCoinsFromModuleToModule which is not affected by the blocklist."}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.li,{children:"Run TransferRewardsToFeeCollector in the endblock"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Now, nobody can send millions of junk denoms to the FeePoolAddress because it is on the block list. If they send millions of junk denoms to the ConsumerRewardPool, this does not matter because all balances are not iterated over, only those which are in the ConsumerRewardDenoms set."}),"\n",(0,i.jsx)(n.p,{children:"We also add a new tx: register-consumer-reward-denom, and a new query: registered-consumer-reward-denoms"}),"\n",(0,i.jsx)(n.h3,{id:"consumer",children:"Consumer"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Create a new param RewardDenoms with a list of strings"}),"\n",(0,i.jsx)(n.li,{children:"Create a new param ProviderRewardDenoms with a list of strings"}),"\n",(0,i.jsx)(n.li,{children:"Create a function AllowedRewardDenoms which iterates over ProviderRewardDenoms and converts each denom to its ibc-prefixed denom using the provider chain's ibc channel information, then concatenates the RewardDenoms list and returns the combined list of allowed denoms."}),"\n",(0,i.jsx)(n.li,{children:"In SendRewardsToProvider, instead of iterating over the balances of all denoms in the ToSendToProvider address, iterate over AllowedRewardDenoms"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Now, if somebody sends millions of junk denoms to ToSendToProvider, they will not be iterated over. Only the RewardDenoms and ProviderRewardDenoms will be iterated over. Since we do not require this feature to be permissionless on the consumer, the registration fee process is not needed."}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Denom DOS is no longer possible on either provider or consumer."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Consumer chain teams must pay a fee to register a denom for distribution on the provider, and add some extra parameters in their genesis file."}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>d,a:()=>r});var i=s(7294);const o={},t=i.createContext(o);function r(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/cf411473.69556536.js b/assets/js/cf411473.69556536.js
new file mode 100644
index 0000000000..0e655c793b
--- /dev/null
+++ b/assets/js/cf411473.69556536.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3153],{511:(t,e,i)=>{i.r(e),i.d(e,{assets:()=>s,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>a,toc:()=>p});var n=i(5893),c=i(1151);const o={sidebar_position:4},r="Technical Specification",a={id:"introduction/technical-specification",title:"Technical Specification",description:"For a technical deep dive into the replicated security protocol, see the specification.",source:"@site/docs/introduction/technical-specification.md",sourceDirName:"introduction",slug:"/introduction/technical-specification",permalink:"/interchain-security/introduction/technical-specification",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"Interchain Security Parameters",permalink:"/interchain-security/introduction/params"},next:{title:"Upgrading to ICS v5.0.0",permalink:"/interchain-security/upgrading/migrate_v4_v5"}},s={},p=[];function u(t){const e={a:"a",h1:"h1",p:"p",...(0,c.a)(),...t.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h1,{id:"technical-specification",children:"Technical Specification"}),"\n",(0,n.jsxs)(e.p,{children:["For a technical deep dive into the replicated security protocol, see the ",(0,n.jsx)(e.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/README.md",children:"specification"}),"."]})]})}function d(t={}){const{wrapper:e}={...(0,c.a)(),...t.components};return e?(0,n.jsx)(e,{...t,children:(0,n.jsx)(u,{...t})}):u(t)}},1151:(t,e,i)=>{i.d(e,{Z:()=>a,a:()=>r});var n=i(7294);const c={},o=n.createContext(c);function r(t){const e=n.useContext(o);return n.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function a(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(c):t.components||c:r(t.components),n.createElement(o.Provider,{value:e},t.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d0088cb9.e41155f8.js b/assets/js/d0088cb9.e41155f8.js
new file mode 100644
index 0000000000..ffefe64094
--- /dev/null
+++ b/assets/js/d0088cb9.e41155f8.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[709],{7015:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>h,contentTitle:()=>a,default:()=>l,frontMatter:()=>t,metadata:()=>r,toc:()=>d});var i=o(5893),s=o(1151);const t={sidebar_position:14,title:"Slashing on the provider for consumer equivocation"},a="ADR 013: Slashing on the provider for consumer equivocation",r={id:"adrs/adr-013-equivocation-slashing",title:"Slashing on the provider for consumer equivocation",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-013-equivocation-slashing.md",sourceDirName:"adrs",slug:"/adrs/adr-013-equivocation-slashing",permalink:"/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:14,frontMatter:{sidebar_position:14,title:"Slashing on the provider for consumer equivocation"},sidebar:"tutorialSidebar",previous:{title:"Separate Releasing",permalink:"/interchain-security/v5.0.0/adrs/adr-012-separate-releasing"},next:{title:"Epochs",permalink:"/interchain-security/v5.0.0/adrs/adr-014-epochs"}},h={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Single-chain slashing",id:"single-chain-slashing",level:3},{value:"Slashing undelegations and redelegations",id:"slashing-undelegations-and-redelegations",level:4},{value:"Slashing delegations",id:"slashing-delegations",level:4},{value:"Old evidence",id:"old-evidence",level:4},{value:"Slashing for equivocation on the consumer",id:"slashing-for-equivocation-on-the-consumer",level:3},{value:"Proposed solution",id:"proposed-solution",level:2},{value:"Implementation",id:"implementation",level:3},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function c(e){const n={a:"a",blockquote:"blockquote",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-013-slashing-on-the-provider-for-consumer-equivocation",children:"ADR 013: Slashing on the provider for consumer equivocation"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"1st Sept. 2023: Initial draft"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Accepted"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsxs)(n.p,{children:["This ADR presents some approaches on how to slash on the provider chain validators that performed equivocations on consumer chains.\nCurrently, the provider chain can ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"receive and verify evidence of equivocation"}),", but it cannot slash the misbehaving validator."]}),"\n",(0,i.jsx)(n.p,{children:"In the remainder of this section, we explain how slashing is performed on a single chain and show why slashing on the provider for equivocation on the consumer is challenging."}),"\n",(0,i.jsxs)(n.p,{children:["Note that future versions of the Cosmos SDK, CometBFT, and ibc-go could modify the way we slash, etc. Therefore, a future reader of this ADR, should note that when we refer to Cosmos SDK, CometBFT, and ibc-go we specifically refer to their ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/intro/overview",children:"v0.47"}),", ",(0,i.jsx)(n.a,{href:"https://docs.cometbft.com/v0.37/",children:"v0.37"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc-go/blob/v7.3.0",children:"v7.3.0"})," versions respectively."]}),"\n",(0,i.jsx)(n.h3,{id:"single-chain-slashing",children:"Single-chain slashing"}),"\n",(0,i.jsxs)(n.p,{children:["Slashing is implemented across the ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/slashing",children:"slashing"}),"\nand ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/staking",children:"staking"})," modules.\nThe slashing module's keeper calls the staking module's ",(0,i.jsx)(n.code,{children:"Slash()"})," method, passing among others, the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," (i.e., the height when the equivocation occurred), the validator's ",(0,i.jsx)(n.code,{children:"power"})," at the infraction height, and the ",(0,i.jsx)(n.code,{children:"slashFactor"})," (currently set to ",(0,i.jsx)(n.code,{children:"5%"})," in case of equivocation on the Cosmos Hub)."]}),"\n",(0,i.jsx)(n.h4,{id:"slashing-undelegations-and-redelegations",children:"Slashing undelegations and redelegations"}),"\n",(0,i.jsxs)(n.p,{children:["To slash undelegations, ",(0,i.jsx)(n.code,{children:"Slash"})," goes through all undelegations and checks whether they started before or after the infraction occurred. If an undelegation started before the ",(0,i.jsx)(n.code,{children:"infractionHeight"}),", then it is ",(0,i.jsx)(n.strong,{children:"not"})," slashed, otherwise it is slashed by ",(0,i.jsx)(n.code,{children:"slashFactor"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The slashing of redelegations happens in a similar way, meaning that ",(0,i.jsx)(n.code,{children:"Slash"})," goes through all redelegations and checks whether the redelegations started before or after the ",(0,i.jsx)(n.code,{children:"infractionHeight"}),"."]}),"\n",(0,i.jsx)(n.h4,{id:"slashing-delegations",children:"Slashing delegations"}),"\n",(0,i.jsxs)(n.p,{children:["Besides undelegations and redelegations, the validator's delegations need to also be slashed.\nThis is performed by deducting the appropriate amount of tokens from the validator. Note that this deduction is computed based on the voting ",(0,i.jsx)(n.code,{children:"power"})," the misbehaving validator had at the height of the equivocation. As a result of the tokens deduction,\nthe ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/staking#delegator-shares",children:"tokens per share"}),"\nreduce and hence later on, when delegators undelegate or redelegate, the delegators retrieve back less\ntokens, effectively having their tokens slashed. The rationale behind this slashing mechanism, as mentioned in the ",(0,i.jsx)(n.a,{href:"https://docs.cosmos.network/v0.47/modules/staking#delegator-shares",children:"Cosmos SDK documentation"})]}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"[...] is to simplify the accounting around slashing. Rather than iteratively slashing the tokens of every delegation entry, instead the Validators total bonded tokens can be slashed, effectively reducing the value of each issued delegator share."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["This approach of slashing delegations does not utilize the\n",(0,i.jsx)(n.code,{children:"infractionHeight"})," in any way and hence the following scenario could occur:"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["a validator ",(0,i.jsx)(n.code,{children:"V"})," performs an equivocation at a height ",(0,i.jsx)(n.code,{children:"Hi"})]}),"\n",(0,i.jsxs)(n.li,{children:["a new delegator ",(0,i.jsx)(n.code,{children:"D"})," delegates to ",(0,i.jsx)(n.code,{children:"V"})," after height ",(0,i.jsx)(n.code,{children:"Hi"})]}),"\n",(0,i.jsxs)(n.li,{children:["evidence of the equivocation by validator ",(0,i.jsx)(n.code,{children:"V"})," is received"]}),"\n",(0,i.jsxs)(n.li,{children:["the tokens of delegator ",(0,i.jsx)(n.code,{children:"D"})," are slashed"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["In the above scenario, delegator ",(0,i.jsx)(n.code,{children:"D"})," is slashed, even though ",(0,i.jsx)(n.code,{children:"D"}),"'s voting power did not contribute to the infraction."]}),"\n",(0,i.jsx)(n.h4,{id:"old-evidence",children:"Old evidence"}),"\n",(0,i.jsxs)(n.p,{children:["In the single-chain case, old evidence (e.g., from 3 years ago) is ignored. This is achieved through\n",(0,i.jsx)(n.a,{href:"https://docs.cometbft.com/v0.37/spec/consensus/evidence",children:"CometBFT"})," that ignores old evidence based on the parameters ",(0,i.jsx)(n.code,{children:"MaxAgeNumBlocks"})," and ",(0,i.jsx)(n.code,{children:"MaxAgeDuration"})," (see ",(0,i.jsx)(n.a,{href:"https://github.com/cometbft/cometbft/blob/v0.37.0/evidence/pool.go#271",children:"here"}),").\nAdditionally, note that when the evidence is sent by CometBFT to the application, the evidence is rechecked in the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/evidence/keeper/infraction.go#L54",children:"evidence module"})," of Cosmos SDK and if it is old, the evidence is ignored.\nIn Cosmos Hub, the ",(0,i.jsx)(n.code,{children:"MaxAgeNumBlocks"})," is set to 1000000 (i.e., ~70 days if we assume we need ~6 sec per block) and ",(0,i.jsx)(n.code,{children:"MaxAgeDuration"})," is set to 172800000000000 ns (i.e., 2 days). Because of this check, we can easily exclude old evidence."]}),"\n",(0,i.jsx)(n.h3,{id:"slashing-for-equivocation-on-the-consumer",children:"Slashing for equivocation on the consumer"}),"\n",(0,i.jsxs)(n.p,{children:["In the single-chain case, slashing requires both the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and the voting ",(0,i.jsx)(n.code,{children:"power"}),".\nIn order to slash on the provider for an equivocation on a consumer, we need to have both the provider's ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and voting ",(0,i.jsx)(n.code,{children:"power"}),".\nNote that the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," on the consumer chain must be mapped to a height on the provider chain.\nUnless we have a way to find the corresponding ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and ",(0,i.jsx)(n.code,{children:"power"})," on the provider chain, we cannot slash for equivocation on the consumer in the same way as we would slash in the single-chain case."]}),"\n",(0,i.jsxs)(n.p,{children:["The challenge of figuring out the corresponding ",(0,i.jsx)(n.code,{children:"infractionHeight"})," and ",(0,i.jsx)(n.code,{children:"power"})," values on the provider chain is due to the following trust assumption:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["We trust the consensus layer and validator set of the consumer chains, ",(0,i.jsx)(n.em,{children:"but we do not trust the application layer"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["As a result, we cannot trust anything that stems from the ",(0,i.jsx)(n.em,{children:"application state"})," of a consumer chain."]}),"\n",(0,i.jsxs)(n.p,{children:["Note that when a relayer or a user sends evidence through a ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"MsgSubmitConsumerDoubleVoting"})," message, the provider gets access to ",(0,i.jsx)(n.a,{href:"https://github.com/cometbft/cometbft/blob/v0.37.0/types/evidence.go#L35",children:"DuplicateVoteEvidence"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-protobuf",children:'type DuplicateVoteEvidence struct {\n\tVoteA *Vote `json:"vote_a"`\n\tVoteB *Vote `json:"vote_b"`\n\n\t// abci specific information\n\tTotalVotingPower int64\n\tValidatorPower int64\n\tTimestamp time.Time\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:['The "abci specific information" fields cannot be trusted because they are not signed. Therefore,\nwe can use neither ',(0,i.jsx)(n.code,{children:"ValidatorPower"})," for slashing on the provider chain, nor the ",(0,i.jsx)(n.code,{children:"Timestamp"})," to check the evidence age. We can get the ",(0,i.jsx)(n.code,{children:"infractionHeight"})," from the votes, but this ",(0,i.jsx)(n.code,{children:"infractionHeight"})," corresponds to the infraction height on the consumer and ",(0,i.jsx)(n.strong,{children:"not"})," on the provider chain.\nSimilarly, when a relayer or a user sends evidence through a ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/826",children:"MsgSubmitConsumerMisbehaviour"})," message, the provider gets access to ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/ibc-go/blob/v7.3.0/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L79",children:"Misbehaviour"})," that we cannot use to extract the infraction height, power, or the time on the provider chain."]}),"\n",(0,i.jsx)(n.h2,{id:"proposed-solution",children:"Proposed solution"}),"\n",(0,i.jsx)(n.p,{children:"As a first iteration, we propose the following approach. At the moment the provider receives evidence of equivocation on a consumer:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["slash all the undelegations and redelegations using ",(0,i.jsx)(n.code,{children:"slashFactor"}),";"]}),"\n",(0,i.jsxs)(n.li,{children:["slash all delegations using as voting ",(0,i.jsx)(n.code,{children:"power"})," the sum of the voting power of the misbehaving validator and the power of all the ongoing undelegations and redelegations."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Evidence expiration:"})," Additionally, because we cannot infer the actual time of the evidence (i.e., the timestamp of the evidence cannot be trusted), we do not consider ",(0,i.jsx)(n.em,{children:"evidence expiration"})," and hence old evidence is never ignored (e.g., the provider would act on 3 year-old evidence of equivocation on a consumer).\nAdditionally, we do not need to store equivocation evidence to avoid slashing a validator more than once, because we ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/evidence/keeper/infraction.go#L94",children:"do not slash"})," tombstoned validators and we ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/evidence/keeper/infraction.go#L138",children:"tombstone"})," a validator when slashed."]}),"\n",(0,i.jsxs)(n.p,{children:["We do not act on evidence that was signed by a validator ",(0,i.jsx)(n.a,{href:"https://tutorials.cosmos.network/tutorials/9-path-to-prod/3-keys.html#what-validator-keys",children:"consensus key"})," that is ",(0,i.jsx)(n.em,{children:"pruned"})," when we receive the evidence. We prune a validator's consensus key if the validator has assigned a new consumer key (using ",(0,i.jsx)(n.code,{children:"MsgAssignConsumerKey"}),") and an unbonding period on the consumer chain has elapsed (see ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-001-key-assignment.md",children:"key assignment ADR"}),"). Note that the provider chain is informed that the unbonding period has elapsed on the consumer when the provider receives a ",(0,i.jsx)(n.code,{children:"VSCMaturedPacket"})," and because of this, if the consumer delays the sending of a ",(0,i.jsx)(n.code,{children:"VSCMaturedPacket"}),", we would delay the pruning of the key as well."]}),"\n",(0,i.jsx)(n.h3,{id:"implementation",children:"Implementation"}),"\n",(0,i.jsxs)(n.p,{children:["The following logic needs to be added to the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"HandleConsumerDoubleVoting"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/826",children:"HandleConsumerMisbehaviour"})," methods:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:"undelegationsInTokens := sdk.NewInt(0)\nfor _, v := range k.stakingKeeper.GetUnbondingDelegationsFromValidator(ctx, validatorAddress) {\n for _, entry := range v.Entries {\n if entry.IsMature(now) && !entry.OnHold() {\n // undelegation no longer eligible for slashing, skip it\n continue\n }\n undelegationsInTokens = undelegationsInTokens.Add(entry.InitialBalance)\n }\n}\n\nredelegationsInTokens := sdk.NewInt(0)\nfor _, v := range k.stakingKeeper.GetRedelegationsFromSrcValidator(ctx, validatorAddress) {\n for _, entry := range v.Entries {\n if entry.IsMature(now) && !entry.OnHold() {\n // redelegation no longer eligible for slashing, skip it\n continue\n }\n redelegationsInTokens = redelegationsInTokens.Add(entry.InitialBalance)\n }\n}\n\ninfractionHeight := 0\nundelegationsAndRedelegationsInPower = sdk.TokensToConsensusPower(undelegationsInTokens.Add(redelegationsInTokens))\ntotalPower := validator's voting power + undelegationsAndRedelegationsInPower\nslashFraction := k.slashingKeeper.SlashFractionDoubleSign(ctx)\n\nk.stakingKeeper.Slash(ctx, validatorConsAddress, infractionHeight, totalPower, slashFraction, DoubleSign)\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Infraction height:"})," We provide a zero ",(0,i.jsx)(n.code,{children:"infractionHeight"})," to the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L33",children:"Slash"})," method in order to slash all ongoing undelegations and redelegations (see checks in ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L92",children:"Slash"}),", ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L195",children:"SlashUnbondingDelegation"}),", and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/x/staking/keeper/slash.go#L249",children:"SlashRedelegation"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Power:"})," We pass the sum of the voting power of the misbehaving validator when the evidence was received (i.e., at evidence height) and the power of all the ongoing undelegations and redelegations.\nIf we assume that the ",(0,i.jsx)(n.code,{children:"slashFactor"})," is ",(0,i.jsx)(n.code,{children:"5%"}),", then the voting power we pass is ",(0,i.jsx)(n.code,{children:"power + totalPower(undelegations) + totalPower(redelegations)"}),".\nHence, when the ",(0,i.jsx)(n.code,{children:"Slash"})," method slashes all the undelegations and redelegations it would end up with ",(0,i.jsx)(n.code,{children:"0.05 * power + 0.05 * totalPower(undelegations) + 0.05 * totalPower(redelegations) - 0.05 * totalPower(undelegations) - 0.05 * totalPower(redelegations) = 0.05 * power"})," and hence it would slash ",(0,i.jsx)(n.code,{children:"5%"})," of the validator's power when the evidence is received."]}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsx)(n.p,{children:"With the proposed approach we can quickly implement slashing functionality on the provider chain for consumer chain equivocations.\nThis approach does not need to change the staking module and therefore does not change in any way how slashing is performed today for a single chain."}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["We ",(0,i.jsx)(n.em,{children:"definitely"})," slash more when it comes to undelegations and redelegations because we slash for all of them without considering an ",(0,i.jsx)(n.code,{children:"infractionHeight"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["We ",(0,i.jsx)(n.em,{children:"potentially"})," slash more than what we would have slashed if we knew the voting ",(0,i.jsx)(n.code,{children:"power"})," at the corresponding ",(0,i.jsx)(n.code,{children:"infractionHeight"})," in the provider chain."]}),"\n",(0,i.jsx)(n.li,{children:"We slash on old evidence of equivocation on a consumer."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-005-cryptographic-equivocation-verification.md",children:"ADR 005: Cryptographic verification of equivocation evidence"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/732",children:"EPIC tracking cryptographic equivocation feature"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://forum.cosmos.network/t/cryptographic-equivocation-slashing-design/11400",children:"Cosmos Hub Forum discussion on cryptographic equivocation slashing"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>r,a:()=>a});var i=o(7294);const s={},t=i.createContext(s);function a(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d0d0ba0d.87d75440.js b/assets/js/d0d0ba0d.87d75440.js
new file mode 100644
index 0000000000..7bf49fe252
--- /dev/null
+++ b/assets/js/d0d0ba0d.87d75440.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8772],{9133:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>a,metadata:()=>i,toc:()=>h});var s=t(5893),o=t(1151);const a={sidebar_position:11,title:"Standalone to Consumer Changeover"},r=void 0,i={id:"adrs/adr-010-standalone-changeover",title:"Standalone to Consumer Changeover",description:"ADR 010: Standalone to Consumer Changeover",source:"@site/docs/adrs/adr-010-standalone-changeover.md",sourceDirName:"adrs",slug:"/adrs/adr-010-standalone-changeover",permalink:"/interchain-security/adrs/adr-010-standalone-changeover",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:11,frontMatter:{sidebar_position:11,title:"Standalone to Consumer Changeover"},sidebar:"tutorialSidebar",previous:{title:"Soft Opt-Out",permalink:"/interchain-security/adrs/adr-009-soft-opt-out"},next:{title:"Improving testing and increasing confidence",permalink:"/interchain-security/adrs/adr-011-improving-test-confidence"}},c={},h=[{value:"ADR 010: Standalone to Consumer Changeover",id:"adr-010-standalone-to-consumer-changeover",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Process",id:"process",level:3},{value:"Changes to CCV Protocol",id:"changes-to-ccv-protocol",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"adr-010-standalone-to-consumer-changeover",children:"ADR 010: Standalone to Consumer Changeover"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"6/30/23: Feature completed, first draft of ADR."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsx)(n.p,{children:"Implemented"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"https://github.com/Stride-Labs/stride",children:"Stride"}),' will be the first consumer to "changeover" from a standalone cosmos blockchain, to a consumer chain secured by the Cosmos Hub. This document outlines the changes made to support this changeover process.']}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsx)(n.h3,{id:"process",children:"Process"}),"\n",(0,s.jsx)(n.p,{children:'Prior to the changeover, the consumer chain will have an existing staking keeper and validator set, these may be referred to as the "standalone staking keeper" and "standalone validator set" respectively.'}),"\n",(0,s.jsx)(n.p,{children:"The first step in the changeover process is to submit a ConsumerAdditionProposal. If the proposal passes, the provider will create a new IBC client for the consumer at spawn time, with the provider's validator set. A consumer genesis will also be constructed by the provider for validators to query. Within this consumer genesis contains the initial validator set for the consumer to apply after the changeover."}),"\n",(0,s.jsx)(n.p,{children:"Next, the standalone consumer chain runs an upgrade which adds the CCV module, and is properly setup to execute changeover logic."}),"\n",(0,s.jsx)(n.p,{children:"The consumer upgrade height must be reached after the provider has created the new IBC client. Any Interchain Security validators who will run the consumer, but are not a part of the sovereign validator set, must sync up a full node before the consumer upgrade height is reached. The disk state of said full node will be used to run the consumer chain after the changeover has completed."}),"\n",(0,s.jsxs)(n.p,{children:["The meat of the changeover logic is that the consumer chain validator set is updated to that which was specified by the provider via the queried consumer genesis. Validators which were a part of the old set, but not the new set, are given zero voting power. Once these validator updates are given to Comet, the set is committed, and in effect 2 blocks later (see ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/f10e780df182158d95a30f7cf94588b2d0479309/x/ccv/consumer/keeper/changeover.go#L19",children:"FirstConsumerHeight"}),")."]}),"\n",(0,s.jsx)(n.p,{children:"A relayer then establishes the new IBC connection between the provider and consumer. The CCV channel handshake is started on top of this connection. Once the CCV channel is established and VSC packets are being relayed, the consumer chain is secured by the provider."}),"\n",(0,s.jsx)(n.h3,{id:"changes-to-ccv-protocol",children:"Changes to CCV Protocol"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Consumer Genesis state is updated to include a ",(0,s.jsx)(n.code,{children:"PreCCV"})," boolean. When this boolean is set true in the consumer genesis JSON, ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/f10e780df182158d95a30f7cf94588b2d0479309/x/ccv/consumer/keeper/changeover.go",children:"special logic"})," is executed on InitGenesis to trigger the changeover process on the consumer's first endblocker after the upgrade which adds the CCV module. Note that InitGenesis is not automatically called during chain upgrades, so the consumer must manually call the consumer's InitGenesis method in an upgrade handler."]}),"\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})," type is updated to include a ",(0,s.jsx)(n.code,{children:"DistributionTransmissionChannel"})," field. This field allows the consumer to use an existing IBC transfer channel to send rewards as a part of the CCV protocol. Consumers that're not changing over from a standalone chain will leave this field blank, indicating that a new transfer channel should be created on top of the same connection as the CCV channel."]}),"\n",(0,s.jsx)(n.li,{children:"The CCV consumer keeper is updated to contain an optional reference to the standalone staking keeper. The standalone staking keeper is used to slash for infractions that happened before the changeover was completed. Ie. any infraction from a block height before the changeover, that is submitted after the changeover, will call the standalone staking keeper's slash method. Note that a changeover consumer's standalone staking keeper becomes a democracy module keeper, so it is possible for a governance token to be slashed."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Existing cosmos chains are now able to onboard over to a consumer chain secured by a provider."}),"\n",(0,s.jsx)(n.li,{children:"The previous staking keepers for such chains can be transitioned to democracy staking module keepers."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The delineation between different types of consumers in this repo becomes less clear. Ie. there is code in the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/f10e780df182158d95a30f7cf94588b2d0479309/app/consumer-democracy/app.go",children:"democracy consumer's app.go"})," that only applies to a previously standalone chain, but that file also serves as the base for a normal democracy consumer launched with RS from genesis."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["EPIC: Standalone to Consumer Changeover ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/756",children:"#756"})]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://app.excalidraw.com/l/9UFOCMAZLAI/5EVLj0WJcwt",children:"Changeover diagram from Stride"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>i,a:()=>r});var s=t(7294);const o={},a=s.createContext(o);function r(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d0d80f5c.af276b99.js b/assets/js/d0d80f5c.af276b99.js
new file mode 100644
index 0000000000..92b6d50d29
--- /dev/null
+++ b/assets/js/d0d80f5c.af276b99.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9982],{2543:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>l,frontMatter:()=>a,metadata:()=>t,toc:()=>c});var i=s(5893),r=s(1151);const a={sidebar_position:1},o="Key Assignment",t={id:"features/key-assignment",title:"Key Assignment",description:"Key Assignment (aka. as key delegation) allows validator operators to use different consensus keys for each consumer chain validator node that they operate.",source:"@site/versioned_docs/version-v5.0.0/features/key-assignment.md",sourceDirName:"features",slug:"/features/key-assignment",permalink:"/interchain-security/v5.0.0/features/key-assignment",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Upgrading to ICS v5.0.0",permalink:"/interchain-security/v5.0.0/upgrading/migrate_v4_v5"},next:{title:"Reward Distribution",permalink:"/interchain-security/v5.0.0/features/reward-distribution"}},d={},c=[{value:"Rules",id:"rules",level:2},{value:"Adding a key",id:"adding-a-key",level:2},{value:"Changing a key",id:"changing-a-key",level:2},{value:"Removing a key",id:"removing-a-key",level:2},{value:"Querying proposed consumer chains",id:"querying-proposed-consumer-chains",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"key-assignment",children:"Key Assignment"}),"\n",(0,i.jsx)(n.p,{children:"Key Assignment (aka. as key delegation) allows validator operators to use different consensus keys for each consumer chain validator node that they operate.\nThere are various reasons to use different consensus keys on different chains, but the main benefit is that validator's provider chain consensus key cannot be compromised if their consumer chain node (or other infrastructure) gets compromised. Interchain security module adds queries and transactions for assigning keys on consumer chains."}),"\n",(0,i.jsxs)(n.p,{children:["The feature is outlined in this ",(0,i.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-001-key-assignment",children:"ADR-001"})]}),"\n",(0,i.jsxs)(n.p,{children:["By sending an ",(0,i.jsx)(n.code,{children:"AssignConsumerKey"})," transaction, validators are able to indicate which consensus key they will be using to validate a consumer chain. On receiving the transaction, if the key assignment is valid, the provider will use the assigned consensus key when it sends future voting power updates to the consumer that involve the validator."]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"Key assignment is handled only by the provider chain - the consumer chains are not aware of the fact that different consensus keys represent the same validator entity."})}),"\n",(0,i.jsx)(n.h2,{id:"rules",children:"Rules"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"a key can be assigned as soon as the consumer addition proposal is submitted to the provider"}),"\n",(0,i.jsx)(n.li,{children:"validator A cannot assign consumer key K to consumer chain X if there is already a validator B (B!=A) using K on the provider"}),"\n",(0,i.jsx)(n.li,{children:"validator A cannot assign consumer key K to consumer chain X if there is already a validator B using K on X"}),"\n",(0,i.jsx)(n.li,{children:"a new validator on the provider cannot use a consensus key K if K is already used by any validator on any consumer chain"}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsx)(n.p,{children:"Validators can use a different key for each consumer chain."})}),"\n",(0,i.jsx)(n.h2,{id:"adding-a-key",children:"Adding a key"}),"\n",(0,i.jsx)(n.p,{children:"First, create a new node on the consumer chain using the equivalent:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"consumerd init \n"})}),"\n",(0,i.jsx)(n.p,{children:"Then query your node for the consensus key."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'consumerd tendermint show-validator # {"@type":"/cosmos.crypto.ed25519.PubKey","key":""}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Then, make an ",(0,i.jsx)(n.code,{children:"assign-consensus-key"})," transaction on the provider chain in order to inform the provider chain about the consensus key you will be using for a specific consumer chain."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad tx provider assign-consensus-key '' --from --home --gas 900000 -b sync -y -o json\n"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"consumer-chain-id"})," is the string identifier of the consumer chain, as assigned on the provider chain"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"consumer-pub-key"})," has the following format ",(0,i.jsx)(n.code,{children:'{"@type":"/cosmos.crypto.ed25519.PubKey","key":""}'})]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Check that the key was assigned correctly by querying the provider:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider validator-consumer-key cosmosvalcons1e....3xsj3ayzf4uv6\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You must use a ",(0,i.jsx)(n.code,{children:"valcons"})," address. You can obtain it by querying your node on the provider ",(0,i.jsx)(n.code,{children:"gaiad tendermint show-address"})]}),"\n",(0,i.jsx)(n.p,{children:"OR"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider validator-provider-key consumervalcons1e....123asdnoaisdao\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You must use a ",(0,i.jsx)(n.code,{children:"valcons"})," address. You can obtain it by querying your node on the consumer ",(0,i.jsx)(n.code,{children:"consumerd tendermint show-address"})]}),"\n",(0,i.jsx)(n.p,{children:"OR"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider all-pairs-valconsensus-address \n"})}),"\n",(0,i.jsxs)(n.p,{children:["You just need to use the ",(0,i.jsx)(n.code,{children:"chainId"})," of consumer to query all pairs valconsensus address with ",(0,i.jsx)(n.code,{children:"consumer-pub-key"})," for each of pair"]}),"\n",(0,i.jsx)(n.h2,{id:"changing-a-key",children:"Changing a key"}),"\n",(0,i.jsx)(n.p,{children:"To change your key, simply repeat all of the steps listed above. Take note that your old key will be remembered for at least the unbonding period of the consumer chain so any slashes can be correctly applied"}),"\n",(0,i.jsx)(n.h2,{id:"removing-a-key",children:"Removing a key"}),"\n",(0,i.jsxs)(n.p,{children:["To remove a key, simply switch it back to the consensus key you have assigned on the provider chain by following steps in the ",(0,i.jsx)(n.code,{children:"Adding a key"})," section and using your provider consensus key."]}),"\n",(0,i.jsx)(n.h2,{id:"querying-proposed-consumer-chains",children:"Querying proposed consumer chains"}),"\n",(0,i.jsx)(n.p,{children:"To query the consumer addition proposals that are in the voting period, you can use the following command on the provider:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gaiad query provider list-proposed-consumer-chains\n"})}),"\n",(0,i.jsx)(n.p,{children:"This query is valuable for staying informed about when keys can be assigned to newly proposed consumer chains."})]})}function l(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>t,a:()=>o});var i=s(7294);const r={},a=i.createContext(r);function o(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d1daeca6.bfecf8bd.js b/assets/js/d1daeca6.bfecf8bd.js
new file mode 100644
index 0000000000..cf59526e4c
--- /dev/null
+++ b/assets/js/d1daeca6.bfecf8bd.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3845],{6142:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>t,toc:()=>c});var i=o(5893),r=o(1151);const s={sidebar_position:3},a="ICS Provider Proposals",t={id:"features/proposals",title:"ICS Provider Proposals",description:"Interchain security module introduces new proposal types to the provider.",source:"@site/docs/features/proposals.md",sourceDirName:"features",slug:"/features/proposals",permalink:"/interchain-security/features/proposals",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"tutorialSidebar",previous:{title:"Reward Distribution",permalink:"/interchain-security/features/reward-distribution"},next:{title:"Consumer Initiated Slashing",permalink:"/interchain-security/features/slashing"}},d={},c=[{value:"ConsumerAdditionProposal",id:"consumeradditionproposal",level:2},{value:"ConsumerRemovalProposal",id:"consumerremovalproposal",level:2},{value:"ConsumerModificationProposal",id:"consumermodificationproposal",level:2},{value:"ChangeRewardDenomProposal",id:"changerewarddenomproposal",level:2}];function l(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"ics-provider-proposals",children:"ICS Provider Proposals"}),"\n",(0,i.jsx)(n.p,{children:"Interchain security module introduces new proposal types to the provider."}),"\n",(0,i.jsx)(n.p,{children:"The proposals are used to propose upcoming interchain security events through governance."}),"\n",(0,i.jsx)(n.h2,{id:"consumeradditionproposal",children:(0,i.jsx)(n.code,{children:"ConsumerAdditionProposal"})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["If you are preparing a ",(0,i.jsx)(n.code,{children:"ConsumerAdditionProposal"})," you can find more information in the ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/onboarding",children:"consumer onboarding checklist"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Proposal type used to suggest adding a new consumer chain."}),"\n",(0,i.jsxs)(n.p,{children:["When proposals of this type are passed and the ",(0,i.jsx)(n.code,{children:"spawn_time"})," specified in the proposal is reached, all provider chain validators are expected to run infrastructure (validator nodes) for the proposed consumer chain."]}),"\n",(0,i.jsx)(n.p,{children:"Minimal example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",children:'{\n // Time on the provider chain at which the consumer chain genesis is finalized and all validators\n // will be responsible for starting their consumer chain validator node.\n "spawn_time": "2023-02-28T20:40:00.000000Z",\n "title": "Add consumer chain",\n "description": ".md description of your chain and all other relevant information",\n "chain_id": "newchain-1",\n "initial_height" : {\n "revision_height": 0,\n "revision_number": 1,\n },\n // Unbonding period for the consumer chain.\n // It should be smaller than that of the provider.\n "unbonding_period": 86400000000000,\n // Timeout period for CCV related IBC packets.\n // Packets are considered timed-out after this interval elapses.\n "ccv_timeout_period": 259200000000000,\n "transfer_timeout_period": 1800000000000,\n "consumer_redistribution_fraction": "0.75",\n "blocks_per_distribution_transmission": 1000,\n "historical_entries": 10000,\n "genesis_hash": "d86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0",\n "binary_hash": "376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1",\n "distribution_transmission_channel": "channel-123",\n "top_N": 95,\n "validators_power_cap": 0,\n "validator_set_cap": 0,\n "allowlist": [],\n "denylist": []\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["More examples can be found in the interchain security testnet repository ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/stopped/baryon-1/proposal-baryon-1.json",children:"here"})," and ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/stopped/noble-1/start-proposal-noble-1.json",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"consumerremovalproposal",children:(0,i.jsx)(n.code,{children:"ConsumerRemovalProposal"})}),"\n",(0,i.jsx)(n.p,{children:"Proposal type used to suggest removing an existing consumer chain."}),"\n",(0,i.jsx)(n.p,{children:"When proposals of this type are passed, the consumer chain in question will be gracefully removed from interchain security and validators will no longer be required to run infrastructure for the specified chain.\nAfter the consumer chain removal, the chain in question will no longer be secured by the provider's validator set."}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["The chain in question my continue to produce blocks, but the validator set can no longer be slashed for any infractions committed on that chain.\nAdditional steps are required to completely offboard a consumer chain, such as re-introducing the staking module and removing the provider's validators from the active set.\nMore information will be made available in the ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/offboarding",children:"Consumer Offboarding Checklist"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Minimal example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",children:'{\n // the time on the provider chain at which all validators are responsible to stop their consumer chain validator node\n "stop_time": "2023-03-07T12:40:00.000000Z",\n // the chain-id of the consumer chain to be stopped\n "chain_id": "consumerchain-1",\n "title": "This was a great chain",\n "description": "Here is a .md formatted string specifying removal details"\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"consumermodificationproposal",children:(0,i.jsx)(n.code,{children:"ConsumerModificationProposal"})}),"\n",(0,i.jsx)(n.p,{children:"Proposal type used to change the power shaping parameters of a running consumer chain, as well as to change a Top N running\nconsumer chain to an Opt-In chain and vice versa."}),"\n",(0,i.jsxs)(n.p,{children:["When a ",(0,i.jsx)(n.code,{children:"ConsumerModificationProposal"})," passes for a running consumer chain, the consumer chain would change all its\nparameters to the ones passed in the ",(0,i.jsx)(n.code,{children:"ConsumerModificationProposal"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Assume, a ",(0,i.jsx)(n.code,{children:"chain-1"})," is a Top N chain. If the following ",(0,i.jsx)(n.code,{children:"ConsumerModificationProposal"})," passes, then ",(0,i.jsx)(n.code,{children:"chain-1"})," would become\nan Opt-In chain with a 40% validators power cap, a maximum number of 30 validators, and one denylisted validator."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",children:'{\n "title": "Modify consumer chain",\n "description": ".md description of your chain and all other relevant information",\n "chain_id": "chain-1",\n "top_N": 0,\n "validators_power_cap": 40,\n "validator_set_cap": 30,\n "allowlist": [],\n "denylist": ["cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq"]\n}\n'})}),"\n",(0,i.jsxs)(n.admonition,{type:"warning",children:[(0,i.jsxs)(n.p,{children:["If ",(0,i.jsx)(n.code,{children:"top_N"}),", ",(0,i.jsx)(n.code,{children:"validators_power_cap"}),", or some other argument is not included in the proposal, then it is considered\nthat the default value is set for this argument. For example, if a Top 50% chain wants to only modify ",(0,i.jsx)(n.code,{children:"validators_power_cap"}),"\nfrom 35 to 40, then the ",(0,i.jsx)(n.code,{children:"ConsumerModificationProposal"})," would still need to include that ",(0,i.jsx)(n.code,{children:"top_N"})," is 50. Otherwise\n",(0,i.jsx)(n.code,{children:"top_N"})," would be set to its default value of 0, and the chain would become an Opt-In chain."]}),(0,i.jsxs)(n.p,{children:["To be ",(0,i.jsx)(n.strong,{children:"safe"}),", always include ",(0,i.jsx)(n.code,{children:"top_N"})," and all the power shaping parameters in your ",(0,i.jsx)(n.code,{children:"ConsumerModificationProposal"}),"."]})]}),"\n",(0,i.jsx)(n.h2,{id:"changerewarddenomproposal",children:"ChangeRewardDenomProposal"}),"\n",(0,i.jsx)(n.p,{children:"Proposal type used to mutate the set of denoms accepted by the provider as rewards."}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["A ",(0,i.jsx)(n.code,{children:"ChangeRewardDenomProposal"})," will only be accepted on the provider chain if at least one of the ",(0,i.jsx)(n.code,{children:"denomsToAdd"})," or ",(0,i.jsx)(n.code,{children:"denomsToRemove"})," fields is populated with at least one denom. Also, a denom cannot be repeated in both sets."]})}),"\n",(0,i.jsx)(n.p,{children:"Minimal example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",children:'{\n "title": "Add uatom as a reward denom",\n "description": "Here is more information about the proposal",\n "denomsToAdd": ["uatom"],\n "denomsToRemove": []\n}\n'})}),"\n",(0,i.jsxs)(n.admonition,{type:"tip",children:[(0,i.jsxs)(n.p,{children:["Besides native provider denoms (e.g., ",(0,i.jsx)(n.code,{children:"uatom"})," for the Cosmos Hub), please use the ",(0,i.jsx)(n.code,{children:"ibc/*"})," denom trace format.\nFor example, for ",(0,i.jsx)(n.code,{children:"untrn"})," transferred over the path ",(0,i.jsx)(n.code,{children:"transfer/channel-569"}),", the denom trace\ncan be queried using the following command:"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"> gaiad query ibc-transfer denom-hash transfer/channel-569/untrn\nhash: 0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5\n"})}),(0,i.jsxs)(n.p,{children:["Then use the resulting hash in the ",(0,i.jsx)(n.code,{children:"ChangeRewardDenomProposal"}),", e.g.,"]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",children:'{\n "title": "Add untrn as a reward denom",\n "description": "Here is more information about the proposal",\n "denomsToAdd": ["ibc/0025F8A87464A471E66B234C4F93AEC5B4DA3D42D7986451A059273426290DD5"],\n "denomsToRemove": []\n}\n'})})]})]})}function h(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>t,a:()=>a});var i=o(7294);const r={},s=i.createContext(r);function a(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d21f9ede.fc07846e.js b/assets/js/d21f9ede.fc07846e.js
new file mode 100644
index 0000000000..098735fc3a
--- /dev/null
+++ b/assets/js/d21f9ede.fc07846e.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4932],{4330:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var i=s(5893),o=s(1151);const r={sidebar_position:13,title:"Separate Releasing"},t="ADR 012: Separate Releasing",a={id:"adrs/adr-012-separate-releasing",title:"Separate Releasing",description:"Changelog",source:"@site/docs/adrs/adr-012-separate-releasing.md",sourceDirName:"adrs",slug:"/adrs/adr-012-separate-releasing",permalink:"/interchain-security/adrs/adr-012-separate-releasing",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:13,frontMatter:{sidebar_position:13,title:"Separate Releasing"},sidebar:"tutorialSidebar",previous:{title:"Improving testing and increasing confidence",permalink:"/interchain-security/adrs/adr-011-improving-test-confidence"},next:{title:"Slashing on the provider for consumer equivocation",permalink:"/interchain-security/adrs/adr-013-equivocation-slashing"}},l={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Spike results",id:"spike-results",level:3},{value:"Why go.mod split is not the way to go",id:"why-gomod-split-is-not-the-way-to-go",level:3},{value:"Why separate repos is cool but also not the way to go",id:"why-separate-repos-is-cool-but-also-not-the-way-to-go",level:3},{value:"Decision",id:"decision",level:2},{value:"Example release flow",id:"example-release-flow",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function c(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-012-separate-releasing",children:"ADR 012: Separate Releasing"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[8/18/22,": Initial draft of idea in ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801",children:"#801"})]}),"\n",(0,i.jsxs)(n.li,{children:[8/22/22,": Put idea in this ADR"]}),"\n",(0,i.jsxs)(n.li,{children:[.05,": Reject this ADR"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Rejected"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.h3,{id:"spike-results",children:"Spike results"}),"\n",(0,i.jsxs)(n.p,{children:["I explored the idea of ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801",children:"#801"})," with this ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/shawn%2Fgo-mod-split-aug-spike",children:"spike branch"}),". Here's my conclusions:"]}),"\n",(0,i.jsxs)(n.p,{children:["Splitting this repo to have multiple go.mods is possible. However there are various intricacies involved in decoupling the package hierarchy to have ",(0,i.jsx)(n.code,{children:"x/ccv/types"})," as the lowest level dep, with ",(0,i.jsx)(n.code,{children:"x/ccv/consumer"})," and ",(0,i.jsx)(n.code,{children:"x/ccv/provider"})," being one dep layer above, with high-level tests depending on all three of the mentioned packages. I'd estimate this decoupling would take 2-5 workdays to finish, and require significant review effort."]}),"\n",(0,i.jsx)(n.h3,{id:"why-gomod-split-is-not-the-way-to-go",children:"Why go.mod split is not the way to go"}),"\n",(0,i.jsxs)(n.p,{children:["Let's take a step back and remember the issue we're trying to solve - ",(0,i.jsx)(n.strong,{children:"We need a clean way to decouple semver/releasing for the consumer and provider modules"}),". After more consideration, splitting up go.mods gives us little benefit in achieving this. Reasons:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The ",(0,i.jsx)(n.code,{children:"go.mod"})," dependency system is tied to git tags for the entire repo (ex: ",(0,i.jsx)(n.code,{children:"require github.com/cometbft/cometbft v0.37.2"})," refers to a historical tag for the entire cometbft repo)."]}),"\n",(0,i.jsx)(n.li,{children:"It'd be an odd dev experience to allow modules to reference past releases of other modules in the same repo. When would we ever want the consumer module to reference a past release of the types module for example?"}),"\n",(0,i.jsxs)(n.li,{children:["If we allow for ",(0,i.jsx)(n.code,{children:"go.mod"})," replace statements to build from local source code, why split up the package deps at all?"]}),"\n",(0,i.jsxs)(n.li,{children:["Splitting go.mods adds a bunch of complexity with ",(0,i.jsx)(n.code,{children:"go.work"})," files and all that shiz. VSCode does not play well with multiple module repos either."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"why-separate-repos-is-cool-but-also-not-the-way-to-go",children:"Why separate repos is cool but also not the way to go"}),"\n",(0,i.jsxs)(n.p,{children:["All this considered, the cleanest solution to decoupling semver/releasing for the consumer and provider modules would be to have multiple repos, each with their own go.mod (3-4 repos total including high level tests). With this scheme we could separately tag each repo as changes are merged, they could share some code from ",(0,i.jsx)(n.code,{children:"types"})," being an external dep, etc."]}),"\n",(0,i.jsx)(n.p,{children:"I don't think any of us want to split up the monorepo, that's a lot of work and seems like bikeshedding. There's another solution that's very simple.."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsxs)(n.p,{children:["Slightly adapting ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/cca008d856e3ffc60ec1a486871d0faa702abe26/CONTRIBUTING.md#semantic-versioning",children:"the current semver ruleset"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"A library API breaking change to EITHER the provider or consumer module will result in an increase of the MAJOR version number for BOTH modules (X.y.z-provider AND X.y.z-consumer)."}),"\n",(0,i.jsx)(n.li,{children:"A state breaking change (change requiring coordinated upgrade and/or state migration) will result in an increase of the MINOR version number for the AFFECTED module(s) (x.Y.z-provider AND/OR x.Y.z-consumer)."}),"\n",(0,i.jsx)(n.li,{children:"Any other changes (including node API breaking changes) will result in an increase of the PATCH version number for the AFFECTED module(s) (x.y.Z-provider AND/OR x.y.Z-consumer)."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"example-release-flow",children:"Example release flow"}),"\n",(0,i.jsxs)(n.p,{children:["We upgrade ",(0,i.jsx)(n.code,{children:"main"})," to use a new version of SDK. This is a major version bump, triggering a new release for both the provider and consumer modules, ",(0,i.jsx)(n.code,{children:"v5.0.0-provider"})," and ",(0,i.jsx)(n.code,{children:"v5.0.0-consumer"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["A state breaking change is merged to ",(0,i.jsx)(n.code,{children:"main"})," for the provider module. We release only a ",(0,i.jsx)(n.code,{children:"v5.1.0-provider"})," off main."]}),"\n",(0,i.jsxs)(n.li,{children:["Another state breaking change is merged to ",(0,i.jsx)(n.code,{children:"main"})," for the provider module. We release only a ",(0,i.jsx)(n.code,{children:"v5.2.0-provider"})," off main."]}),"\n",(0,i.jsxs)(n.li,{children:["At this point, the latest consumer version is still ",(0,i.jsx)(n.code,{children:"v5.0.0-consumer"}),". We now merge a state breaking change for the consumer module to ",(0,i.jsx)(n.code,{children:"main"}),", and consequently release ",(0,i.jsx)(n.code,{children:"v5.1.0-consumer"}),". Note that ",(0,i.jsx)(n.code,{children:"v5.1.0-consumer"})," is tagged off a LATER commit from main than ",(0,i.jsx)(n.code,{children:"v5.2.0-provider"}),". This is fine, as the consumer module should not be affected by the provider module's state breaking changes."]}),"\n",(0,i.jsxs)(n.li,{children:["Once either module sees a library API breaking change, we bump the major version for both modules. For example, we merge a library API breaking change to ",(0,i.jsx)(n.code,{children:"main"})," for the provider module. We release ",(0,i.jsx)(n.code,{children:"v6.0.0-provider"})," and ",(0,i.jsx)(n.code,{children:"v6.0.0-consumer"})," off main. Note that most often, a library API breaking change will affect both modules simultaneously (example being bumping sdk version)."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Consumer repos have clear communication of what tagged versions are relevant to them. Consumer devs should know to never reference an ICS version that starts with ",(0,i.jsx)(n.code,{children:"provider"}),", even if it'd technically build."]}),"\n",(0,i.jsx)(n.li,{children:"Consumer and provider modules do not deviate as long as we continually release off a shared main branch. Backporting remains relatively unchanged besides being explicit about what module(s) your changes should affect."}),"\n",(0,i.jsx)(n.li,{children:"No code changes, just changes in process. Very simple."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"~~Slightly more complexity.~~Considerably more complex to manage the ICS library.\nThis is because ICS needs to support multiple versions of SDK (e.g., 0.45, 0.47, 0.50).\nIn addition, ICS needs to support a special fork of SDK (with LSM included) for the Cosmos Hub.\nThis means that instead of focusing on main the development team needs to manage multiple release\nbranches with different dependency trees."}),"\n",(0,i.jsx)(n.li,{children:"This solution does not allow having provider and consumer on separate versions of e.g. the Cosmos SDK."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.blockquote,{children:["\n",(0,i.jsx)(n.p,{children:"Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!"}),"\n"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801",children:"#801"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/801#issuecomment-1683349298",children:"#801 comment"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>a,a:()=>t});var i=s(7294);const o={},r=i.createContext(o);function t(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:t(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d2e13769.80866211.js b/assets/js/d2e13769.80866211.js
new file mode 100644
index 0000000000..b5c12d84be
--- /dev/null
+++ b/assets/js/d2e13769.80866211.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8382],{3396:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>l});var o=i(5893),s=i(1151);const t={sidebar_position:2,title:"ADR Template"},a="ADR 007: Pause validator unbonding during equivocation proposal",r={id:"adrs/adr-007-pause-unbonding-on-eqv-prop",title:"ADR Template",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-007-pause-unbonding-on-eqv-prop.md",sourceDirName:"adrs",slug:"/adrs/adr-007-pause-unbonding-on-eqv-prop",permalink:"/interchain-security/v5.0.0/adrs/adr-007-pause-unbonding-on-eqv-prop",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"ADR Template"},sidebar:"tutorialSidebar",previous:{title:"ADR Template",permalink:"/interchain-security/v5.0.0/adrs/adr-004-denom-dos-fixes"},next:{title:"ADR Template",permalink:"/interchain-security/v5.0.0/adrs/adr-template"}},d={},l=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"How",id:"how",level:3},{value:"When pause",id:"when-pause",level:3},{value:"When unpause",id:"when-unpause",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"adr-007-pause-validator-unbonding-during-equivocation-proposal",children:"ADR 007: Pause validator unbonding during equivocation proposal"}),"\n",(0,o.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"2023-05-16: Initial Draft"}),"\n",(0,o.jsx)(n.li,{children:"2023-11-30: Change the status to rejected"}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,o.jsx)(n.p,{children:"Rejected"}),"\n",(0,o.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Note:"})," ADR rejected as the equivocation proposal was removed by the\ncryptographic verification of equivocation feature\n(see ",(0,o.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR-005"})," and\n",(0,o.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing",children:"ADR-013"}),")."]}),"\n",(0,o.jsx)(n.p,{children:"Currently, if an equivocation slashing proposal is created after more than one\nweek has passed since the equivocation, it is possible that the validator in\nquestion could unbond and get away without being slashed, since the unbonding\nperiod is 3 weeks, and the voting period is 2 weeks. For this reason, it might\nbe good to pause unbondings for validators named in an equivocation slashing\nproposal until the proposal's voting period is over."}),"\n",(0,o.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,o.jsx)(n.h3,{id:"how",children:"How"}),"\n",(0,o.jsxs)(n.p,{children:["Pausing the unbonding period is already possible thanks to the changes in the\n",(0,o.jsx)(n.code,{children:"staking"})," module of the cosmos-sdk:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"stakingKeeper.PutUnbondingOnHold"})," pauses an unbonding period"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"stakingKeeper.UnbondingCanComplete"})," unpauses an unbonding period"]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["These methods use a reference counter under the hood, that gets incremented\nevery time ",(0,o.jsx)(n.code,{children:"PutUnbondingOnHold"})," is called, and decreased when\n",(0,o.jsx)(n.code,{children:"UnbondingCanComplete"})," is called instead. A specific unbonding is considered\nfully unpaused when its underlying reference counter reaches 0. Therefore, as\nlong as we safeguard consistency - i.e. we make sure we eventually decrement\nthe reference counter for each time we have incremented it - we can safely use\nthis existing mechanism without conflicts with the ",(0,o.jsx)(n.em,{children:"Completion of Unbonding\nOperations"})," system."]}),"\n",(0,o.jsx)(n.h3,{id:"when-pause",children:"When pause"}),"\n",(0,o.jsxs)(n.p,{children:["The unbonding period (if there is any unbonding) should be paused once an\nequivocation proposal enters the voting period. For that, the ",(0,o.jsx)(n.code,{children:"gov"})," module's\nhook ",(0,o.jsx)(n.code,{children:"AfterProposalDeposit"})," can be used."]}),"\n",(0,o.jsx)(n.p,{children:"If the hook is triggered with a an equivocation proposal in voting period, then\nfor each equivocation of the proposal, the unbonding operations of the related\nvalidator that were initiated after the equivocation block time must be paused"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"i.e. the underlying reference counter has to be increased."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Note that even after the voting period has started, a proposal can receive\nadditional deposits. The hook is triggered however at arrival of a deposit, so\na check to verify that the proposal is not already in voting period is\nrequired."}),"\n",(0,o.jsx)(n.h3,{id:"when-unpause",children:"When unpause"}),"\n",(0,o.jsxs)(n.p,{children:["We can use a ",(0,o.jsx)(n.code,{children:"gov"})," module's hook also here and it is\n",(0,o.jsx)(n.code,{children:"AfterProposalVotingPeriodEnded"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"If the hook is triggered with an equivocation proposal, then for each\nassociated equivocation, the unbonding operations of the related validator that\nwere initiated between the equivocation block time and the start of the\nproposal voting period must be unpaused - i.e. decrease the underlying\nreference counter - regardless of the proposal outcome."}),"\n",(0,o.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,o.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Validators subject to an equivocation proposal cannot finish unbonding\ntheir tokens before the end of the voting period."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"A malicious consumer chain could forge slash packets enabling submission of\nan equivocation proposal on the provider chain, resulting in the freezing of\nvalidator's unbondings for an undeterminated amount of time."}),"\n",(0,o.jsx)(n.li,{children:"Misbehavior on a consumer chain can potentially go unpunished, if no one\nsubmits an equivocation proposal in time, or if the proposal doesn't pass."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"This feature can't be used for social slashing, because an equivocation\nproposal is only accepted if there's a slash log for the related\nvalidator(s), meaning the consumer chain has reported the equivocation to\nthe provider chain."}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/747",children:"https://github.com/cosmos/interchain-security/issues/747"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/791",children:"https://github.com/cosmos/interchain-security/pull/791"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>a});var o=i(7294);const s={},t=o.createContext(s);function a(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/d784d738.71e628a7.js b/assets/js/d784d738.71e628a7.js
new file mode 100644
index 0000000000..779eeadf6d
--- /dev/null
+++ b/assets/js/d784d738.71e628a7.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7333],{5093:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>s,contentTitle:()=>a,default:()=>u,frontMatter:()=>r,metadata:()=>c,toc:()=>h});var i=o(5893),t=o(1151);const r={sidebar_position:1},a="Developing an ICS consumer chain",c={id:"consumer-development/app-integration",title:"Developing an ICS consumer chain",description:"When developing an ICS consumer chain, besides just focusing on your chain's logic you should aim to allocate time to ensure that your chain is compatible with the ICS protocol.",source:"@site/docs/consumer-development/app-integration.md",sourceDirName:"consumer-development",slug:"/consumer-development/app-integration",permalink:"/interchain-security/consumer-development/app-integration",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Power Shaping",permalink:"/interchain-security/features/power-shaping"},next:{title:"Consumer Chain Governance",permalink:"/interchain-security/consumer-development/consumer-chain-governance"}},s={},h=[{value:"Basic consumer chain",id:"basic-consumer-chain",level:2},{value:"Democracy consumer chain",id:"democracy-consumer-chain",level:2},{value:"Standalone chain to consumer chain changeover",id:"standalone-chain-to-consumer-chain-changeover",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"developing-an-ics-consumer-chain",children:"Developing an ICS consumer chain"}),"\n",(0,i.jsx)(n.p,{children:"When developing an ICS consumer chain, besides just focusing on your chain's logic you should aim to allocate time to ensure that your chain is compatible with the ICS protocol.\nTo help you on your journey, the ICS team has provided multiple examples of a minimum viable consumer chain applications."}),"\n",(0,i.jsx)(n.h2,{id:"basic-consumer-chain",children:"Basic consumer chain"}),"\n",(0,i.jsxs)(n.p,{children:["The source code for the example app can be found ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/main/app/consumer",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Please note that consumer chains do not implement the staking module - part of the validator set of the provider is replicated over to the consumer,\nmeaning that the consumer uses a subset of provider validator set and the stake of the validators on the provider determines their stake on the consumer.\nNote that after the introduction of ",(0,i.jsx)(n.a,{href:"/interchain-security/adrs/adr-015-partial-set-security",children:"Partial Set Security"}),", not all the provider validators have to validate a consumer chain (e.g., if ",(0,i.jsx)(n.code,{children:"top_N != 100"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:["Your chain should import the consumer module from ",(0,i.jsx)(n.code,{children:"x/consumer"})," and register it in the correct places in your ",(0,i.jsx)(n.code,{children:"app.go"}),".\nThe ",(0,i.jsx)(n.code,{children:"x/consumer"})," module will allow your chain to communicate with the provider using the ICS protocol. The module handles all IBC communication with the provider, and it is a simple drop-in.\nYou should not need to manage or override any code from the ",(0,i.jsx)(n.code,{children:"x/consumer"})," module."]}),"\n",(0,i.jsx)(n.h2,{id:"democracy-consumer-chain",children:"Democracy consumer chain"}),"\n",(0,i.jsxs)(n.p,{children:["The source code for the example app can be found ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/main/app/consumer-democracy",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This type of consumer chain wraps the basic CosmosSDK ",(0,i.jsx)(n.code,{children:"x/distribution"}),", ",(0,i.jsx)(n.code,{children:"x/staking"})," and ",(0,i.jsx)(n.code,{children:"x/governance"})," modules allowing the consumer chain to perform democratic actions such as participating and voting within the chain's governance system."]}),"\n",(0,i.jsxs)(n.p,{children:["This allows the consumer chain to leverage those modules while also using the ",(0,i.jsx)(n.code,{children:"x/consumer"})," module."]}),"\n",(0,i.jsx)(n.p,{children:'With these modules enabled, the consumer chain can mint its own governance tokens, which can then be delegated to prominent community members which are referred to as "representatives" (as opposed to "validators" in standalone chains). The token may have different use cases besides just voting on governance proposals.'}),"\n",(0,i.jsx)(n.h2,{id:"standalone-chain-to-consumer-chain-changeover",children:"Standalone chain to consumer chain changeover"}),"\n",(0,i.jsxs)(n.p,{children:["See the ",(0,i.jsx)(n.a,{href:"/interchain-security/consumer-development/changeover-procedure",children:"standalone chain to consumer chain changeover guide"})," for more information on how to transition your standalone chain to a consumer chain."]})]})}function u(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>c,a:()=>a});var i=o(7294);const t={},r=i.createContext(t);function a(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:a(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/da448d6e.641c7bd2.js b/assets/js/da448d6e.641c7bd2.js
new file mode 100644
index 0000000000..65b4a4fb47
--- /dev/null
+++ b/assets/js/da448d6e.641c7bd2.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4744],{1974:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>d});var o=i(5893),s=i(1151);const t={sidebar_position:4,title:"Equivocation governance proposal"},a="ADR 003: Equivocation governance proposal",r={id:"adrs/adr-003-equivocation-gov-proposal",title:"Equivocation governance proposal",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-003-equivocation-gov-proposal.md",sourceDirName:"adrs",slug:"/adrs/adr-003-equivocation-gov-proposal",permalink:"/interchain-security/v5.0.0/adrs/adr-003-equivocation-gov-proposal",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Equivocation governance proposal"},sidebar:"tutorialSidebar",previous:{title:"Jail Throttling",permalink:"/interchain-security/v5.0.0/adrs/adr-002-throttle"},next:{title:"Cryptographic verification of equivocation evidence",permalink:"/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification"}},c={},d=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"adr-003-equivocation-governance-proposal",children:"ADR 003: Equivocation governance proposal"}),"\n",(0,o.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"2023-02-06: Initial draft"}),"\n",(0,o.jsx)(n.li,{children:"2023-11-30: Change status to deprecated"}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,o.jsx)(n.p,{children:"Deprecated"}),"\n",(0,o.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Note:"})," ADR deprecated as the equivocation proposal was removed by the\ncryptographic verification of equivocation feature\n(see ",(0,o.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR-005"})," and\n",(0,o.jsx)(n.a,{href:"/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing",children:"ADR-013"}),")."]}),"\n",(0,o.jsx)(n.p,{children:"We want to limit the possibilities of a consumer chain to execute actions on the provider chain to maintain and ensure optimum security of the provider chain."}),"\n",(0,o.jsx)(n.p,{children:"For instance, a malicious consumer consumer chain can send slash packet to the provider chain, which will slash a validator without the need of providing an evidence."}),"\n",(0,o.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,o.jsx)(n.p,{children:"To protect against a malicious consumer chain, slash packets unrelated to downtime are ignored by the provider chain. Thus, an other mechanism is required to punish validators that have committed a double-sign on a consumer chain."}),"\n",(0,o.jsxs)(n.p,{children:["A new kind of governance proposal is added to the ",(0,o.jsx)(n.code,{children:"provider"})," module, allowing to slash and tombstone a validator for double-signing in case of any harmful action on the consumer chain."]}),"\n",(0,o.jsxs)(n.p,{children:["If such proposal passes, the proposal handler delegates to the ",(0,o.jsx)(n.code,{children:"evidence"})," module to process the equivocation. This module ensures the evidence isn\u2019t too old, or else ignores it (see ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/21021b837882d1d40f1d79bcbc4fad2e79a3fefe/x/evidence/keeper/infraction.go#L54-L62",children:"code"}),"). ",(0,o.jsx)(n.em,{children:"Too old"})," is determined by 2 consensus params :"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"evidence.max_age_duration"})," number of nanoseconds before an evidence is considered too old"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"evidence.max_age_numblocks"})," number of blocks before an evidence is considered too old."]}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"On the hub, those parameters are equals to"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-json",children:'// From https://cosmos-rpc.polkachu.com/consensus_params?height=13909682\n(...)\n"evidence": {\n\t"max_age_num_blocks": "1000000",\n\t"max_age_duration": "172800000000000",\n (...)\n},\n(...)\n'})}),"\n",(0,o.jsxs)(n.p,{children:["A governance proposal takes 14 days, so those parameters must be big enough so the evidence provided in the proposal is not ignored by the ",(0,o.jsx)(n.code,{children:"evidence"})," module when the proposal passes and is handled by the hub."]}),"\n",(0,o.jsxs)(n.p,{children:["For ",(0,o.jsx)(n.code,{children:"max_age_num_blocks=1M"}),", the parameter is big enough if we consider the hub produces 12k blocks per day (",(0,o.jsx)(n.code,{children:"blocks_per_year/365 = 436,0000/365"}),"). The evidence can be up to 83 days old (",(0,o.jsx)(n.code,{children:"1,000,000/12,000"}),") and not be ignored."]}),"\n",(0,o.jsxs)(n.p,{children:["For ",(0,o.jsx)(n.code,{children:"max_age_duration=172,800,000,000,000"}),", the parameter is too low, because the value is in nanoseconds so it\u2019s 2 days. Fortunately the condition that checks those 2 parameters uses a ",(0,o.jsx)(n.strong,{children:"AND"}),", so if ",(0,o.jsx)(n.code,{children:"max_age_num_blocks"})," condition passes, the evidence won\u2019t be ignored."]}),"\n",(0,o.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,o.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Remove the possibility from a malicious consumer chain to \u201cattack\u201d the provider chain by slashing/jailing validators."}),"\n",(0,o.jsx)(n.li,{children:"Provide a more acceptable implementation for the validator community."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Punishment action of double-signing isn\u2019t \u201cautomated\u201d, a governance proposal is required which takes more time."}),"\n",(0,o.jsx)(n.li,{children:"You need to pay 250ATOM to submit an equivocation evidence."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,o.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["PR that ignores non downtime slash packet : ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/692",children:"https://github.com/cosmos/interchain-security/pull/692"})]}),"\n",(0,o.jsxs)(n.li,{children:["PR that adds the governance slash proposal: ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/703",children:"https://github.com/cosmos/interchain-security/pull/703"})]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>a});var o=i(7294);const s={},t=o.createContext(s);function a(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/dc9efaba.5a3ab637.js b/assets/js/dc9efaba.5a3ab637.js
new file mode 100644
index 0000000000..8292321f20
--- /dev/null
+++ b/assets/js/dc9efaba.5a3ab637.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1324],{38:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var t=o(5893),r=o(1151);const i={sidebar_position:4,title:"Offboarding Checklist"},s="Consumer Offboarding",a={id:"consumer-development/offboarding",title:"Offboarding Checklist",description:"To offboard a consumer chain simply submit a ConsumerRemovalProposal governance proposal listing a stop_time. After stop time passes, the provider chain will remove the chain from the ICS protocol (it will stop sending validator set updates).",source:"@site/docs/consumer-development/offboarding.md",sourceDirName:"consumer-development",slug:"/consumer-development/offboarding",permalink:"/interchain-security/consumer-development/offboarding",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Offboarding Checklist"},sidebar:"tutorialSidebar",previous:{title:"Onboarding Checklist",permalink:"/interchain-security/consumer-development/onboarding"},next:{title:"Changeover Procedure",permalink:"/interchain-security/consumer-development/changeover-procedure"}},c={},d=[];function l(e){const n={code:"code",h1:"h1",p:"p",pre:"pre",...(0,r.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"consumer-offboarding",children:"Consumer Offboarding"}),"\n",(0,t.jsxs)(n.p,{children:["To offboard a consumer chain simply submit a ",(0,t.jsx)(n.code,{children:"ConsumerRemovalProposal"})," governance proposal listing a ",(0,t.jsx)(n.code,{children:"stop_time"}),". After stop time passes, the provider chain will remove the chain from the ICS protocol (it will stop sending validator set updates)."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'// ConsumerRemovalProposal is a governance proposal on the provider chain to remove (and stop) a consumer chain.\n// If it passes, all the consumer chain\'s state is removed from the provider chain. The outstanding unbonding\n// operation funds are released.\n{\n // the title of the proposal\n "title": "This was a great chain",\n "description": "Here is a .md formatted string specifying removal details",\n // the chain-id of the consumer chain to be stopped\n "chain_id": "consumerchain-1",\n // the time on the provider chain at which all validators are responsible to stop their consumer chain validator node\n "stop_time": "2023-03-07T12:40:00.000000Z",\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"More information will be listed in a future version of this document."})]})}function p(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>a,a:()=>s});var t=o(7294);const r={},i=t.createContext(r);function s(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/ded36896.f0182e76.js b/assets/js/ded36896.f0182e76.js
new file mode 100644
index 0000000000..ad69ef062a
--- /dev/null
+++ b/assets/js/ded36896.f0182e76.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7429],{2030:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>c});var o=i(5893),s=i(1151);const t={sidebar_position:2,title:"Pause validator unbonding during equivocation proposal"},a="ADR 007: Pause validator unbonding during equivocation proposal",r={id:"adrs/adr-007-pause-unbonding-on-eqv-prop",title:"Pause validator unbonding during equivocation proposal",description:"Changelog",source:"@site/docs/adrs/adr-007-pause-unbonding-on-eqv-prop.md",sourceDirName:"adrs",slug:"/adrs/adr-007-pause-unbonding-on-eqv-prop",permalink:"/interchain-security/adrs/adr-007-pause-unbonding-on-eqv-prop",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"Pause validator unbonding during equivocation proposal"},sidebar:"tutorialSidebar",previous:{title:"Denom DOS fixes",permalink:"/interchain-security/adrs/adr-004-denom-dos-fixes"},next:{title:"Key Assignment",permalink:"/interchain-security/adrs/adr-001-key-assignment"}},d={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"How",id:"how",level:3},{value:"When pause",id:"when-pause",level:3},{value:"When unpause",id:"when-unpause",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"adr-007-pause-validator-unbonding-during-equivocation-proposal",children:"ADR 007: Pause validator unbonding during equivocation proposal"}),"\n",(0,o.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"2023-05-16: Initial Draft"}),"\n",(0,o.jsx)(n.li,{children:"2023-11-30: Change the status to rejected"}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,o.jsx)(n.p,{children:"Rejected"}),"\n",(0,o.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Note:"})," ADR rejected as the equivocation proposal was removed by the\ncryptographic verification of equivocation feature\n(see ",(0,o.jsx)(n.a,{href:"/interchain-security/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR-005"})," and\n",(0,o.jsx)(n.a,{href:"/interchain-security/adrs/adr-013-equivocation-slashing",children:"ADR-013"}),")."]}),"\n",(0,o.jsx)(n.p,{children:"Currently, if an equivocation slashing proposal is created after more than one\nweek has passed since the equivocation, it is possible that the validator in\nquestion could unbond and get away without being slashed, since the unbonding\nperiod is 3 weeks, and the voting period is 2 weeks. For this reason, it might\nbe good to pause unbondings for validators named in an equivocation slashing\nproposal until the proposal's voting period is over."}),"\n",(0,o.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,o.jsx)(n.h3,{id:"how",children:"How"}),"\n",(0,o.jsxs)(n.p,{children:["Pausing the unbonding period is already possible thanks to the changes in the\n",(0,o.jsx)(n.code,{children:"staking"})," module of the cosmos-sdk:"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"stakingKeeper.PutUnbondingOnHold"})," pauses an unbonding period"]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.code,{children:"stakingKeeper.UnbondingCanComplete"})," unpauses an unbonding period"]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["These methods use a reference counter under the hood, that gets incremented\nevery time ",(0,o.jsx)(n.code,{children:"PutUnbondingOnHold"})," is called, and decreased when\n",(0,o.jsx)(n.code,{children:"UnbondingCanComplete"})," is called instead. A specific unbonding is considered\nfully unpaused when its underlying reference counter reaches 0. Therefore, as\nlong as we safeguard consistency - i.e. we make sure we eventually decrement\nthe reference counter for each time we have incremented it - we can safely use\nthis existing mechanism without conflicts with the ",(0,o.jsx)(n.em,{children:"Completion of Unbonding\nOperations"})," system."]}),"\n",(0,o.jsx)(n.h3,{id:"when-pause",children:"When pause"}),"\n",(0,o.jsxs)(n.p,{children:["The unbonding period (if there is any unbonding) should be paused once an\nequivocation proposal enters the voting period. For that, the ",(0,o.jsx)(n.code,{children:"gov"})," module's\nhook ",(0,o.jsx)(n.code,{children:"AfterProposalDeposit"})," can be used."]}),"\n",(0,o.jsx)(n.p,{children:"If the hook is triggered with a an equivocation proposal in voting period, then\nfor each equivocation of the proposal, the unbonding operations of the related\nvalidator that were initiated after the equivocation block time must be paused"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"i.e. the underlying reference counter has to be increased."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Note that even after the voting period has started, a proposal can receive\nadditional deposits. The hook is triggered however at arrival of a deposit, so\na check to verify that the proposal is not already in voting period is\nrequired."}),"\n",(0,o.jsx)(n.h3,{id:"when-unpause",children:"When unpause"}),"\n",(0,o.jsxs)(n.p,{children:["We can use a ",(0,o.jsx)(n.code,{children:"gov"})," module's hook also here and it is\n",(0,o.jsx)(n.code,{children:"AfterProposalVotingPeriodEnded"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"If the hook is triggered with an equivocation proposal, then for each\nassociated equivocation, the unbonding operations of the related validator that\nwere initiated between the equivocation block time and the start of the\nproposal voting period must be unpaused - i.e. decrease the underlying\nreference counter - regardless of the proposal outcome."}),"\n",(0,o.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,o.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Validators subject to an equivocation proposal cannot finish unbonding\ntheir tokens before the end of the voting period."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"A malicious consumer chain could forge slash packets enabling submission of\nan equivocation proposal on the provider chain, resulting in the freezing of\nvalidator's unbondings for an undeterminated amount of time."}),"\n",(0,o.jsx)(n.li,{children:"Misbehavior on a consumer chain can potentially go unpunished, if no one\nsubmits an equivocation proposal in time, or if the proposal doesn't pass."}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"This feature can't be used for social slashing, because an equivocation\nproposal is only accepted if there's a slash log for the related\nvalidator(s), meaning the consumer chain has reported the equivocation to\nthe provider chain."}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/747",children:"https://github.com/cosmos/interchain-security/issues/747"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/pull/791",children:"https://github.com/cosmos/interchain-security/pull/791"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>r,a:()=>a});var o=i(7294);const s={},t=o.createContext(s);function a(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/ded5fac2.f0ee3953.js b/assets/js/ded5fac2.f0ee3953.js
new file mode 100644
index 0000000000..2858b66e3f
--- /dev/null
+++ b/assets/js/ded5fac2.f0ee3953.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2383],{4249:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>h});var a=i(5893),n=i(1151);const o={sidebar_position:5},r="Partial Set Security",s={id:"features/partial-set-security",title:"Partial Set Security",description:"Partial Set Security (PSS) allows consumer chains to leverage only a subset of validators from the provider chain, which offers more flexibility than the traditional Replicated Security model. By introducing the top_N parameter, each consumer chain can choose the extent of security needed:",source:"@site/versioned_docs/version-v4.2.0-docs/features/partial-set-security.md",sourceDirName:"features",slug:"/features/partial-set-security",permalink:"/interchain-security/v4.2.0/features/partial-set-security",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:5,frontMatter:{sidebar_position:5},sidebar:"tutorialSidebar",previous:{title:"Consumer Initiated Slashing",permalink:"/interchain-security/v4.2.0/features/slashing"},next:{title:"Power Shaping",permalink:"/interchain-security/v4.2.0/features/power-shaping"}},c={},h=[];function l(e){const t={admonition:"admonition",code:"code",h1:"h1",li:"li",p:"p",ul:"ul",...(0,n.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h1,{id:"partial-set-security",children:"Partial Set Security"}),"\n",(0,a.jsx)(t.p,{children:"Partial Set Security (PSS) allows consumer chains to leverage only a subset of validators from the provider chain, which offers more flexibility than the traditional Replicated Security model. By introducing the top_N parameter, each consumer chain can choose the extent of security needed:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsx)(t.p,{children:"Top N: Requires the top N% validators from the provider chain to secure the consumer chain. This guarantees that the validators with the most power on the provider will validate the consumer chain, while others can voluntarily opt in."}),"\n"]}),"\n",(0,a.jsxs)(t.li,{children:["\n",(0,a.jsxs)(t.p,{children:["Opt-In: If the ",(0,a.jsx)(t.code,{children:"top_N"})," parameter is set to zero, no validator is mandated to secure the consumer chain. Instead, any validator from the provider chain can opt in using a dedicated transaction."]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(t.p,{children:"An advantage of a Top N chain is that the consumer chain is guaranteed to receive at least a certain fraction of the market cap of the provider chain in security. In turn, this chain needs to be approved by governance, since validators will be forced to run the chain. Thus, Top N chains should typically expect to need to provide a strong case for why they should be added to the provider chain, and they should make sure they offer enough rewards to incentivize validators and delegators to vote for their proposal."}),"\n",(0,a.jsx)(t.p,{children:"Opt-In chains, on the other hand, are more flexible. While for technical reasons, they are also currently added via governance proposals, since validators are never forced to validate these chains and simply opt in if they want to, they should typically expect to get their proposals approved much more easily compared to Top N chains, since validators that do not want to validate the chain can simply choose not to opt in.\nHowever, opt in chains do not get a fixed amount of security as a relation of the market cap of the provider as top N chains do, so opt in chains might want to keep an eye on how many validators have opted in to validate their chain and adjust their reward emissions accordingly to incentivize validators."}),"\n",(0,a.jsx)(t.admonition,{type:"tip",children:(0,a.jsx)(t.p,{children:"Partial Set Security is handled only by the provider chain - the consumer chains are simply sent validator sets, and they are not aware that this represents only a subset of the provider chain's validator set."})}),"\n",(0,a.jsxs)(t.admonition,{type:"caution",children:[(0,a.jsx)(t.p,{children:"Both Opt In and Top N chains currently require a governance proposal to be added to the provider chain."}),(0,a.jsx)(t.p,{children:"For Top N chains, this is also the long term vision for how they are launched."}),(0,a.jsx)(t.p,{children:"For Opt In chains, this is a temporary measure to prevent issues around chain ID squatting, i.e. someone could spuriously register many desirable chain IDs of upcoming consumer chain and simply deny legitimate consumer chains from using them. Eventually, the plan is to allow launching Opt In chains permissionlessly without going through governance, with quality control being handled by the market of validators deciding which chains they would like to validate on."})]})]})}function d(e={}){const{wrapper:t}={...(0,n.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},1151:(e,t,i)=>{i.d(t,{Z:()=>s,a:()=>r});var a=i(7294);const n={},o=a.createContext(n);function r(e){const t=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),a.createElement(o.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/e005c37e.7aec7bcf.js b/assets/js/e005c37e.7aec7bcf.js
new file mode 100644
index 0000000000..9f201f6cf3
--- /dev/null
+++ b/assets/js/e005c37e.7aec7bcf.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2883],{5837:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>r,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>c,toc:()=>h});var n=t(5893),s=t(1151);const o={sidebar_position:4,title:"Cryptographic verification of equivocation evidence"},a="ADR 005: Cryptographic verification of equivocation evidence",c={id:"adrs/adr-005-cryptographic-equivocation-verification",title:"Cryptographic verification of equivocation evidence",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-005-cryptographic-equivocation-verification.md",sourceDirName:"adrs",slug:"/adrs/adr-005-cryptographic-equivocation-verification",permalink:"/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:4,frontMatter:{sidebar_position:4,title:"Cryptographic verification of equivocation evidence"},sidebar:"tutorialSidebar",previous:{title:"Equivocation governance proposal",permalink:"/interchain-security/v4.2.0/adrs/adr-003-equivocation-gov-proposal"},next:{title:"Throttle with retries",permalink:"/interchain-security/v4.2.0/adrs/adr-008-throttle-retries"}},r={},h=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Light Client Attack",id:"light-client-attack",level:3},{value:"Double Signing Attack",id:"double-signing-attack",level:3},{value:"Decision",id:"decision",level:2},{value:"Light Client Attack",id:"light-client-attack-1",level:3},{value:"Double Signing Attack",id:"double-signing-attack-1",level:3},{value:"Current limitations:",id:"current-limitations",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"References",id:"references",level:2}];function l(e){const i={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,s.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"adr-005-cryptographic-verification-of-equivocation-evidence",children:"ADR 005: Cryptographic verification of equivocation evidence"}),"\n",(0,n.jsx)(i.h2,{id:"changelog",children:"Changelog"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"5/1/2023: First draft"}),"\n",(0,n.jsx)(i.li,{children:"7/23/2023: Add light client attacks handling"}),"\n",(0,n.jsx)(i.li,{children:"9/6/2023: Add double signing attacks handling"}),"\n",(0,n.jsx)(i.li,{children:"11/3/2023: Update limitations to clarify amnesia attacks are ignored"}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"status",children:"Status"}),"\n",(0,n.jsx)(i.p,{children:"Accepted"}),"\n",(0,n.jsx)(i.h2,{id:"context",children:"Context"}),"\n",(0,n.jsx)(i.p,{children:"Currently, we use a governance proposal to slash validators for equivocation (double signing and light client attacks).\nEvery proposal needs to go through a (two weeks) voting period before it can be approved.\nGiven a three-week unbonding period, this means that an equivocation proposal needs to be submitted within one week since the infraction occurred."}),"\n",(0,n.jsx)(i.p,{children:"This ADR proposes a system to slash validators automatically for equivocation, immediately upon the provider chain's receipt of the evidence. Another thing to note is that we intend to introduce this system in stages, since even the partial ability to slash and/or tombstone is a strict improvement in security.\nThe feature is implemented in two parts, each with its dedicated endpoint. One endpoint handles light client attacks, while the other handles double signing attacks."}),"\n",(0,n.jsx)(i.h3,{id:"light-client-attack",children:"Light Client Attack"}),"\n",(0,n.jsx)(i.p,{children:"In a nutshell, the light client is a process that solely verifies a specific state machine's\nconsensus without executing the transactions. The light clients get new headers by querying\nmultiple nodes, called primary and witness nodes."}),"\n",(0,n.jsxs)(i.p,{children:["Light clients download new headers committed on chain from a primary. Headers can be verified in two ways: sequentially,\nwhere the block height of headers is serial, or using skipping. This second verification method allows light clients to download headers\nwith nonconsecutive block height, where some intermediate headers are skipped (see ",(0,n.jsx)(i.a,{href:"https://arxiv.org/pdf/2010.07031.pdf",children:"Tendermint Light Client, Figure 1 and Figure 3"}),").\nAdditionally, light clients are cross-checking new headers obtained from a primary with witnesses to ensure all nodes share the same state."]}),"\n",(0,n.jsxs)(i.p,{children:["A light client attack occurs when a Byzantine validator sends invalid headers to a light client.\nAs the light client doesn't execute transactions, it can be deceived into trusting corrupted application state transitions.\nFor instance, if a light client receives header ",(0,n.jsx)(i.code,{children:"A"})," from the primary and header ",(0,n.jsx)(i.code,{children:"B"})," from a witness for the same block height ",(0,n.jsx)(i.code,{children:"H"}),",\nand both headers are successfully verified, it indicates a light client attack.\nNote that in this case, either the primary or the witness or both are malicious."]}),"\n",(0,n.jsxs)(i.p,{children:["The types of light client attacks are defined by analyzing the differences between the conflicting headers.\nThere are three types of light client attacks: lunatic attack, equivocation attack, and amnesia attack.\nFor details, see the ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/main/spec/light-client/attacks/notes-on-evidence-handling.md#evidence-handling",children:"CometBFT specification"}),"."]}),"\n",(0,n.jsxs)(i.p,{children:["When a light client agent detects two conflicting headers, it will initially verify their traces (see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/light/detector.go#L28",children:"cometBFT detector"}),") using its primary and witness nodes.\nIf these headers pass successful verification, the Byzantine validators will be identified based on the header's commit signatures\nand the type of light client attack. The agent will then transmit this information to its nodes using a ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#light-client-attacks",children:(0,n.jsx)(i.code,{children:"LightClientAttackEvidence"})})," evidence to be eventually voted on and added to a block.\nNote that from a light client agent perspective, it is not possible to establish whether a primary or a witness node, or both, are malicious.\nTherefore, it will create and send two evidences: one against the primary (sent to the witness), and one against the witness (sent to the primary).\nBoth nodes will then verify it before broadcasting it and adding it to the ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/evidence/pool.go#L28",children:"evidence pool"}),".\nIf an evidence is finally committed to a block, the chain's evidence module will execute it, resulting in the jailing and the slashing of the validators responsible for the light client attack."]}),"\n",(0,n.jsxs)(i.p,{children:["Light clients are a core component of IBC. In the event of a light client attack, IBC relayers notify the affected chains by submitting an ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/ibc-go/blob/v4.4.2/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L79",children:"IBC misbehavior message"}),".\nA misbehavior message includes the conflicting headers that constitute a light client attack evidence. Upon receiving such a message,\na chain will first verify whether these headers would have convinced its light client. This verification is achieved by checking\nthe header states against the light client consensus states (see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/ibc-go/blob/v4.4.2/modules/light-clients/07-tendermint/types/misbehaviour_handle.go#L24",children:"IBC misbehaviour handler"}),'). If the misbehaviour is successfully verified, the chain will then "freeze" the\nlight client, halting any further trust in or updating of its states.']}),"\n",(0,n.jsx)(i.h3,{id:"double-signing-attack",children:"Double Signing Attack"}),"\n",(0,n.jsxs)(i.p,{children:["A double signing attack, also known as equivocation,\noccurs when a validator votes for two different blocks in the same round of the CometBFT consensus.\nThis consensus mechanism operates with multiple voting rounds at each block height,\nand it strictly prohibits sending two votes of the same type during a round\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/consensus.md#state-machine-overview",children:"CometBFT State Machine Overview"}),")."]}),"\n",(0,n.jsxs)(i.p,{children:["When a node observes two votes from the same peer, it will use these two votes to create\na ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/types/evidence.go#L35",children:(0,n.jsx)(i.code,{children:"DuplicateVoteEvidence"})}),"\nevidence and gossip it to the other nodes in the network\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#detection",children:"CometBFT equivocation detection"}),").\nEach node will then verify the evidence according to the CometBFT rules that define a valid double signing infraction, and based on this verification, they will decide whether to add the evidence to a block.\nDuring the evidence verification process, the signatures of the conflicting votes must be verified successfully.\nNote that this is achieved using the public key of the misbehaving validator, along with the chain ID of the chain where the infraction occurred (see ",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/spec/consensus/evidence.md#verification",children:"CometBFT equivocation verification"}),")."]}),"\n",(0,n.jsxs)(i.p,{children:["Once a double signing evidence is committed to a block, the consensus layer will report the equivocation to the evidence module of the Cosmos SDK application layer.\nThe application will, in turn, punish the malicious validator through jailing, tombstoning and slashing\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.45.16-ics-lsm/x/evidence/keeper/infraction.go#L263",children:"handleEquivocationEvidence"}),")."]}),"\n",(0,n.jsx)(i.h2,{id:"decision",children:"Decision"}),"\n",(0,n.jsx)(i.h3,{id:"light-client-attack-1",children:"Light Client Attack"}),"\n",(0,n.jsxs)(i.p,{children:["In the first part of the feature, we introduce a new endpoint: ",(0,n.jsx)(i.code,{children:"HandleConsumerMisbehaviour(ctx sdk.Context, misbehaviour ibctmtypes.Misbehaviour)"}),".\nThe main idea is to leverage the current IBC misbehaviour handling and update it to solely jail and slash the validators that\nperformed a light client attack. Note that in this context, we assume that chains connected via a light client\nshare the same validator set, as is the case with Replicated Security."]}),"\n",(0,n.jsx)(i.p,{children:"This endpoint reuses the IBC client libraries to verify that the misbehaviour headers would have fooled the light client.\nAdditionally, it\u2019s crucial that the endpoint logic results in the slashing and jailing of validators under the same conditions\nas a light client agent detector. Therefore, the endpoint ensures that the two conditions are met:\nthe headers in the misbehaviour message have the same block height, and\nthe light client isn\u2019t expired."}),"\n",(0,n.jsx)(i.p,{children:"After having successfully verified a misbehaviour, the endpoint executes the jailing and slashing of the malicious validators similarly as in the evidence module."}),"\n",(0,n.jsx)(i.h3,{id:"double-signing-attack-1",children:"Double Signing Attack"}),"\n",(0,n.jsxs)(i.p,{children:["In the second part of the feature, we introduce a new endpoint ",(0,n.jsx)(i.code,{children:"HandleConsumerDoubleVoting( ctx sdk.Context, evidence *tmtypes.DuplicateVoteEvidence, chainID string, pubkey cryptotypes.PubKey)"}),".\nSimply put, the handling logic verifies a double signing evidence against a provided\npublic key and chain ID and, if successful, executes the jailing of the malicious validator who double voted."]}),"\n",(0,n.jsxs)(i.p,{children:["We define a new\n",(0,n.jsx)(i.code,{children:"MsgSubmitConsumerDoubleVoting"})," message to report a double voting evidence observed\non a consumer chain to the endpoint of the provider chain. This message contains two fields:\na double signing evidence\n",(0,n.jsx)(i.code,{children:"duplicate_vote_evidence"})," and a light client header for the infraction block height,\nreferred to as ",(0,n.jsx)(i.code,{children:"infraction_block_header"}),".\nThe latter provides the malicious validator's public key and the chain ID required to verify the signature of the votes contained in the evidence."]}),"\n",(0,n.jsxs)(i.p,{children:["Note that double signing evidence is not verified using the same conditions as in the implementation CometBFT (see\n",(0,n.jsx)(i.a,{href:"https://github.com/cometbft/cometbft/blob/v0.34.28/evidence/verify.go#L19",children:(0,n.jsx)(i.code,{children:"verify(evidence types.Evidence)"})})," method). Specifically, we do not check that the evidence hasn't expired.\nMore details can be found in the ",(0,n.jsx)(i.a,{href:"#current-limitations",children:'"Current limitations"'})," section below."]}),"\n",(0,n.jsxs)(i.p,{children:["Upon a successful equivocation verification, the misbehaving validator is jailed for the maximum time\n(see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.45.16-ics-lsm/x/evidence/types/params.go#L11",children:"DoubleSignJailEndTime"}),"\nin the SDK evidence module)."]}),"\n",(0,n.jsx)(i.h3,{id:"current-limitations",children:"Current limitations:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"We cannot derive an infraction height from the evidence, so it is only possible to jail validators, not actually slash them.\nTo explain the technical reasons behind this limitation, let's recap the initial consumer initiated slashing logic.\nIn a nutshell, consumer heights are mapped to provider heights through VSCPackets, namely through the so called vscIDs.\nWhen an infraction occurs on the consumer, a SlashPacket containing the vscID obtained from mapping the consumer infraction height\nis sent to the provider. Upon receiving the packet, the provider maps the consumer infraction height to a local infraction height,\nwhich is used to slash the misbehaving validator. In the context of untrusted consumer chains, all their states, including vscIDs,\ncould be corrupted and therefore cannot be used for slashing purposes."}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsx)(i.p,{children:"For the same reasons explained above, the age of a consumer double signing evidence can't be verified,\neither using its infraction height or its unsigned timestamp. Note that changes the jailing behaviour, potentially leading to a validator's jailing based on some \"old\" evidence from a consumer, which wouldn't occur if the consumer were a standalone chain."}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsxs)(i.p,{children:["In the first stage of this feature, validators are jailed indefinitely without being tombstoned.\nThe underlying reason is that a malicious validator could take advantage of getting tombstoned\nto avoid being slashed on the provider (",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/1232#issuecomment-1693127641",children:"see comment"}),")."]}),"\n"]}),"\n",(0,n.jsxs)(i.li,{children:["\n",(0,n.jsxs)(i.p,{children:["Currently, the endpoint can only handle ",(0,n.jsx)(i.em,{children:"equivocation"})," light client attacks. This is because the ",(0,n.jsx)(i.em,{children:"lunatic"})," attacks require the endpoint to possess the ability to dissociate which header is conflicted or trusted upon receiving a misbehavior message. Without this information, it's not possible to extract the Byzantine validators from the conflicting headers (see ",(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/826#discussion_r1268668684",children:"comment"}),'). In addition, "amnesia" attacks are ignored, similar to CometBFT (see ',(0,n.jsx)(i.a,{href:"https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-047-handling-evidence-from-light-client.md#negative",children:"ADR-056"}),")."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"consequences",children:"Consequences"}),"\n",(0,n.jsx)(i.h3,{id:"positive",children:"Positive"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"It is now possible for the provider chain to jail validators who committed\nlight client or double signing attacks on a consumer chain."}),"\n"]}),"\n",(0,n.jsx)(i.h3,{id:"negative",children:"Negative"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"N/A"}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/826",children:"ICS misbehaviour handling PR"})}),"\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/pull/1232",children:"Consumer double voting handler PR"})}),"\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://docs.google.com/document/d/1fe1uSJl1ZIYWXoME3Yf4Aodvz7V597Ric875JH-rigM/edit#heading=h.rv4t8i6d6jfn",children:"Architectural diagrams"})}),"\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-013-equivocation-slashing.md",children:"ADR on equivocation slashing"})}),"\n"]})]})}function d(e={}){const{wrapper:i}={...(0,s.a)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},1151:(e,i,t)=>{t.d(i,{Z:()=>c,a:()=>a});var n=t(7294);const s={},o=n.createContext(s);function a(e){const i=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function c(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/e0ad375d.01b8369f.js b/assets/js/e0ad375d.01b8369f.js
new file mode 100644
index 0000000000..53aa066706
--- /dev/null
+++ b/assets/js/e0ad375d.01b8369f.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1840],{3978:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>d});var n=o(5893),i=o(1151);const s={sidebar_position:10,title:"Soft Opt-Out"},a=void 0,r={id:"adrs/adr-009-soft-opt-out",title:"Soft Opt-Out",description:"ADR 009: Soft Opt-Out",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-009-soft-opt-out.md",sourceDirName:"adrs",slug:"/adrs/adr-009-soft-opt-out",permalink:"/interchain-security/v4.2.0/adrs/adr-009-soft-opt-out",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:10,frontMatter:{sidebar_position:10,title:"Soft Opt-Out"},sidebar:"tutorialSidebar",previous:{title:"Throttle with retries",permalink:"/interchain-security/v4.2.0/adrs/adr-008-throttle-retries"},next:{title:"Standalone to Consumer Changeover",permalink:"/interchain-security/v4.2.0/adrs/adr-010-standalone-changeover"}},l={},d=[{value:"ADR 009: Soft Opt-Out",id:"adr-009-soft-opt-out",level:2},{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function c(e){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"adr-009-soft-opt-out",children:"ADR 009: Soft Opt-Out"}),"\n",(0,n.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"6/13/23: Initial draft of ADR. Feature already implemented and in production."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,n.jsx)(t.p,{children:"Accepted"}),"\n",(0,n.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,n.jsxs)(t.p,{children:["Some small validators may not have the resources needed to validate all consumer chains. Therefore a need exists to allow the bottom ",(0,n.jsx)(t.code,{children:"x%"})," of validators to opt-out of validating a consumer chain. Meaning downtime infractions for these validators are dropped without ever reaching the provider."]}),"\n",(0,n.jsx)(t.p,{children:"This document specifies a modification to the ccv protocol which allows the bottom x% of the validator set by power to opt out of validating consumer chains without being jailed or otherwise punished for it. The feature is implemented with entirely consumer-side code."}),"\n",(0,n.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,n.jsxs)(t.p,{children:["A consumer param exists, known as ",(0,n.jsx)(t.code,{children:"SoftOptOutThreshold"}),", which is a string decimal in the range of [0, 0.2], that determines the portion of validators which are allowed to opt out of validating that specific consumer."]}),"\n",(0,n.jsxs)(t.p,{children:["In every consumer beginblocker, a function is ran which determines the so called ",(0,n.jsx)(t.em,{children:"smallest non opt-out voting power"}),". Validators with voting power greater than or equal to this value must validate the consumer chain, while validators below this value may opt out of validating the consumer chain."]}),"\n",(0,n.jsxs)(t.p,{children:["The smallest non opt-out voting power is recomputed every beginblocker in ",(0,n.jsx)(t.code,{children:"UpdateSmallestNonOptOutPower()"}),". In a nutshell, the method obtains the total voting power of the consumer, iterates through the full valset (ordered power ascending) keeping track of a power sum, and when ",(0,n.jsx)(t.code,{children:"powerSum / totalPower > SoftOptOutThreshold"}),", the ",(0,n.jsx)(t.code,{children:"SmallestNonOptOutPower"})," is found and persisted."]}),"\n",(0,n.jsxs)(t.p,{children:["Then, whenever the ",(0,n.jsx)(t.code,{children:"Slash()"})," interface is executed on the consumer, if the voting power of the relevant validator being slashed is less than ",(0,n.jsx)(t.code,{children:"SmallestNonOptOutPower"})," for that block, the slash request is dropped and never sent to the provider."]}),"\n",(0,n.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,n.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Small validators can opt out of validating specific consumers without being punished for it."}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["The bottom ",(0,n.jsx)(t.code,{children:"x%"})," is still part of the total voting power of the consumer chain. This means that if the soft opt-out threshold is set to ",(0,n.jsx)(t.code,{children:"10%"})," for example, and every validator in the bottom ",(0,n.jsx)(t.code,{children:"10%"})," opts out from validating the consumer, then a ",(0,n.jsx)(t.code,{children:"24%"})," downtime of the remaining voting power would halt the chain. This may be especially problematic during consumer upgrades."]}),"\n",(0,n.jsxs)(t.li,{children:["In nominal scenarios, consumers with soft opt out enabled will be constructing slash packets for small vals, which may be dropped. This is wasted computation, but necessary to keep implementation simple. Note that the sdk's ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/d3f09c222243bb3da3464969f0366330dcb977a8/x/slashing/keeper/infractions.go#L75",children:"full downtime logic"})," is always executed on the consumer, which can be computationally expensive and slow down certain blocks."]}),"\n",(0,n.jsx)(t.li,{children:"In a consumer chain, when a validator that has opted out becomes the proposer, there will naturally be no proposal made and validators would need to move to the next consensus round for the same height to reach a decision. As a result, we would need more time to finalize blocks on a consumer chain."}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"neutral",children:"Neutral"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Validators in the bottom of the valset who don't have to validate, may receive large delegation(s) which suddenly boost the validator to the subset that has to validate. This may catch the validator off guard."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Original issue with some napkin math ",(0,n.jsx)(t.a,{href:"https://github.com/cosmos/interchain-security/issues/784",children:"#784"})]}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},1151:(e,t,o)=>{o.d(t,{Z:()=>r,a:()=>a});var n=o(7294);const i={},s=n.createContext(i);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/e2ddbbfd.d395360c.js b/assets/js/e2ddbbfd.d395360c.js
new file mode 100644
index 0000000000..f51de25daf
--- /dev/null
+++ b/assets/js/e2ddbbfd.d395360c.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8892],{2005:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>c,frontMatter:()=>s,metadata:()=>r,toc:()=>l});var a=i(5893),n=i(1151);const s={sidebar_position:18,title:"ICS with Inactive Provider Validators"},o="ADR 017: ICS with Inactive Provider Validators",r={id:"adrs/adr-017-allowing-inactive-validators",title:"ICS with Inactive Provider Validators",description:"Changelog",source:"@site/docs/adrs/adr-017-allowing-inactive-validators.md",sourceDirName:"adrs",slug:"/adrs/adr-017-allowing-inactive-validators",permalink:"/interchain-security/adrs/adr-017-allowing-inactive-validators",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:18,frontMatter:{sidebar_position:18,title:"ICS with Inactive Provider Validators"},sidebar:"tutorialSidebar",previous:{title:"Security aggregation",permalink:"/interchain-security/adrs/adr-016-securityaggregation"}},d={},l=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Changes to the state",id:"changes-to-the-state",level:3},{value:"Risk Mitigations",id:"risk-mitigations",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Sybil attacks",id:"sybil-attacks",level:4},{value:"Reputational damage is not a deterrent",id:"reputational-damage-is-not-a-deterrent",level:4},{value:"Additional negative consequences",id:"additional-negative-consequences",level:4},{value:"Neutral",id:"neutral",level:3},{value:"Alternative considerations",id:"alternative-considerations",level:2},{value:"Modifying the staking module",id:"modifying-the-staking-module",level:3},{value:"Allowing unbonding validators to validate",id:"allowing-unbonding-validators-to-validate",level:3},{value:"References",id:"references",level:2}];function h(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",ul:"ul",...(0,n.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h1,{id:"adr-017-ics-with-inactive-provider-validators",children:"ADR 017: ICS with Inactive Provider Validators"}),"\n",(0,a.jsx)(t.h2,{id:"changelog",children:"Changelog"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"15th May 2024: Initial draft"}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"status",children:"Status"}),"\n",(0,a.jsx)(t.p,{children:"Proposed"}),"\n",(0,a.jsx)(t.h2,{id:"context",children:"Context"}),"\n",(0,a.jsx)(t.p,{children:"Currently, only validators in the active set on the provider can validate on consumer chains, which limits the number of validators that can participate in Interchain Security (ICS).\nValidators outside of the active set might be willing\nto validate on consumer chains, but we might not want to make the provider validator set larger, e.g. to not put more strain on the consensus engine.\nThis runs the risk of leaving consumer chains with too few validators."}),"\n",(0,a.jsxs)(t.p,{children:["The purpose of this ADR is to allow validators that are ",(0,a.jsx)(t.em,{children:"not"})," part of the consensus process on the provider chain (because they are inactive)\nto validate on consumer chains."]}),"\n",(0,a.jsx)(t.p,{children:'In the context of this ADR, "consensus validator set" is the set of validators participating in the consensus protocol, and "staking validator set" is the set of validators viewed as active by the staking module.'}),"\n",(0,a.jsx)(t.p,{children:"Currently, the staking module, provider module, and CometBFT interact in this way:"}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"inactivevals_before.png",src:i(4823).Z+"",width:"874",height:"723"})}),"\n",(0,a.jsxs)(t.p,{children:["The staking module keeps a list of validators. The ",(0,a.jsx)(t.code,{children:"MaxValidators"}),' validators with the largest amount of stake are "active" validators. ',(0,a.jsx)(t.code,{children:"MaxValidators"})," is a parameter of the staking module. The staking module sends these validators to CometBFT to inform which validators make up the next consensus validators, that is, the set of validators participating in the consensus process. Separately, the provider module reads the list of bonded validators and sends this to the consumer chain, after shaping it according to which validators are opted in and the parameters set by the consumer chain for allowlist, denylist, etc."]}),"\n",(0,a.jsx)(t.h2,{id:"decision",children:"Decision"}),"\n",(0,a.jsx)(t.p,{children:"The proposed solution to allow validators that are not participating in the consensus process on the provider (inactive validators) is to change 3 main things:"}),"\n",(0,a.jsxs)(t.p,{children:["a) increase the ",(0,a.jsx)(t.code,{children:"MaxValidators"})," parameter of the staking module"]}),"\n",(0,a.jsxs)(t.p,{children:["b) do ",(0,a.jsx)(t.em,{children:"not"})," take the updates for CometBFT directly from the bonded validators in the staking module, by wrapping the staking modules ",(0,a.jsx)(t.code,{children:"EndBlocker"})," with a dummy EndBlocker that doesn't return any validator updates. Instead, we adjust the provider module to return validator updates on its EndBlocker. These validator updates are obtained by ",(0,a.jsx)(t.em,{children:"filtering"})," the bonded validators to send only the first ",(0,a.jsx)(t.code,{children:"MaxProviderConsensusValidators"})," (sorted by largest amount of stake first) many validators to CometBFT"]}),"\n",(0,a.jsx)(t.p,{children:"c) use the enlarged list of bonded validators from the staking module as basis for the validator set that the provider module sends to consumer chains (again after applying power shaping and filtering out validatiors that are not opted in)."}),"\n",(0,a.jsx)(t.p,{children:"In consequence, the provider chain can keep a reasonably-sized consensus validator set, while giving consumer chains a much larger pool of potential validators."}),"\n",(0,a.jsx)(t.p,{children:(0,a.jsx)(t.img,{alt:"inactivevals_after.png",src:i(9022).Z+"",width:"874",height:"723"})}),"\n",(0,a.jsx)(t.p,{children:"Some additional considerations:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Migration: In the migration, the last consensus validator set will be set to the last active validator set from the view of the staking module. Existing consumer chains are migrated to have a validator set size cap (otherwise, they could end up with a huge validator set including all the staking-but-not-consensus-active validators from the provider chain)"}),"\n",(0,a.jsxs)(t.li,{children:["Slashing: Validators that are not part of the active set on the provider chain can still be jailed for downtime on a consumer chain (via an Interchain Security SlashPacket sent to the provider, who will then jail the validator), but they ",(0,a.jsx)(t.em,{children:"are not"})," slashed for downtime on the provider chain.\nThis is achieved without any additional changes to the slashing module, because the slashing module checks for downtime by looking at the consensus participants reported by CometBFT, and thus with the proposed solution, validators that are not part of the consensus validators on the provider chain are not considered for downtime slashing (see ",(0,a.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.11/x/slashing/abci.go#L22",children:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.11/x/slashing/abci.go#L22"}),")."]}),"\n",(0,a.jsxs)(t.li,{children:["Rewards: Validators that are not part of the active set on the provider chain can still receive rewards on the consumer chain, but they ",(0,a.jsx)(t.em,{children:"do not"})," receive rewards from the provider chain. This change is\nachieved without further changes to staking or reward distributions, because similar to downtime, rewards are based on the consensus validator set (see ",(0,a.jsx)(t.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.11/x/distribution/abci.go#L28",children:"https://github.com/cosmos/cosmos-sdk/blob/v0.47.11/x/distribution/abci.go#L28"}),")"]}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"changes-to-the-state",children:"Changes to the state"}),"\n",(0,a.jsx)(t.p,{children:"The following changes to the state are required:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:["Introduce the ",(0,a.jsx)(t.code,{children:"MaxProviderConsensusValidators"})," parameter to the provider module, which is the number of validators that the provider module will send to consumer chains."]}),"\n",(0,a.jsxs)(t.li,{children:["Store the provider consensus validator set in the provider module state under the ",(0,a.jsx)(t.code,{children:"LastProviderConsensusValsPrefix"})," key. This is the last set of validators that the provider sent to the consensus engine. This is needed to compute the ValUpdates to send to the consensus engine (by diffing the current set with this last sent set)."]}),"\n",(0,a.jsxs)(t.li,{children:["Increase the ",(0,a.jsx)(t.code,{children:"MaxValidators"})," parameter of the staking module to the desired size of the potential validator\nset of consumer chains."]}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"risk-mitigations",children:"Risk Mitigations"}),"\n",(0,a.jsx)(t.p,{children:"To mitigate risks from validators with little stake, we introduce a minimum stake requirement for validators to be able to validate on consumer chains, which can be set by each consumer chain independently, with a default value set by the provider chain."}),"\n",(0,a.jsx)(t.p,{children:"Additionally, we independently allow individual consumer chains to disable this feature, which will disallow validators from outside the provider active set from validating on the consumer chain and revert them to the previous behaviour of only considering validators of the provider that are part of the active consensus validator set."}),"\n",(0,a.jsx)(t.p,{children:"Additional risk mitigations are to increase the active set size slowly, and to monitor the effects on the network closely. For the first iteration, we propose to increase the active set size to 200 validators (while keeping the consensus validators to 180), thus letting the 20 validators with the most stake outside of the active set validate on consumer chains."}),"\n",(0,a.jsx)(t.h2,{id:"consequences",children:"Consequences"}),"\n",(0,a.jsx)(t.h3,{id:"positive",children:"Positive"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Validators outside of the active set can validate on consumer chains without having an impact on the consensus engine of the provider chain"}),"\n",(0,a.jsx)(t.li,{children:"Consumer chains can have a much larger validator set than the provider chain if they prefer this e.g. for decentralization reasons"}),"\n",(0,a.jsx)(t.li,{children:"Consumer chain teams can, with much less cost than today, start up their own consumer chain node to keep the chain running (in a centralized manner) even if no hub validators have opted in to validate on the chain. This is useful to stop the chain from ending up with an empty validator set and becoming recoverable only with a hardfork"}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"negative",children:"Negative"}),"\n",(0,a.jsx)(t.p,{children:"Allowing validators from the inactive set brings with it some additional risks.\nIn general, consumer chains will now face some of the problems also faced by standalone chains. It\u2019s reasonable to assume that the validator set on the hub has a minimum amount of operational quality due to being battle tested and decentralized, and consumer chains with validators from outside the hub active set cannot rely on this as much anymore."}),"\n",(0,a.jsx)(t.h4,{id:"sybil-attacks",children:"Sybil attacks"}),"\n",(0,a.jsx)(t.p,{children:"With the restricted size of the active set today, it\u2019s clear that the set is at least minimally competitive and it is not trivial to spin up multiple nodes as a validator."}),"\n",(0,a.jsx)(t.p,{children:"When we make the \u201cpotential validator set\u201d much larger, we should assume that it becomes much less competitive to be part of that set, and thus trivial for single entities to control many of those validators."}),"\n",(0,a.jsx)(t.h4,{id:"reputational-damage-is-not-a-deterrent",children:"Reputational damage is not a deterrent"}),"\n",(0,a.jsx)(t.p,{children:"For validators in the active set, we typically assume that if they would misbehave, they pay a large reputational cost. This represents delegators deciding to switch validators (potentially even on chains other than the one the misbehaviour happened on), and loss of credibility in the ecosystem. With the much larger active set, it seems prudent to assume that reputational damage is not a deterrent for many validators. They might only have minimal amounts of delegated stake and control most of it themselves, so they might not be deterred from performing actions that would usually bring reputational damage."}),"\n",(0,a.jsx)(t.h4,{id:"additional-negative-consequences",children:"Additional negative consequences"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"The provider keeper will need to implement the staking keeper interface, and modules need to be wired up to either the staking or provider keeper, depending on whether they need the consensus or staking validator set"}),"\n",(0,a.jsx)(t.li,{children:"This will impact how future modules are integrated, since we will need to consider whether those modules should consider the consensus validators or the bonded validators (which other modules might assume to be the same)"}),"\n"]}),"\n",(0,a.jsx)(t.h3,{id:"neutral",children:"Neutral"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"There might be validators that are bonded, but not validating on any chain at all. This is not a problem, but it might be a bit confusing."}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"alternative-considerations",children:"Alternative considerations"}),"\n",(0,a.jsx)(t.h3,{id:"modifying-the-staking-module",children:"Modifying the staking module"}),"\n",(0,a.jsxs)(t.p,{children:["We could instead adapt the ",(0,a.jsx)(t.em,{children:"staking module"})," with a similar change.\nThis might be better if it turns out that the staking module active set is used in many other places."]}),"\n",(0,a.jsx)(t.h3,{id:"allowing-unbonding-validators-to-validate",children:"Allowing unbonding validators to validate"}),"\n",(0,a.jsx)(t.p,{children:"Instead of increasing the active set size, we could allow validators that are unbonded (but still exist on the provider) to validate consumer chains.\nFor this, we would need to:"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsx)(t.li,{children:"Modify the VSC updates to consider the set of all validators, even unbonded ones, instead of just active ones"}),"\n",(0,a.jsx)(t.li,{children:"Adjust our downtime jailing/equivocation slashing logic to work correctly with unbonded validators. This is very hard, because redelegations are not usually tracked for unbonded validators."}),"\n"]}),"\n",(0,a.jsx)(t.h2,{id:"references",children:"References"}),"\n",(0,a.jsxs)(t.ul,{children:["\n",(0,a.jsxs)(t.li,{children:[(0,a.jsx)(t.a,{href:"/interchain-security/adrs/adr-016-securityaggregation",children:"Security Aggregation"})," has similar concerns where the staking validator set will differ from the consensus validator set"]}),"\n"]})]})}function c(e={}){const{wrapper:t}={...(0,n.a)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},9022:(e,t,i)=>{i.d(t,{Z:()=>a});const a=i.p+"assets/images/inactivevals_after-ac23b4c6474ed6bb2105369cdf8482a0.png"},4823:(e,t,i)=>{i.d(t,{Z:()=>a});const a=i.p+"assets/images/inactivevals_before-a963b865d2029f6629845f7b1beb215b.png"},1151:(e,t,i)=>{i.d(t,{Z:()=>r,a:()=>o});var a=i(7294);const n={},s=a.createContext(n);function o(e){const t=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),a.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/e50733a4.f44db361.js b/assets/js/e50733a4.f44db361.js
new file mode 100644
index 0000000000..d275a4bb56
--- /dev/null
+++ b/assets/js/e50733a4.f44db361.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1937],{1370:(n,e,i)=>{i.r(e),i.d(e,{assets:()=>d,contentTitle:()=>t,default:()=>p,frontMatter:()=>s,metadata:()=>a,toc:()=>h});var r=i(5893),o=i(1151);const s={sidebar_position:4},t="Consumer Initiated Slashing",a={id:"features/slashing",title:"Consumer Initiated Slashing",description:"A consumer chain is essentially a regular Cosmos-SDK based chain that uses the Interchain Security module to achieve economic security by stake deposited on the provider chain, instead of its own chain.",source:"@site/versioned_docs/version-v4.2.0-docs/features/slashing.md",sourceDirName:"features",slug:"/features/slashing",permalink:"/interchain-security/v4.2.0/features/slashing",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:4,frontMatter:{sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"ICS Provider Proposals",permalink:"/interchain-security/v4.2.0/features/proposals"},next:{title:"Partial Set Security",permalink:"/interchain-security/v4.2.0/features/partial-set-security"}},d={},h=[{value:"Downtime Infractions",id:"downtime-infractions",level:2},{value:"Equivocation Infractions",id:"equivocation-infractions",level:2},{value:"Report equivocation infractions through CLI",id:"report-equivocation-infractions-through-cli",level:3},{value:"Report equivocation infractions with Hermes",id:"report-equivocation-infractions-with-hermes",level:3}];function c(n){const e={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,o.a)(),...n.components},{Details:i}=e;return i||function(n,e){throw new Error("Expected "+(e?"component":"object")+" `"+n+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(e.h1,{id:"consumer-initiated-slashing",children:"Consumer Initiated Slashing"}),"\n",(0,r.jsx)(e.p,{children:"A consumer chain is essentially a regular Cosmos-SDK based chain that uses the Interchain Security module to achieve economic security by stake deposited on the provider chain, instead of its own chain.\nIn essence, provider chain and consumer chains are different networks (different infrastructures) that are bound together by the provider's validator set. By being bound to the provider's validator set, a consumer chain inherits the economic security guarantees of the provider chain (in terms of total stake)."}),"\n",(0,r.jsx)(e.p,{children:"To maintain the proof of stake model, the consumer chain is able to send evidence of infractions (double signing and downtime) to the provider chain so the offending validators can be penalized.\nAny infraction committed on any of the consumer chains is reflected on the provider and all other consumer chains."}),"\n",(0,r.jsx)(e.p,{children:"In the current implementation there are two important changes brought by the Interchain Security module."}),"\n",(0,r.jsx)(e.h2,{id:"downtime-infractions",children:"Downtime Infractions"}),"\n",(0,r.jsx)(e.p,{children:"Downtime infractions are reported by consumer chains and are acted upon on the provider as soon as the provider receives the infraction evidence."}),"\n",(0,r.jsx)(e.p,{children:"Instead of slashing, the provider will only jail offending validator for the duration of time established by the chain parameters."}),"\n",(0,r.jsx)(e.admonition,{type:"info",children:(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.a,{href:"/interchain-security/v4.2.0/adrs/adr-002-throttle",children:"Slash throttling"})," (sometimes called jail throttling) mechanism ensures that only a fraction of the validator set can be jailed at any one time to prevent malicious consumer chains from harming the provider."]})}),"\n",(0,r.jsx)(e.p,{children:"Note that validators are only jailed for downtime on consumer chains that they opted-in to validate on,\nor in the case of Top N chains, where they are automatically opted in by being in the Top N% of the validator set on the provider."}),"\n",(0,r.jsx)(e.h2,{id:"equivocation-infractions",children:"Equivocation Infractions"}),"\n",(0,r.jsxs)(e.p,{children:["Equivocation infractions are reported by external agents (e.g., relayers) that can submit to the provider evidence of light client or double signing attacks observed on a consumer chain.\nThe evidence is submitted by sending ",(0,r.jsx)(e.code,{children:"MsgSubmitConsumerMisbehaviour"})," or ",(0,r.jsx)(e.code,{children:"MsgSubmitConsumerDoubleVoting"})," transactions to the provider.\nWhen valid evidence is received, the malicious validators are slashed, jailed, and tombstoned on the provider.\nThis is enabled through the ",(0,r.jsx)(e.em,{children:"cryptographic verification of equivocation"})," feature.\nFor more details, see ",(0,r.jsx)(e.a,{href:"/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR-005"})," and ",(0,r.jsx)(e.a,{href:"/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing",children:"ADR-013"}),"."]}),"\n",(0,r.jsx)(e.h3,{id:"report-equivocation-infractions-through-cli",children:"Report equivocation infractions through CLI"}),"\n",(0,r.jsx)(e.p,{children:"The ICS provider module offers two commands for submitting evidence of misbehavior originating from a consumer chain.\nBelow are two examples illustrating the process on Cosmos Hub."}),"\n",(0,r.jsx)(e.p,{children:"Use the following command to submit evidence of double signing attacks:"}),"\n",(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-bash",children:"gaiad tx provider submit-consumer-double-voting [path/to/evidence.json] [path/to/infraction_header.json] --from node0 --home ../node0 --chain-id $CID \n"})}),"\n",(0,r.jsxs)(i,{children:[(0,r.jsxs)("summary",{children:["Example of ",(0,r.jsx)(e.code,{children:"evidence.json"})]}),(0,r.jsx)("div",{children:(0,r.jsx)("div",{children:(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-json",children:'{\n "vote_a": {\n "type": 1,\n "height": 25,\n "round": 0,\n "block_id": {\n "hash": "tBBWTqjECl31S/clZGoxLdDqs93kTvy3qhpPqET/laY=",\n "part_set_header": {\n "total": 1,\n "hash": "ai2qCLgVZAFph4FJ4Cqw5QW1GZKR4zjOv0bI/Um5AIc="\n }\n },\n "timestamp": "2023-11-20T12:57:54.565207Z",\n "validator_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "signature": "y9yILm9hmv45BZwAaaq9mS1FpH7QeAIJ5Jkcc3U2/k5uks9cuqr4NTIwaIrqMSMKwxVyqiR56xmCT59a6AngAA=="\n },\n "vote_b": {\n "type": 1,\n "height": 25,\n "round": 0,\n "block_id": {\n "hash": "3P06pszgPatuIdLTP5fDWiase4SYHIq9YXGSbRk9/50=",\n "part_set_header": {\n "total": 1,\n "hash": "S+SbOMxFRzfeNNpX9/jyFMz94VwBKk7Dpx6ZyvSYyNU="\n }\n },\n "timestamp": "2023-11-20T12:57:54.599273Z",\n "validator_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "validator_index": 0,\n "signature": "DGFcn4Um1t2kXW60+JhMk5cj7ZFdE5goKVOGiZkLwnNv43+6aGmOWjoq0SHYVzM4MwSwOwbhgZNbkWX+EHGUBw=="\n },\n "total_voting_power": 300,\n "validator_power": 100,\n "timestamp": "2023-11-20T12:57:51.267308Z"\n}\n'})})})})]}),"\n",(0,r.jsxs)(i,{children:[(0,r.jsxs)("summary",{children:["Example of ",(0,r.jsx)(e.code,{children:"infraction_header.json"})]}),(0,r.jsx)("div",{children:(0,r.jsx)("div",{children:(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-json",children:'{\n "signed_header": {\n "header": {\n "version": {\n "block": 11,\n "app": 2\n },\n "chain_id": "consumer",\n "height": 22,\n "time": "2023-11-20T12:57:40.479686Z",\n "last_block_id": {\n "hash": "L63hyLJ+y9+fpb7WYKdmmBhPHwbfEGQEuKmvGzyBPiY=",\n "part_set_header": {\n "total": 18,\n "hash": "euzRQjN7MjGtM6skXM4B8wOgAldWGfZSJRA9JRlO42s="\n }\n },\n "last_commit_hash": "qdDJwVziW3pPqmf8QDGZG+5HVd3OF7fCVh2Z8KQqNVU=",\n "data_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",\n "validators_hash": "pVc+gSYkGesaP3OkK4ig3DBi4o9/GCdXGtO/PQ6i/Ik=",\n "next_validators_hash": "pVc+gSYkGesaP3OkK4ig3DBi4o9/GCdXGtO/PQ6i/Ik=",\n "consensus_hash": "BICRvH3cKD93v7+R1zxE2ljD34qcvIZ0Bdi389qtoi8=",\n "app_hash": "Yu3HX62w7orbbY/pm2QEK7yIwR+AlNdjSSqiK1kmuJM=",\n "last_results_hash": "Yu3HX62w7orbbY/pm2QEK7yIwR+AlNdjSSqiK1kmuJM=",\n "evidence_hash": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",\n "proposer_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA="\n },\n "commit": {\n "height": 22,\n "round": 1,\n "block_id": {\n "hash": "PKrS32IEZoFY2q2S3iQ68HQL751ieBhf5Eu/Y5Z/QPg=",\n "part_set_header": {\n "total": 1,\n "hash": "8UuA7Oqw5AH/KOacpmHVSMOIDe4l2eC8VmdH2mzcpiM="\n }\n },\n "signatures": [\n {\n "block_id_flag": 2,\n "validator_address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "timestamp": "2023-11-20T12:57:44.076538Z",\n "signature": "bSOH4+Vg2I37zeJphOguGOD0GK3JzM1ghSgJd0UlW/DHn1u9Hvv4EekHuCu6qwRLZcuS/ZxNlmr9qYNfxX3bDA=="\n },\n {\n "block_id_flag": 2,\n "validator_address": "i/A830FM7cfmA8yTn9n3xBg5XpU=",\n "timestamp": "2020-01-02T00:07:00Z",\n "signature": "7bXSDtlOwGK/gLEsFpTWOzm2TFoaARrWQUpbgWEwKtLlUs7iE06TOvJ3yPPfTfqqN/qYnvxxgjl0M0EhUWu5Bg=="\n },\n {\n "block_id_flag": 2,\n "validator_address": "lrQDkJ2fk7UAgNzRZfcwMKSYa2E=",\n "timestamp": "2023-11-20T12:57:44.076519Z",\n "signature": "Pb6G4bCg4wafmV89WNnzXxbSCknZUHnSQfSCE5QMFxPtSUIN4A7SK5m7yltqMJF5zkyenlFiEI4J3OZ4KCjCAw=="\n },\n {\n "block_id_flag": 2,\n "validator_address": "+R94nXSeM1Z49e/CXpyHT3M+h3k=",\n "timestamp": "2023-11-20T12:57:44.057451Z",\n "signature": "j3EasIHNYA6MxW/PiWyruzHsjVsBV9t11W6Qx800WMm/+P+CkfR+UZAp7MPTvKZEZFuh3GUsBtyfb/vA+jJWCw=="\n }\n ]\n }\n },\n "validator_set": {\n "validators": [\n {\n "address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "pub_key": {\n "ed25519": "dtn+SfD+4QLo0+t0hAoP6Q2sGjh0XEI3LWVG+doh3u0="\n },\n "voting_power": 100,\n "proposer_priority": -200\n },\n {\n "address": "lrQDkJ2fk7UAgNzRZfcwMKSYa2E=",\n "pub_key": {\n "ed25519": "UgN2JsjPy2WLh7dzJRBkUQtdgNoT4/uGj7kbIVqqHT8="\n },\n "voting_power": 100,\n "proposer_priority": 100\n },\n {\n "address": "+R94nXSeM1Z49e/CXpyHT3M+h3k=",\n "pub_key": {\n "ed25519": "5svW8261x+cZosp2xIhqzgt2tyuawrSDyHlpbgS3BC4="\n },\n "voting_power": 100,\n "proposer_priority": 100\n },\n {\n "address": "aCG1hw85Zz7Ylgpsy263IJVJEMA=",\n "pub_key": {\n "ed25519": "dtn+SfD+4QLo0+t0hAoP6Q2sGjh0XEI3LWVG+doh3u0="\n },\n "voting_power": 100,\n "proposer_priority": -200\n }\n ],\n "proposer": {\n "address": "VUz+QceJ8Nu7GbJuVItwsfVjybA=",\n "pub_key": {\n "ed25519": "0s8KDTgEcwmOBrHWvV7mtBlItJ3upgM1FJsciwREdy4="\n },\n "voting_power": 1,\n "proposer_priority": -3\n }\n },\n "trusted_height": {\n "revision_height": 18\n },\n "trusted_validators": {\n "validators": [\n {\n "address": "VUz+QceJ8Nu7GbJuVItwsfVjybA=",\n "pub_key": {\n "ed25519": "0s8KDTgEcwmOBrHWvV7mtBlItJ3upgM1FJsciwREdy4="\n },\n "voting_power": 1,\n "proposer_priority": -3\n },\n {\n "address": "i/A830FM7cfmA8yTn9n3xBg5XpU=",\n "pub_key": {\n "ed25519": "FCmIw7hSuiAoWk/2f4LuGQ+3zx5101xiqU8DoC5wGkg="\n },\n "voting_power": 1,\n "proposer_priority": 1\n },\n {\n "address": "2DrZF0roNnnvEy4NS2aY811ncKg=",\n "pub_key": {\n "ed25519": "MI9c6sphsWlx0RAHCYOjMRXMFkTUaEYwOiOKG/0tsMs="\n },\n "voting_power": 1,\n "proposer_priority": 1\n },\n {\n "address": "73aN0uOc5b/Zfq2Xcjl0kH2r+tw=",\n "pub_key": {\n "ed25519": "gWNcDup4mdnsuqET4QeFRzVb+FnSP4Vz3iNMj5wvWXk="\n },\n "voting_power": 1,\n "proposer_priority": 1\n }\n ],\n "proposer": {\n "address": "VUz+QceJ8Nu7GbJuVItwsfVjybA=",\n "pub_key": {\n "ed25519": "0s8KDTgEcwmOBrHWvV7mtBlItJ3upgM1FJsciwREdy4="\n },\n "voting_power": 1,\n "proposer_priority": -3\n }\n }\n}\n'})})})})]}),"\n",(0,r.jsx)(e.p,{children:"Use the following command to submit evidence of light client attacks:"}),"\n",(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-bash",children:"gaiad tx provider submit-consumer-misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0 --chain-id $CID\n"})}),"\n",(0,r.jsxs)(i,{children:[(0,r.jsxs)("summary",{children:["Example of ",(0,r.jsx)(e.code,{children:"misbehaviour.json"})]}),(0,r.jsx)("div",{children:(0,r.jsx)("div",{children:(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-json",children:'{\n "client_id": "07-tendermint-0",\n "header_1": {\n "signed_header": {\n "header": {\n "version": {\n "block": "11",\n "app": "2"\n },\n "chain_id": "testchain2",\n "height": "19",\n "time": "2020-01-02T00:08:10Z",\n "last_block_id": {\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "part_set_header": {\n "total": 10000,\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n }\n },\n "last_commit_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "data_hash": "bW4ouLmLUycELqUKV91G5syFHHLlKL3qpu/e7v5moLg=",\n "validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "next_validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "consensus_hash": "5eVmxB7Vfj/4zBDxhBeHiLj6pgKwfPH0JSF72BefHyQ=",\n "app_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "last_results_hash": "CS4FhjAkftYAmGOhLu4RfSbNnQi1rcqrN/KrNdtHWjc=",\n "evidence_hash": "c4ZdsI9J1YQokF04mrTKS5bkWjIGx6adQ6Xcc3LmBxQ=",\n "proposer_address": "CbKqPquy50bcrY7JRdW7zXybSuA="\n },\n "commit": {\n "height": "19",\n "round": 1,\n "block_id": {\n "hash": "W2xVqzPw03ZQ1kAMpcpht9WohwMzsGnyKKNjPYKDF6U=",\n "part_set_header": {\n "total": 3,\n "hash": "hwgKOc/jNqZj6lwNm97vSTq9wYt8Pj4MjmYTVMGDFDI="\n }\n },\n "signatures": [\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "PGTquCtnTNFFY5HfEFz9f9pA7PYqjtQfBwHq6cxF/Ux8OI6nVqyadD9a84Xm7fSm6mqdW+T6YVfqIKmIoRjJDQ=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "0e39yoBorwORAH/K9qJ7D1N1Yr7CutMiQJ+oiIK39eMhuoK3UWzQyMGRLzDOIDupf8yD99mvGVVAlNIODlV3Dg=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "lhc2tkwydag9D1iLQhdDCE8GgrHP94M1LbHFYMoL9tExaEq6RiFW/k71TQH5x96XQ9XYOznMIHKC2BDh4GlnAQ=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "timestamp": "2020-01-02T00:08:10Z",\n "signature": "8xeSBf0nSFs/X/rQ9CZLzwkJJhQBLA2jKdPGP3MlULxm992XxrOsIYq47u1daxvSsn6ql5OVYjzBNU0qbPpvCA=="\n }\n ]\n }\n },\n "validator_set": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n },\n "trusted_height": {\n "revision_number": "0",\n "revision_height": "18"\n },\n "trusted_validators": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n }\n },\n "header_2": {\n "signed_header": {\n "header": {\n "version": {\n "block": "11",\n "app": "2"\n },\n "chain_id": "testchain2",\n "height": "19",\n "time": "2020-01-02T00:08:20Z",\n "last_block_id": {\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",\n "part_set_header": {\n "total": 10000,\n "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="\n }\n },\n "last_commit_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "data_hash": "bW4ouLmLUycELqUKV91G5syFHHLlKL3qpu/e7v5moLg=",\n "validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "next_validators_hash": "ImwBH++bKKkm2NDCwOxRn04P5GWWypgzeLVZWoc10+I=",\n "consensus_hash": "5eVmxB7Vfj/4zBDxhBeHiLj6pgKwfPH0JSF72BefHyQ=",\n "app_hash": "dPJh3vUG5ls8NeP/SBSEkIgTOzrkFOROqhKnuk2zRgc=",\n "last_results_hash": "CS4FhjAkftYAmGOhLu4RfSbNnQi1rcqrN/KrNdtHWjc=",\n "evidence_hash": "c4ZdsI9J1YQokF04mrTKS5bkWjIGx6adQ6Xcc3LmBxQ=",\n "proposer_address": "CbKqPquy50bcrY7JRdW7zXybSuA="\n },\n "commit": {\n "height": "19",\n "round": 1,\n "block_id": {\n "hash": "IZM8NKS+8FHB7CBmgB8Nz7BRVVXiiyqMQDvHFUvgzxo=",\n "part_set_header": {\n "total": 3,\n "hash": "hwgKOc/jNqZj6lwNm97vSTq9wYt8Pj4MjmYTVMGDFDI="\n }\n },\n "signatures": [\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "pLIEZ4WSAtnMsgryujheHSq4+YG3RqTfMn2ZxgEymr0wyi+BNlQAKRtRfesm0vfYxvjzc/jhGqtUqHtSIaCwCQ=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "XG7iTe/spWyTUkT7XDzfLMpYqrdyqizE4/X4wl/W+1eaQp0WsCHYnvPU3x9NAnYfZzaKdonZiDWs7wacbZTcDg=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "TqegK7ORuICSy++wVdPHt8fL2WfPlYsMPv1XW79wUdcjnQkezOM50OSqYaP4ua5frIZsn+sWteDrlqFTdkl3BA=="\n },\n {\n "block_id_flag": "BLOCK_ID_FLAG_COMMIT",\n "validator_address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "timestamp": "2020-01-02T00:08:20Z",\n "signature": "dhvp3XlIaCxx5MFDs0TCkAPHSm0PS2EtJzYAx2c/7MWdLwUJFZrAUTeimQE2c9i9ro91cjZn/vI0/oFRXab6Aw=="\n }\n ]\n }\n },\n "validator_set": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n },\n "trusted_height": {\n "revision_number": "0",\n "revision_height": "18"\n },\n "trusted_validators": {\n "validators": [\n {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n {\n "address": "Ua+R3vfKH1LWhRg/k8PbA/uSLnc=",\n "pub_key": {\n "ed25519": "H+7myYFFaCBTAxPiYaTX4IZIRtaUu+rcJVp+doLxd8c="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "Uns+2wsfv6IYTpOnYfAnPplVzTE=",\n "pub_key": {\n "ed25519": "QMHyl6i2OjmMEh73VXS5QBdsQ1vQ2mU3XzKGAhnKqmc="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n },\n {\n "address": "sS7FyKFPDEG7StI+4o3+6fZy1pY=",\n "pub_key": {\n "ed25519": "uSNKjObXRHsNslEdqdublnVDa4Vc2aoCpr0j+Fuvv5U="\n },\n "voting_power": "1",\n "proposer_priority": "1"\n }\n ],\n "proposer": {\n "address": "CbKqPquy50bcrY7JRdW7zXybSuA=",\n "pub_key": {\n "ed25519": "sUkpD9xhOgWna0dv4bSwI7N7CkyH6q1bBDPYhjRolaY="\n },\n "voting_power": "1",\n "proposer_priority": "-3"\n },\n "total_voting_power": "0"\n }\n }\n}\n'})})})})]}),"\n",(0,r.jsx)(e.h3,{id:"report-equivocation-infractions-with-hermes",children:"Report equivocation infractions with Hermes"}),"\n",(0,r.jsxs)(e.p,{children:["Ensure you have a well-configured Hermes ",(0,r.jsx)(e.code,{children:"v1.7.3+"})," relayer effectively relaying packets between a consumer chain and a provider chain.\nThe following command demonstrates how to run a Hermes instance in ",(0,r.jsx)(e.em,{children:"evidence mode"})," to detect misbehaviors on a consumer chain and automatically submit the evidence to the provider chain."]}),"\n",(0,r.jsx)(e.pre,{children:(0,r.jsx)(e.code,{className:"language-bash",children:"hermes evidence --chain \n"})}),"\n",(0,r.jsx)(e.admonition,{type:"tip",children:(0,r.jsxs)(e.p,{children:[(0,r.jsx)(e.code,{children:"hermes evidence"})," takes a ",(0,r.jsx)(e.code,{children:"--check-past-blocks"})," option giving the possibility to look for older evidence (default is 100)."]})})]})}function p(n={}){const{wrapper:e}={...(0,o.a)(),...n.components};return e?(0,r.jsx)(e,{...n,children:(0,r.jsx)(c,{...n})}):c(n)}},1151:(n,e,i)=>{i.d(e,{Z:()=>a,a:()=>t});var r=i(7294);const o={},s=r.createContext(o);function t(n){const e=r.useContext(s);return r.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function a(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(o):n.components||o:t(n.components),r.createElement(s.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/e5b5a87b.c1818ef8.js b/assets/js/e5b5a87b.c1818ef8.js
new file mode 100644
index 0000000000..60cee29636
--- /dev/null
+++ b/assets/js/e5b5a87b.c1818ef8.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5313],{6407:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>d,frontMatter:()=>s,metadata:()=>r,toc:()=>l});var i=t(5893),a=t(1151);const s={sidebar_position:3,title:"Onboarding Checklist"},o="Consumer Onboarding Checklist",r={id:"consumer-development/onboarding",title:"Onboarding Checklist",description:"The following checklists will aid in onboarding a new consumer chain to interchain security.",source:"@site/versioned_docs/version-v4.2.0-docs/consumer-development/onboarding.md",sourceDirName:"consumer-development",slug:"/consumer-development/onboarding",permalink:"/interchain-security/v4.2.0/consumer-development/onboarding",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:3,frontMatter:{sidebar_position:3,title:"Onboarding Checklist"},sidebar:"tutorialSidebar",previous:{title:"Consumer Chain Governance",permalink:"/interchain-security/v4.2.0/consumer-development/consumer-chain-governance"},next:{title:"Offboarding Checklist",permalink:"/interchain-security/v4.2.0/consumer-development/offboarding"}},c={},l=[{value:"1. Complete testing & integration",id:"1-complete-testing--integration",level:2},{value:"2. Create an Onboarding Repository",id:"2-create-an-onboarding-repository",level:2},{value:"3. Submit a Governance Proposal",id:"3-submit-a-governance-proposal",level:2},{value:"4. Launch",id:"4-launch",level:2}];function h(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",input:"input",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"consumer-onboarding-checklist",children:"Consumer Onboarding Checklist"}),"\n",(0,i.jsx)(n.p,{children:"The following checklists will aid in onboarding a new consumer chain to interchain security."}),"\n",(0,i.jsxs)(n.p,{children:["Additionally, you can check the ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md",children:"testnet repo"})," for a comprehensive guide on preparing and launching consumer chains."]}),"\n",(0,i.jsx)(n.h2,{id:"1-complete-testing--integration",children:"1. Complete testing & integration"}),"\n",(0,i.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test integration with gaia"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","test your protocol with supported relayer versions (minimum hermes 1.4.1)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","reach out to the ICS team if you are facing issues"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"2-create-an-onboarding-repository",children:"2. Create an Onboarding Repository"}),"\n",(0,i.jsx)(n.p,{children:"To help validators and other node runners onboard onto your chain, please prepare a repository with information on how to run your chain."}),"\n",(0,i.jsx)(n.p,{children:"This should include (at minimum):"}),"\n",(0,i.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json without CCV data (before the proposal passes)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json with CCV data (after spawn time passes). Check if CCV data needs to be transformed (see ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/consumer-development/consumer-genesis-transformation",children:"Transform Consumer Genesis"}),")"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","information about relevant seed/peer nodes you are running"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","relayer information (compatible versions)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","copy of your governance proposal (as JSON)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","a script showing how to start your chain and connect to peers (optional)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take feedback from other developers, validators and community regarding your onboarding repo and make improvements where applicable"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Example of such a repository can be found ",(0,i.jsx)(n.a,{href:"https://github.com/hyphacoop/ics-testnets/tree/main/game-of-chains-2022/sputnik",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"3-submit-a-governance-proposal",children:"3. Submit a Governance Proposal"}),"\n",(0,i.jsxs)(n.p,{children:["Before you submit a ",(0,i.jsx)(n.code,{children:"ConsumerChainAddition"})," proposal, please consider allowing at least a day between your proposal passing and the chain spawn time. This will allow the validators, other node operators and the community to prepare for the chain launch.\nIf possible, please set your spawn time so people from different parts of the globe can be available in case of emergencies. Ideally, you should set your spawn time to be between 12:00 UTC and 20:00 UTC so most validator operators are available and ready to respond to any issues."]}),"\n",(0,i.jsxs)(n.p,{children:["Additionally, reach out to the community via the ",(0,i.jsx)(n.a,{href:"https://forum.cosmos.network/",children:"forum"})," to formalize your intention to become an ICS consumer, gather community support and accept feedback from the community, validators and developers."]}),"\n",(0,i.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine your chain's spawn time"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine consumer chain parameters to be put in the proposal"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","take note to include a link to your onboarding repository"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","describe the purpose and benefits of running your chain"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","determine whether your chain should be an Opt-In chain or a Top N chain (see ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/partial-set-security",children:"Partial Set Security"}),")"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","if desired, decide on power-shaping parameters (see ",(0,i.jsx)(n.a,{href:"/interchain-security/v4.2.0/features/power-shaping",children:"Power Shaping"}),")"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Example of a consumer chain addition proposal."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-js",children:'// ConsumerAdditionProposal is a governance proposal on the provider chain to spawn a new consumer chain.\n// If it passes, if the top_N parameter is not equal to 0, the top N% of validators by voting power on the provider chain are expected to validate the consumer chain at spawn time.\n// Otherwise, only validators that opted in during the proposal period are expected to validate the consumer chain at spawn time.\n// It is recommended that spawn time occurs after the proposal end time.\n{\n // Title of the proposal\n "title": "Add consumer chain",\n // Description of the proposal\n // format the text as a .md file and include the file in your onboarding repository\n "description": ".md description of your chain and all other relevant information",\n // Proposed chain-id of the new consumer chain.\n // Must be unique from all other consumer chain ids of the executing provider chain.\n "chain_id": "newchain-1",\n // Initial height of new consumer chain.\n // For a completely new chain, this will be {0,1}.\n "initial_height" : {\n "revision_height": 0,\n "revision_number": 1,\n },\n // Hash of the consumer chain genesis state without the consumer CCV module genesis params.\n // It is used for off-chain confirmation of genesis.json validity by validators and other parties.\n "genesis_hash": "d86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0",\n // Hash of the consumer chain binary that should be run by validators on chain initialization.\n // It is used for off-chain confirmation of binary validity by validators and other parties.\n "binary_hash": "376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1",\n // Time on the provider chain at which the consumer chain genesis is finalized and validators\n // will be responsible for starting their consumer chain validator node.\n "spawn_time": "2023-02-28T20:40:00.000000Z",\n // Unbonding period for the consumer chain.\n // It should be smaller than that of the provider.\n "unbonding_period": 86400000000000,\n // Timeout period for CCV related IBC packets.\n // Packets are considered timed-out after this interval elapses.\n "ccv_timeout_period": 259200000000000,\n // IBC transfer packets will timeout after this interval elapses.\n "transfer_timeout_period": 1800000000000,\n // The fraction of tokens allocated to the consumer redistribution address during distribution events.\n // The fraction is a string representing a decimal number. For example "0.75" would represent 75%.\n // The reward amount distributed to the provider is calculated as: 1 - consumer_redistribution_fraction.\n "consumer_redistribution_fraction": "0.75",\n // BlocksPerDistributionTransmission is the number of blocks between IBC token transfers from the consumer chain to the provider chain.\n // eg. send rewards to the provider every 1000 blocks\n "blocks_per_distribution_transmission": 1000,\n // The number of historical info entries to persist in store.\n // This param is a part of the cosmos sdk staking module. In the case of\n // a ccv enabled consumer chain, the ccv module acts as the staking module.\n "historical_entries": 10000,\n // The ID of a token transfer channel used for the Reward Distribution\n\t// sub-protocol. If DistributionTransmissionChannel == "", a new transfer\n\t// channel is created on top of the same connection as the CCV channel.\n\t// Note that transfer_channel_id is the ID of the channel end on the consumer chain.\n // it is most relevant for chains performing a standalone to consumer changeover\n // in order to maintain the existing ibc transfer channel\n "distribution_transmission_channel": "channel-123",\n // Corresponds to the percentage of validators that have to validate the chain under the Top N case.\n // For example, 53 corresponds to a Top 53% chain, meaning that the top 53% provider validators by voting power\n // have to validate the proposed consumer chain. top_N can either be 0 or any value in [50, 100].\n // A chain can join with top_N == 0 as an Opt In chain, or with top_N \u2208 [50, 100] as a Top N chain.\n "top_N": 95,\n // Corresponds to the maximum power (percentage-wise) a validator can have on the consumer chain. For instance, if\n // `validators_power_cap` is set to 32, it means that no validator can have more than 32% of the voting power on the\n // consumer chain. Note that this might not be feasible. For example, think of a consumer chain with only\n // 5 validators and with `validators_power_cap` set to 10%. In such a scenario, at least one validator would need\n // to have more than 20% of the total voting power. Therefore, `validators_power_cap` operates on a best-effort basis.\n "validators_power_cap": 0,\n // Corresponds to the maximum number of validators that can validate a consumer chain.\n // Only applicable to Opt In chains. Setting `validator_set_cap` on a Top N chain is a no-op.\n "validator_set_cap": 0,\n // Corresponds to a list of provider consensus addresses of validators that are the ONLY ones that can validate\n // the consumer chain.\n "allowlist": [],\n // Corresponds to a list of provider consensus addresses of validators that CANNOT validate the consumer chain.\n "denylist": []\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"4-launch",children:"4. Launch"}),"\n",(0,i.jsxs)(n.p,{children:["The consumer chain starts after at least 66.67% of its voting power comes online.\nNote that this means 66.67% of the voting power in the ",(0,i.jsx)(n.em,{children:"consumer"})," validator set, which will be comprised of all validators that either opted in to the chain or are part of the top N% of the provider chain (and are thus automatically opted in).\nThe consumer chain is considered interchain secured once the appropriate CCV channels are established and the first validator set update is propagated from the provider to the consumer"]}),"\n",(0,i.jsxs)(n.ul,{className:"contains-task-list",children:["\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","provide a repo with onboarding instructions for validators (it should already be listed in the proposal)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","genesis.json with ccv data populated (MUST contain the initial validator set)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","maintenance & emergency contact info (relevant discord, telegram, slack or other communication channels)"]}),"\n",(0,i.jsxs)(n.li,{className:"task-list-item",children:[(0,i.jsx)(n.input,{type:"checkbox",disabled:!0})," ","have a block explorer in place to track chain activity & health"]}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>r,a:()=>o});var i=t(7294);const a={},s=i.createContext(a);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/e69e9c61.942ce78c.js b/assets/js/e69e9c61.942ce78c.js
new file mode 100644
index 0000000000..a67a8a79dd
--- /dev/null
+++ b/assets/js/e69e9c61.942ce78c.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6882],{2489:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>s,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var i=r(5893),t=r(1151);const a={sidebar_position:17,title:"Security aggregation"},s="ADR 016: Security aggregation",o={id:"adrs/adr-016-securityaggregation",title:"Security aggregation",description:"Changelog",source:"@site/docs/adrs/adr-016-securityaggregation.md",sourceDirName:"adrs",slug:"/adrs/adr-016-securityaggregation",permalink:"/interchain-security/adrs/adr-016-securityaggregation",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:17,frontMatter:{sidebar_position:17,title:"Security aggregation"},sidebar:"tutorialSidebar",previous:{title:"Partial Set Security",permalink:"/interchain-security/adrs/adr-015-partial-set-security"},next:{title:"ICS with Inactive Provider Validators",permalink:"/interchain-security/adrs/adr-017-allowing-inactive-validators"}},d={},l=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Alternative Approaches",id:"alternative-approaches",level:2},{value:"Rewards",id:"rewards",level:3},{value:"Decision",id:"decision",level:2},{value:"Rewards will be sent back to external chains instead of paying rewards for external stakers on Cosmos chain",id:"rewards-will-be-sent-back-to-external-chains-instead-of-paying-rewards-for-external-stakers-on-cosmos-chain",level:3},{value:"Detailed Design",id:"detailed-design",level:2},{value:"Power Mixing",id:"power-mixing",level:3},{value:"Integration with ICS provider",id:"integration-with-ics-provider",level:4},{value:"Integration with ICS consumer",id:"integration-with-ics-consumer",level:4},{value:"Queries",id:"queries",level:3},{value:"Reward Handler",id:"reward-handler",level:3},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"Questions:",id:"questions",level:2},{value:"References",id:"references",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-016-security-aggregation",children:"ADR 016: Security aggregation"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2024-04-24: Initial draft of ADR"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Proposed"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsx)(n.p,{children:"Security Aggregation enables staking of tokens from external sources such as Ethereum or Bitcoin to Cosmos blockchains. By integrating Security Aggregation, a Cosmos blockchain can be secured by both native tokens and external tokens (e.g. ETH, BTC)."}),"\n",(0,i.jsx)(n.p,{children:"Security Aggregation consists of the following parts:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"A mechanism for delegating external tokens to Cosmos validators, such as Babylon or EigenLayer AVS contract."}),"\n",(0,i.jsx)(n.li,{children:"An oracle that tracks how much external stake has been delegated to each Cosmos validator and provides price feeds for external tokens."}),"\n",(0,i.jsx)(n.li,{children:"Power mixing: a mechanism to combine external and native stake to derive the power of each validator."}),"\n",(0,i.jsx)(n.li,{children:"A reward distribution protocol that enables sending back rewards to the external source."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"External staking information is received from an oracle together with price information of related stakes.\nThe CosmosLayer derives validator powers based on external and native staking information and initiates rewarding of external depositors."}),"\n",(0,i.jsxs)(n.p,{children:["This ADR describes the ",(0,i.jsx)(n.em,{children:"Cosmos modules"})," of the solution."]}),"\n",(0,i.jsx)(n.h2,{id:"alternative-approaches",children:"Alternative Approaches"}),"\n",(0,i.jsx)(n.h3,{id:"rewards",children:"Rewards"}),"\n",(0,i.jsx)(n.p,{children:"As an alternative to sending rewards back to the external chains, stakers could be rewarded on the Cosmos chain.\nThis would require a mapping of external addresses to addresses on Cosmos chain for each staker on external source.\nIn addition detailed external staking information such as staking addresses, amount of stakes per staker and validator, etc. have to be provided by the oracle."}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.h3,{id:"rewards-will-be-sent-back-to-external-chains-instead-of-paying-rewards-for-external-stakers-on-cosmos-chain",children:"Rewards will be sent back to external chains instead of paying rewards for external stakers on Cosmos chain"}),"\n",(0,i.jsx)(n.p,{children:"Rewards will be sent back to external chains instead of paying rewards for external stakers on Cosmos chain"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"due to amount of additional staking information to be sent and tracked by the oracle"}),"\n",(0,i.jsx)(n.li,{children:"due to the additional complexity of managing external and Cosmos addresses"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"detailed-design",children:"Detailed Design"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"Power Mixing"})," feature and ",(0,i.jsx)(n.code,{children:"Reward Distribution"})," protocol are an integral part of the Security Aggregation solution.\nThe ",(0,i.jsx)(n.code,{children:"Power Mixing"})," module provides the capability of deriving validator power based on stake originated from external sources such as Ethereum/Bitcoin and the native staking module.\nThe ",(0,i.jsx)(n.code,{children:"Reward Distribution"})," manages the process of sending rewards to external stakers."]}),"\n",(0,i.jsx)(n.h3,{id:"power-mixing",children:"Power Mixing"}),"\n",(0,i.jsxs)(n.p,{children:["Power Mixing provides the final validator powers based on staking information of the native chain and the external stakes. The information about external staking and related price feeds are received from an oracle.\nOnce the final validator powers are determined the result is submitted to the underlying CometBFT consensus layer by ",(0,i.jsx)(n.a,{href:"https://docs.cometbft.com/v0.38/spec/abci/abci++_app_requirements#updating-the-validator-set",children:"updating"})," the validator set."]}),"\n",(0,i.jsx)(n.p,{children:"Requirements:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"validator updates are performed on each EndBlock"}),"\n",(0,i.jsx)(n.li,{children:"a validator's power is determined based on its native on-chain stakes and external stakes"}),"\n",(0,i.jsx)(n.li,{children:"price information of staked tokens is used to determine a validator\u2019s power, e.g. price ratio (price of native on-chain token / price of external stake)"}),"\n",(0,i.jsx)(n.li,{children:"price information of native/external tokens are received from an oracle"}),"\n",(0,i.jsx)(n.li,{children:"staking information from external sources received from the oracle"}),"\n",(0,i.jsxs)(n.li,{children:["native staking information are received from the ",(0,i.jsx)(n.code,{children:"Cosmos SDK Staking Module"})]}),"\n",(0,i.jsx)(n.li,{children:"set of validator stakes from oracle always have the current price, full set of validators, and current stakes"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"Power Mixing"})," implementation"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["queries current validators and their powers from ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/cosmos-sdk/blob/a6f3fbfbeb7ea94bda6369a7163a523e118a123c/x/staking/types/staking.pb.go#L415",children:"x/staking"}),"\nand from oracle (see below)."]}),"\n",(0,i.jsx)(n.li,{children:"calculates power updates by mixing power values of external and internal sources\nFollowing pseudocode snippet shows a possible implementation of how power mixing\nfeature works."}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-golang",children:"// PowerSource is an abstract entity providing validator powers which\n// are used by the mixer. This can be an oracle, staking module or an\n// IBC connected bridge.\ntype PowerSource interface {\n GetValidatorUpdates() []abci.ValidatorUpdate\n}\n\n// MixPowers calculates power updates by mixing validator powers from different sources\nfunc (k *Keeper) MixPowers(source ...PowerSource) []abci.ValidatorUpdate {\n var valUpdate []abci.ValidatorUpdate\n for _, ps := range source {\n // mix powers from two sets of validator updates an return set of validator updates\n // with aggregated powers\n valUpdate = mixPower(valUpdate, ps.GetValidatorUpdates())\n }\n return valUpdate\n}\n\nfunc (k *keeper) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {\n // GetPowerSources (including local staking module)\n registeredPowerSource := GetPowerSources()\n return k.MixPowers(registeredPowerSource...)\n}\n"})}),"\n",(0,i.jsxs)(n.h4,{id:"integration-with-ics-provider",children:["Integration with ",(0,i.jsx)(n.code,{children:"ICS provider"})]}),"\n",(0,i.jsxs)(n.p,{children:["The provider module updates the validator set on CometBFT instead of the SDK staking module (x/staking). The provider implementation will intervene in this behavior and ensure that the validator updates are taken from the ",(0,i.jsx)(n.code,{children:"Power Mixing"})," feature."]}),"\n",(0,i.jsxs)(n.p,{children:["External power sources are managed by the provider module. Only registered power sources can provide input to the ",(0,i.jsx)(n.code,{children:"Power Mixing"})," feature.\nPower sources will be assigned a unique identifier which will be used by the oracle, provider module and the power mixing and rewarding feature."]}),"\n",(0,i.jsxs)(n.p,{children:["Updates with the next validator set are sent to consumer chains on each epoch (see ",(0,i.jsx)(n.code,{children:"EndBlockVSU()"}),").\nWhen collecting the validator updates for each consumer chain (see ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper#Keeper.QueueVSCPackets",children:(0,i.jsx)(n.code,{children:"QueueVSCPackets()"})}),"), the validator powers of the bonded validators will be updated with the validator powers from the external sources using the ",(0,i.jsx)(n.code,{children:"Power Mixing"})," module.\nThese updates are sent as part of the VSC packets to all registered consumer chains."]}),"\n",(0,i.jsxs)(n.h4,{id:"integration-with-ics-consumer",children:["Integration with ",(0,i.jsx)(n.code,{children:"ICS consumer"})]}),"\n",(0,i.jsx)(n.p,{children:"Consumer chains receive validator updates as part of VSC packets from the provider.\nThese packets contain validator powers which were already mixed with external staked powers."}),"\n",(0,i.jsx)(n.h3,{id:"queries",children:"Queries"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-protobuf",children:"// GetValidatorUpdates returns the power mixed validator results from the provided sources\nservice Query {\n rpc GetValidatorUpdates(PowerMixedValUpdateRequest) PowerMixedValUpdateResponse {};\n}\n\n// PowerMixedValUpdateRequest contains the list of power sources on which the\n// power mixing should be based on\nmessage PowerMixedValUpdateRequest {\n repeated PowerSource sources;\n}\n\n// PowerMixedValUpdateResponse returns the validator set with the updated powers\n// from the power mixing feature\nmessage PowerMixedValUpdateResponse {\n repeated abci.ValidatorUpdate val_set\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"The following queries will be provided by the oracle"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-protobuf",children:'service Query {\n rpc GetExtValidators(GetExtValidatorRequest) returns (ExtValidatorsResponse) {\n option (google.api.http).get = "oracle/v1/get_validators";\n };\n}\n\nmessage GetExtValidatorRequest {}\n\n// ExtValidatorsResponse is the response from GetExtValidators queries\nmessage ExtValidatorsResponse {\n repeated ExtValPower powers;\n}\n\n// ExtValPower represents a validator with its staking and token information,\n// where:\n// `power_source_identifier` is the identifier of the registered power source\n// `validator_address` is the address of the validator\n// `stakes` is the total amount of stakes for a validator\n// `denom` is the source token of the stake e.g. ETH,BTC\n// `price_ratio` is the ratio of price of the external token to the price of the \'local\' token\nmessage ExtValPower {\n string power_source_identifier;\n string validator_address;\n uint64 stakes;\n string denom;\n float price_ratio;\n}\n\n// GetPrice returns a price feed for a given token\nservice Query {\n rpc GetPrice(GetPriceRequest) returns (GetPriceResponse) {\n option (google.api.http).get = "/oracle/v1/get_price";\n };\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"For security reasons the amount of external stakes needs to be limited. Limitation of external staking could be driven by governance and is not subject of this version of the ADR."}),"\n",(0,i.jsx)(n.h3,{id:"reward-handler",children:"Reward Handler"}),"\n",(0,i.jsxs)(n.p,{children:["For native staked tokens the ",(0,i.jsx)(n.code,{children:"Distribution Module"})," of the Cosmos SDK is taking care of sending the rewards to stakers.\nFor stakes originated from external chains (Ethereum/Bitcoin) the ",(0,i.jsx)(n.code,{children:"Reward Handler"})," module sends rewards to EigenLayer/Babylon.\nThe transfer of rewards is done using a bridge between the Cosmos chain and the external provider chain."]}),"\n",(0,i.jsxs)(n.p,{children:["Note: currently there's no support paying rewards on EigenLayer (see ",(0,i.jsx)(n.a,{href:"https://www.coindesk.com/tech/2024/04/10/eigenlayer-cryptos-biggest-project-launch-this-year-is-still-missing-crucial-functionality/",children:"here"}),")"]}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Allow external depositors to stake their tokens to secure a Cosmos chain"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Dependency to external sources e.g (price feeds) for validator power calculation"}),"\n",(0,i.jsx)(n.li,{children:"Security impact"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Additional complexity for staking"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"questions",children:"Questions:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Slashing: subject of this ADR? (Defined but ",(0,i.jsx)(n.a,{href:"https://www.coindesk.com/tech/2024/04/10/eigenlayer-cryptos-biggest-project-launch-this-year-is-still-missing-crucial-functionality/",children:"not activated"})," currently on EigenLayer)."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.eigenlayer.xyz/",children:"EigenLayer"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://babylonchain.io/",children:"Babylon"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>o,a:()=>s});var i=r(7294);const t={},a=i.createContext(t);function s(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/ea42cb80.f06fff1b.js b/assets/js/ea42cb80.f06fff1b.js
new file mode 100644
index 0000000000..89e0042dff
--- /dev/null
+++ b/assets/js/ea42cb80.f06fff1b.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4117],{5956:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var r=i(5893),t=i(1151);const s={sidebar_position:1,title:"ADRs"},c="Architecture Decision Records (ADR)",a={id:"adrs/intro",title:"ADRs",description:"This is a location to record all high-level architecture decisions in the Interchain Security project.",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/intro.md",sourceDirName:"adrs",slug:"/adrs/intro",permalink:"/interchain-security/v4.2.0/adrs/intro",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:1,frontMatter:{sidebar_position:1,title:"ADRs"},sidebar:"tutorialSidebar",previous:{title:"Frequently Asked Questions",permalink:"/interchain-security/v4.2.0/faq"},next:{title:"ADR Template",permalink:"/interchain-security/v4.2.0/adrs/adr-004-denom-dos-fixes"}},o={},d=[{value:"Table of Contents",id:"table-of-contents",level:2},{value:"Accepted",id:"accepted",level:3},{value:"Proposed",id:"proposed",level:3},{value:"Rejected",id:"rejected",level:3},{value:"Deprecated",id:"deprecated",level:3}];function h(e){const n={a:"a",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,t.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"architecture-decision-records-adr",children:"Architecture Decision Records (ADR)"}),"\n",(0,r.jsx)(n.p,{children:"This is a location to record all high-level architecture decisions in the Interchain Security project."}),"\n",(0,r.jsxs)(n.p,{children:["You can read more about the ADR concept in this ",(0,r.jsx)(n.a,{href:"https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0#.78xhdix6t",children:"blog post"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"An ADR should provide:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Context on the relevant goals and the current state"}),"\n",(0,r.jsx)(n.li,{children:"Proposed changes to achieve the goals"}),"\n",(0,r.jsx)(n.li,{children:"Summary of pros and cons"}),"\n",(0,r.jsx)(n.li,{children:"References"}),"\n",(0,r.jsx)(n.li,{children:"Changelog"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Note the distinction between an ADR and a spec. The ADR provides the context, intuition, reasoning, and\njustification for a change in architecture, or for the architecture of something\nnew. The spec is much more compressed and streamlined summary of everything as\nit is or should be."}),"\n",(0,r.jsx)(n.p,{children:"If recorded decisions turned out to be lacking, convene a discussion, record the new decisions here, and then modify the code to match."}),"\n",(0,r.jsx)(n.p,{children:"Note the context/background should be written in the present tense."}),"\n",(0,r.jsxs)(n.p,{children:["To suggest an ADR, please make use of the ",(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-template",children:"ADR template"})," provided."]}),"\n",(0,r.jsx)(n.h2,{id:"table-of-contents",children:"Table of Contents"}),"\n",(0,r.jsx)(n.h3,{id:"accepted",children:"Accepted"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-001-key-assignment",children:"ADR 001: Key Assignment"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-002-throttle",children:"ADR 002: Jail Throttling"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-004-denom-dos-fixes",children:"ADR 004: Denom DOS fixes"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification",children:"ADR 005: Cryptographic verification of equivocation evidence"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-008-throttle-retries",children:"ADR 008: Throttle with retries"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-009-soft-opt-out",children:"ADR 009: Soft Opt-Out"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-010-standalone-changeover",children:"ADR 010: Standalone to Consumer Changeover"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing",children:"ADR 013: Slashing on the provider for consumer equivocation"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"proposed",children:"Proposed"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-011-improving-test-confidence",children:"ADR 011: Improving testing and increasing confidence"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-014-epochs",children:"ADR 014: Epochs"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-015-partial-set-security",children:"ADR 015: Partial Set Security"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"rejected",children:"Rejected"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-007-pause-unbonding-on-eqv-prop",children:"ADR 007: Pause validator unbonding during equivocation proposal"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-012-separate-releasing",children:"ADR 012: Separate Releasing"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"deprecated",children:"Deprecated"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/interchain-security/v4.2.0/adrs/adr-003-equivocation-gov-proposal",children:"ADR 003: Equivocation governance proposal"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>a,a:()=>c});var r=i(7294);const t={},s=r.createContext(t);function c(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:c(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/ed5b9256.caab0441.js b/assets/js/ed5b9256.caab0441.js
new file mode 100644
index 0000000000..5bdcdbe1c9
--- /dev/null
+++ b/assets/js/ed5b9256.caab0441.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8081],{8297:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>r,toc:()=>h});var i=o(5893),t=o(1151);const a={sidebar_position:1},s="Developing an ICS consumer chain",r={id:"consumer-development/app-integration",title:"Developing an ICS consumer chain",description:"When developing an ICS consumer chain, besides just focusing on your chain's logic you should aim to allocate time to ensure that your chain is compatible with the ICS protocol.",source:"@site/versioned_docs/version-v5.0.0/consumer-development/app-integration.md",sourceDirName:"consumer-development",slug:"/consumer-development/app-integration",permalink:"/interchain-security/v5.0.0/consumer-development/app-integration",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Consumer Initiated Slashing",permalink:"/interchain-security/v5.0.0/features/slashing"},next:{title:"Consumer Chain Governance",permalink:"/interchain-security/v5.0.0/consumer-development/consumer-chain-governance"}},c={},h=[{value:"Basic consumer chain",id:"basic-consumer-chain",level:2},{value:"Democracy consumer chain",id:"democracy-consumer-chain",level:2},{value:"Standalone chain to consumer chain changeover",id:"standalone-chain-to-consumer-chain-changeover",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"developing-an-ics-consumer-chain",children:"Developing an ICS consumer chain"}),"\n",(0,i.jsx)(n.p,{children:"When developing an ICS consumer chain, besides just focusing on your chain's logic you should aim to allocate time to ensure that your chain is compatible with the ICS protocol.\nTo help you on your journey, the ICS team has provided multiple examples of a minimum viable consumer chain applications."}),"\n",(0,i.jsx)(n.h2,{id:"basic-consumer-chain",children:"Basic consumer chain"}),"\n",(0,i.jsxs)(n.p,{children:["The source code for the example app can be found ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/main/app/consumer",children:"here"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Please note that consumer chains do not implement the staking module - the validator set is replicated from the provider, meaning that the provider and the consumer use the same validator set and their stake on the provider directly determines their stake on the consumer.\nAt present there is no opt-in mechanism available, so all validators of the provider must also validate on the provider chain."}),"\n",(0,i.jsxs)(n.p,{children:["Your chain should import the consumer module from ",(0,i.jsx)(n.code,{children:"x/consumer"})," and register it in the correct places in your ",(0,i.jsx)(n.code,{children:"app.go"}),".\nThe ",(0,i.jsx)(n.code,{children:"x/consumer"})," module will allow your chain to communicate with the provider using the ICS protocol. The module handles all IBC communication with the provider, and it is a simple drop-in.\nYou should not need to manage or override any code from the ",(0,i.jsx)(n.code,{children:"x/consumer"})," module."]}),"\n",(0,i.jsx)(n.h2,{id:"democracy-consumer-chain",children:"Democracy consumer chain"}),"\n",(0,i.jsxs)(n.p,{children:["The source code for the example app can be found ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/main/app/consumer-democracy",children:"here"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This type of consumer chain wraps the basic CosmosSDK ",(0,i.jsx)(n.code,{children:"x/distribution"}),", ",(0,i.jsx)(n.code,{children:"x/staking"})," and ",(0,i.jsx)(n.code,{children:"x/governance"})," modules allowing the consumer chain to perform democratic actions such as participating and voting within the chain's governance system."]}),"\n",(0,i.jsxs)(n.p,{children:["This allows the consumer chain to leverage those modules while also using the ",(0,i.jsx)(n.code,{children:"x/consumer"})," module."]}),"\n",(0,i.jsx)(n.p,{children:'With these modules enabled, the consumer chain can mint its own governance tokens, which can then be delegated to prominent community members which are referred to as "representatives" (as opposed to "validators" in standalone chains). The token may have different use cases besides just voting on governance proposals.'}),"\n",(0,i.jsx)(n.h2,{id:"standalone-chain-to-consumer-chain-changeover",children:"Standalone chain to consumer chain changeover"}),"\n",(0,i.jsx)(n.p,{children:"This feature is being actively worked on. Information will be provided at a later time."})]})}function d(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},1151:(e,n,o)=>{o.d(n,{Z:()=>r,a:()=>s});var i=o(7294);const t={},a=i.createContext(t);function s(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/f0745980.e1109473.js b/assets/js/f0745980.e1109473.js
new file mode 100644
index 0000000000..c876d329a3
--- /dev/null
+++ b/assets/js/f0745980.e1109473.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7143],{7134:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>t,default:()=>h,frontMatter:()=>o,metadata:()=>d,toc:()=>a});var r=n(5893),s=n(1151);const o={sidebar_position:3},t="Interchain Security Parameters",d={id:"introduction/params",title:"Interchain Security Parameters",description:"The parameters necessary for Interchain Security (ICS) are defined in",source:"@site/versioned_docs/version-v5.0.0/introduction/params.md",sourceDirName:"introduction",slug:"/introduction/params",permalink:"/interchain-security/v5.0.0/introduction/params",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"tutorialSidebar",previous:{title:"Terminology",permalink:"/interchain-security/v5.0.0/introduction/terminology"},next:{title:"Technical Specification",permalink:"/interchain-security/v5.0.0/introduction/technical-specification"}},c={},a=[{value:"Time-Based Parameters",id:"time-based-parameters",level:2},{value:"ProviderUnbondingPeriod",id:"providerunbondingperiod",level:3},{value:"ConsumerUnbondingPeriod",id:"consumerunbondingperiod",level:3},{value:"TrustingPeriodFraction",id:"trustingperiodfraction",level:3},{value:"CCVTimeoutPeriod",id:"ccvtimeoutperiod",level:3},{value:"InitTimeoutPeriod",id:"inittimeoutperiod",level:3},{value:"VscTimeoutPeriod",id:"vsctimeoutperiod",level:3},{value:"BlocksPerDistributionTransmission",id:"blocksperdistributiontransmission",level:3},{value:"TransferPeriodTimeout",id:"transferperiodtimeout",level:3},{value:"Reward Distribution Parameters",id:"reward-distribution-parameters",level:2},{value:"ConsumerRedistributionFraction",id:"consumerredistributionfraction",level:3},{value:"BlocksPerDistributionTransmission",id:"blocksperdistributiontransmission-1",level:3},{value:"TransferTimeoutPeriod",id:"transfertimeoutperiod",level:3},{value:"DistributionTransmissionChannel",id:"distributiontransmissionchannel",level:3},{value:"ProviderFeePoolAddrStr",id:"providerfeepooladdrstr",level:3},{value:"Slash Throttle Parameters",id:"slash-throttle-parameters",level:2},{value:"SlashMeterReplenishPeriod",id:"slashmeterreplenishperiod",level:3},{value:"SlashMeterReplenishFraction",id:"slashmeterreplenishfraction",level:3},{value:"MaxThrottledPackets",id:"maxthrottledpackets",level:3},{value:"RetryDelayPeriod",id:"retrydelayperiod",level:3},{value:"Epoch Parameters",id:"epoch-parameters",level:2},{value:"BlocksPerEpoch",id:"blocksperepoch",level:3}];function l(e){const i={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.h1,{id:"interchain-security-parameters",children:"Interchain Security Parameters"}),"\n",(0,r.jsx)(i.p,{children:"The parameters necessary for Interchain Security (ICS) are defined in"}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:["the ",(0,r.jsx)(i.code,{children:"Params"})," structure in ",(0,r.jsx)(i.code,{children:"proto/interchain_security/ccv/provider/v1/provider.proto"})," for the provider;"]}),"\n",(0,r.jsxs)(i.li,{children:["the ",(0,r.jsx)(i.code,{children:"Params"})," structure in ",(0,r.jsx)(i.code,{children:"proto/interchain_security/ccv/consumer/v1/consumer.proto"})," for the consumer."]}),"\n"]}),"\n",(0,r.jsx)(i.h2,{id:"time-based-parameters",children:"Time-Based Parameters"}),"\n",(0,r.jsx)(i.p,{children:"ICS relies on the following time-based parameters."}),"\n",(0,r.jsx)(i.h3,{id:"providerunbondingperiod",children:"ProviderUnbondingPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ProviderUnbondingPeriod"})," is the unbonding period on the provider chain as configured during chain genesis. This parameter can later be changed via governance."]}),"\n",(0,r.jsx)(i.h3,{id:"consumerunbondingperiod",children:"ConsumerUnbondingPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"})," is the unbonding period on the consumer chain."]}),"\n",(0,r.jsxs)(i.admonition,{type:"info",children:[(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"})," is set via the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})," governance proposal to add a new consumer chain.\nIt is recommended that every consumer chain set and unbonding period shorter than ",(0,r.jsx)(i.code,{children:"ProviderUnbondingPeriod"})]}),(0,r.jsx)("br",{}),(0,r.jsx)(i.p,{children:"Example:"}),(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod = ProviderUnbondingPeriod - one day\n"})})]}),"\n",(0,r.jsx)(i.p,{children:"Unbonding operations (such as undelegations) are completed on the provider only after the unbonding period elapses on every consumer."}),"\n",(0,r.jsx)(i.h3,{id:"trustingperiodfraction",children:"TrustingPeriodFraction"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TrustingPeriodFraction"})," is used to calculate the ",(0,r.jsx)(i.code,{children:"TrustingPeriod"})," of created IBC clients on both provider and consumer chains."]}),"\n",(0,r.jsxs)(i.p,{children:["Setting ",(0,r.jsx)(i.code,{children:"TrustingPeriodFraction"})," to ",(0,r.jsx)(i.code,{children:"0.5"})," would result in the following:"]}),"\n",(0,r.jsx)(i.pre,{children:(0,r.jsx)(i.code,{children:"TrustingPeriodFraction = 0.5\nProviderClientOnConsumerTrustingPeriod = ProviderUnbondingPeriod * 0.5\nConsumerClientOnProviderTrustingPeriod = ConsumerUnbondingPeriod * 0.5\n"})}),"\n",(0,r.jsxs)(i.p,{children:["Note that a light clients must be updated within the ",(0,r.jsx)(i.code,{children:"TrustingPeriod"})," in order to avoid being frozen."]}),"\n",(0,r.jsxs)(i.p,{children:["For more details, see the ",(0,r.jsx)(i.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/client/ics-007-tendermint-client/README.md",children:"IBC specification of Tendermint clients"}),"."]}),"\n",(0,r.jsx)(i.h3,{id:"ccvtimeoutperiod",children:"CCVTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"CCVTimeoutPeriod"})," is the period used to compute the timeout timestamp when sending IBC packets."]}),"\n",(0,r.jsxs)(i.p,{children:["For more details, see the ",(0,r.jsx)(i.a,{href:"https://github.com/cosmos/ibc/blob/main/spec/core/ics-004-channel-and-packet-semantics/README.md#sending-packets",children:"IBC specification of Channel & Packet Semantics"}),"."]}),"\n",(0,r.jsx)(i.admonition,{type:"warning",children:(0,r.jsx)(i.p,{children:"If a sent packet is not relayed within this period, then the packet times out. The CCV channel used by the interchain security protocol is closed, and the corresponding consumer is removed."})}),"\n",(0,r.jsx)(i.p,{children:"CCVTimeoutPeriod may have different values on the provider and consumer chains."}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"CCVTimeoutPeriod"})," on the provider ",(0,r.jsx)(i.strong,{children:"must"})," be larger than ",(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"})]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"CCVTimeoutPeriod"})," on the consumer is initial set via the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})]}),"\n"]}),"\n",(0,r.jsx)(i.h3,{id:"inittimeoutperiod",children:"InitTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"InitTimeoutPeriod"})," is the maximum allowed duration for CCV channel initialization to execute."]}),"\n",(0,r.jsxs)(i.p,{children:["For any consumer chain, if the CCV channel is not established within ",(0,r.jsx)(i.code,{children:"InitTimeoutPeriod"})," then the consumer chain will be removed and therefore will not be secured by the provider chain."]}),"\n",(0,r.jsxs)(i.p,{children:["The countdown starts when the ",(0,r.jsx)(i.code,{children:"spawn_time"})," specified in the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})," is reached."]}),"\n",(0,r.jsx)(i.h3,{id:"vsctimeoutperiod",children:"VscTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"VscTimeoutPeriod"})," is the provider-side param that enables the provider to timeout VSC packets even when a consumer chain is not live.\nIf the ",(0,r.jsx)(i.code,{children:"VscTimeoutPeriod"})," is ever reached for a consumer chain that chain will be considered not live and removed from interchain security."]}),"\n",(0,r.jsx)(i.admonition,{type:"tip",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"VscTimeoutPeriod"})," MUST be larger than the ",(0,r.jsx)(i.code,{children:"ConsumerUnbondingPeriod"}),"."]})}),"\n",(0,r.jsx)(i.h3,{id:"blocksperdistributiontransmission",children:"BlocksPerDistributionTransmission"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," is the number of blocks between rewards transfers from the consumer to the provider."]}),"\n",(0,r.jsx)(i.h3,{id:"transferperiodtimeout",children:"TransferPeriodTimeout"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TransferPeriodTimeout"})," is the period used to compute the timeout timestamp when sending IBC transfer packets from a consumer to the provider."]}),"\n",(0,r.jsxs)(i.p,{children:["If this timeout expires, then the transfer is attempted again after ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," blocks."]}),"\n",(0,r.jsxs)(i.ul,{children:["\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"TransferPeriodTimeout"})," on the consumer is initial set via the ",(0,r.jsx)(i.code,{children:"ConsumerAdditionProposal"})," gov proposal to add the consumer"]}),"\n",(0,r.jsxs)(i.li,{children:[(0,r.jsx)(i.code,{children:"TransferPeriodTimeout"})," should be smaller than ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission x avg_block_time"})]}),"\n"]}),"\n",(0,r.jsx)(i.h2,{id:"reward-distribution-parameters",children:"Reward Distribution Parameters"}),"\n",(0,r.jsx)(i.admonition,{type:"tip",children:(0,r.jsxs)(i.p,{children:["The following chain parameters dictate consumer chain distribution amount and frequency.\nThey are set at consumer genesis and ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"}),", ",(0,r.jsx)(i.code,{children:"ConsumerRedistributionFraction"}),"\n",(0,r.jsx)(i.code,{children:"TransferTimeoutPeriod"})," must be provided in every ",(0,r.jsx)(i.code,{children:"ConsumerChainAddition"})," proposal."]})}),"\n",(0,r.jsx)(i.h3,{id:"consumerredistributionfraction",children:"ConsumerRedistributionFraction"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ConsumerRedistributionFraction"})," is the fraction of tokens allocated to the consumer redistribution address during distribution events. The fraction is a string representing a decimal number. For example ",(0,r.jsx)(i.code,{children:'"0.75"'})," would represent ",(0,r.jsx)(i.code,{children:"75%"}),"."]}),"\n",(0,r.jsxs)(i.admonition,{type:"tip",children:[(0,r.jsx)(i.p,{children:"Example:"}),(0,r.jsxs)(i.p,{children:["With ",(0,r.jsx)(i.code,{children:"ConsumerRedistributionFraction"})," set to ",(0,r.jsx)(i.code,{children:'"0.75"'})," the consumer chain would send ",(0,r.jsx)(i.code,{children:"75%"})," of its block rewards and accumulated fees to the consumer redistribution address, and the remaining ",(0,r.jsx)(i.code,{children:"25%"})," to the provider chain every ",(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," blocks."]})]}),"\n",(0,r.jsx)(i.h3,{id:"blocksperdistributiontransmission-1",children:"BlocksPerDistributionTransmission"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"BlocksPerDistributionTransmission"})," is the number of blocks between IBC token transfers from the consumer chain to the provider chain."]}),"\n",(0,r.jsx)(i.h3,{id:"transfertimeoutperiod",children:"TransferTimeoutPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"TransferTimeoutPeriod"})," is the timeout period for consumer chain reward distribution IBC packets."]}),"\n",(0,r.jsx)(i.h3,{id:"distributiontransmissionchannel",children:"DistributionTransmissionChannel"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"DistributionTransmissionChannel"})," is the provider chain IBC channel used for receiving consumer chain reward distribution token transfers. This is automatically set during the consumer-provider handshake procedure."]}),"\n",(0,r.jsx)(i.h3,{id:"providerfeepooladdrstr",children:"ProviderFeePoolAddrStr"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"ProviderFeePoolAddrStr"})," is the provider chain fee pool address used for receiving consumer chain reward distribution token transfers. This is automatically set during the consumer-provider handshake procedure."]}),"\n",(0,r.jsx)(i.h2,{id:"slash-throttle-parameters",children:"Slash Throttle Parameters"}),"\n",(0,r.jsx)(i.h3,{id:"slashmeterreplenishperiod",children:"SlashMeterReplenishPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"SlashMeterReplenishPeriod"})," exists on the provider such that once the slash meter becomes not-full, the slash meter is replenished after this period has elapsed."]}),"\n",(0,r.jsxs)(i.p,{children:["The meter is replenished to an amount equal to the slash meter allowance for that block, or ",(0,r.jsx)(i.code,{children:"SlashMeterReplenishFraction * CurrentTotalVotingPower"}),"."]}),"\n",(0,r.jsx)(i.h3,{id:"slashmeterreplenishfraction",children:"SlashMeterReplenishFraction"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"SlashMeterReplenishFraction"})," exists on the provider as the portion (in range [0, 1]) of total voting power that is replenished to the slash meter when a replenishment occurs."]}),"\n",(0,r.jsxs)(i.p,{children:["This param also serves as a maximum fraction of total voting power that the slash meter can hold. The param is set/persisted as a string, and converted to a ",(0,r.jsx)(i.code,{children:"sdk.Dec"})," when used."]}),"\n",(0,r.jsx)(i.h3,{id:"maxthrottledpackets",children:"MaxThrottledPackets"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"MaxThrottledPackets"})," exists on the provider as the maximum amount of throttled slash or vsc matured packets that can be queued from a single consumer before the provider chain halts, it should be set to a large value."]}),"\n",(0,r.jsx)(i.p,{children:"This param would allow provider binaries to panic deterministically in the event that packet throttling results in a large amount of state-bloat. In such a scenario, packet throttling could prevent a violation of safety caused by a malicious consumer, at the cost of provider liveness."}),"\n",(0,r.jsx)(i.admonition,{type:"info",children:(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"MaxThrottledPackets"})," was deprecated in ICS versions >= v3.2.0 due to the implementation of ",(0,r.jsx)(i.a,{href:"/interchain-security/v5.0.0/adrs/adr-008-throttle-retries",children:"ADR-008"}),"."]})}),"\n",(0,r.jsx)(i.h3,{id:"retrydelayperiod",children:"RetryDelayPeriod"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"RetryDelayPeriod"})," exists on the consumer for ",(0,r.jsx)(i.strong,{children:"ICS versions >= v3.2.0"})," (introduced by the implementation of ",(0,r.jsx)(i.a,{href:"/interchain-security/v5.0.0/adrs/adr-008-throttle-retries",children:"ADR-008"}),") and is the period at which the consumer retries to send a ",(0,r.jsx)(i.code,{children:"SlashPacket"})," that was rejected by the provider."]}),"\n",(0,r.jsx)(i.h2,{id:"epoch-parameters",children:"Epoch Parameters"}),"\n",(0,r.jsx)(i.h3,{id:"blocksperepoch",children:"BlocksPerEpoch"}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.code,{children:"BlocksPerEpoch"})," exists on the provider for ",(0,r.jsx)(i.strong,{children:"ICS versions >= 3.3.0"})," (introduced by the implementation of ",(0,r.jsx)(i.a,{href:"/interchain-security/v5.0.0/adrs/adr-014-epochs",children:"ADR-014"}),")\nand corresponds to the number of blocks that constitute an epoch. This param is set to 600 by default. Assuming we need 6 seconds to\ncommit a block, the duration of an epoch corresponds to 1 hour. This means that a ",(0,r.jsx)(i.code,{children:"VSCPacket"})," would be sent to a consumer\nchain once at the end of every epoch, so once every 600 blocks. This parameter can be adjusted via a governance proposal,\nhowever careful consideration is needed so that ",(0,r.jsx)(i.code,{children:"BlocksPerEpoch"})," is not too large. A large ",(0,r.jsx)(i.code,{children:"BlocksPerEpoch"})," could lead to a delay\nof ",(0,r.jsx)(i.code,{children:"VSCPacket"}),"s and hence potentially lead to ",(0,r.jsx)(i.a,{href:"https://informal.systems/blog/learning-to-live-with-unbonding-pausing",children:"unbonding pausing"}),".\nFor setting ",(0,r.jsx)(i.code,{children:"BlocksPerEpoch"}),", we also need to consider potential slow chain upgrades that could delay the sending of a\n",(0,r.jsx)(i.code,{children:"VSCPacket"}),", as well as potential increases in the time it takes to commit a block (e.g., from 6 seconds to 30 seconds)."]})]})}function h(e={}){const{wrapper:i}={...(0,s.a)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},1151:(e,i,n)=>{n.d(i,{Z:()=>d,a:()=>t});var r=n(7294);const s={},o=r.createContext(s);function t(e){const i=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function d(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:t(e.components),r.createElement(o.Provider,{value:i},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/f5589540.4abf59ac.js b/assets/js/f5589540.4abf59ac.js
new file mode 100644
index 0000000000..207bdbb845
--- /dev/null
+++ b/assets/js/f5589540.4abf59ac.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6499],{5573:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>r,metadata:()=>i,toc:()=>h});var o=t(5893),a=t(1151);const r={sidebar_position:2},s="Consumer Chain Governance",i={id:"consumer-development/consumer-chain-governance",title:"Consumer Chain Governance",description:'Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We\'ll cover what these are in the "Whitelist" section below.',source:"@site/docs/consumer-development/consumer-chain-governance.md",sourceDirName:"consumer-development",slug:"/consumer-development/consumer-chain-governance",permalink:"/interchain-security/consumer-development/consumer-chain-governance",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:2,frontMatter:{sidebar_position:2},sidebar:"tutorialSidebar",previous:{title:"Developing an ICS consumer chain",permalink:"/interchain-security/consumer-development/app-integration"},next:{title:"Onboarding Checklist",permalink:"/interchain-security/consumer-development/onboarding"}},c={},h=[{value:"Democracy module",id:"democracy-module",level:2},{value:"CosmWasm",id:"cosmwasm",level:2},{value:"The Whitelist",id:"the-whitelist",level:2}];function l(e){const n={a:"a",h1:"h1",h2:"h2",p:"p",...(0,a.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"consumer-chain-governance",children:"Consumer Chain Governance"}),"\n",(0,o.jsx)(n.p,{children:'Different consumer chains can do governance in different ways. However, no matter what the governance method is, there are a few settings specifically related to consensus that consumer chain governance cannot change. We\'ll cover what these are in the "Whitelist" section below.'}),"\n",(0,o.jsx)(n.h2,{id:"democracy-module",children:"Democracy module"}),"\n",(0,o.jsx)(n.p,{children:"The democracy module provides a governance experience identical to what exists on a standalone Cosmos chain, with one small but important difference. On a standalone Cosmos chain validators can act as representatives for their delegators by voting with their stake, but only if the delegator themselves does not vote. This is a lightweight form of liquid democracy."}),"\n",(0,o.jsx)(n.p,{children:"Using the democracy module on a consumer chain is the exact same experience, except for the fact that it is not the actual validator set of the chain (since it is a consumer chain, these are the Cosmos Hub validators) acting as representatives. Instead, there is a separate representative role who token holders can delegate to and who can perform the functions that validators do in Cosmos governance, without participating in proof of stake consensus."}),"\n",(0,o.jsxs)(n.p,{children:["For an example, see the ",(0,o.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/tree/main/app/consumer-democracy",children:"Democracy Consumer"})]}),"\n",(0,o.jsx)(n.h2,{id:"cosmwasm",children:"CosmWasm"}),"\n",(0,o.jsx)(n.p,{children:"There are several great DAO and governance frameworks written as CosmWasm contracts. These can be used as the main governance system for a consumer chain. Actions triggered by the CosmWasm governance contracts are able to affect parameters and trigger actions on the consumer chain."}),"\n",(0,o.jsxs)(n.p,{children:["For an example, see ",(0,o.jsx)(n.a,{href:"https://github.com/neutron-org/neutron/",children:"Neutron"}),"."]}),"\n",(0,o.jsx)(n.h2,{id:"the-whitelist",children:"The Whitelist"}),"\n",(0,o.jsxs)(n.p,{children:["Not everything on a consumer chain can be changed by the consumer's governance. Some settings having to do with consensus etc. can only be changed by the provider chain. Consumer chains include a whitelist of parameters that are allowed to be changed by the consumer chain governance. For an example, see ",(0,o.jsx)(n.a,{href:"https://github.com/neutron-org/neutron/blob/main/app/proposals_allowlisting.go",children:"Neutron's"})," whitelist."]})]})}function m(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>i,a:()=>s});var o=t(7294);const a={},r=o.createContext(a);function s(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/f6addb2b.aca89816.js b/assets/js/f6addb2b.aca89816.js
new file mode 100644
index 0000000000..a1f51b7d8f
--- /dev/null
+++ b/assets/js/f6addb2b.aca89816.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[35],{279:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>a,metadata:()=>o,toc:()=>h});var s=i(5893),t=i(1151);const a={sidebar_position:1},r="Overview",o={id:"validators/overview",title:"Overview",description:"We advise that you join the Interchain Security testnet to gain hands-on experience with running consumer chains.",source:"@site/docs/validators/overview.md",sourceDirName:"validators",slug:"/validators/overview",permalink:"/interchain-security/validators/overview",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:1,frontMatter:{sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Consumer Genesis Transformation",permalink:"/interchain-security/consumer-development/consumer-genesis-transformation"},next:{title:"Joining Interchain Security testnet",permalink:"/interchain-security/validators/joining-testnet"}},c={},h=[{value:"Startup sequence overview",id:"startup-sequence-overview",level:2},{value:"1. Consumer Chain init + 2. Genesis generation",id:"1-consumer-chain-init--2-genesis-generation",level:3},{value:"3. Submit Proposal",id:"3-submit-proposal",level:3},{value:"4. CCV Genesis state generation",id:"4-ccv-genesis-state-generation",level:3},{value:"5. Updating the genesis file",id:"5-updating-the-genesis-file",level:3},{value:"6. Chain start",id:"6-chain-start",level:3},{value:"7. Creating IBC connections",id:"7-creating-ibc-connections",level:3},{value:"Downtime Infractions",id:"downtime-infractions",level:2},{value:"Double-signing Infractions",id:"double-signing-infractions",level:2},{value:"Key assignment",id:"key-assignment",level:2},{value:"References:",id:"references",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["We advise that you join the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/tree/master/interchain-security",children:"Interchain Security testnet"})," to gain hands-on experience with running consumer chains."]})}),"\n",(0,s.jsxs)(n.p,{children:["At present, Interchain Security requires some or all the validators of the provider chain (ie. Cosmos Hub) to run validator nodes for a consumer chain.\nWhether a validator has to run a validator node for a consumer chain depends on whether the consumer chain is a Top N or an\nOpt-In chain and also on the ",(0,s.jsx)(n.a,{href:"/interchain-security/features/power-shaping",children:"power-shaping features"}),". A validator can use the\n",(0,s.jsxs)(n.a,{href:"/interchain-security/validators/partial-set-security-for-validators#which-chains-does-a-validator-have-to-validate",children:[(0,s.jsx)(n.code,{children:"has-to-validate"})," query"]}),"\nto keep track of all the chains it has to validate."]}),"\n",(0,s.jsxs)(n.p,{children:["Once a ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})," passes, relevant validators need to prepare to run the consumer chain binaries (these will be linked in their proposals) and set up validator nodes on governance-approved consumer chains."]}),"\n",(0,s.jsx)(n.p,{children:"Provider chain and consumer chains represent standalone chains that only share part of the validator set."}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"To validate a consumer chain and be eligible for rewards, validators are required to be in the active set of the provider chain (first 180 validators for Cosmos Hub)."})}),"\n",(0,s.jsx)(n.h2,{id:"startup-sequence-overview",children:"Startup sequence overview"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer chains cannot start and be secured by the validator set of the provider unless a ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})," is passed.\nEach proposal contains defines a ",(0,s.jsx)(n.code,{children:"spawn_time"})," - the timestamp when the consumer chain genesis is finalized and the consumer chain clients get initialized on the provider."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["Validators are required to run consumer chain binaries only after ",(0,s.jsx)(n.code,{children:"spawn_time"})," has passed."]})}),"\n",(0,s.jsx)(n.p,{children:"Please note that any additional instructions pertaining to specific consumer chain launches will be available before spawn time. The chain start will be stewarded by the Cosmos Hub team and the teams developing their respective consumer chains."}),"\n",(0,s.jsxs)(n.p,{children:["The image below illustrates the startup sequence\n",(0,s.jsx)(n.img,{alt:"startup",src:i(4090).Z+"",width:"942",height:"632"})]}),"\n",(0,s.jsx)(n.h3,{id:"1-consumer-chain-init--2-genesis-generation",children:"1. Consumer Chain init + 2. Genesis generation"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer chain team initializes the chain genesis.json and prepares binaries which will be listed in the ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"})]}),"\n",(0,s.jsx)(n.h3,{id:"3-submit-proposal",children:"3. Submit Proposal"}),"\n",(0,s.jsxs)(n.p,{children:["Consumer chain team (or their advocates) submits a ",(0,s.jsx)(n.code,{children:"ConsumerAdditionProposal"}),".\nThe most important parameters for validators are:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"spawn_time"})," - the time after which the consumer chain must be started"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"genesis_hash"})," - hash of the pre-ccv genesis.json; the file does not contain any validator info -> the information is available only after the proposal is passed and ",(0,s.jsx)(n.code,{children:"spawn_time"})," is reached"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"binary_hash"})," - hash of the consumer chain binary used to validate the software builds"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"4-ccv-genesis-state-generation",children:"4. CCV Genesis state generation"}),"\n",(0,s.jsxs)(n.p,{children:["After reaching ",(0,s.jsx)(n.code,{children:"spawn_time"})," the provider chain will automatically create the CCV validator states that will be used to populate the corresponding fields in the consumer chain ",(0,s.jsx)(n.code,{children:"genesis.json"}),". The CCV validator set consists of the validator set on the provider at ",(0,s.jsx)(n.code,{children:"spawn_time"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"The state can be queried on the provider chain (in this case the Cosmos Hub):"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:" gaiad query provider consumer-genesis -o json > ccvconsumer_genesis.json\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This is used by the launch coordinator to create the final ",(0,s.jsx)(n.code,{children:"genesis.json"})," that will be distributed to validators in step 5."]}),"\n",(0,s.jsx)(n.h3,{id:"5-updating-the-genesis-file",children:"5. Updating the genesis file"}),"\n",(0,s.jsxs)(n.p,{children:["Upon reaching the ",(0,s.jsx)(n.code,{children:"spawn_time"})," the initial validator set state will become available on the provider chain. The initial validator set is included in the ",(0,s.jsx)(n.strong,{children:"final genesis.json"})," of the consumer chain."]}),"\n",(0,s.jsx)(n.h3,{id:"6-chain-start",children:"6. Chain start"}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsx)(n.p,{children:"The consumer chain will start producing blocks as soon as 66.67% of the provider chain's voting power comes online (on the consumer chain). The relayer should be started after block production commences."})}),"\n",(0,s.jsxs)(n.p,{children:["The new ",(0,s.jsx)(n.code,{children:"genesis.json"})," containing the initial validator set will be distributed to validators by the consumer chain team (launch coordinator). Each validator should use the provided ",(0,s.jsx)(n.code,{children:"genesis.json"})," to start their consumer chain node."]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["Please pay attention to any onboarding repositories provided by the consumer chain teams.\nRecommendations are available in ",(0,s.jsx)(n.a,{href:"/interchain-security/consumer-development/onboarding",children:"Consumer Onboarding Checklist"}),".\nAnother comprehensive guide is available in the ",(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md",children:"Interchain Security testnet repo"}),"."]})}),"\n",(0,s.jsx)(n.h3,{id:"7-creating-ibc-connections",children:"7. Creating IBC connections"}),"\n",(0,s.jsx)(n.p,{children:"Finally, to fully establish interchain security an IBC relayer is used to establish connections and create the required channels."}),"\n",(0,s.jsx)(n.admonition,{type:"warning",children:(0,s.jsx)(n.p,{children:"The relayer can establish the connection only after the consumer chain starts producing blocks."})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"hermes create connection --a-chain --a-client 07-tendermint-0 --b-client \nhermes create channel --a-chain --a-port consumer --b-port provider --order ordered --a-connection connection-0 --channel-version 1\nhermes start\n"})}),"\n",(0,s.jsx)(n.h2,{id:"downtime-infractions",children:"Downtime Infractions"}),"\n",(0,s.jsxs)(n.p,{children:["At present, the consumer chain can report evidence about downtime infractions to the provider chain. The ",(0,s.jsx)(n.code,{children:"min_signed_per_window"})," and ",(0,s.jsx)(n.code,{children:"signed_blocks_window"})," can be different on each consumer chain and are subject to changes via consumer chain governance."]}),"\n",(0,s.jsxs)(n.admonition,{type:"info",children:[(0,s.jsx)(n.p,{children:"Causing a downtime infraction on any consumer chain will not incur a slash penalty. Instead, the offending validator will be jailed on the provider chain and consequently on all consumer chains."}),(0,s.jsxs)(n.p,{children:["To unjail, the validator must wait for the jailing period to elapse on the provider chain and ",(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/main/validators/validator-setup#unjail-validator",children:"submit an unjail transaction"})," on the provider chain. After unjailing on the provider, the validator will be unjailed on all consumer chains."]}),(0,s.jsxs)(n.p,{children:["More information is available in ",(0,s.jsx)(n.a,{href:"/interchain-security/features/slashing#downtime-infractions",children:"Downtime Slashing documentation"})]})]}),"\n",(0,s.jsx)(n.h2,{id:"double-signing-infractions",children:"Double-signing Infractions"}),"\n",(0,s.jsxs)(n.p,{children:["To learn more about equivocation handling in interchain security check out the ",(0,s.jsx)(n.a,{href:"/interchain-security/features/slashing",children:"Slashing"})," documentation section."]}),"\n",(0,s.jsx)(n.h2,{id:"key-assignment",children:"Key assignment"}),"\n",(0,s.jsx)(n.p,{children:"Validators can use different consensus keys on the provider and each of the consumer chains. The consumer chain consensus key must be registered on the provider before use."}),"\n",(0,s.jsxs)(n.p,{children:["For more information check out the ",(0,s.jsx)(n.a,{href:"/interchain-security/features/key-assignment",children:"Key assignment overview and guide"})]}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/main/validators/validator-faq",children:"Cosmos Hub Validators FAQ"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/main/validators/validator-setup",children:"Cosmos Hub Running a validator"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://github.com/cosmos/testnets/blob/master/interchain-security/CONSUMER_LAUNCH_GUIDE.md#chain-launch",children:"Startup Sequence"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"https://hub.cosmos.network/main/validators/validator-setup#unjail-validator",children:"Submit Unjailing Transaction"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},4090:(e,n,i)=>{i.d(n,{Z:()=>s});const s=i.p+"assets/images/hypha-consumer-start-process-2141109f76c584706dd994d7965fd692.svg"},1151:(e,n,i)=>{i.d(n,{Z:()=>o,a:()=>r});var s=i(7294);const t={},a=s.createContext(t);function r(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/f8a7cbf6.7e411975.js b/assets/js/f8a7cbf6.7e411975.js
new file mode 100644
index 0000000000..388cc41380
--- /dev/null
+++ b/assets/js/f8a7cbf6.7e411975.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2527],{4097:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>t,default:()=>h,frontMatter:()=>s,metadata:()=>d,toc:()=>c});var a=n(5893),i=n(1151);const s={sidebar_position:3},t="Withdrawing consumer chain validator rewards",d={id:"validators/withdraw_rewards",title:"Withdrawing consumer chain validator rewards",description:"Here are example steps for withdrawing rewards from consumer chains in the provider chain",source:"@site/versioned_docs/version-v5.0.0/validators/withdraw_rewards.md",sourceDirName:"validators",slug:"/validators/withdraw_rewards",permalink:"/interchain-security/v5.0.0/validators/withdraw_rewards",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:3,frontMatter:{sidebar_position:3},sidebar:"tutorialSidebar",previous:{title:"Joining Interchain Security testnet",permalink:"/interchain-security/v5.0.0/validators/joining-testnet"},next:{title:"Validator Instructions for Changeover Procedure",permalink:"/interchain-security/v5.0.0/validators/changeover-procedure"}},o={},c=[{value:"Querying validator rewards",id:"querying-validator-rewards",level:2},{value:"Withdrawing rewards and commission",id:"withdrawing-rewards-and-commission",level:2},{value:"1. Withdraw rewards",id:"1-withdraw-rewards",level:3},{value:"2. Confirm withdrawal",id:"2-confirm-withdrawal",level:3}];function l(e){const r={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(r.h1,{id:"withdrawing-consumer-chain-validator-rewards",children:"Withdrawing consumer chain validator rewards"}),"\n",(0,a.jsx)(r.p,{children:"Here are example steps for withdrawing rewards from consumer chains in the provider chain"}),"\n",(0,a.jsxs)(r.admonition,{type:"info",children:[(0,a.jsxs)(r.p,{children:["The examples used are from ",(0,a.jsx)(r.code,{children:"rs-testnet"}),", the replicated security persistent testnet."]}),(0,a.jsxs)(r.p,{children:["Validator operator address: ",(0,a.jsx)(r.code,{children:"cosmosvaloper1e5yfpc8l6g4808fclmlyd38tjgxuwshnmjkrq6"}),"\nSelf-delegation address: ",(0,a.jsx)(r.code,{children:"cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf"})]})]}),"\n",(0,a.jsx)(r.p,{children:"Prior to withdrawing rewards, query balances for self-delegation address:"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:'gaiad q bank balances cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf\n\nbalances:\n- amount: "1000000000000"\n denom: uatom\npagination:\n next_key: null\n total: "0"\n'})}),"\n",(0,a.jsx)(r.h2,{id:"querying-validator-rewards",children:"Querying validator rewards"}),"\n",(0,a.jsx)(r.p,{children:"Query rewards for the validator address:"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:'gaiad q distribution rewards cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf cosmosvaloper1e5yfpc8l6g4808fclmlyd38tjgxuwshnmjkrq6\n\nrewards:\n- amount: "158.069895000000000000"\n denom: ibc/2CB0E87E2A742166FEC0A18D6FBF0F6AD4AA1ADE694792C1BD6F5E99088D67FD\n- amount: "841842390516.072526500000000000"\n denom: uatom\n'})}),"\n",(0,a.jsxs)(r.p,{children:["The ",(0,a.jsx)(r.code,{children:"ibc/2CB0E87E2A742166FEC0A18D6FBF0F6AD4AA1ADE694792C1BD6F5E99088D67FD"})," denom represents rewards from a consumer chain."]}),"\n",(0,a.jsx)(r.h2,{id:"withdrawing-rewards-and-commission",children:"Withdrawing rewards and commission"}),"\n",(0,a.jsx)(r.h3,{id:"1-withdraw-rewards",children:"1. Withdraw rewards"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:"gaiad tx distribution withdraw-rewards cosmosvaloper1e5yfpc8l6g4808fclmlyd38tjgxuwshnmjkrq6 --from cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf --commission --chain-id provider --gas auto --fees 500uatom -b block -y\n\ntxhash: A7E384FB1958211B43B7C06527FC7D4471FB6B491EE56FDEA9C5634D76FF1B9A\n"})}),"\n",(0,a.jsx)(r.h3,{id:"2-confirm-withdrawal",children:"2. Confirm withdrawal"}),"\n",(0,a.jsx)(r.p,{children:"After withdrawing rewards self-delegation address balance to confirm rewards were withdrawn:"}),"\n",(0,a.jsx)(r.pre,{children:(0,a.jsx)(r.code,{className:"language-bash",children:'gaiad q bank balances cosmos1e5yfpc8l6g4808fclmlyd38tjgxuwshn7xzkvf\n\nbalances:\n- amount: "216"\n denom: ibc/2CB0E87E2A742166FEC0A18D6FBF0F6AD4AA1ADE694792C1BD6F5E99088D67FD\n- amount: "2233766225342"\n denom: uatom\npagination:\n next_key: null\n total: "0"\n'})})]})}function h(e={}){const{wrapper:r}={...(0,i.a)(),...e.components};return r?(0,a.jsx)(r,{...e,children:(0,a.jsx)(l,{...e})}):l(e)}},1151:(e,r,n)=>{n.d(r,{Z:()=>d,a:()=>t});var a=n(7294);const i={},s=a.createContext(i);function t(e){const r=a.useContext(s);return a.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function d(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),a.createElement(s.Provider,{value:r},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/fc26cd25.e6be4cde.js b/assets/js/fc26cd25.e6be4cde.js
new file mode 100644
index 0000000000..a10654c3d5
--- /dev/null
+++ b/assets/js/fc26cd25.e6be4cde.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9198],{6801:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>c});var s=t(5893),i=t(1151);const o={sidebar_position:2,title:"ADR Template"},r="ADR [ADR-NUMBER]: [TITLE]",a={id:"adrs/adr-template",title:"ADR Template",description:"Changelog",source:"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-template.md",sourceDirName:"adrs",slug:"/adrs/adr-template",permalink:"/interchain-security/v4.2.0/adrs/adr-template",draft:!1,unlisted:!1,tags:[],version:"v4.2.0-docs",sidebarPosition:2,frontMatter:{sidebar_position:2,title:"ADR Template"},sidebar:"tutorialSidebar",previous:{title:"ADR Template",permalink:"/interchain-security/v4.2.0/adrs/adr-007-pause-unbonding-on-eqv-prop"},next:{title:"Key Assignment",permalink:"/interchain-security/v4.2.0/adrs/adr-001-key-assignment"}},l={},c=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function d(e){const n={blockquote:"blockquote",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",ul:"ul",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"adr-adr-number-title",children:"ADR [ADR-NUMBER]: [TITLE]"}),"\n",(0,s.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:'A decision may be "proposed" if it hasn\'t been agreed upon yet, or "accepted" once it is agreed upon. If a later ADR changes or reverses a decision, it may be marked as "deprecated" or "superseded" with a reference to its replacement.'}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"[Deprecated|Proposed|Accepted]"}),"\n",(0,s.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"This section contains all the context one needs to understand the current state, and why there is a problem. It should be as succinct as possible and introduce the high level idea behind the solution."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"This section explains all of the details of the proposed solution, including implementation details.\nIt should also describe affects / corollary items that may need to be changed as a part of this.\nIf the proposed change will be large, please also indicate a way to do the change to maximize ease of review.\n(e.g. the optimal split of things to do between separate PR's)"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:'This section describes the consequences, after applying the decision. All consequences should be summarized here, not just the "positive" ones.'}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,s.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,s.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,s.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsx)(n.p,{children:"Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!"}),"\n"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"[references]"}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>r});var s=t(7294);const i={},o=s.createContext(i);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/ff0782b1.cbedc7fd.js b/assets/js/ff0782b1.cbedc7fd.js
new file mode 100644
index 0000000000..79b1be05c8
--- /dev/null
+++ b/assets/js/ff0782b1.cbedc7fd.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7540],{3769:e=>{e.exports=JSON.parse('{"name":"docusaurus-plugin-content-docs","id":"default"}')}}]);
\ No newline at end of file
diff --git a/assets/js/ff9311cc.0e55d588.js b/assets/js/ff9311cc.0e55d588.js
new file mode 100644
index 0000000000..a375ab532f
--- /dev/null
+++ b/assets/js/ff9311cc.0e55d588.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5051],{151:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>o,metadata:()=>a,toc:()=>h});var i=t(5893),s=t(1151);const o={sidebar_position:15,title:"Epochs"},r="ADR 014: Epochs",a={id:"adrs/adr-014-epochs",title:"Epochs",description:"Changelog",source:"@site/versioned_docs/version-v5.0.0/adrs/adr-014-epochs.md",sourceDirName:"adrs",slug:"/adrs/adr-014-epochs",permalink:"/interchain-security/v5.0.0/adrs/adr-014-epochs",draft:!1,unlisted:!1,tags:[],version:"v5.0.0",sidebarPosition:15,frontMatter:{sidebar_position:15,title:"Epochs"},sidebar:"tutorialSidebar",previous:{title:"Slashing on the provider for consumer equivocation",permalink:"/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing"},next:{title:"Partial Set Security",permalink:"/interchain-security/v5.0.0/adrs/adr-015-partial-set-security"}},c={},h=[{value:"Changelog",id:"changelog",level:2},{value:"Status",id:"status",level:2},{value:"Context",id:"context",level:2},{value:"Decision",id:"decision",level:2},{value:"Consequences",id:"consequences",level:2},{value:"Positive",id:"positive",level:3},{value:"Negative",id:"negative",level:3},{value:"Neutral",id:"neutral",level:3},{value:"References",id:"references",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"adr-014-epochs",children:"ADR 014: Epochs"}),"\n",(0,i.jsx)(n.h2,{id:"changelog",children:"Changelog"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"2024-01-05: Proposed, first draft of ADR."}),"\n",(0,i.jsx)(n.li,{children:"2024-02-29: Updated so that it describes the implementation where we store the whole consumer validator set."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"status",children:"Status"}),"\n",(0,i.jsx)(n.p,{children:"Proposed"}),"\n",(0,i.jsx)(n.h2,{id:"context",children:"Context"}),"\n",(0,i.jsxs)(n.p,{children:["In every block that the provider valset changes, a ",(0,i.jsx)(n.code,{children:"VSCPacket"})," must be sent to every consumer and a corresponding ",(0,i.jsx)(n.code,{children:"VSCMaturedPacket"})," sent back.\nGiven that the validator powers may change very often on the provider chain (e.g., the Cosmos Hub), this approach results in a large workload for the relayers.\nAlthough the validator powers may change very often, these changes are usually small and have an insignificant impact on the chain's security.\nIn other words, the valset on the consumers can be slightly outdated without affecting security.\nAs a matter of fact, this already happens due to relaying delays."]}),"\n",(0,i.jsxs)(n.p,{children:["As a solution, this ADR introduces the concept of ",(0,i.jsx)(n.em,{children:"epochs"}),".\nAn epoch consists of multiple blocks.\nThe provider sends ",(0,i.jsx)(n.code,{children:"VSCPacket"}),"s once per epoch.\nA ",(0,i.jsx)(n.code,{children:"VSCPacket"})," contains all the validator updates that are needed by a consumer chain."]}),"\n",(0,i.jsx)(n.h2,{id:"decision",children:"Decision"}),"\n",(0,i.jsx)(n.p,{children:"The implementation of epochs requires the following changes:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"For each consumer chain, we store the consumer validator set that is currently (i.e., in this epoch) validating the\nconsumer chain. For each validator in the set we store i) its voting power, and ii) the public key that it is\nusing on the consumer chain during the current (i.e., ongoing) epoch.\nThe initial consumer validator set for a chain is set during the creation of the consumer genesis."}),"\n",(0,i.jsxs)(n.li,{children:["We introduce the ",(0,i.jsx)(n.code,{children:"BlocksPerEpoch"})," param that sets the number of blocks in an epoch. By default, ",(0,i.jsx)(n.code,{children:"BlocksPerEpoch"})," is\nset to be 600 which corresponds to 1 hour, assuming 6 seconds per block. This param can be changed through\na ",(0,i.jsx)(n.em,{children:"governance proposal"}),". In the provider ",(0,i.jsx)(n.code,{children:"EndBlock"})," we check ",(0,i.jsx)(n.code,{children:"BlockHeight() % BlocksPerEpoch() == 0"}),"\nto decide when an epoch has ended."]}),"\n",(0,i.jsxs)(n.li,{children:["At the end of every epoch, if there were validator set changes on the provider, then for every consumer chain, we\nconstruct a ",(0,i.jsx)(n.code,{children:"VSCPacket"})," with all the validator updates and add it to the list of ",(0,i.jsx)(n.code,{children:"PendingVSCPackets"}),". We compute the\nvalidator updates needed by a consumer chain by comparing the stored list of consumer validators with the current\nbonded validators on the provider, with something similar to this:"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:"// get the valset that has been validating the consumer chain during this epoch \ncurrentValidators := GetConsumerValSet(consumerChain)\n// generate the validator updates needed to be sent through a `VSCPacket` by comparing the current validators \n// in the epoch with the latest bonded validators\nvalUpdates := DiffValidators(currentValidators, stakingmodule.GetBondedValidators())\n// update the current validators set for the upcoming epoch to be the latest bonded validators instead\nSetConsumerValSet(stakingmodule.GetBondedValidators())\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that a validator can change its consumer public key for a specific consumer chain an arbitrary amount of times during\na block and during an epoch. Then, when we generate the validator updates in ",(0,i.jsx)(n.code,{children:"DiffValidators"}),", we have to check whether\nthe current consumer public key (retrieved by calling ",(0,i.jsx)(n.code,{children:"GetValidatorConsumerPubKey"}),") is different from the consumer public\nkey the validator was using in the current epoch."]}),"\n",(0,i.jsx)(n.h2,{id:"consequences",children:"Consequences"}),"\n",(0,i.jsx)(n.h3,{id:"positive",children:"Positive"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Reduce the cost of relaying."}),"\n",(0,i.jsx)(n.li,{children:"Reduce the amount of IBC packets needed for ICS."}),"\n",(0,i.jsxs)(n.li,{children:["Simplifies ",(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/blob/main/docs/docs/adrs/adr-001-key-assignment.md",children:"key-assignment code"})," because\nwe only need to check if the ",(0,i.jsx)(n.code,{children:"consumer_public_key"})," has been modified since the last epoch to generate an update."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"negative",children:"Negative"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Increase the delay in the propagation of validator set changes (but for reasonable epoch lengths on the order of ~hours or less, this is unlikely to be significant)."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"neutral",children:"Neutral"}),"\n",(0,i.jsx)(n.p,{children:"N/A"}),"\n",(0,i.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://github.com/cosmos/interchain-security/issues/1087",children:"EPIC"})}),"\n"]})]})}function l(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>a,a:()=>r});var i=t(7294);const s={},o=i.createContext(s);function r(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/main.11e71de7.js b/assets/js/main.11e71de7.js
new file mode 100644
index 0000000000..5a2aefc146
--- /dev/null
+++ b/assets/js/main.11e71de7.js
@@ -0,0 +1,2 @@
+/*! For license information please see main.11e71de7.js.LICENSE.txt */
+(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[179],{723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});n(7294);var r=n(8356),a=n.n(r),i=n(6887);const o={"00147ff4":[()=>n.e(2110).then(n.bind(n,9075)),"@site/docs/frequently-asked-questions.md",9075],"06b45df8":[()=>n.e(9599).then(n.t.bind(n,4562,19)),"~docs/default/version-v-5-0-0-metadata-prop-841.json",4562],"07d76e7d":[()=>n.e(2189).then(n.bind(n,7488)),"@site/docs/features/key-assignment.md",7488],"0cb1d302":[()=>n.e(1085).then(n.bind(n,5398)),"@site/docs/validators/joining-neutron.md",5398],"1097399d":[()=>n.e(6548).then(n.bind(n,5191)),"@site/versioned_docs/version-v5.0.0/adrs/adr-011-improving-test-confidence.md",5191],"16d4e57d":[()=>n.e(5387).then(n.bind(n,1258)),"@site/versioned_docs/version-v5.0.0/introduction/terminology.md",1258],17896441:[()=>Promise.all([n.e(532),n.e(7918)]).then(n.bind(n,7078)),"@theme/DocItem",7078],"1ae81764":[()=>n.e(2262).then(n.bind(n,9436)),"@site/versioned_docs/version-v4.2.0-docs/introduction/terminology.md",9436],"1ca82e41":[()=>n.e(7617).then(n.bind(n,1343)),"@site/versioned_docs/version-v5.0.0/consumer-development/consumer-genesis-transformation.md",1343],"21cfc626":[()=>n.e(52).then(n.bind(n,964)),"@site/versioned_docs/version-v5.0.0/index.mdx",964],"21dfdb60":[()=>n.e(5932).then(n.bind(n,2702)),"@site/versioned_docs/version-v5.0.0/adrs/adr-template.md",2702],"2510f7b4":[()=>n.e(2558).then(n.bind(n,6250)),"@site/versioned_docs/version-v4.2.0-docs/validators/joining-neutron.md",6250],"26981f24":[()=>n.e(1483).then(n.bind(n,5183)),"@site/versioned_docs/version-v5.0.0/consumer-development/changeover-procedure.md",5183],"287de311":[()=>n.e(7184).then(n.bind(n,3879)),"@site/versioned_docs/version-v4.2.0-docs/validators/overview.md",3879],"2a9fa04d":[()=>n.e(3670).then(n.bind(n,8328)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-008-throttle-retries.md",8328],"2c92eef1":[()=>n.e(3158).then(n.bind(n,6386)),"@site/versioned_docs/version-v5.0.0/introduction/technical-specification.md",6386],"2ed06975":[()=>n.e(1038).then(n.bind(n,439)),"@site/versioned_docs/version-v5.0.0/adrs/intro.md",439],"3672b5b7":[()=>n.e(320).then(n.bind(n,9873)),"@site/docs/introduction/params.md",9873],"3ec9db48":[()=>n.e(8233).then(n.bind(n,4554)),"@site/versioned_docs/version-v4.2.0-docs/features/reward-distribution.md",4554],"3f3637cb":[()=>n.e(3596).then(n.bind(n,9529)),"@site/versioned_docs/version-v4.2.0-docs/introduction/overview.md",9529],"3f869ff5":[()=>n.e(4470).then(n.bind(n,4522)),"@site/versioned_docs/version-v4.2.0-docs/features/power-shaping.md",4522],"405e8773":[()=>n.e(5180).then(n.bind(n,1912)),"@site/versioned_docs/version-v4.2.0-docs/validators/joining-testnet.md",1912],"4106f1c5":[()=>n.e(842).then(n.bind(n,7049)),"@site/docs/features/slashing.md",7049],"4179ee03":[()=>n.e(6073).then(n.bind(n,2069)),"@site/docs/upgrading/migrate_v4_v5.md",2069],"425bba28":[()=>n.e(1118).then(n.bind(n,737)),"@site/docs/consumer-development/consumer-genesis-transformation.md",737],"434502c4":[()=>n.e(411).then(n.bind(n,854)),"@site/versioned_docs/version-v5.0.0/features/slashing.md",854],"46057b98":[()=>n.e(3159).then(n.bind(n,8812)),"@site/docs/adrs/adr-003-equivocation-gov-proposal.md",8812],"491e9485":[()=>n.e(6784).then(n.bind(n,953)),"@site/versioned_docs/version-v5.0.0/adrs/adr-008-throttle-retries.md",953],"4c7d82ee":[()=>n.e(7649).then(n.bind(n,1915)),"@site/docs/adrs/adr-005-cryptographic-equivocation-verification.md",1915],"4edc808e":[()=>n.e(4173).then(n.bind(n,7559)),"@site/docs/index.mdx",7559],"4edefe03":[()=>n.e(918).then(n.bind(n,7168)),"@site/versioned_docs/version-v5.0.0/adrs/adr-005-cryptographic-equivocation-verification.md",7168],"4f50acdf":[()=>n.e(9815).then(n.bind(n,7125)),"@site/docs/validators/joining-testnet.md",7125],53123775:[()=>n.e(2234).then(n.bind(n,8621)),"@site/versioned_docs/version-v5.0.0/upgrading/migrate_v4_v5.md",8621],"536acd9c":[()=>n.e(4279).then(n.bind(n,8276)),"@site/versioned_docs/version-v4.2.0-docs/validators/changeover-procedure.md",8276],"54e4400b":[()=>n.e(2344).then(n.bind(n,6064)),"@site/docs/adrs/adr-001-key-assignment.md",6064],"578fb1aa":[()=>n.e(2323).then(n.bind(n,8522)),"@site/docs/features/reward-distribution.md",8522],"5cdffc34":[()=>n.e(4895).then(n.bind(n,8961)),"@site/versioned_docs/version-v5.0.0/validators/overview.md",8961],"5cee3276":[()=>n.e(1996).then(n.bind(n,434)),"@site/versioned_docs/version-v5.0.0/introduction/overview.md",434],"5e95c892":[()=>n.e(9661).then(n.bind(n,1892)),"@theme/DocsRoot",1892],"5fa9786a":[()=>n.e(2341).then(n.bind(n,5370)),"@site/versioned_docs/version-v4.2.0-docs/consumer-development/consumer-genesis-transformation.md",5370],"61e9b0fd":[()=>n.e(5402).then(n.bind(n,5615)),"@site/versioned_docs/version-v5.0.0/frequently-asked-questions.md",5615],"624b8b53":[()=>n.e(9709).then(n.bind(n,1461)),"@site/versioned_docs/version-v5.0.0/adrs/adr-012-separate-releasing.md",1461],"6382e28e":[()=>n.e(1660).then(n.bind(n,3501)),"@site/versioned_docs/version-v4.2.0-docs/consumer-development/offboarding.md",3501],"68191a78":[()=>n.e(4438).then(n.bind(n,266)),"@site/docs/adrs/adr-011-improving-test-confidence.md",266],69416719:[()=>n.e(6873).then(n.bind(n,5911)),"@site/docs/features/democracy-modules.md",5911],"6b52739c":[()=>n.e(9419).then(n.bind(n,6319)),"@site/docs/adrs/adr-015-partial-set-security.md",6319],"6b8df643":[()=>n.e(4335).then(n.bind(n,8355)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-014-epochs.md",8355],"6cc1db80":[()=>n.e(8714).then(n.bind(n,6187)),"@site/versioned_docs/version-v5.0.0/validators/joining-neutron.md",6187],"6df65b06":[()=>n.e(4366).then(n.bind(n,4878)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-002-throttle.md",4878],"6f71328c":[()=>n.e(8560).then(n.bind(n,9371)),"@site/docs/adrs/adr-013-equivocation-slashing.md",9371],"700b5f22":[()=>n.e(5612).then(n.bind(n,8734)),"@site/docs/validators/partial-set-security-for-validators.md",8734],"70938a03":[()=>n.e(5457).then(n.bind(n,5610)),"@site/docs/consumer-development/changeover-procedure.md",5610],"72e9af3b":[()=>n.e(903).then(n.bind(n,8161)),"@site/versioned_docs/version-v5.0.0/adrs/adr-009-soft-opt-out.md",8161],"7380b9fa":[()=>n.e(1877).then(n.bind(n,6263)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-003-equivocation-gov-proposal.md",6263],"758625d4":[()=>n.e(321).then(n.bind(n,5477)),"@site/docs/validators/withdraw_rewards.md",5477],"75f9ba63":[()=>n.e(5296).then(n.bind(n,2372)),"@site/versioned_docs/version-v4.2.0-docs/validators/partial-set-security-for-validators.md",2372],"7616f23a":[()=>n.e(2247).then(n.bind(n,1422)),"@site/docs/introduction/overview.md",1422],"775e2592":[()=>n.e(7375).then(n.bind(n,6180)),"@site/docs/adrs/adr-008-throttle-retries.md",6180],"7aa430a8":[()=>n.e(7506).then(n.bind(n,6525)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-007-pause-unbonding-on-eqv-prop.md",6525],"829e00bf":[()=>n.e(8718).then(n.bind(n,1118)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-004-denom-dos-fixes.md",1118],"83f6d28d":[()=>n.e(7534).then(n.bind(n,7915)),"@site/versioned_docs/version-v5.0.0/validators/joining-stride.md",7915],"852eba87":[()=>n.e(2473).then(n.bind(n,8939)),"@site/versioned_docs/version-v4.2.0-docs/introduction/params.md",8939],"867425db":[()=>n.e(8477).then(n.bind(n,5024)),"@site/versioned_docs/version-v4.2.0-docs/frequently-asked-questions.md",5024],"8a86a05c":[()=>n.e(5938).then(n.bind(n,8380)),"@site/versioned_docs/version-v5.0.0/consumer-development/onboarding.md",8380],"8d3b6fe8":[()=>n.e(1163).then(n.bind(n,6216)),"@site/versioned_docs/version-v4.2.0-docs/consumer-development/consumer-chain-governance.md",6216],"903c2771":[()=>n.e(6054).then(n.bind(n,461)),"@site/docs/adrs/adr-009-soft-opt-out.md",461],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"94b74966":[()=>n.e(6673).then(n.bind(n,2546)),"@site/versioned_docs/version-v4.2.0-docs/consumer-development/changeover-procedure.md",2546],"95875ea0":[()=>n.e(3813).then(n.bind(n,2180)),"@site/docs/consumer-development/onboarding.md",2180],"97662a95":[()=>n.e(3859).then(n.bind(n,9541)),"@site/versioned_docs/version-v4.2.0-docs/validators/withdraw_rewards.md",9541],98891868:[()=>n.e(4964).then(n.bind(n,2177)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-001-key-assignment.md",2177],99394557:[()=>n.e(9897).then(n.bind(n,3347)),"@site/versioned_docs/version-v4.2.0-docs/index.mdx",3347],"99c91eb8":[()=>n.e(5112).then(n.bind(n,9697)),"@site/versioned_docs/version-v5.0.0/validators/joining-testnet.md",9697],"9b334c7f":[()=>n.e(5118).then(n.bind(n,9651)),"@site/versioned_docs/version-v5.0.0/consumer-development/offboarding.md",9651],"9be59c75":[()=>n.e(6420).then(n.bind(n,4408)),"@site/docs/features/power-shaping.md",4408],"9c202c81":[()=>n.e(6625).then(n.bind(n,5626)),"@site/versioned_docs/version-v5.0.0/features/reward-distribution.md",5626],"9fa21ee5":[()=>n.e(3500).then(n.bind(n,7809)),"@site/versioned_docs/version-v5.0.0/validators/changeover-procedure.md",7809],a088363e:[()=>n.e(6530).then(n.bind(n,6682)),"@site/versioned_docs/version-v4.2.0-docs/features/proposals.md",6682],a09d3327:[()=>n.e(8270).then(n.bind(n,3696)),"@site/docs/adrs/adr-014-epochs.md",3696],a2707102:[()=>n.e(457).then(n.bind(n,5077)),"@site/docs/adrs/intro.md",5077],a6888f58:[()=>n.e(7487).then(n.bind(n,4753)),"@site/versioned_docs/version-v5.0.0/adrs/adr-001-key-assignment.md",4753],a7bd4aaa:[()=>n.e(8518).then(n.bind(n,8564)),"@theme/DocVersionRoot",8564],a8cc50aa:[()=>n.e(787).then(n.bind(n,2973)),"@site/versioned_docs/version-v5.0.0/adrs/adr-002-throttle.md",2973],a94703ab:[()=>Promise.all([n.e(532),n.e(4368)]).then(n.bind(n,2674)),"@theme/DocRoot",2674],a95292b9:[()=>n.e(5474).then(n.bind(n,3623)),"@site/versioned_docs/version-v4.2.0-docs/consumer-development/app-integration.md",3623],aa5e9d52:[()=>n.e(4244).then(n.bind(n,9950)),"@site/versioned_docs/version-v5.0.0/adrs/adr-010-standalone-changeover.md",9950],ab367a53:[()=>n.e(3784).then(n.t.bind(n,5003,19)),"~docs/default/version-v-4-2-0-docs-metadata-prop-633.json",5003],ac4ec955:[()=>n.e(3297).then(n.bind(n,6114)),"@site/docs/adrs/adr-004-denom-dos-fixes.md",6114],ae015673:[()=>n.e(2108).then(n.bind(n,2165)),"@site/versioned_docs/version-v4.2.0-docs/validators/joining-stride.md",2165],ae63551b:[()=>n.e(5056).then(n.bind(n,6873)),"@site/docs/validators/joining-stride.md",6873],af3e09f2:[()=>n.e(4440).then(n.bind(n,8501)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-012-separate-releasing.md",8501],b22483fb:[()=>n.e(4533).then(n.bind(n,4875)),"@site/versioned_docs/version-v4.2.0-docs/introduction/technical-specification.md",4875],b2a29569:[()=>n.e(8864).then(n.bind(n,3567)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-013-equivocation-slashing.md",3567],b8d345cd:[()=>n.e(4341).then(n.bind(n,186)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-011-improving-test-confidence.md",186],b8e16dc5:[()=>n.e(6705).then(n.bind(n,1528)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-010-standalone-changeover.md",1528],b93225b7:[()=>n.e(7144).then(n.bind(n,8304)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-015-partial-set-security.md",8304],bbea31d2:[()=>n.e(109).then(n.bind(n,662)),"@site/docs/adrs/adr-002-throttle.md",662],bc8b8418:[()=>n.e(4704).then(n.bind(n,1824)),"@site/docs/introduction/terminology.md",1824],bdf2101f:[()=>n.e(7943).then(n.bind(n,3644)),"@site/versioned_docs/version-v5.0.0/features/proposals.md",3644],bfc97f30:[()=>n.e(9253).then(n.bind(n,3473)),"@site/docs/features/partial-set-security.md",3473],c1444bce:[()=>n.e(5776).then(n.bind(n,7258)),"@site/versioned_docs/version-v5.0.0/adrs/adr-015-partial-set-security.md",7258],c2cfb320:[()=>n.e(1429).then(n.bind(n,6639)),"@site/docs/validators/changeover-procedure.md",6639],c3827980:[()=>n.e(5032).then(n.bind(n,5082)),"@site/versioned_docs/version-v5.0.0/consumer-development/consumer-chain-governance.md",5082],c551d695:[()=>n.e(4635).then(n.bind(n,5414)),"@site/versioned_docs/version-v4.2.0-docs/features/key-assignment.md",5414],caea946b:[()=>n.e(3713).then(n.bind(n,5483)),"@site/versioned_docs/version-v5.0.0/adrs/adr-004-denom-dos-fixes.md",5483],cf411473:[()=>n.e(3153).then(n.bind(n,511)),"@site/docs/introduction/technical-specification.md",511],d0088cb9:[()=>n.e(709).then(n.bind(n,7015)),"@site/versioned_docs/version-v5.0.0/adrs/adr-013-equivocation-slashing.md",7015],d0d0ba0d:[()=>n.e(8772).then(n.bind(n,9133)),"@site/docs/adrs/adr-010-standalone-changeover.md",9133],d0d80f5c:[()=>n.e(9982).then(n.bind(n,2543)),"@site/versioned_docs/version-v5.0.0/features/key-assignment.md",2543],d1daeca6:[()=>n.e(3845).then(n.bind(n,6142)),"@site/docs/features/proposals.md",6142],d21f9ede:[()=>n.e(4932).then(n.bind(n,4330)),"@site/docs/adrs/adr-012-separate-releasing.md",4330],d2e13769:[()=>n.e(8382).then(n.bind(n,3396)),"@site/versioned_docs/version-v5.0.0/adrs/adr-007-pause-unbonding-on-eqv-prop.md",3396],d784d738:[()=>n.e(7333).then(n.bind(n,5093)),"@site/docs/consumer-development/app-integration.md",5093],da448d6e:[()=>n.e(4744).then(n.bind(n,1974)),"@site/versioned_docs/version-v5.0.0/adrs/adr-003-equivocation-gov-proposal.md",1974],dc9efaba:[()=>n.e(1324).then(n.bind(n,38)),"@site/docs/consumer-development/offboarding.md",38],ded36896:[()=>n.e(7429).then(n.bind(n,2030)),"@site/docs/adrs/adr-007-pause-unbonding-on-eqv-prop.md",2030],ded5fac2:[()=>n.e(2383).then(n.bind(n,4249)),"@site/versioned_docs/version-v4.2.0-docs/features/partial-set-security.md",4249],e005c37e:[()=>n.e(2883).then(n.bind(n,5837)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-005-cryptographic-equivocation-verification.md",5837],e0ad375d:[()=>n.e(1840).then(n.bind(n,3978)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-009-soft-opt-out.md",3978],e2ddbbfd:[()=>n.e(8892).then(n.bind(n,2005)),"@site/docs/adrs/adr-017-allowing-inactive-validators.md",2005],e50733a4:[()=>n.e(1937).then(n.bind(n,1370)),"@site/versioned_docs/version-v4.2.0-docs/features/slashing.md",1370],e5b5a87b:[()=>n.e(5313).then(n.bind(n,6407)),"@site/versioned_docs/version-v4.2.0-docs/consumer-development/onboarding.md",6407],e69e9c61:[()=>n.e(6882).then(n.bind(n,2489)),"@site/docs/adrs/adr-016-securityaggregation.md",2489],ea42cb80:[()=>n.e(4117).then(n.bind(n,5956)),"@site/versioned_docs/version-v4.2.0-docs/adrs/intro.md",5956],ed5b9256:[()=>n.e(8081).then(n.bind(n,8297)),"@site/versioned_docs/version-v5.0.0/consumer-development/app-integration.md",8297],f0745980:[()=>n.e(7143).then(n.bind(n,7134)),"@site/versioned_docs/version-v5.0.0/introduction/params.md",7134],f5589540:[()=>n.e(6499).then(n.bind(n,5573)),"@site/docs/consumer-development/consumer-chain-governance.md",5573],f6addb2b:[()=>n.e(35).then(n.bind(n,279)),"@site/docs/validators/overview.md",279],f8a7cbf6:[()=>n.e(2527).then(n.bind(n,4097)),"@site/versioned_docs/version-v5.0.0/validators/withdraw_rewards.md",4097],fc26cd25:[()=>n.e(9198).then(n.bind(n,6801)),"@site/versioned_docs/version-v4.2.0-docs/adrs/adr-template.md",6801],ff0782b1:[()=>n.e(7540).then(n.t.bind(n,3769,19)),"/home/runner/work/interchain-security/interchain-security/docs/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],ff9311cc:[()=>n.e(5051).then(n.bind(n,151)),"@site/versioned_docs/version-v5.0.0/adrs/adr-014-epochs.md",151]};var s=n(5893);function l(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,s.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,s.jsx)("p",{children:String(t)}),(0,s.jsx)("div",{children:(0,s.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,s.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,s.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,s.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,s.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var c=n(9670),u=n(226);function d(e,t){if("*"===e)return a()({loading:l,loader:()=>n.e(1772).then(n.bind(n,1772)),modules:["@theme/NotFound"],webpack:()=>[1772],render(e,t){const n=e.default;return(0,s.jsx)(u.z,{value:{plugin:{name:"native",id:"default"}},children:(0,s.jsx)(n,{...t})})}});const r=i[`${e}-${t}`],d={},p=[],f=[],h=(0,c.Z)(r);return Object.entries(h).forEach((e=>{let[t,n]=e;const r=o[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),a().Map({loading:l,loader:d,modules:p,webpack:()=>f,render(t,n){const a=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const i=r.default;if(!i)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof i&&"function"!=typeof i||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{i[e]=r[e]}));let o=a;const s=n.split(".");s.slice(0,-1).forEach((e=>{o=o[e]})),o[s[s.length-1]]=i}));const i=a.__comp;delete a.__comp;const o=a.__context;return delete a.__context,(0,s.jsx)(u.z,{value:o,children:(0,s.jsx)(i,{...a,...n})})}})}const p=[{path:"/interchain-security/",component:d("/interchain-security/","a71"),routes:[{path:"/interchain-security/v4.2.0",component:d("/interchain-security/v4.2.0","03e"),routes:[{path:"/interchain-security/v4.2.0",component:d("/interchain-security/v4.2.0","c06"),routes:[{path:"/interchain-security/v4.2.0",component:d("/interchain-security/v4.2.0","c8a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-001-key-assignment",component:d("/interchain-security/v4.2.0/adrs/adr-001-key-assignment","c79"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-002-throttle",component:d("/interchain-security/v4.2.0/adrs/adr-002-throttle","ec7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-003-equivocation-gov-proposal",component:d("/interchain-security/v4.2.0/adrs/adr-003-equivocation-gov-proposal","a0f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-004-denom-dos-fixes",component:d("/interchain-security/v4.2.0/adrs/adr-004-denom-dos-fixes","ba0"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification",component:d("/interchain-security/v4.2.0/adrs/adr-005-cryptographic-equivocation-verification","74f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-007-pause-unbonding-on-eqv-prop",component:d("/interchain-security/v4.2.0/adrs/adr-007-pause-unbonding-on-eqv-prop","83c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-008-throttle-retries",component:d("/interchain-security/v4.2.0/adrs/adr-008-throttle-retries","e78"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-009-soft-opt-out",component:d("/interchain-security/v4.2.0/adrs/adr-009-soft-opt-out","24f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-010-standalone-changeover",component:d("/interchain-security/v4.2.0/adrs/adr-010-standalone-changeover","854"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-011-improving-test-confidence",component:d("/interchain-security/v4.2.0/adrs/adr-011-improving-test-confidence","5cf"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-012-separate-releasing",component:d("/interchain-security/v4.2.0/adrs/adr-012-separate-releasing","448"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing",component:d("/interchain-security/v4.2.0/adrs/adr-013-equivocation-slashing","0de"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-014-epochs",component:d("/interchain-security/v4.2.0/adrs/adr-014-epochs","1d2"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-015-partial-set-security",component:d("/interchain-security/v4.2.0/adrs/adr-015-partial-set-security","0f9"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/adr-template",component:d("/interchain-security/v4.2.0/adrs/adr-template","83a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/adrs/intro",component:d("/interchain-security/v4.2.0/adrs/intro","cf8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/consumer-development/app-integration",component:d("/interchain-security/v4.2.0/consumer-development/app-integration","3ff"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/consumer-development/changeover-procedure",component:d("/interchain-security/v4.2.0/consumer-development/changeover-procedure","05c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/consumer-development/consumer-chain-governance",component:d("/interchain-security/v4.2.0/consumer-development/consumer-chain-governance","04a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/consumer-development/consumer-genesis-transformation",component:d("/interchain-security/v4.2.0/consumer-development/consumer-genesis-transformation","70d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/consumer-development/offboarding",component:d("/interchain-security/v4.2.0/consumer-development/offboarding","5bb"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/consumer-development/onboarding",component:d("/interchain-security/v4.2.0/consumer-development/onboarding","9f8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/faq",component:d("/interchain-security/v4.2.0/faq","45b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/features/key-assignment",component:d("/interchain-security/v4.2.0/features/key-assignment","42d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/features/partial-set-security",component:d("/interchain-security/v4.2.0/features/partial-set-security","be3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/features/power-shaping",component:d("/interchain-security/v4.2.0/features/power-shaping","71f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/features/proposals",component:d("/interchain-security/v4.2.0/features/proposals","3b6"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/features/reward-distribution",component:d("/interchain-security/v4.2.0/features/reward-distribution","f4c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/features/slashing",component:d("/interchain-security/v4.2.0/features/slashing","ad1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/introduction/overview",component:d("/interchain-security/v4.2.0/introduction/overview","348"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/introduction/params",component:d("/interchain-security/v4.2.0/introduction/params","432"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/introduction/technical-specification",component:d("/interchain-security/v4.2.0/introduction/technical-specification","77c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/introduction/terminology",component:d("/interchain-security/v4.2.0/introduction/terminology","de3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/validators/changeover-procedure",component:d("/interchain-security/v4.2.0/validators/changeover-procedure","e1e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/validators/joining-neutron",component:d("/interchain-security/v4.2.0/validators/joining-neutron","402"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/validators/joining-stride",component:d("/interchain-security/v4.2.0/validators/joining-stride","63b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/validators/joining-testnet",component:d("/interchain-security/v4.2.0/validators/joining-testnet","476"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/validators/overview",component:d("/interchain-security/v4.2.0/validators/overview","689"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/validators/partial-set-security-for-validators",component:d("/interchain-security/v4.2.0/validators/partial-set-security-for-validators","1d8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v4.2.0/validators/withdraw_rewards",component:d("/interchain-security/v4.2.0/validators/withdraw_rewards","cbb"),exact:!0,sidebar:"tutorialSidebar"}]}]},{path:"/interchain-security/v5.0.0",component:d("/interchain-security/v5.0.0","49c"),routes:[{path:"/interchain-security/v5.0.0",component:d("/interchain-security/v5.0.0","8b2"),routes:[{path:"/interchain-security/v5.0.0",component:d("/interchain-security/v5.0.0","77d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-001-key-assignment",component:d("/interchain-security/v5.0.0/adrs/adr-001-key-assignment","2b0"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-002-throttle",component:d("/interchain-security/v5.0.0/adrs/adr-002-throttle","f23"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-003-equivocation-gov-proposal",component:d("/interchain-security/v5.0.0/adrs/adr-003-equivocation-gov-proposal","32c"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-004-denom-dos-fixes",component:d("/interchain-security/v5.0.0/adrs/adr-004-denom-dos-fixes","329"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification",component:d("/interchain-security/v5.0.0/adrs/adr-005-cryptographic-equivocation-verification","284"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-007-pause-unbonding-on-eqv-prop",component:d("/interchain-security/v5.0.0/adrs/adr-007-pause-unbonding-on-eqv-prop","652"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-008-throttle-retries",component:d("/interchain-security/v5.0.0/adrs/adr-008-throttle-retries","212"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-009-soft-opt-out",component:d("/interchain-security/v5.0.0/adrs/adr-009-soft-opt-out","d57"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-010-standalone-changeover",component:d("/interchain-security/v5.0.0/adrs/adr-010-standalone-changeover","542"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-011-improving-test-confidence",component:d("/interchain-security/v5.0.0/adrs/adr-011-improving-test-confidence","9a5"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-012-separate-releasing",component:d("/interchain-security/v5.0.0/adrs/adr-012-separate-releasing","be6"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing",component:d("/interchain-security/v5.0.0/adrs/adr-013-equivocation-slashing","2b3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-014-epochs",component:d("/interchain-security/v5.0.0/adrs/adr-014-epochs","d93"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-015-partial-set-security",component:d("/interchain-security/v5.0.0/adrs/adr-015-partial-set-security","641"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/adr-template",component:d("/interchain-security/v5.0.0/adrs/adr-template","f5d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/adrs/intro",component:d("/interchain-security/v5.0.0/adrs/intro","374"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/consumer-development/app-integration",component:d("/interchain-security/v5.0.0/consumer-development/app-integration","117"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/consumer-development/changeover-procedure",component:d("/interchain-security/v5.0.0/consumer-development/changeover-procedure","afb"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/consumer-development/consumer-chain-governance",component:d("/interchain-security/v5.0.0/consumer-development/consumer-chain-governance","4f4"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/consumer-development/consumer-genesis-transformation",component:d("/interchain-security/v5.0.0/consumer-development/consumer-genesis-transformation","a7a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/consumer-development/offboarding",component:d("/interchain-security/v5.0.0/consumer-development/offboarding","f26"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/consumer-development/onboarding",component:d("/interchain-security/v5.0.0/consumer-development/onboarding","834"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/faq",component:d("/interchain-security/v5.0.0/faq","8d9"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/features/key-assignment",component:d("/interchain-security/v5.0.0/features/key-assignment","cf8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/features/proposals",component:d("/interchain-security/v5.0.0/features/proposals","873"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/features/reward-distribution",component:d("/interchain-security/v5.0.0/features/reward-distribution","66f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/features/slashing",component:d("/interchain-security/v5.0.0/features/slashing","ed3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/introduction/overview",component:d("/interchain-security/v5.0.0/introduction/overview","caf"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/introduction/params",component:d("/interchain-security/v5.0.0/introduction/params","ace"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/introduction/technical-specification",component:d("/interchain-security/v5.0.0/introduction/technical-specification","0bb"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/introduction/terminology",component:d("/interchain-security/v5.0.0/introduction/terminology","b9d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/upgrading/migrate_v4_v5",component:d("/interchain-security/v5.0.0/upgrading/migrate_v4_v5","197"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/validators/changeover-procedure",component:d("/interchain-security/v5.0.0/validators/changeover-procedure","3fc"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/validators/joining-neutron",component:d("/interchain-security/v5.0.0/validators/joining-neutron","668"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/validators/joining-stride",component:d("/interchain-security/v5.0.0/validators/joining-stride","6dd"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/validators/joining-testnet",component:d("/interchain-security/v5.0.0/validators/joining-testnet","e66"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/validators/overview",component:d("/interchain-security/v5.0.0/validators/overview","943"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/v5.0.0/validators/withdraw_rewards",component:d("/interchain-security/v5.0.0/validators/withdraw_rewards","f93"),exact:!0,sidebar:"tutorialSidebar"}]}]},{path:"/interchain-security/",component:d("/interchain-security/","e1b"),routes:[{path:"/interchain-security/",component:d("/interchain-security/","255"),routes:[{path:"/interchain-security/adrs/adr-001-key-assignment",component:d("/interchain-security/adrs/adr-001-key-assignment","b01"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-002-throttle",component:d("/interchain-security/adrs/adr-002-throttle","049"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-003-equivocation-gov-proposal",component:d("/interchain-security/adrs/adr-003-equivocation-gov-proposal","d6f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-004-denom-dos-fixes",component:d("/interchain-security/adrs/adr-004-denom-dos-fixes","9f0"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-005-cryptographic-equivocation-verification",component:d("/interchain-security/adrs/adr-005-cryptographic-equivocation-verification","97a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-007-pause-unbonding-on-eqv-prop",component:d("/interchain-security/adrs/adr-007-pause-unbonding-on-eqv-prop","309"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-008-throttle-retries",component:d("/interchain-security/adrs/adr-008-throttle-retries","cde"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-009-soft-opt-out",component:d("/interchain-security/adrs/adr-009-soft-opt-out","126"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-010-standalone-changeover",component:d("/interchain-security/adrs/adr-010-standalone-changeover","8ee"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-011-improving-test-confidence",component:d("/interchain-security/adrs/adr-011-improving-test-confidence","6de"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-012-separate-releasing",component:d("/interchain-security/adrs/adr-012-separate-releasing","711"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-013-equivocation-slashing",component:d("/interchain-security/adrs/adr-013-equivocation-slashing","f62"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-014-epochs",component:d("/interchain-security/adrs/adr-014-epochs","4bf"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-015-partial-set-security",component:d("/interchain-security/adrs/adr-015-partial-set-security","638"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-016-securityaggregation",component:d("/interchain-security/adrs/adr-016-securityaggregation","5e9"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/adr-017-allowing-inactive-validators",component:d("/interchain-security/adrs/adr-017-allowing-inactive-validators","0eb"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/adrs/intro",component:d("/interchain-security/adrs/intro","130"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/consumer-development/app-integration",component:d("/interchain-security/consumer-development/app-integration","634"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/consumer-development/changeover-procedure",component:d("/interchain-security/consumer-development/changeover-procedure","39d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/consumer-development/consumer-chain-governance",component:d("/interchain-security/consumer-development/consumer-chain-governance","f51"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/consumer-development/consumer-genesis-transformation",component:d("/interchain-security/consumer-development/consumer-genesis-transformation","491"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/consumer-development/offboarding",component:d("/interchain-security/consumer-development/offboarding","b9a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/consumer-development/onboarding",component:d("/interchain-security/consumer-development/onboarding","81f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/faq",component:d("/interchain-security/faq","e46"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/features/democracy-modules",component:d("/interchain-security/features/democracy-modules","0d1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/features/key-assignment",component:d("/interchain-security/features/key-assignment","6a8"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/features/partial-set-security",component:d("/interchain-security/features/partial-set-security","15b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/features/power-shaping",component:d("/interchain-security/features/power-shaping","157"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/features/proposals",component:d("/interchain-security/features/proposals","85e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/features/reward-distribution",component:d("/interchain-security/features/reward-distribution","133"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/features/slashing",component:d("/interchain-security/features/slashing","e4f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/introduction/overview",component:d("/interchain-security/introduction/overview","287"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/introduction/params",component:d("/interchain-security/introduction/params","aae"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/introduction/technical-specification",component:d("/interchain-security/introduction/technical-specification","e7d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/introduction/terminology",component:d("/interchain-security/introduction/terminology","11e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/upgrading/migrate_v4_v5",component:d("/interchain-security/upgrading/migrate_v4_v5","578"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/validators/changeover-procedure",component:d("/interchain-security/validators/changeover-procedure","e7d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/validators/joining-neutron",component:d("/interchain-security/validators/joining-neutron","3d1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/validators/joining-stride",component:d("/interchain-security/validators/joining-stride","b1f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/validators/joining-testnet",component:d("/interchain-security/validators/joining-testnet","82d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/validators/overview",component:d("/interchain-security/validators/overview","ccb"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/validators/partial-set-security-for-validators",component:d("/interchain-security/validators/partial-set-security-for-validators","a1e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/validators/withdraw_rewards",component:d("/interchain-security/validators/withdraw_rewards","2b7"),exact:!0,sidebar:"tutorialSidebar"},{path:"/interchain-security/",component:d("/interchain-security/","725"),exact:!0,sidebar:"tutorialSidebar"}]}]}]},{path:"*",component:d("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>i,t:()=>o});var r=n(7294),a=n(5893);const i=r.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{o(!0)}),[]),(0,a.jsx)(i.Provider,{value:n,children:t})}},7221:(e,t,n)=>{"use strict";var r=n(7294),a=n(745),i=n(3727),o=n(405),s=n(412);const l=[n(2497),n(3310),n(8320),n(2295)];var c=n(723),u=n(6550),d=n(8790),p=n(5893);function f(e){let{children:t}=e;return(0,p.jsx)(p.Fragment,{children:t})}var h=n(5742),m=n(2263),g=n(4996),v=n(6668),y=n(1944),b=n(4711),w=n(9727),k=n(3320),x=n(8780),S=n(197);function _(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,m.Z)(),r=(0,b.l)(),a=n[e].htmlLang,i=e=>e.replace("-","_");return(0,p.jsxs)(h.Z,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,p.jsx)("meta",{property:"og:locale",content:i(a)}),Object.values(n).filter((e=>a!==e.htmlLang)).map((e=>(0,p.jsx)("meta",{property:"og:locale:alternate",content:i(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function E(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,m.Z)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,m.Z)(),{pathname:r}=(0,u.TH)();return e+(0,x.applyTrailingSlash)((0,g.Z)(r),{trailingSlash:n,baseUrl:t})}(),a=t?`${n}${t}`:r;return(0,p.jsxs)(h.Z,{children:[(0,p.jsx)("meta",{property:"og:url",content:a}),(0,p.jsx)("link",{rel:"canonical",href:a})]})}function C(){const{i18n:{currentLocale:e}}=(0,m.Z)(),{metadata:t,image:n}=(0,v.L)();return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(h.Z,{children:[(0,p.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,p.jsx)("body",{className:w.h})]}),n&&(0,p.jsx)(y.d,{image:n}),(0,p.jsx)(E,{}),(0,p.jsx)(_,{}),(0,p.jsx)(S.Z,{tag:k.HX,locale:e}),(0,p.jsx)(h.Z,{children:t.map(((e,t)=>(0,p.jsx)("meta",{...e},t)))})]})}const T=new Map;function j(e){if(T.has(e.pathname))return{...e,pathname:T.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return T.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return T.set(e.pathname,t),{...e,pathname:t}}var N=n(8934),L=n(8940),A=n(469);function P(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>a.forEach((e=>e?.()))}const O=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,A.Z)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,a=t.hash===n.hash,i=t.search===n.search;if(r&&a&&!i)return;const{hash:o}=t;if(o){const e=decodeURIComponent(o.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),P("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function R(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class I extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=s.Z.canUseDOM?P("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=P("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),R(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,p.jsx)(O,{previousLocation:this.previousLocation,location:t,children:(0,p.jsx)(u.AW,{location:t,render:()=>e})})}}const F=I,D="__docusaurus-base-url-issue-banner-container",M="__docusaurus-base-url-issue-banner",z="__docusaurus-base-url-issue-banner-suggestion-container";function B(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${D}';\n var bannerHtml = ${JSON.stringify(function(e){return`\n