diff --git a/.changelog/unreleased/api-breaking/provider/2095-proto-message-fix.md b/.changelog/unreleased/api-breaking/provider/2095-proto-message-fix.md index bb41e17a3c..2fa746a166 100644 --- a/.changelog/unreleased/api-breaking/provider/2095-proto-message-fix.md +++ b/.changelog/unreleased/api-breaking/provider/2095-proto-message-fix.md @@ -1,2 +1,2 @@ -- Fix incorrect message defitions in the proto files of the provider module +- Fix incorrect message definitions in the proto files of the provider module ([\#2095](https://github.com/cosmos/interchain-security/pull/2095)) \ No newline at end of file diff --git a/.changelog/unreleased/api-breaking/provider/2098-vscmatured-removal.md b/.changelog/unreleased/api-breaking/provider/2098-vscmatured-removal.md new file mode 100644 index 0000000000..b5bb3ff5cc --- /dev/null +++ b/.changelog/unreleased/api-breaking/provider/2098-vscmatured-removal.md @@ -0,0 +1,7 @@ +- The removal of `VSCMaturedPackets` entail several API breaking changes. + ([\#2098](https://github.com/cosmos/interchain-security/pull/2098)) + + - Remove the `oldest_unconfirmed_vsc` query -- used to get + the send timestamp of the oldest unconfirmed VSCPacket. + - Deprecate the `init_timeout_period` and `vsc_timeout_period` parameters + from the provider module. diff --git a/.changelog/unreleased/dependencies/2113-bump-ibc.md b/.changelog/unreleased/dependencies/2113-bump-ibc.md new file mode 100644 index 0000000000..05104f8c46 --- /dev/null +++ b/.changelog/unreleased/dependencies/2113-bump-ibc.md @@ -0,0 +1,3 @@ +- Bump [ibc-go](https://github.com/cosmos/ibc-go) to + [v8.4.0](https://github.com/cosmos/ibc-go/releases/tag/v8.4.0). + ([\#2113](https://github.com/cosmos/interchain-security/pull/2113)) \ No newline at end of file diff --git a/.changelog/unreleased/features/provider/2098-vscmatured-removal.md b/.changelog/unreleased/features/provider/2098-vscmatured-removal.md new file mode 100644 index 0000000000..aa370d81d2 --- /dev/null +++ b/.changelog/unreleased/features/provider/2098-vscmatured-removal.md @@ -0,0 +1,8 @@ +- Remove `VSCMaturedPackets` from the provider module, which entails the following + changes to the provider. + ([\#2098](https://github.com/cosmos/interchain-security/pull/2098)) + + - Remove unbonding operations pausing. + - Remove the CCV channel initialization timeout. + - Remove `VSCPackets` timeout. + - Redesign key assignment pruning -- prune old consumer keys after the unbonding period elapses. diff --git a/.changelog/unreleased/features/provider/2106-query-blocks-until-next-epoch.md b/.changelog/unreleased/features/provider/2106-query-blocks-until-next-epoch.md new file mode 100644 index 0000000000..070fa487e9 --- /dev/null +++ b/.changelog/unreleased/features/provider/2106-query-blocks-until-next-epoch.md @@ -0,0 +1,2 @@ +- Add a query to get the blocks until the next epoch begins + ([\#2106](https://github.com/cosmos/interchain-security/pull/2106)) \ No newline at end of file diff --git a/.changelog/unreleased/state-breaking/provider/2095-proto-message-fix.md b/.changelog/unreleased/state-breaking/provider/2095-proto-message-fix.md index bb41e17a3c..2fa746a166 100644 --- a/.changelog/unreleased/state-breaking/provider/2095-proto-message-fix.md +++ b/.changelog/unreleased/state-breaking/provider/2095-proto-message-fix.md @@ -1,2 +1,2 @@ -- Fix incorrect message defitions in the proto files of the provider module +- Fix incorrect message definitions in the proto files of the provider module ([\#2095](https://github.com/cosmos/interchain-security/pull/2095)) \ No newline at end of file diff --git a/.changelog/unreleased/state-breaking/provider/2098-vscmatured-removal.md b/.changelog/unreleased/state-breaking/provider/2098-vscmatured-removal.md new file mode 100644 index 0000000000..bc2dc743c2 --- /dev/null +++ b/.changelog/unreleased/state-breaking/provider/2098-vscmatured-removal.md @@ -0,0 +1,2 @@ +- Remove `VSCMaturedPackets` from the provider module. + ([\#2098](https://github.com/cosmos/interchain-security/pull/2098)) diff --git a/.coderabbit.yml b/.coderabbit.yml index 7dfe09c9ba..665c551b1c 100644 --- a/.coderabbit.yml +++ b/.coderabbit.yml @@ -21,9 +21,6 @@ reviews: - path: "**/*_test.go" instructions: | "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request. Only report issues that you have a high degree of confidence in." - - path: "**/*.md" - instructions: | - "Assess the documentation for misspellings, grammatical errors, missing documentation and correctness. Please DO NOT report any missing or superfluous newlines, in particular at the end or beginning of files. Only report issues that you have a high degree of confidence in." - path: ".changelog/*" instructions: | "Assess the changes in the changelog for correctness and completeness, particularly flagging missing changes. Only report issues that you have a high degree of confidence in." diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 8aea8d5a38..9fdf9aa5b0 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -50,7 +50,7 @@ jobs: # multi-platform images and export cache # https://github.com/docker/setup-buildx-action - name: Set up Docker Buildx - uses: docker/setup-buildx-action@aa33708b10e362ff993539393ff100fa93ed6a27 # v3.5.0 + uses: docker/setup-buildx-action@3d68780484996aa9d417bb9016193885cdf1f299 # v3.6.0 # Login against a Docker registry except on PR diff --git a/.github/workflows/proto-registry.yml b/.github/workflows/proto-registry.yml index f1f52b55c7..6718f0e94c 100644 --- a/.github/workflows/proto-registry.yml +++ b/.github/workflows/proto-registry.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: bufbuild/buf-setup-action@v1.34.0 + - uses: bufbuild/buf-setup-action@v1.35.1 - uses: bufbuild/buf-push-action@v1 with: input: "proto" diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml index e9f040fc44..8478816fc3 100644 --- a/.github/workflows/proto.yml +++ b/.github/workflows/proto.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: bufbuild/buf-setup-action@v1.34.0 + - uses: bufbuild/buf-setup-action@v1.35.1 - uses: bufbuild/buf-breaking-action@v1 with: input: "proto" diff --git a/app/consumer/app.go b/app/consumer/app.go index 8eb64bf5c6..28e0e642e5 100644 --- a/app/consumer/app.go +++ b/app/consumer/app.go @@ -490,7 +490,6 @@ func New( vestingtypes.ModuleName, ibcconsumertypes.ModuleName, ) - app.SetPreBlocker(app.PreBlocker) app.MM.SetOrderEndBlockers( crisistypes.ModuleName, diff --git a/app/provider/app.go b/app/provider/app.go index 7b42d525b5..e6876137b9 100644 --- a/app/provider/app.go +++ b/app/provider/app.go @@ -512,7 +512,11 @@ func New( govtypes.NewMultiGovHooks(app.ProviderKeeper.Hooks()), ) - providerModule := ibcprovider.NewAppModule(&app.ProviderKeeper, app.GetSubspace(providertypes.ModuleName)) + providerModule := ibcprovider.NewAppModule( + &app.ProviderKeeper, + app.GetSubspace(providertypes.ModuleName), + keys[providertypes.StoreKey], + ) app.TransferKeeper = ibctransferkeeper.NewKeeper( appCodec, diff --git a/app/sovereign/app.go b/app/sovereign/app.go index 328fb5e4b9..b5653995b6 100644 --- a/app/sovereign/app.go +++ b/app/sovereign/app.go @@ -116,7 +116,7 @@ import ( const ( AppName = "interchain-security-s" upgradeName = "v07-Theta" // arbitrary name, define your own appropriately named upgrade - AccountAddressPrefix = "cosmos" + AccountAddressPrefix = "consumer" ) var ( @@ -602,6 +602,7 @@ func New( app.SetAnteHandler(anteHandler) app.SetInitChainer(app.InitChainer) + app.SetPreBlocker(app.PreBlocker) app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) diff --git a/cmd/interchain-security-sd/main.go b/cmd/interchain-security-sd/main.go index 99f6b9b371..dbd46acc60 100644 --- a/cmd/interchain-security-sd/main.go +++ b/cmd/interchain-security-sd/main.go @@ -6,11 +6,14 @@ import ( svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" + appparams "github.com/cosmos/interchain-security/v5/app/params" app "github.com/cosmos/interchain-security/v5/app/sovereign" + "github.com/cosmos/interchain-security/v5/cmd/interchain-security-sd/cmd" ) func main() { + appparams.SetAddressPrefixes(app.AccountAddressPrefix) rootCmd := cmd.NewRootCmd() if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil { diff --git a/docs/docs/adrs/adr-017-allowing-inactive-validators.md b/docs/docs/adrs/adr-017-allowing-inactive-validators.md index 45df5df13e..dd4ff1b10a 100644 --- a/docs/docs/adrs/adr-017-allowing-inactive-validators.md +++ b/docs/docs/adrs/adr-017-allowing-inactive-validators.md @@ -10,7 +10,7 @@ title: ICS with Inactive Provider Validators ## Status -Proposed +Accepted ## Context diff --git a/docs/docs/adrs/adr-018-remove-vscmatured.md b/docs/docs/adrs/adr-018-remove-vscmatured.md new file mode 100644 index 0000000000..f7cdd55492 --- /dev/null +++ b/docs/docs/adrs/adr-018-remove-vscmatured.md @@ -0,0 +1,188 @@ +--- +sidebar_position: 19 +title: Remove VSCMatured Packets +--- +# ADR 018: Remove VSCMatured Packets + +## Changelog +* 19/06/2024: Create initial draft + +## Status + +Accepted + +## Context + +> The idea of removing VSCMatured packets was first suggested by [Jae Kwon](https://github.com/jaekwon) over a conversation in 2022. +> As a result of that conversation, [an ADR was proposed](https://github.com/cosmos/interchain-security/pull/712) to halt consumer chain if VSC packets are no longer received. +> The ADR was not accepted due to other considerations regarding the safety of consumer chains. +> See [this blog post](https://informal.systems/blog/learning-to-live-with-unbonding-pausing) for more details. + +The consumer module on the consumer chains is a representation of the Hub’s staking module, i.e., it provides an _asynchronous_ view of the voting powers and indirectly of the locked collateral. +The key word here is _asynchronous_, which means that (in theory) there is no bound on the lag between the Hub’s view of stake and the consumer’s view of stake. +The reasons for this asynchrony are relaying delays and chain liveness (e.g., a consumer could be down for a long period of time without affecting the liveness of the staking module on the Hub). + +The current version of ICS uses `VSCMaturedPackets` to create on the consumers a _partially synchronous_ view of the Hub’s staking module. +Partially synchronous means that the lag between the Hub’s view of stake and the consumer’s view of stake is bounded, because consumers that exceed this lag are forcibly removed from the protocol. +Basically, unlocking collateral from the Hub is being delayed until the consumers’ `UnbondingPeriod` elapses. +The reason the view is only partially synchronous is that eventually the collateral is unlocked, i.e., if `VSCMaturedPackets` are not received from a consumer for `VscTimeoutPeriod` (default: 5 weeks), then the consumer is removed from ICS and the collateral is unlocked. +Note that keeping the stake locked “forever” would affect the Hub’s liveness, so it’s not a viable option. + +The issue is that whatever attack is possible with an asynchronous view of the staking module, it is eventually possible with the partially synchronous view as well. +For example, an attacker could wait for `VscTimeoutPeriod` for the collateral to be unlocked and then send invalid headers to third-party chains that are not aware the consumer's collateral is no longer locked on the Hub (i.e., the consumer is no longer part of ICS). + +Moreover, with the introduction of [PSS](./adr-015-partial-set-security.md), a consumer’s validator set could “lie” about its `UnbondingPeriod` elapsing by sending `VSCMaturedPackets` earlier. +This would result in a discrepancy between a light client’s view of the `UnbondingPeriod` and the actual Hub’s `UnbondingPeriod`. + +## Decision + +This ADR proposes the removal of `VSCMaturedPackets`. The reason is twofold. +First, `VSCMaturedPackets` provide a "false" sense of correctness as the attack described above is still possible. +Second, `VSCMaturedPackets` add considerable complexity to the ICS protocol -- an extra message plus the pausing of unbonding operations that can affect the UX. + +To simplify the upgrading process, removing `VSCMaturedPackets` can be done in two releases: + +* (R1) Update the provider to drop `VSCMaturedPackets`. +* (R2) Update the consumer to stop sending `VSCMaturedPackets`. + +As a result, once the provider chain runs R1, the consumers can start upgrading to R2. + +### Provider Changes (R1) + +#### Parameters + +Deprecate the `InitTimeoutPeriod` and `VscTimeoutPeriod` parameters. + +#### State + +Add the following key prefix to the state: + +- `ConsumerAddrsToPruneV2BytePrefix` -- the byte prefix for storing consumer validators addresses that need to be pruned. + These are stored as + ``` + ConsumerAddrsToPruneV2BytePrefix | len(chainID) | chainID | ts -> (consumer_address1, consumer_address2, ...) + ``` + where `ts` is the timestamp at which the consumer validators addresses can be pruned. + +Migrate the consumer validator addresses stored under the `ConsumerAddrsToPruneBytePrefix` to the new prefix `ConsumerAddrsToPruneV2BytePrefix`. +Note that these consumer validators addresses are stored as +``` +ConsumerAddrsToPruneBytePrefix | len(chainID) | chainID | vscID -> (consumer_address1, consumer_address2, ...) +``` +where `vscID` is the ID of the first VSCPacket sent after these consumer validator addresses were changed. +These means that we can use the `VscSendTimestamp`s to compute the timestamps when these consumer validator addresses can be pruned, i.e., +```golang +func MigrateConsumerAddrsToPrune() + iterator := sdk.KVStorePrefixIterator(store, []byte{providertypes.ConsumerAddrsToPruneBytePrefix}) + for ; iterator.Valid(); iterator.Next() { + chainID, vscID, _ := providertypes.ParseChainIdAndUintIdKey(providertypes.ConsumerAddrsToPruneBytePrefix, iterator.Key()) + // use the VscSendTimestamp index to compute the timestamp at which this consumer addresses can be pruned + vscSendTimestampKey := providertypes.ChainIdAndUintIdKey(providertypes.VscSendTimestampBytePrefix, chainID, vscID) + timeBz := store.Get(vscSendTimestampKey) + sentTime, _ := sdk.ParseTimeBytes(timeBz) + pruneTs := sentTime.Add(sk.UnbondingTime(ctx)) + + var addrs providertypes.AddressList + addrs.Unmarshal(iterator.Value()) + + for _, addr := range addrs.Addresses { + consumerAddr := providertypes.NewConsumerConsAddress(addr) + pk.AppendConsumerAddrsToPrune(ctx, chainID, pruneTs, consumerAddr) + } + } +} +``` + +Remove the following key prefixes from the state. Note that these removals require state migration. + +- `MaturedUnbondingOpsByteKey` -- the byte key that stores the list of all unbonding operations ids that have matured from a consumer chain perspective. +- `UnbondingOpBytePrefix` -- the byte prefix that stores a record of all the ids of consumer chains that need to unbond before a given unbonding operation can unbond on this chain. +- `UnbondingOpIndexBytePrefix` -- the byte prefix of the index for looking up which unbonding operations are waiting for a given consumer chain to unbond. +- `InitTimeoutTimestampBytePrefix` -- the byte prefix for storing the init timeout timestamp for a given consumer chainID. +- `VscSendTimestampBytePrefix` -- the byte prefix for storing the list of VSC sending timestamps for a given consumer chainID. +- `ConsumerAddrsToPruneBytePrefix` -- the byte prefix for storing the mapping from VSC IDs to consumer validators addresses that need to be pruned. + +#### State Transitions + +Removing `VSCMaturedPackets` affects three ICS sub-protocols (see [HandleVSCMaturedPacket](https://github.com/cosmos/interchain-security/blob/v4.2.0/x/ccv/provider/keeper/relay.go#L51)): unbonding operations pausing, `VSCPackets` timeout, and key assignment pruning. +The first two are no longer needed, while the third (key assignment pruning) needs to be redesigned to not depend on `VSCMaturedPackets`. + +**Removing unbonding operations pausing:** + +- Make the `AfterUnbondingInitiated` hook a no-op. As a result, unbonding operations are no longer paused. +- Stop calling the `UnbondingCanComplete` method from the staking keeper. This entails, it is no longer necessary to append `MaturedUnbondingOps` and the `completeMaturedUnbondingOps` method can be removed. +- Note, that during the upgrade, all unbonding operations stored under the `UnbondingOpBytePrefix` prefix need to be completed (via the `UnbondingCanComplete` method from the staking keeper). +- Remove the init timeout timestamp logic from the following methods: `CreateConsumerClient`, `SetConsumerChain`, and `EndBlockCCR`. + +**Removing `VSCPackets` timeout:** + +- Stop setting VSC send timestamps when sending `VSCPackets`. +- Stop removing the VSC send timestamps when receiving `VSCMaturedPackets`. +- Remove the logic from `EndBlockCCR` that checks if the first VSC send timestamp in iterator plus `VscTimeoutPeriod` exceeds the current block time. + +**Redesign key assignment pruning.** The reason for keeping "old" consumer addresses is to enable slashing / jailing validators that misbehave on consumer chains, +i.e., the slashing logic uses the `GetProviderAddrFromConsumerAddr` method that accesses the mapping from validator addresses on consumer chains to validator addresses on the provider chain (`ValidatorsByConsumerAddrBytePrefix`). +Thus, "old" consumer addresses are no longer needed after the provider's `UnbondingPeriod` elapses. +This means that once a validator changes its key on a consumer, we can prune the address corresponding to the "old" key after `UnbondingPeriod`. +This requires the following changes: + +- Adapt the `AppendConsumerAddrsToPrune()` method to use the timestamp at which it is safe to prune the consumer validator address (instead of the current `vscID`). +- Add a new method `ConsumeConsumerAddrsToPrune(ts)` that returns the list of consumer addresses that can be pruned at timestamp `ts`. +- Adapt the `PruneKeyAssignments()` method to call `ConsumeConsumerAddrsToPrune(ctx.BlockTime())`. +- Call the `PruneKeyAssignments()` method from every `EndBlock()` instead of calling it from `HandleVSCMaturedPacket()`. + +#### Queries + +Remove the `oldest_unconfirmed_vsc` query. + +### Consumer Changes (R2) + +#### Parameters + +Given that currently relayers use the consumer `UnbondingPeriod` (see `ConsumerParams`), this param cannot be deprecated. +Note that Hermes queries the `UnbondingPeriod` for sanity checks and to set the default trusting period when it is not specified. +As a result, the `UnbondingTime` method from the staking interface will continue to be used to retrieve the consumer's `UnbondingPeriod`. + +#### State + +Remove the following key prefixes from the state: + +- `PacketMaturityTimeBytePrefix` -- the byte prefix that will store maturity time for each received VSC packet + +Note that these removals require state migration. + +#### State Transitions + +To stop the consumer chains from sending `VSCMaturedPackets`, it is sufficient to not store the maturity time of `VSCPacket`s when receiving them, i.e., do not call `SetPacketMaturityTime` from the `OnRecvVSCPacket()` method. +Note that eventually, no additional `VSCMaturedPackets` will be added to the sending queue as `QueueVSCMaturedPackets` iterates over elapsed maturity times. +In addition, to clean up the code, the `QueueVSCMaturedPackets` must be removed. + +#### Messages + +`VSCMaturedPacketData` is deprecated. +Note that this is a wire-breaking change -- older consumer versions will send `VSCMaturedPackets` and older provider versions will expect to receive `VSCMaturedPackets`. + +## Consequences + +### Positive + +- Remove feature that provides a "false" sense of correctness. +- Remove unnecessary complexity, from both ICS and Cosmos SDK. +- Remove one IBC packet and, thus, reduce relaying cost. +- Remove unbonding pausing logic that could affect the UX. + +### Negative + +- Large refactor that might introduce unexpected bugs. +- Consumer chains are no longer removed if the duration between creating a client and creating the CCV channel exceeds `InitTimeoutPeriod`. + This means that if the CCV channel is not created on time, the client expires and the consumer chain can no longer start without a ClientUpdate proposal or re-submitting a `ConsumerAdditionProposal`. + +### Neutral + +- Consumer chains are no longer removed after a `VscTimeoutPeriod` of inactivity. + Note that consumers are still removed if their CCV channel expires, which usually happens after two weeks instead of five weeks (the default value for `VscTimeoutPeriod`). + +## References + +- [PR #712](https://github.com/cosmos/interchain-security/pull/712) -- Proposal to set an expiration date on the consumer chain updated on each VSCPacket received to ensure the chain is up-to-date. +- [Learning to Live with “Unbonding Pausing”](https://informal.systems/blog/learning-to-live-with-unbonding-pausing) blog post. diff --git a/docs/docs/adrs/adr-019-permissionless-ics.md b/docs/docs/adrs/adr-019-permissionless-ics.md new file mode 100644 index 0000000000..59b13659a4 --- /dev/null +++ b/docs/docs/adrs/adr-019-permissionless-ics.md @@ -0,0 +1,348 @@ +--- +sidebar_position: 20 +title: Permissionless ICS +--- +# ADR 019: Permissionless Interchain Security + +## Changelog +* 27th of June, 2024: Initial draft + +## Status + +Accepted + +## Context +Currently, a consumer chain can join _Interchain Security_ (ICS) only through a [governance proposal](../features/proposals.md). +A governance proposal was needed before the introduction of [Partial Set Security](../features/partial-set-security.md) (PSS) +because validators were required to validate a consumer chain. However, after the introduction of PSS, a consumer chain can +be either _Top N_ or _Opt In_. If a chain is an Opt In chain, then no validator is required to validate this chain unless they choose to. +Because of this, we can launch an Opt In consumer chain without going through a governance proposal. + +This ADR presents _Permissionless_ ICS, a way in which an [_Opt In_](adr-015-partial-set-security.md) consumer chain can join +ICS without needing a governance proposal but by simply issuing a transaction. + +## Decision +In Permissionless ICS, launching an Opt In chain is **only** possible through a transaction and not through a [`MsgConsumerAddition`](https://github.com/cosmos/interchain-security/blob/v5.1.0/proto/interchain_security/ccv/provider/v1/tx.proto#L111) +proposal. Naturally, Permissionless ICS does not eliminate governance proposals, as proposals are still necessary for Top N chains. +Because of this, this ADR outlines a solution that also refactors governance proposals (i.e., `MsgConsumerAddition`, `MsgConsumerModification`, and `MsgConsumerRemoval`) +so that Top N and Opt In chains can share as much functionality as possible. +Note, that to make the distinction between governance-proposed versus transaction-launched chains clearer, in Permissionless ICS, +we can only launch, update, or stop Top N chains with governance proposals, and we can only launch, update, or stop Opt In chains with transactions. +Additionally, a Top N chain can transform to an Opt In chain through a gov proposal, but for simplicity, in this first +iteration of Permissionless, an Opt In chain cannot transform to a Top N chain. + +### The Phases of a Consumer Chain + +We first present the notion of an _owner_ of a consumer chain before showing the specific phases of a consumer chain. + +**Owner.** A consumer chain has an _owner_, which is simply an address. Only the owner can interact (i.e., launch, update, or stop) +with the chain. The owner of an Opt In chain is the one who signed the initial transaction to register a consumer chain (more on this later). +Naturally, an Opt In chain can change its owner at any point. The owner of a Top N chain is the account of the governance module. +Therefore, any changes on a Top N chain have to go through governance proposals. + +A consumer chain can reside in four phases: i) _registered_, ii) _initialized_, iii) _launched_, and iv) _stopped_ phase as seen +in the diagram below: +![Phases of a consumer chain](./figures/adr19_phases_of_a_consumer_chain.png) + +**Registered phase.** In the _registered phase_, a consumer chain is assigned a unique identifier that identifies a consumer chain +that can later be used to interact with the specific consumer chain (e.g., when a validator opts in on a chain). +After a chain has been registered, it can later be initialized and then launched. Specifically, Permissionless ICS introduces +a `MsgRegisterConsumer` message that can be used to register **both** Top N and Opt In consumer chains. +In the registered phase, it is not yet known if the consumer chain would end up being a Top N or an Opt In chain and hence +the owner of the consumer chain at this phase is the one that signed the `MsgRegisterConsumer`. +Note that currently, a consumer chain is registered when first proposed through a `MsgConsumerAddition` proposal +message but with Permissionless ICS, the `MsgConsumerAddition` is deprecated and chains have to issue a `MsgRegisterConsumer` message instead. +A consumer chain in the registered phase might not launch, e.g., a later governance proposal might not pass or +the Opt In chain might never be initialized. + +**Initialized phase.** The _initialized phase_ means that the chain has set all the needed parameters to launch but has +not yet launched. To initialize an Opt In chain, the owner of the chain has to issue a `MsgInitializeConsumer` message +and potentially a `MsgUpdateConsumer` if they want to set up specific parameters (e.g., [power-shaping features](https://cosmos.github.io/interchain-security/features/power-shaping)). +Similarly, a Top N chain has to issue the same two messages (i.e, `MsgInitializeConsumer`, `MsgUpdateConsumer`) as part of a +governance proposal and if the governance proposal passes, the consumer chain is considered to be initialized. The moment +a governance proposal is proposed for a Top N chain, the owner changes to be the account of the governance module. +While in the initialized phase, an Opt In chain can choose to change the consumer chain parameters, such as `spawnTime`, etc. +by issuing a new `MsgInitializeConsumer` or `MsgUpdateConsumer` messages. +This is not the case for Top N chains, where a `MsgUpdateConsumer` can only be issued after a consumer +chain [has launched](https://github.com/cosmos/interchain-security/blob/v5.1.0/x/ccv/provider/keeper/legacy_proposal.go#L89). + +**Launched phase.** In the _launched phase_ the consumer chain is running and is consuming a subset of the validator set +of the provider. When the [`spawnTime`](https://github.com/cosmos/interchain-security/blob/v5.1.0/proto/interchain_security/ccv/provider/v1/provider.proto#L57) +passes and [at least one validator has opted in](https://github.com/cosmos/interchain-security/blob/v5.1.0/x/ccv/provider/keeper/proposal.go#L430) +the chain can launch and moves to the launched phase. Note that a Top N chain can launch if and only if the `spawnTime` has passed and +the initialization proposal has successfully passed. While in launched phase, a consumer chain can choose to modify +its parameters through `MsgUpdateConsumer`. Naturally, only the owner of the chain can issue `MsgUpdateConsumer`, thus +for Top N chains, the chain can be updated only through a governance proposal that contains a `MsgUpdateConsumer`. + +**Stopped phase.** Lastly, the owner of a chain can choose to exit ICS by executing a `MsgRemoveConsumer`. +After some period of time (e.g., provider's unbonding period), all state related to the stopped consumer chain can be removed. +We keep track of the state of the consumer chain for some period, so that we are able to punish validators for misbehaviours +that occurred before the consumer chain stopped. + +Note that everything described so far and everything that follows applies to consumer chains that transition from standalone chains as well. + +### From `chainId` to `consumerId` +A hindrance in moving to Permissionless ICS is [chain-id squatting](https://forum.cosmos.network/t/pss-permissionless-vs-premissioned-lite-opt-in-consumer-chains/12984/17). +In a permissionless setting, anyone could issue a transaction to launch a consumer chain with a `chainId` that might already be used by some other consumer chain. This is a problem +because in the current design the majority of stored state for a consumer chain is indexed using the `chainId` as the key (e.g., +see [key used to store client ids](https://github.com/cosmos/interchain-security/blob/v5.1.0/x/ccv/provider/types/keys.go#L245)). +To tackle this problem, in Permissionless ICS, we introduce the `consumerId` that defines a consumer chain and is simply +an increasing counter (i.e., `counter`), thus we can support multiple consumer chains with the same `chainId`. +Another way to understand this is with an analogy between consumer chains and IBC clients: Imagine having multiple IBC clients +that each point to different consumer chains, but all share the exact same `chainId`. It is then up to the user to select the +appropriate client (i.e., `clientId`) based on the actual chain they want to communicate with. Similarly, there can be multiple +consumer chains with the exact same `chainId`, and it is the responsibility of the validators to choose the one they wish +to interact with by providing the right `consumerId`. + +Note that with Permissionless ICS, all interactions on a consumer chain have to use the `consumerId` instead of the `chainId`. +For example, if a validator opts in on a chain using `MsgOptIn`, the validator has to provide the `consumerId`. To also +provide the `consumerId` for Top N consumers chains, we store a mapping between `proposalID` to `consumerId`. This storing +takes place in the [`AfterProposalSubmission`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.8/x/gov/types/hooks.go#L19) hook. +Specifically, for the equivocation evidence, we update the `MsgSubmitConsumerMisbehaviour` and `MsgSubmitConsumerDoubleVoting` messages to include the `consumerId`, +and change [Hermes](https://github.com/informalsystems/hermes) to include `consumerId` in those constructed messages as well. +Hermes can find out the `consumerId` by querying the provider's `clientId` for some consumer chain (i.e., `query ccvconsumer provider-info`) +and then asking the provider chain for the `consumerId` that corresponds to this `clientId`. To do this, we need to store +the `clientId` to `consumerId` association on the provider and introduce a query to retrieve the `clientId` +given the `consumerId`. + +#### State +As a result of using `consumerId`, we have to migrate a substantial chunk of state to re-index it using `consumerId` as the key. +Currently, in ICS we have state that is indexed by a multitude of [keys](https://github.com/cosmos/interchain-security/blob/v5.1.0/x/ccv/provider/types/keys.go#L40). +In the table below, we see the ones that are associated with a `chainId` and how often state under those keys gets updated. +Additionally, for each key, the table shows whose action can lead to the setting or deletion of the state associated with that key. +An action can stem either from: i) a consumer chain (e.g., through a `MsgUpdateConsumer` message, an IBC packet sent over to the provider, etc.), +ii) a provider chain (e.g., at the end of a block some action is taken), or by iii) a validator (e.g., through a `MsgAssignConsumerKey` message) +or a combination of them. + +| Key | Description | Who can set this? | Who can delete this? | How often are `chainId`-associated keys updated? | +|-----------------------------------------|------------------------------------------------------------------------------------------------------------------------------|:--------------------------------:|:--------------------------------:|----------------------------------------------------------------------------------------------------------| +| `ChainToChannelBytePrefix` | Stores the CCV `channelID` for a specific chain | consumer chain | consumer chain | Only once (during set up) | +| `ChannelToChainBytePrefix` | Stores `chainId` for a specific channel | consumer chain | consumer chain | Only once (during set up) | +| `ChainToClientBytePrefix` | Stores the `clientID` for a specific chain | consumer chain | consumer chain | Only once (during set up) | +| `PendingCAPBytePrefix` | Stores pending consumer addition proposals | consumer chain | provider chain | Only once (for successful proposal) | +| `PendingCRPBytePrefix` | Stores pending consumer removal proposals | consumer chain | provider chain | Only once (for successful proposal) | +| `ConsumerGenesisBytePrefix` | Stores the consumer genesis for a specific chain | consumer chain | consumer chain | Only once (during set up) | +| `SlashAcksBytePrefix` | Stores slash acks for a specific consumer chain | consumer chain | provider chain | Every time we receive a Slash packet | +| `PendingVSCsBytePrefix` | Stores `VSCPacket`s for a specific consumer chain | provider chain | provider chain | Every [epoch](https://github.com/cosmos/interchain-security/blob/v5.1.0/docs/docs/adrs/adr-014-epochs.md) | +| `ConsumerValidatorsBytePrefix` | Stores consumer key per validator per consumer chain | validator | consumer chain | Every `MsgAssignConsumerKey` or `MsgOptIn` | +| `ValidatorsByConsumerAddrBytePrefix` | Stores consumer to provider validator address | validator | consumer or provider chain | Every `MsgAssignConsumerKey` or `MsgOptIn` | +| `EquivocationEvidenceMinHeightBytePrefix`| Stores min height for a consumer chain | consumer chain | consumer chain | Only once (during set up) | +| `ProposedConsumerChainByteKey` | Stores `proposalID`s for consumer chains with proposals in the voting period | not applicable for Opt In chains | not applicable for Opt In chains | Created when the proposal is submitted and deleted when the proposal's voting period ends | +| `ConsumerValidatorBytePrefix` | Stores consumer validators for a specific chain | validator | validator or consumer chain | Potentially at every epoch | +| `OptedInBytePrefix` | Stores opted-in validators for a specific chain | validator | validator or consumer chain | Potentially at every block | +| `TopNBytePrefix` | Stores whether a consumer chain is Top N or not | not applicable for Opt In chains | not applicable for Opt In chains | Every parameter update | +| `ValidatorsPowerCapPrefix` | Stores the power cap of a chain | consumer chain | consumer chain | Every parameter update | +| `ValidatorSetCapPrefix` | Stores the set cap of a chain | consumer chain | consumer chain | Every parameter update | +| `AllowlistPrefix` | Stores the allowlist of a chain | consumer chain | consumer chain | Every parameter update | +| `DenylistPrefix` | Stores the denylist of a chain | consumer chain | consumer chain | Every parameter update | +| `ConsumerRewardsAllocationBytePrefix` | Stores the ICS rewards per chain | consumer or provider chain | provider chain | Every IBC transfer packet that sends rewards to the provider | +| `ConsumerCommissionRatePrefix` | Commission rate per chain per validator | validator | consumer chain | Every `MsgSetConsumerCommissionRate` message | +| `MinimumPowerInTopNBytePrefix` | Stores the minimum power needed to opt in for a chain | not applicable for Opt In chains | not applicable for Opt In chains | Every epoch | +| `ConsumerAddrsToPruneV2BytePrefix` | Stores consumer addresses to be pruned (as part of `VSCMaturedPacket`s deprecation) | validator or provider chain | provider chain | Every `MsgAssignConsumerKey` or `MsgOptIn` and later during actual pruning | + +Everything stored under one of the above keys is associated with a `chainId` and has to be migrated to new state under a `consumerId`. + +### New Messages +In this section, we describe the new messages (i.e., `MsgRegisterConsumer`, `MsgInitializeConsumer`, `MsgUpdateConsumer` and `MsgRemoveConsumer`) +that Permissionless ICS introduces. +Then, we describe how to utilize these messages with our existing codebase. + +#### Register a Consumer Chain +We first have to register a chain before launching it, irrespectively of whether it is Top N or Opt In. +This is done through the following message: +```protobuf +message MsgRegisterConsumer { + // the registration record that contains information for the registered chain + ConsumerRegistrationRecord registration_record; +} +``` + +where `ConsumerRegistrationRecord` contains information about the to-be-launched consumer chain before it launches. + +```protobuf +message ConsumerRegistrationRecord { + // the title of the chain to-be-launched + string title; + // the description of the chain to-be-launched + string description; + // the chain id of the new consumer chain + string chain_id; +} +``` + +This response of this message contains a single `string`, that is the `consumerId` for this registered consumer chain and sets +a consumer chain in its registered phase. With the returned `consumerId`, validators can already opt in on the consumer +chain to show their potential interest on the chain. + +The owner of the consumer chain is the one that signed the `MsgRegisterConsumer` message. + +To prevent an attacker spamming the system by creating bogus consumer chains, we set a fixed cost for sending a `MsgRegisterConsumer` (configurable via a parameter). + +#### Initialize a Consumer Chain +To move an Opt In consumer chain to its initialized phase, we issue a `MsgInitializeConsumer` message that is as follows: + +```protobuf +message MsgInitializeConsumer { + // consumer id of the to-be-updated consumer chain + string consumer_id; + // the initialization record that contains initialization parameters for the upcoming chain + ConsumerInitializationRecord initialization_record; +} +``` +where `ConsumerInitializationRecord` contains the following: +```protobuf +message ConsumerInitializationRecord { + // ---------- ---------- ---------- + // Following fields are used when the consumer chain launches and are not needed by the provider afterwards. + // ---------- ---------- ---------- + + // the proposed initial height of new consumer chain. + // For a completely new chain, this will be {0,1}. However, it may be + // different if this is a chain that is converting to a consumer chain. + ibc.core.client.v1.Height initial_height; + // The hash of the consumer chain genesis state without the consumer CCV + // module genesis params. It is used for off-chain confirmation of + // genesis.json validity by validators and other parties. + bytes genesis_hash; + // The hash of the consumer chain binary that should be run by validators on + // chain initialization. It is used for off-chain confirmation of binary + // validity by validators and other parties. + bytes binary_hash; + // spawn time is the time on the provider chain at which the consumer chain + // genesis is finalized and all validators will be responsible for starting + // their consumer chain validator node. + google.protobuf.Timestamp spawn_time; + // Unbonding period for the consumer, + // which should be smaller than that of the provider in general. + google.protobuf.Duration unbonding_period; + + + // ---------- ---------- ---------- + // Following fields are used to construct the consumer genesis of the to-be-launched consumer chain + // and are set up as params on the consumer chain. Those params can then be directly modified by the consumer chain. + // ---------- ---------- ---------- + + // Sent CCV related IBC packets will timeout after this duration + google.protobuf.Duration ccv_timeout_period; + // Sent transfer related IBC packets will timeout after this duration + google.protobuf.Duration transfer_timeout_period; + // 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.75" would represent 75%. + string consumer_redistribution_fraction; + // BlocksPerDistributionTransmission is the number of blocks between + // ibc-token-transfers from the consumer chain to the provider chain. On + // sending transmission event, `consumer_redistribution_fraction` of the + // accumulated tokens are sent to the consumer redistribution address. + int64 blocks_per_distribution_transmission; + // The number of historical info entries to persist in store. + // This param is a part of the cosmos sdk staking module. In the case of + // a ccv enabled consumer chain, the ccv module acts as the staking module. + int64 historical_entries; + // The ID of a token transfer channel used for the Reward Distribution + // sub-protocol. If DistributionTransmissionChannel == "", a new transfer + // channel is created on top of the same connection as the CCV channel. + // Note that transfer_channel_id is the ID of the channel end on the consumer + // chain. it is most relevant for chains performing a sovereign to consumer + // changeover in order to maintain the existing ibc transfer channel + string distribution_transmission_channel; +} +``` + +`ConsumerInitializationRecord` contains _almost_ everything that is contained in [`MsgConsumerAddition`](https://github.com/cosmos/interchain-security/blob/v5.1.0/proto/interchain_security/ccv/provider/v1/tx.proto#L111). +Note that as part of this work, we deprecate [`ConsumerAdditionProposal`](https://github.com/cosmos/interchain-security/blob/v5.1.0/proto/interchain_security/ccv/provider/v1/provider.proto#L30). + +For each `consumerId`, we store its corresponding `ConsumerInitializationRecord`. For Top N chains, we can perform this +store by using the [`AfterProposalVotingPeriodEnded`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.8/x/gov/types/hooks.go#L52). + +Note that we need to extensively check the fields of the provided `ConsumerInitializationRecord` to guarantee that no consumer +chain launches with problematic parameters (e.g., we need to have maximum length for the `chainId`, etc.). +As a starter we look into the [usual validity conditions](https://github.com/cosmos/interchain-security/blob/v5.1.0/x/ccv/provider/types/msg.go#L244). + +For all chains in the initialized phase, we keep a mapping between `consumerId` and the underlying `ConsumerInitializationRecord`. +This way, we can respond to queries that ask for all the consumer chain's parameters. For example, retrieving the +`spawn_time` of consumer chain with a given `consumerId`. + +`MsgInitializeConsumer` can be executed multiple times for the same Opt In consumer chain during its initialized phase +to potentially change its to-be-launched parameters (e.g., `spawnTime`). + +A Top N can move to the initialized phase only if the owner of the registered chain issues a governance proposal +with two messages, `MsgInitializeConsumer` and `MsgUpdateConsumer`, and the proposal passes. + +#### Modify a Consumer Chain +We reuse the [MsgConsumerModification](https://github.com/cosmos/interchain-security/blob/v5.1.0/proto/interchain_security/ccv/provider/v1/tx.proto#L294) +message to update parameters of an Opt In chain that is in its initialized or launched phase, but rename the message +to `MsgUpdateConsumer`. This message can only be executed by the owner of a consumer +chain and hence only the owner can change the parameters (e.g., `validators_power_cap`, `allowlist`, etc.) +of the consumer chain. Recall that if the consumer chain is a Top N chain, then the owner is the address of the +governance account. + +We refactor `MsgUpdateConsumer` to be as follows: +```protobuf +message MsgUpdateConsumer { + // consumer id of the to-be-updated consumer chain + string consumer_id; + ConsumerUpdateRecord update_record; +} +``` + +where `ConsumerUpdateRecord` contains the following: +``` +message ConsumerUpdateRecord { + // `owner_address` cannot be modified by a Top N chain, unless it moves to an Opt In chain (i.e., `top_N == 0`) + string owner_address; + uint32 top_N; + uint32 validators_power_cap; + uint32 validator_set_cap; + repeated string allowlist; + repeated string denylist; +} +``` + +Note, that even though a consumer chain is initialized with all the arguments in `ConsumerUpdateRecord`, +the `MsgUpdateConsumer` updates only the `owner_address` and the `consumer_update_record`. This is because +all the other arguments are either useless (e.g., `spawnTime`) after a chain has started, or can be updated directly +by the consumer chain params (e.g., `consumer_redistribution_fraction`). + +#### Remove (Stop) a Consumer Chain +We reuse the `MsgConsumerRemoval` (renamed to `MsgRemoveConsumer`) so we can stop any Opt In chain at any point in time. +Note that all relevant state for this consumer chain remains on the provider's state before getting removed after the time +of an unbonding period (of the provider) has passed. This is to enable potential slashing for any infraction that might have been incurred until now. +Note however that we never recycle previously-used `consumerId`s. Naturally, this message can only be issued by the owner of the consumer chain. + +```protobuf +message MsgRemoveConsumer { + // the consumerId as returned by `MsgRegisterConsumer` + string consumer_id; + // the time on the provider chain at which all validators are responsible to + // stop their consumer chain validator node + google.protobuf.Timestamp stop_time; +} +``` + +#### Examples of Launching a Consumer Chain +The figures below depict some examples of some of the phases a consumer chain resides in to launch. + +![Examples of a launching consumer chain](./figures/adr19_flows_of_launching_a_consumer_chain.png) + + +### Additional Modifications +We need to perform multiple migrations. All state needs to be reindex based on a `consumerId` instead of the `chainId`. +Because we only have two consumer chains at the moment, this is not going to be an expensive migration even if we have some live +consumer chains that are being voted upon. Similarly, all the messages, queries, etc. would need to be changed to operate on a `consumerId` +instead of a `chainId`. + +It is **important** to migrate any ongoing `ConsumerAdditionProposal`s when we upgrade before we actually deprecate `ConsumerAdditionProposal`s. + +## Consequences + +### Positive +- Easier to launch an Opt In consumer chain because no governance is required. + +### Negative +- Extensive migration and overhaul of existing code base (as part of API-breaking changes) that could lead to bugs and more work in auditing this. + + +## References +[CHIPs Discussion phase: Permissionless ICS](https://forum.cosmos.network/t/chips-discussion-phase-permissionless-ics/13955) +[Chain-id squatting](https://forum.cosmos.network/t/pss-permissionless-vs-premissioned-lite-opt-in-consumer-chains/12984/17) \ No newline at end of file diff --git a/docs/docs/adrs/figures/adr19_flows_of_launching_a_consumer_chain.excalidraw b/docs/docs/adrs/figures/adr19_flows_of_launching_a_consumer_chain.excalidraw new file mode 100644 index 0000000000..4e9c57cce0 --- /dev/null +++ b/docs/docs/adrs/figures/adr19_flows_of_launching_a_consumer_chain.excalidraw @@ -0,0 +1,3277 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "type": "ellipse", + "version": 432, + "versionNonce": 656013628, + "index": "a1", + "isDeleted": false, + "id": "SI0HtgaAMGQsMr1Y7bXrA", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 512.4765625, + "y": 248.29980468749991, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 143.13281250000014, + "height": 137.65234375000014, + "seed": 1039402003, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "type": "text", + "id": "A97toxLGgigcGTMSLzFRE" + }, + { + "id": "zeENeKW4p1ce_DWzf-29f", + "type": "arrow" + }, + { + "id": "qIMMSItT6zGcYO5ZUPcar", + "type": "arrow" + } + ], + "updated": 1721898441262, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 772, + "versionNonce": 276787644, + "index": "a1V", + "isDeleted": false, + "id": "A97toxLGgigcGTMSLzFRE", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 547.7299002905518, + "y": 306.9585237065766, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 72.41595458984375, + "height": 20, + "seed": 262978077, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "initialized", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "SI0HtgaAMGQsMr1Y7bXrA", + "originalText": "initialized", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "ellipse", + "version": 225, + "versionNonce": 1063465660, + "index": "a2", + "isDeleted": false, + "id": "y5DOCeanki7NLMac-YZU_", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 963.30078125, + "y": 252.48730468749994, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 113.27734375, + "height": 113.27734375, + "seed": 303821331, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "id": "zeENeKW4p1ce_DWzf-29f", + "type": "arrow" + }, + { + "type": "text", + "id": "_lR4nCPdco_VXP-hHHxFx" + }, + { + "id": "hoUATc742qsSXGtb3zXhk", + "type": "arrow" + }, + { + "id": "6m4pEWBrlMrOpXdR2qMdd", + "type": "arrow" + } + ], + "updated": 1721898441262, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 69, + "versionNonce": 241531708, + "index": "a2G", + "isDeleted": false, + "id": "_lR4nCPdco_VXP-hHHxFx", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 987.2738821091236, + "y": 299.07638760228764, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 65.23196411132812, + "height": 20, + "seed": 2116710579, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "launched", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "y5DOCeanki7NLMac-YZU_", + "originalText": "launched", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 818, + "versionNonce": 352917936, + "index": "a4", + "isDeleted": false, + "id": "-Ezkh_kc6H-iZ8_N1SUwz", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 728.4853515625, + "y": 18.888671874999943, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 462.22369116544724, + "height": 40, + "seed": 176740147, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "JQNfOufG1Sc3Ln1iHc6v8", + "type": "arrow" + } + ], + "updated": 1721977797787, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "proposal with MsgInitializeConsumer & MsgUpdateConsumer\nto start a Top N chain", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "proposal with MsgInitializeConsumer & MsgUpdateConsumer\nto start a Top N chain", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 3380, + "versionNonce": 1334694320, + "index": "a5", + "isDeleted": false, + "id": "JQNfOufG1Sc3Ln1iHc6v8", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 863.2801567822762, + "y": 66.26969410176584, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 208.7131111905685, + "height": 55.219229040456455, + "seed": 428750077, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721977807991, + "link": null, + "locked": false, + "startBinding": { + "elementId": "-Ezkh_kc6H-iZ8_N1SUwz", + "focus": 0.14349370214591656, + "gap": 7.381022226765893 + }, + "endBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": 0.1824872496377905, + "gap": 2.2713741813428783 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -106.6058242763097, + 51.06445336557442 + ], + [ + -208.7131111905685, + 55.219229040456455 + ] + ] + }, + { + "type": "text", + "version": 1068, + "versionNonce": 1922126672, + "index": "a6", + "isDeleted": false, + "id": "9NwhWEx9olM4fARFt5hZe", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 189.74827575683594, + "y": -17.066406250000057, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 308.01581835746765, + "height": 80, + "seed": 304812115, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "NAUT1CeeaW6ntAtOKbXGS", + "type": "arrow" + } + ], + "updated": 1721977650326, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "tx to register\nan Opt In or Top N consumer chain\n(MsgRegisterConsumer)\nowner = signer of MsgRegisterConsumer", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "tx to register\nan Opt In or Top N consumer chain\n(MsgRegisterConsumer)\nowner = signer of MsgRegisterConsumer", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 331, + "versionNonce": 1834637060, + "index": "a7", + "isDeleted": false, + "id": "zeENeKW4p1ce_DWzf-29f", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 663.2551165518071, + "y": 319.75738423211857, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 299.31331302963645, + "height": 5.083241028410356, + "seed": 783684445, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721898441294, + "link": null, + "locked": false, + "startBinding": { + "elementId": "9VJjnsFNvss8g8B_wchEr", + "focus": -1.1953607235764194, + "gap": 6.181092330381375 + }, + "endBinding": { + "elementId": "y5DOCeanki7NLMac-YZU_", + "focus": -0.08074296871041202, + "gap": 1.0000000000000995 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 299.31331302963645, + -5.083241028410356 + ] + ] + }, + { + "type": "text", + "version": 418, + "versionNonce": 1250834364, + "index": "a8", + "isDeleted": false, + "id": "9VJjnsFNvss8g8B_wchEr", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 669.0216369628906, + "y": 325.93847656249994, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 252.0958709716797, + "height": 60, + "seed": 1053753011, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "zeENeKW4p1ce_DWzf-29f", + "type": "arrow" + } + ], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "chain's spawnTime passed\nAND\nat least one validator opted in", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "chain's spawnTime passed\nAND\nat least one validator opted in", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 417, + "versionNonce": 7026096, + "index": "aF", + "isDeleted": false, + "id": "FgsFB8OrGtx1-nlYRY0Uz", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1100.889877319336, + "y": 155.14941406249994, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 229.75984984636307, + "height": 40, + "seed": 51301117, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "hoUATc742qsSXGtb3zXhk", + "type": "arrow" + } + ], + "updated": 1721979486389, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "MsgUpdateConsumer for both\nTop N and Opt In chains", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgUpdateConsumer for both\nTop N and Opt In chains", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 936, + "versionNonce": 1806394884, + "index": "aG", + "isDeleted": false, + "id": "hoUATc742qsSXGtb3zXhk", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1043.1909748738744, + "y": 254.20084659464027, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 81.51926732005495, + "height": 77.65472732322138, + "seed": 684481907, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721898441295, + "link": null, + "locked": false, + "startBinding": { + "elementId": "y5DOCeanki7NLMac-YZU_", + "focus": -0.6276577497929622, + "gap": 3.005298194275724 + }, + "endBinding": { + "elementId": "y5DOCeanki7NLMac-YZU_", + "focus": 0.6500438788511836, + "gap": 6.714013400352123 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 81.51926732005495, + -47.95974594543503 + ], + [ + 34.8604592337133, + 29.69498137778635 + ] + ] + }, + { + "type": "ellipse", + "version": 356, + "versionNonce": 411466172, + "index": "aK", + "isDeleted": false, + "id": "U2EhanfFFSg1GNh4uQ9Xo", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 973.2587890625, + "y": 528.0859375, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 113.27734375, + "height": 113.27734375, + "seed": 420095965, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "type": "text", + "id": "RfEXevpkB5rowEFa4mHDD" + }, + { + "id": "6m4pEWBrlMrOpXdR2qMdd", + "type": "arrow" + } + ], + "updated": 1721898441262, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 209, + "versionNonce": 294117948, + "index": "aL", + "isDeleted": false, + "id": "RfEXevpkB5rowEFa4mHDD", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 999.7359029831471, + "y": 574.6750204147877, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 60.22393798828125, + "height": 20, + "seed": 1217602621, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "stopped", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "U2EhanfFFSg1GNh4uQ9Xo", + "originalText": "stopped", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 518, + "versionNonce": 1178907908, + "index": "aM", + "isDeleted": false, + "id": "6m4pEWBrlMrOpXdR2qMdd", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1027.530607098985, + "y": 367.313746063125, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 1.0811756614666592, + "height": 152.58658700381386, + "seed": 354868061, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721898441295, + "link": null, + "locked": false, + "startBinding": { + "elementId": "y5DOCeanki7NLMac-YZU_", + "focus": -0.1267451224869414, + "gap": 2.042177966448442 + }, + "endBinding": { + "elementId": "U2EhanfFFSg1GNh4uQ9Xo", + "focus": -0.014589591451189068, + "gap": 8.198352788681127 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 1.0811756614666592, + 152.58658700381386 + ] + ] + }, + { + "type": "ellipse", + "version": 1043, + "versionNonce": 1743463856, + "index": "aP", + "isDeleted": false, + "id": "_VXIQppCSNb6MIFQLmDdy", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 527.1933593750001, + "y": 49.049845487915945, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 125.71093750000004, + "height": 126.94419050538774, + "seed": 1424716579, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "type": "text", + "id": "ND9wpVssAkaXAtA1CWR-j" + }, + { + "id": "qIMMSItT6zGcYO5ZUPcar", + "type": "arrow" + }, + { + "id": "JQNfOufG1Sc3Ln1iHc6v8", + "type": "arrow" + }, + { + "id": "NAUT1CeeaW6ntAtOKbXGS", + "type": "arrow" + }, + { + "id": "SP-m3QTzlcLoU-_bmfZeN", + "type": "arrow" + } + ], + "updated": 1721977737205, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1438, + "versionNonce": 303490108, + "index": "aQ", + "isDeleted": false, + "id": "ND9wpVssAkaXAtA1CWR-j", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 550.919332346884, + "y": 102.6403917713115, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 78.36793518066406, + "height": 20, + "seed": 704059075, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "registered", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "_VXIQppCSNb6MIFQLmDdy", + "originalText": "registered", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 2498, + "versionNonce": 1811695536, + "index": "aR", + "isDeleted": false, + "id": "qIMMSItT6zGcYO5ZUPcar", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 598.616944950635, + "y": 175.68190954353736, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 95.2174182195338, + "height": 71.14063431860131, + "seed": 711212803, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721977823250, + "link": null, + "locked": false, + "startBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": 0.7831196417981204, + "gap": 1 + }, + "endBinding": { + "elementId": "SI0HtgaAMGQsMr1Y7bXrA", + "focus": -0.9808503194655256, + "gap": 2.5866858268130386 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 93.66378808277591, + 56.75434794509022 + ], + [ + -1.5536301367578846, + 71.14063431860131 + ] + ] + }, + { + "type": "text", + "version": 894, + "versionNonce": 1163437392, + "index": "aS", + "isDeleted": false, + "id": "tONaGSodwA-i1Tr_ZvpZf", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 703.2325744628906, + "y": 211.6659109933036, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 63.951934814453125, + "height": 40, + "seed": 1173975117, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721977821204, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "proposal\npasses", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "proposal\npasses", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 2698, + "versionNonce": 1501320528, + "index": "aW", + "isDeleted": false, + "id": "NAUT1CeeaW6ntAtOKbXGS", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 295.2339916085824, + "y": 72.54770775067982, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 219.9931787394372, + "height": 44.86816430307441, + "seed": 713565901, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721977650641, + "link": null, + "locked": false, + "startBinding": { + "elementId": "9NwhWEx9olM4fARFt5hZe", + "focus": 0.5220455825778929, + "gap": 9.614114000679876 + }, + "endBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": -0.040896091175469475, + "gap": 12.037638560264035 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 49.778852818030145, + 44.86816430307441 + ], + [ + 219.9931787394372, + 43.27181702781314 + ] + ] + }, + { + "type": "arrow", + "version": 2638, + "versionNonce": 2034843580, + "index": "aX", + "isDeleted": false, + "id": "QJHjyYDxam9jq3ifrE6rE", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 553.4126684100163, + "y": 172.7898695168439, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 88.24899059693328, + "height": 80.70767694042144, + "seed": 901908284, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -87.03045455607186, + 30.651422159720436 + ], + [ + 1.218536040861423, + 80.70767694042144 + ] + ] + }, + { + "type": "text", + "version": 954, + "versionNonce": 1840703408, + "index": "aY", + "isDeleted": false, + "id": "OSTXsQ9rLudhM8FpW1Tmi", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 237.52793884277344, + "y": 181.43050856817348, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 220.76788437366486, + "height": 60, + "seed": 1590512260, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721981417956, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "tx to initialize a registered\nOpt In chain\n(MsgInitializeConsumer)", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "tx to initialize a registered\nOpt In chain\n(MsgInitializeConsumer)", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 618, + "versionNonce": 1408338864, + "index": "aZ", + "isDeleted": false, + "id": "YfLjGiz8pwcgaeYLbqk17", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1046.5860595703125, + "y": 407.42009190150674, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 198.86389088630676, + "height": 40, + "seed": 200186756, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721977871422, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "MsgRemoveConsumer for\nTop N and Opt In chains", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgRemoveConsumer for\nTop N and Opt In chains", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1258, + "versionNonce": 1493934000, + "index": "aa", + "isDeleted": false, + "id": "NssF2iYfl_Bnw_ExbSTN9", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 5.903783783236146, + "x": 738.4366388875179, + "y": 102.0454511378703, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 188.03873574733734, + "height": 38.94856770833333, + "seed": 1513132976, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721979493173, + "link": null, + "locked": false, + "fontSize": 15.579427083333332, + "fontFamily": 1, + "text": "If proposal submitted,\nthen owner = gov module", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "If proposal submitted,\nthen owner = gov module", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 3860, + "versionNonce": 1375313744, + "index": "ab", + "isDeleted": false, + "id": "SP-m3QTzlcLoU-_bmfZeN", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 542.8449540584817, + "y": 65.3169816199927, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 107.2195285426966, + "height": 95.35691573040356, + "seed": 1371342672, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721979518514, + "link": null, + "locked": false, + "startBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": -1.0544694371314034, + "gap": 3.5954323396749857 + }, + "endBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": 0.31663537700287836, + "gap": 1.9911615284421913 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 107.2195285426966, + -95.35691573040356 + ], + [ + 82.94381595386449, + -7.418196168042471 + ] + ] + }, + { + "type": "text", + "version": 1314, + "versionNonce": 863552848, + "index": "ac", + "isDeleted": false, + "id": "apwBA2F8OsZLAT7p6l1JS", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 609.4229227304459, + "y": -79.25318690708701, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 569.839707493782, + "height": 40, + "seed": 1979332528, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721979490056, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "If proposal fails,\nthen owner = previous owner (the one that signed MsgRegisterConsumer)", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "If proposal fails,\nthen owner = previous owner (the one that signed MsgRegisterConsumer)", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 772, + "versionNonce": 266696112, + "index": "ae", + "isDeleted": false, + "id": "pwlxDMNk9SimSRoZRuyV3", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 256.2591145833333, + "y": 1317.2654695056733, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 1658.3805338541667, + "height": 0.078125, + "seed": 1129032624, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1658.3805338541667, + 0.078125 + ] + ] + }, + { + "type": "line", + "version": 379, + "versionNonce": 957038512, + "index": "af", + "isDeleted": false, + "id": "-xwyxjAJM89xAkUi-pWLB", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 269.35481770833337, + "y": 1261.0252351306735, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 659246416, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 552, + "versionNonce": 250071472, + "index": "ag", + "isDeleted": false, + "id": "AFDJ07skaLW7VCALYMDj4", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 760.7334914470289, + "y": 1257.3100290018028, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1945500592, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 835, + "versionNonce": 1285755824, + "index": "ah", + "isDeleted": false, + "id": "hDPzA0-vpS0ilSkphkeAA", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1002.3254193314633, + "y": 1269.644565149432, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1257497936, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "arrow", + "version": 627, + "versionNonce": 140844464, + "index": "ai", + "isDeleted": false, + "id": "5RtUeYj4dxxweAu88pxEc", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1824.390625, + "y": 1297.1385163806735, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 88.623046875, + "height": 0, + "seed": 557184848, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 88.623046875, + 0 + ] + ] + }, + { + "type": "text", + "version": 694, + "versionNonce": 1398138800, + "index": "aj", + "isDeleted": false, + "id": "TCPMJfrcd92gSR4Q6cE6S", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1845.7822265625, + "y": 1273.2810945056735, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 40.63996636867523, + "height": 25, + "seed": 1234376112, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "time", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "time", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 653, + "versionNonce": 1503490480, + "index": "ak", + "isDeleted": false, + "id": "cJmAKusziodsDR6vwTHJd", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 213.76562500000006, + "y": 1198.4617585681735, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 227.99981439113617, + "height": 50, + "seed": 844025168, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgRegisterConsumer\nto get the consumer id", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgRegisterConsumer\nto get the consumer id", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 717, + "versionNonce": 40090544, + "index": "al", + "isDeleted": false, + "id": "GastODl-l38mFb5oaAEbj", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 665.4558410644531, + "y": 1198.011929466611, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 210.61980283260345, + "height": 50, + "seed": 44005200, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgInitializeConsumer\nwith spawnTime, etc.", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgInitializeConsumer\nwith spawnTime, etc.", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 801, + "versionNonce": 265340336, + "index": "am", + "isDeleted": false, + "id": "kXfBgGvtmnfZCVwG1uG9V", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 935.2071304321289, + "y": 1199.574429466611, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 224.29981744289398, + "height": 50, + "seed": 2087774640, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgUpdateConsumer\nto set power cap, etc.", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgUpdateConsumer\nto set power cap, etc.", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 966, + "versionNonce": 1057787824, + "index": "an", + "isDeleted": false, + "id": "E1QM7dtsigeuyGX9zwvE0", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1220.2525985836983, + "y": 1202.250210716611, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 242.3997710943222, + "height": 50, + "seed": 608854864, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgInitializeConsumer to\nmodify spawnTime", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgInitializeConsumer to\nmodify spawnTime", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 688, + "versionNonce": 1748965808, + "index": "ao", + "isDeleted": false, + "id": "Wm2pyI04tXykKntCeM85W", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1307.6379193314638, + "y": 1266.2113376103696, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1967873456, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "rectangle", + "version": 657, + "versionNonce": 512779184, + "index": "ap", + "isDeleted": false, + "id": "pfUxn633PL7PLmo5UBP83", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 273.84472656250006, + "y": 1317.1248851957778, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e7f5ff", + "width": 480.92285156250006, + "height": 81.1279296875, + "seed": 394410832, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "ZxRHa3OTec0AyDpAifqQw" + } + ], + "updated": 1721980422671, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 421, + "versionNonce": 1344826800, + "index": "aq", + "isDeleted": false, + "id": "ZxRHa3OTec0AyDpAifqQw", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 429.95622801780706, + "y": 1345.1888500395278, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 168.699848651886, + "height": 25, + "seed": 1250610096, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Registered phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "pfUxn633PL7PLmo5UBP83", + "originalText": "Registered phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1004, + "versionNonce": 1714370480, + "index": "ar", + "isDeleted": false, + "id": "uVblxWqL6Msu5umb9eTvZ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 758.35302734375, + "y": 1318.302456810361, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 660.1660156250001, + "height": 81.1279296875, + "seed": 229232464, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "s-LIv7Mo1IvDb89Gr0uSQ" + } + ], + "updated": 1721980422671, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 782, + "versionNonce": 1691140528, + "index": "as", + "isDeleted": false, + "id": "s-LIv7Mo1IvDb89Gr0uSQ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1007.056105658412, + "y": 1346.366421654111, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 162.75985899567604, + "height": 25, + "seed": 1548969296, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Initialized phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "uVblxWqL6Msu5umb9eTvZ", + "originalText": "Initialized phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 863, + "versionNonce": 2067805008, + "index": "at", + "isDeleted": false, + "id": "zXqjQ2rE_UbSjEHOyMDw3", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1422.1748893529827, + "y": 1318.9168052711786, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 618764720, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980681550, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "text", + "version": 1091, + "versionNonce": 1936463280, + "index": "au", + "isDeleted": false, + "id": "aVp4yECj00-fGLMn7sHnD", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1309.797184765339, + "y": 1450.599820091611, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 177.4198455810547, + "height": 75, + "seed": 1447447888, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422672, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "spawnTime passed\nand at least one\nvalidator opted in", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "spawnTime passed\nand at least one\nvalidator opted in", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1091, + "versionNonce": 851304368, + "index": "ax", + "isDeleted": false, + "id": "s6qt0UIRPRSbMwetkDFg_", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1609.481927216053, + "y": 1212.733609154111, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 202.41985833644867, + "height": 50, + "seed": 1340941744, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422672, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgUpdateConsumer\nto change power cap", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgUpdateConsumer\nto change power cap", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 985, + "versionNonce": 2034657712, + "index": "ay", + "isDeleted": false, + "id": "RRDK6Jp-NdnWMWtYGDDli", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1745.1088831870024, + "y": 1272.6322796427069, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 154253232, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422672, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "rectangle", + "version": 1016, + "versionNonce": 841855920, + "index": "az", + "isDeleted": false, + "id": "4ZMVPnrnF1Dfj8ono67tv", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1425.8107096354167, + "y": 1320.40939512673, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 475.03417968750034, + "height": 79.30663117976157, + "seed": 66445648, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "KC5zECj3By5dDU8JFhAep" + } + ], + "updated": 1721980422672, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 810, + "versionNonce": 597409200, + "index": "b00", + "isDeleted": false, + "id": "KC5zECj3By5dDU8JFhAep", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1587.763779918353, + "y": 1347.7777356509237, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 151.1280391216278, + "height": 24.569950131374355, + "seed": 323827536, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422672, + "link": null, + "locked": false, + "fontSize": 19.655960105099485, + "fontFamily": 1, + "text": "Launched phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "4ZMVPnrnF1Dfj8ono67tv", + "originalText": "Launched phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 771, + "versionNonce": 1263014832, + "index": "b01", + "isDeleted": false, + "id": "7Bq_OzmNwUc0GxjMxTYNY", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 265.25883719345677, + "y": 1666.5525788806733, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 1658.3805338541667, + "height": 0.078125, + "seed": 255347024, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1658.3805338541667, + 0.078125 + ] + ] + }, + { + "type": "line", + "version": 400, + "versionNonce": 1785339312, + "index": "b02", + "isDeleted": false, + "id": "OvebgcABs_rLQivf-TBk2", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 278.3545403184568, + "y": 1610.3123445056733, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1510121296, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 573, + "versionNonce": 750446512, + "index": "b03", + "isDeleted": false, + "id": "4C8GcmxoE4N2CEFpbetdn", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 769.7332140571524, + "y": 1606.5971383768026, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1158821200, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 856, + "versionNonce": 1046639024, + "index": "b04", + "isDeleted": false, + "id": "nHS8CykAzRlhhatMaNhMu", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1011.3251419415867, + "y": 1618.931674524432, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 364841808, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "arrow", + "version": 626, + "versionNonce": 109624240, + "index": "b05", + "isDeleted": false, + "id": "Fs9vTDdorvwlcYw_ubAa_", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1833.3903476101234, + "y": 1646.4256257556733, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 88.623046875, + "height": 0, + "seed": 643899728, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 88.623046875, + 0 + ] + ] + }, + { + "type": "text", + "version": 715, + "versionNonce": 1196803504, + "index": "b06", + "isDeleted": false, + "id": "l3WpHc1Tm8DmkYOar2yuc", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1854.7819491726234, + "y": 1622.5682038806733, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 40.63996636867523, + "height": 25, + "seed": 1179678544, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "time", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "time", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 674, + "versionNonce": 1039241136, + "index": "b07", + "isDeleted": false, + "id": "HVWEVkdCna3gjxJRN-dCZ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 222.7653476101235, + "y": 1547.7488679431735, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 227.99981439113617, + "height": 50, + "seed": 434441552, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgRegisterConsumer\nto get the consumer id", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgRegisterConsumer\nto get the consumer id", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 877, + "versionNonce": 1115953584, + "index": "b08", + "isDeleted": false, + "id": "jpeMZ5SS2jgAqO9FZB17B", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 672.7954074245766, + "y": 1496.999559674944, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 237.25982177257538, + "height": 100, + "seed": 2054611792, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "issue governance\nproposal with\nMsgInitializeConsumer\nand MsgUpdateconsumer", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "issue governance\nproposal with\nMsgInitializeConsumer\nand MsgUpdateconsumer", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 907, + "versionNonce": 1748329392, + "index": "b09", + "isDeleted": false, + "id": "zmw1PyM5vZzw3eZp9f19w", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 936.9607592922523, + "y": 1583.112840924944, + "strokeColor": "#e03131", + "backgroundColor": "transparent", + "width": 170.7798352241516, + "height": 25, + "seed": 1448999248, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "proposal rejected", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "proposal rejected", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1152, + "versionNonce": 489516464, + "index": "b0C", + "isDeleted": false, + "id": "ajHAAKi9tSoXcIkv3aA4L", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 277.09965750595677, + "y": 1665.9562654041108, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e7f5ff", + "width": 1646.6975911458337, + "height": 81.1279296875, + "seed": 948091728, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "2HQsEKAeWiKi5szJa8Io6" + } + ], + "updated": 1721980676778, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 916, + "versionNonce": 1251227568, + "index": "b0D", + "isDeleted": false, + "id": "2HQsEKAeWiKi5szJa8Io6", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1016.0985287529306, + "y": 1694.0202302478608, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 168.699848651886, + "height": 25, + "seed": 355389776, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Registered phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ajHAAKi9tSoXcIkv3aA4L", + "originalText": "Registered phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1323, + "versionNonce": 515241808, + "index": "b0E", + "isDeleted": false, + "id": "o16fHdthOp80uqAN-KkL2", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1015.8097812038734, + "y": 2025.532274518694, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 415.0227864583335, + "height": 81.1279296875, + "seed": 1877485392, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "348R4_XQcWAs6CAl4OV_w" + } + ], + "updated": 1721980415621, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1102, + "versionNonce": 1234865488, + "index": "b0F", + "isDeleted": false, + "id": "348R4_XQcWAs6CAl4OV_w", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1141.9412449352021, + "y": 2053.596239362444, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 162.75985899567604, + "height": 25, + "seed": 352763216, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Initialized phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "o16fHdthOp80uqAN-KkL2", + "originalText": "Initialized phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 897, + "versionNonce": 394027856, + "index": "b0M", + "isDeleted": false, + "id": "jAITNaSlDtSPpvQwpBfRJ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 267.98783052464313, + "y": 2020.76074945359, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 1658.3805338541667, + "height": 0.078125, + "seed": 124954448, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1658.3805338541667, + 0.078125 + ] + ] + }, + { + "type": "line", + "version": 504, + "versionNonce": 917731664, + "index": "b0N", + "isDeleted": false, + "id": "akYH8jPOSYYHRJ0kHn6SF", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 281.08353364964324, + "y": 1964.52051507859, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1463893328, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 677, + "versionNonce": 1251462992, + "index": "b0O", + "isDeleted": false, + "id": "Qds67yg8nIFlUKrTZNb8v", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 772.4622073883388, + "y": 1960.8053089497193, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 483201872, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 960, + "versionNonce": 1266771280, + "index": "b0P", + "isDeleted": false, + "id": "jtzT1eH8RZn8QwNepmt_H", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1014.054135272773, + "y": 1973.1398450973488, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 778971472, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "arrow", + "version": 752, + "versionNonce": 1724398416, + "index": "b0Q", + "isDeleted": false, + "id": "8lhkFCwtbNTRFlmWeRE4n", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1836.1193409413095, + "y": 2000.63379632859, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 88.623046875, + "height": 0, + "seed": 1467776848, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 88.623046875, + 0 + ] + ] + }, + { + "type": "text", + "version": 819, + "versionNonce": 1589924176, + "index": "b0R", + "isDeleted": false, + "id": "CsZ965_KJ8mkVhd3JJHe6", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1857.5109425038095, + "y": 1976.77637445359, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 40.63996636867523, + "height": 25, + "seed": 944772432, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "time", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "time", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 778, + "versionNonce": 1791862608, + "index": "b0S", + "isDeleted": false, + "id": "VptrXV13wo5wjJkN_HnlZ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 225.49434094130987, + "y": 1901.9570385160905, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 227.99981439113617, + "height": 50, + "seed": 641788752, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgRegisterConsumer\nto get the consumer id", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgRegisterConsumer\nto get the consumer id", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1003, + "versionNonce": 389823824, + "index": "b0T", + "isDeleted": false, + "id": "i7B5C0pGmcgSuCqx5vRQP", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 675.524400755763, + "y": 1851.207730247861, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 237.25982177257538, + "height": 100, + "seed": 195494224, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "issue governance\nproposal with\nMsgInitializeConsumer\nand MsgUpdateconsumer", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "issue governance\nproposal with\nMsgInitializeConsumer\nand MsgUpdateconsumer", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1017, + "versionNonce": 623782224, + "index": "b0U", + "isDeleted": false, + "id": "KtxOQmQoRm5cuPDQBNvU5", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 939.6897526234386, + "y": 1937.321011497861, + "strokeColor": "#2f9e44", + "backgroundColor": "transparent", + "width": 156.959858417511, + "height": 25, + "seed": 1205491536, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980635662, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "proposal passes", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "proposal passes", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1270, + "versionNonce": 1806248272, + "index": "b0X", + "isDeleted": false, + "id": "aqECH_oHGd4F7Pq9jBCpa", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 279.82865083714313, + "y": 2020.1644359770276, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e7f5ff", + "width": 731.2353515625001, + "height": 81.1279296875, + "seed": 2041829712, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "J8GsOJGu4wkpH9e3dq06b" + } + ], + "updated": 1721980415621, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1034, + "versionNonce": 894926672, + "index": "b0Y", + "isDeleted": false, + "id": "J8GsOJGu4wkpH9e3dq06b", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 561.0964022924502, + "y": 2048.2284008207776, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 168.699848651886, + "height": 25, + "seed": 244068176, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Registered phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "aqECH_oHGd4F7Pq9jBCpa", + "originalText": "Registered phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 991, + "versionNonce": 2012467536, + "index": "b0Z", + "isDeleted": false, + "id": "jepmnNxu-8rBXJjZKYZKQ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1434.8150636276262, + "y": 2021.9498456357614, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1374274896, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980684670, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "text", + "version": 1229, + "versionNonce": 57883811, + "index": "b0a", + "isDeleted": false, + "id": "prbzcGXJPRqkOVsHpdbs4", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1321.581890289982, + "y": 2150.859422956194, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 176.8798370361328, + "height": 25, + "seed": 1092918096, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721986800613, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "spawnTime passed", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "spawnTime passed", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1327, + "versionNonce": 1288511920, + "index": "b0b", + "isDeleted": false, + "id": "4_i6jup_6Cze3xommPSgL", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1494.9671535740297, + "y": 1916.495816185361, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 231.69981133937836, + "height": 50, + "seed": 1855238480, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980692762, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgUpdateConsumer\nto change denylist, etc.", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgUpdateConsumer\nto change denylist, etc.", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 1250, + "versionNonce": 1557995440, + "index": "b0c", + "isDeleted": false, + "id": "G9GGcs9_A9FENDJhK85f5", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1581.264682461645, + "y": 1974.519486673957, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1636960080, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980691478, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "rectangle", + "version": 1141, + "versionNonce": 1680731472, + "index": "b0d", + "isDeleted": false, + "id": "TuSGExogIwVLdWKpZuLEE", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1437.5394255767267, + "y": 2023.904675074647, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 475.03417968750034, + "height": 79.30663117976157, + "seed": 1987353936, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "Kha-a5kyL8kweb2LvlPtp" + } + ], + "updated": 1721980415621, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 936, + "versionNonce": 1218691920, + "index": "b0e", + "isDeleted": false, + "id": "Kha-a5kyL8kweb2LvlPtp", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1599.492495859663, + "y": 2051.2730155988406, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 151.1280391216278, + "height": 24.569950131374355, + "seed": 1049916240, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 19.655960105099485, + "fontFamily": 1, + "text": "Launched phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "TuSGExogIwVLdWKpZuLEE", + "originalText": "Launched phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 408, + "versionNonce": 396094800, + "index": "b0f", + "isDeleted": false, + "id": "UyHfZ2VJGqV1pDsuTD9cV", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": -108.94270833333303, + "y": 1338.8350902739019, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 341.5998840332031, + "height": 70, + "seed": 723455312, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721981143713, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "successful launch of an \nOpt In chain", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "successful launch of an \nOpt In chain", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 510, + "versionNonce": 1955709360, + "index": "b0g", + "isDeleted": false, + "id": "4n5NjjKLCJsk7c-7uAWhd", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": -50.64974466959666, + "y": 1661.4197256905686, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 263.73187255859375, + "height": 70, + "seed": 1223292336, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "failed launch of a \nTop N chain", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "failed launch of a \nTop N chain", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 577, + "versionNonce": 2112613712, + "index": "b0h", + "isDeleted": false, + "id": "vr9GdN-bw_UUQefiVts9a", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": -83.6536966959635, + "y": 2032.7738923572358, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 328.5238952636719, + "height": 70, + "seed": 1698232144, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980468104, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "successful launch of a \nTop N chain", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "successful launch of a \nTop N chain", + "autoResize": true, + "lineHeight": 1.25 + } + ], + "appState": { + "gridSize": null, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/docs/docs/adrs/figures/adr19_flows_of_launching_a_consumer_chain.png b/docs/docs/adrs/figures/adr19_flows_of_launching_a_consumer_chain.png new file mode 100644 index 0000000000..72dffb2d67 Binary files /dev/null and b/docs/docs/adrs/figures/adr19_flows_of_launching_a_consumer_chain.png differ diff --git a/docs/docs/adrs/figures/adr19_phases_of_a_consumer_chain.excalidraw b/docs/docs/adrs/figures/adr19_phases_of_a_consumer_chain.excalidraw new file mode 100644 index 0000000000..4c4802ae69 --- /dev/null +++ b/docs/docs/adrs/figures/adr19_phases_of_a_consumer_chain.excalidraw @@ -0,0 +1,3404 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "type": "ellipse", + "version": 432, + "versionNonce": 656013628, + "index": "a1", + "isDeleted": false, + "id": "SI0HtgaAMGQsMr1Y7bXrA", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 512.4765625, + "y": 248.29980468749991, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 143.13281250000014, + "height": 137.65234375000014, + "seed": 1039402003, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "type": "text", + "id": "A97toxLGgigcGTMSLzFRE" + }, + { + "id": "zeENeKW4p1ce_DWzf-29f", + "type": "arrow" + }, + { + "id": "qIMMSItT6zGcYO5ZUPcar", + "type": "arrow" + } + ], + "updated": 1721898441262, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 772, + "versionNonce": 276787644, + "index": "a1V", + "isDeleted": false, + "id": "A97toxLGgigcGTMSLzFRE", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 547.7299002905518, + "y": 306.9585237065766, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 72.41595458984375, + "height": 20, + "seed": 262978077, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "initialized", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "SI0HtgaAMGQsMr1Y7bXrA", + "originalText": "initialized", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "ellipse", + "version": 225, + "versionNonce": 1063465660, + "index": "a2", + "isDeleted": false, + "id": "y5DOCeanki7NLMac-YZU_", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 963.30078125, + "y": 252.48730468749994, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 113.27734375, + "height": 113.27734375, + "seed": 303821331, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "id": "zeENeKW4p1ce_DWzf-29f", + "type": "arrow" + }, + { + "type": "text", + "id": "_lR4nCPdco_VXP-hHHxFx" + }, + { + "id": "hoUATc742qsSXGtb3zXhk", + "type": "arrow" + }, + { + "id": "6m4pEWBrlMrOpXdR2qMdd", + "type": "arrow" + } + ], + "updated": 1721898441262, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 69, + "versionNonce": 241531708, + "index": "a2G", + "isDeleted": false, + "id": "_lR4nCPdco_VXP-hHHxFx", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 987.2738821091236, + "y": 299.07638760228764, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 65.23196411132812, + "height": 20, + "seed": 2116710579, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "launched", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "y5DOCeanki7NLMac-YZU_", + "originalText": "launched", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 818, + "versionNonce": 352917936, + "index": "a4", + "isDeleted": false, + "id": "-Ezkh_kc6H-iZ8_N1SUwz", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 728.4853515625, + "y": 18.888671874999943, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 462.22369116544724, + "height": 40, + "seed": 176740147, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "JQNfOufG1Sc3Ln1iHc6v8", + "type": "arrow" + } + ], + "updated": 1721977797787, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "proposal with MsgInitializeConsumer & MsgUpdateConsumer\nto start a Top N chain", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "proposal with MsgInitializeConsumer & MsgUpdateConsumer\nto start a Top N chain", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 3380, + "versionNonce": 1334694320, + "index": "a5", + "isDeleted": false, + "id": "JQNfOufG1Sc3Ln1iHc6v8", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 863.2801567822762, + "y": 66.26969410176584, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 208.7131111905685, + "height": 55.219229040456455, + "seed": 428750077, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721977807991, + "link": null, + "locked": false, + "startBinding": { + "elementId": "-Ezkh_kc6H-iZ8_N1SUwz", + "focus": 0.14349370214591656, + "gap": 7.381022226765893 + }, + "endBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": 0.1824872496377905, + "gap": 2.2713741813428783 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -106.6058242763097, + 51.06445336557442 + ], + [ + -208.7131111905685, + 55.219229040456455 + ] + ] + }, + { + "type": "text", + "version": 1068, + "versionNonce": 1922126672, + "index": "a6", + "isDeleted": false, + "id": "9NwhWEx9olM4fARFt5hZe", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 189.74827575683594, + "y": -17.066406250000057, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 308.01581835746765, + "height": 80, + "seed": 304812115, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "NAUT1CeeaW6ntAtOKbXGS", + "type": "arrow" + } + ], + "updated": 1721977650326, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "tx to register\nan Opt In or Top N consumer chain\n(MsgRegisterConsumer)\nowner = signer of MsgRegisterConsumer", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "tx to register\nan Opt In or Top N consumer chain\n(MsgRegisterConsumer)\nowner = signer of MsgRegisterConsumer", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 331, + "versionNonce": 1834637060, + "index": "a7", + "isDeleted": false, + "id": "zeENeKW4p1ce_DWzf-29f", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 663.2551165518071, + "y": 319.75738423211857, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 299.31331302963645, + "height": 5.083241028410356, + "seed": 783684445, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721898441294, + "link": null, + "locked": false, + "startBinding": { + "elementId": "9VJjnsFNvss8g8B_wchEr", + "focus": -1.1953607235764194, + "gap": 6.181092330381375 + }, + "endBinding": { + "elementId": "y5DOCeanki7NLMac-YZU_", + "focus": -0.08074296871041202, + "gap": 1.0000000000000995 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 299.31331302963645, + -5.083241028410356 + ] + ] + }, + { + "type": "text", + "version": 418, + "versionNonce": 1250834364, + "index": "a8", + "isDeleted": false, + "id": "9VJjnsFNvss8g8B_wchEr", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 669.0216369628906, + "y": 325.93847656249994, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 252.0958709716797, + "height": 60, + "seed": 1053753011, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "zeENeKW4p1ce_DWzf-29f", + "type": "arrow" + } + ], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "chain's spawnTime passed\nAND\nat least one validator opted in", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "chain's spawnTime passed\nAND\nat least one validator opted in", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 417, + "versionNonce": 7026096, + "index": "aF", + "isDeleted": false, + "id": "FgsFB8OrGtx1-nlYRY0Uz", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1100.889877319336, + "y": 155.14941406249994, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 229.75984984636307, + "height": 40, + "seed": 51301117, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "hoUATc742qsSXGtb3zXhk", + "type": "arrow" + } + ], + "updated": 1721979486389, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "MsgUpdateConsumer for both\nTop N and Opt In chains", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgUpdateConsumer for both\nTop N and Opt In chains", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 936, + "versionNonce": 1806394884, + "index": "aG", + "isDeleted": false, + "id": "hoUATc742qsSXGtb3zXhk", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1043.1909748738744, + "y": 254.20084659464027, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 81.51926732005495, + "height": 77.65472732322138, + "seed": 684481907, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721898441295, + "link": null, + "locked": false, + "startBinding": { + "elementId": "y5DOCeanki7NLMac-YZU_", + "focus": -0.6276577497929622, + "gap": 3.005298194275724 + }, + "endBinding": { + "elementId": "y5DOCeanki7NLMac-YZU_", + "focus": 0.6500438788511836, + "gap": 6.714013400352123 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 81.51926732005495, + -47.95974594543503 + ], + [ + 34.8604592337133, + 29.69498137778635 + ] + ] + }, + { + "type": "ellipse", + "version": 356, + "versionNonce": 411466172, + "index": "aK", + "isDeleted": false, + "id": "U2EhanfFFSg1GNh4uQ9Xo", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 973.2587890625, + "y": 528.0859375, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 113.27734375, + "height": 113.27734375, + "seed": 420095965, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "type": "text", + "id": "RfEXevpkB5rowEFa4mHDD" + }, + { + "id": "6m4pEWBrlMrOpXdR2qMdd", + "type": "arrow" + } + ], + "updated": 1721898441262, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 209, + "versionNonce": 294117948, + "index": "aL", + "isDeleted": false, + "id": "RfEXevpkB5rowEFa4mHDD", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 999.7359029831471, + "y": 574.6750204147877, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 60.22393798828125, + "height": 20, + "seed": 1217602621, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "stopped", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "U2EhanfFFSg1GNh4uQ9Xo", + "originalText": "stopped", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 518, + "versionNonce": 1178907908, + "index": "aM", + "isDeleted": false, + "id": "6m4pEWBrlMrOpXdR2qMdd", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1027.530607098985, + "y": 367.313746063125, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 1.0811756614666592, + "height": 152.58658700381386, + "seed": 354868061, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721898441295, + "link": null, + "locked": false, + "startBinding": { + "elementId": "y5DOCeanki7NLMac-YZU_", + "focus": -0.1267451224869414, + "gap": 2.042177966448442 + }, + "endBinding": { + "elementId": "U2EhanfFFSg1GNh4uQ9Xo", + "focus": -0.014589591451189068, + "gap": 8.198352788681127 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 1.0811756614666592, + 152.58658700381386 + ] + ] + }, + { + "type": "ellipse", + "version": 1043, + "versionNonce": 1743463856, + "index": "aP", + "isDeleted": false, + "id": "_VXIQppCSNb6MIFQLmDdy", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 527.1933593750001, + "y": 49.049845487915945, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 125.71093750000004, + "height": 126.94419050538774, + "seed": 1424716579, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "type": "text", + "id": "ND9wpVssAkaXAtA1CWR-j" + }, + { + "id": "qIMMSItT6zGcYO5ZUPcar", + "type": "arrow" + }, + { + "id": "JQNfOufG1Sc3Ln1iHc6v8", + "type": "arrow" + }, + { + "id": "NAUT1CeeaW6ntAtOKbXGS", + "type": "arrow" + }, + { + "id": "SP-m3QTzlcLoU-_bmfZeN", + "type": "arrow" + } + ], + "updated": 1721977737205, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1438, + "versionNonce": 303490108, + "index": "aQ", + "isDeleted": false, + "id": "ND9wpVssAkaXAtA1CWR-j", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 550.919332346884, + "y": 102.6403917713115, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 78.36793518066406, + "height": 20, + "seed": 704059075, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "registered", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "_VXIQppCSNb6MIFQLmDdy", + "originalText": "registered", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 2498, + "versionNonce": 1811695536, + "index": "aR", + "isDeleted": false, + "id": "qIMMSItT6zGcYO5ZUPcar", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 598.616944950635, + "y": 175.68190954353736, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 95.2174182195338, + "height": 71.14063431860131, + "seed": 711212803, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721977823250, + "link": null, + "locked": false, + "startBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": 0.7831196417981204, + "gap": 1 + }, + "endBinding": { + "elementId": "SI0HtgaAMGQsMr1Y7bXrA", + "focus": -0.9808503194655256, + "gap": 2.5866858268130386 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 93.66378808277591, + 56.75434794509022 + ], + [ + -1.5536301367578846, + 71.14063431860131 + ] + ] + }, + { + "type": "text", + "version": 894, + "versionNonce": 1163437392, + "index": "aS", + "isDeleted": false, + "id": "tONaGSodwA-i1Tr_ZvpZf", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 703.2325744628906, + "y": 211.6659109933036, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 63.951934814453125, + "height": 40, + "seed": 1173975117, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721977821204, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "proposal\npasses", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "proposal\npasses", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 2698, + "versionNonce": 1501320528, + "index": "aW", + "isDeleted": false, + "id": "NAUT1CeeaW6ntAtOKbXGS", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 295.2339916085824, + "y": 72.54770775067982, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 219.9931787394372, + "height": 44.86816430307441, + "seed": 713565901, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721977650641, + "link": null, + "locked": false, + "startBinding": { + "elementId": "9NwhWEx9olM4fARFt5hZe", + "focus": 0.5220455825778929, + "gap": 9.614114000679876 + }, + "endBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": -0.040896091175469475, + "gap": 12.037638560264035 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 49.778852818030145, + 44.86816430307441 + ], + [ + 219.9931787394372, + 43.27181702781314 + ] + ] + }, + { + "type": "arrow", + "version": 2638, + "versionNonce": 2034843580, + "index": "aX", + "isDeleted": false, + "id": "QJHjyYDxam9jq3ifrE6rE", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 553.4126684100163, + "y": 172.7898695168439, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 88.24899059693328, + "height": 80.70767694042144, + "seed": 901908284, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721898441262, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -87.03045455607186, + 30.651422159720436 + ], + [ + 1.218536040861423, + 80.70767694042144 + ] + ] + }, + { + "type": "text", + "version": 954, + "versionNonce": 1840703408, + "index": "aY", + "isDeleted": false, + "id": "OSTXsQ9rLudhM8FpW1Tmi", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 237.52793884277344, + "y": 181.43050856817348, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 220.76788437366486, + "height": 60, + "seed": 1590512260, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721981417956, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "tx to initialize a registered\nOpt In chain\n(MsgInitializeConsumer)", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "tx to initialize a registered\nOpt In chain\n(MsgInitializeConsumer)", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 618, + "versionNonce": 1408338864, + "index": "aZ", + "isDeleted": false, + "id": "YfLjGiz8pwcgaeYLbqk17", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1046.5860595703125, + "y": 407.42009190150674, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 198.86389088630676, + "height": 40, + "seed": 200186756, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721977871422, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "MsgRemoveConsumer for\nTop N and Opt In chains", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgRemoveConsumer for\nTop N and Opt In chains", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1258, + "versionNonce": 1493934000, + "index": "aa", + "isDeleted": false, + "id": "NssF2iYfl_Bnw_ExbSTN9", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 5.903783783236146, + "x": 738.4366388875179, + "y": 102.0454511378703, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 188.03873574733734, + "height": 38.94856770833333, + "seed": 1513132976, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721979493173, + "link": null, + "locked": false, + "fontSize": 15.579427083333332, + "fontFamily": 1, + "text": "If proposal submitted,\nthen owner = gov module", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "If proposal submitted,\nthen owner = gov module", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "arrow", + "version": 3860, + "versionNonce": 1375313744, + "index": "ab", + "isDeleted": false, + "id": "SP-m3QTzlcLoU-_bmfZeN", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 542.8449540584817, + "y": 65.3169816199927, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 107.2195285426966, + "height": 95.35691573040356, + "seed": 1371342672, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721979518514, + "link": null, + "locked": false, + "startBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": -1.0544694371314034, + "gap": 3.5954323396749857 + }, + "endBinding": { + "elementId": "_VXIQppCSNb6MIFQLmDdy", + "focus": 0.31663537700287836, + "gap": 1.9911615284421913 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 107.2195285426966, + -95.35691573040356 + ], + [ + 82.94381595386449, + -7.418196168042471 + ] + ] + }, + { + "type": "text", + "version": 1314, + "versionNonce": 863552848, + "index": "ac", + "isDeleted": false, + "id": "apwBA2F8OsZLAT7p6l1JS", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 609.4229227304459, + "y": -79.25318690708701, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 569.839707493782, + "height": 40, + "seed": 1979332528, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721979490056, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 1, + "text": "If proposal fails,\nthen owner = previous owner (the one that signed MsgRegisterConsumer)", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "If proposal fails,\nthen owner = previous owner (the one that signed MsgRegisterConsumer)", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "pwlxDMNk9SimSRoZRuyV3", + "type": "line", + "x": 256.2591145833333, + "y": 1317.2654695056733, + "width": 1658.3805338541667, + "height": 0.078125, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "ae", + "roundness": { + "type": 2 + }, + "seed": 1129032624, + "version": 772, + "versionNonce": 266696112, + "isDeleted": false, + "boundElements": null, + "updated": 1721980422671, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 1658.3805338541667, + 0.078125 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": null + }, + { + "id": "-xwyxjAJM89xAkUi-pWLB", + "type": "line", + "x": 269.35481770833337, + "y": 1261.0252351306735, + "width": 0, + "height": 124.8681640625, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "af", + "roundness": { + "type": 2 + }, + "seed": 659246416, + "version": 379, + "versionNonce": 957038512, + "isDeleted": false, + "boundElements": null, + "updated": 1721980422671, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": null + }, + { + "type": "line", + "version": 552, + "versionNonce": 250071472, + "index": "ag", + "isDeleted": false, + "id": "AFDJ07skaLW7VCALYMDj4", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 760.7334914470289, + "y": 1257.3100290018028, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1945500592, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 835, + "versionNonce": 1285755824, + "index": "ah", + "isDeleted": false, + "id": "hDPzA0-vpS0ilSkphkeAA", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1002.3254193314633, + "y": 1269.644565149432, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1257497936, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "id": "5RtUeYj4dxxweAu88pxEc", + "type": "arrow", + "x": 1824.390625, + "y": 1297.1385163806735, + "width": 88.623046875, + "height": 0, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "ai", + "roundness": { + "type": 2 + }, + "seed": 557184848, + "version": 627, + "versionNonce": 140844464, + "isDeleted": false, + "boundElements": null, + "updated": 1721980422671, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 88.623046875, + 0 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": "arrow" + }, + { + "id": "TCPMJfrcd92gSR4Q6cE6S", + "type": "text", + "x": 1845.7822265625, + "y": 1273.2810945056735, + "width": 40.63996636867523, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aj", + "roundness": null, + "seed": 1234376112, + "version": 694, + "versionNonce": 1398138800, + "isDeleted": false, + "boundElements": null, + "updated": 1721980422671, + "link": null, + "locked": false, + "text": "time", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "time", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "cJmAKusziodsDR6vwTHJd", + "type": "text", + "x": 213.76562500000006, + "y": 1198.4617585681735, + "width": 227.99981439113617, + "height": 50, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "ak", + "roundness": null, + "seed": 844025168, + "version": 653, + "versionNonce": 1503490480, + "isDeleted": false, + "boundElements": null, + "updated": 1721980422671, + "link": null, + "locked": false, + "text": "MsgRegisterConsumer\nto get the consumer id", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgRegisterConsumer\nto get the consumer id", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 717, + "versionNonce": 40090544, + "index": "al", + "isDeleted": false, + "id": "GastODl-l38mFb5oaAEbj", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 665.4558410644531, + "y": 1198.011929466611, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 210.61980283260345, + "height": 50, + "seed": 44005200, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgInitializeConsumer\nwith spawnTime, etc.", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgInitializeConsumer\nwith spawnTime, etc.", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 801, + "versionNonce": 265340336, + "index": "am", + "isDeleted": false, + "id": "kXfBgGvtmnfZCVwG1uG9V", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 935.2071304321289, + "y": 1199.574429466611, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 224.29981744289398, + "height": 50, + "seed": 2087774640, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgUpdateConsumer\nto set power cap, etc.", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgUpdateConsumer\nto set power cap, etc.", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 966, + "versionNonce": 1057787824, + "index": "an", + "isDeleted": false, + "id": "E1QM7dtsigeuyGX9zwvE0", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1220.2525985836983, + "y": 1202.250210716611, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 242.3997710943222, + "height": 50, + "seed": 608854864, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgInitializeConsumer to\nmodify spawnTime", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgInitializeConsumer to\nmodify spawnTime", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 688, + "versionNonce": 1748965808, + "index": "ao", + "isDeleted": false, + "id": "Wm2pyI04tXykKntCeM85W", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1307.6379193314638, + "y": 1266.2113376103696, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1967873456, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "id": "pfUxn633PL7PLmo5UBP83", + "type": "rectangle", + "x": 273.84472656250006, + "y": 1317.1248851957778, + "width": 480.92285156250006, + "height": 81.1279296875, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e7f5ff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "groupIds": [], + "frameId": null, + "index": "ap", + "roundness": { + "type": 3 + }, + "seed": 394410832, + "version": 657, + "versionNonce": 512779184, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "ZxRHa3OTec0AyDpAifqQw" + } + ], + "updated": 1721980422671, + "link": null, + "locked": false + }, + { + "id": "ZxRHa3OTec0AyDpAifqQw", + "type": "text", + "x": 429.95622801780706, + "y": 1345.1888500395278, + "width": 168.699848651886, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "groupIds": [], + "frameId": null, + "index": "aq", + "roundness": null, + "seed": 1250610096, + "version": 421, + "versionNonce": 1344826800, + "isDeleted": false, + "boundElements": null, + "updated": 1721980422671, + "link": null, + "locked": false, + "text": "Registered phase", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "pfUxn633PL7PLmo5UBP83", + "originalText": "Registered phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1004, + "versionNonce": 1714370480, + "index": "ar", + "isDeleted": false, + "id": "uVblxWqL6Msu5umb9eTvZ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 758.35302734375, + "y": 1318.302456810361, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 660.1660156250001, + "height": 81.1279296875, + "seed": 229232464, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "s-LIv7Mo1IvDb89Gr0uSQ" + } + ], + "updated": 1721980422671, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 782, + "versionNonce": 1691140528, + "index": "as", + "isDeleted": false, + "id": "s-LIv7Mo1IvDb89Gr0uSQ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1007.056105658412, + "y": 1346.366421654111, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 162.75985899567604, + "height": 25, + "seed": 1548969296, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422671, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Initialized phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "uVblxWqL6Msu5umb9eTvZ", + "originalText": "Initialized phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 863, + "versionNonce": 2067805008, + "index": "at", + "isDeleted": false, + "id": "zXqjQ2rE_UbSjEHOyMDw3", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1422.1748893529827, + "y": 1318.9168052711786, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 618764720, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980681550, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "text", + "version": 1091, + "versionNonce": 1936463280, + "index": "au", + "isDeleted": false, + "id": "aVp4yECj00-fGLMn7sHnD", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1309.797184765339, + "y": 1450.599820091611, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 177.4198455810547, + "height": 75, + "seed": 1447447888, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422672, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "spawnTime passed\nand at least one\nvalidator opted in", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "spawnTime passed\nand at least one\nvalidator opted in", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1091, + "versionNonce": 851304368, + "index": "ax", + "isDeleted": false, + "id": "s6qt0UIRPRSbMwetkDFg_", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1609.481927216053, + "y": 1212.733609154111, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 202.41985833644867, + "height": 50, + "seed": 1340941744, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422672, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgUpdateConsumer\nto change power cap", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgUpdateConsumer\nto change power cap", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 985, + "versionNonce": 2034657712, + "index": "ay", + "isDeleted": false, + "id": "RRDK6Jp-NdnWMWtYGDDli", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1745.1088831870024, + "y": 1272.6322796427069, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 154253232, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980422672, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "rectangle", + "version": 1016, + "versionNonce": 841855920, + "index": "az", + "isDeleted": false, + "id": "4ZMVPnrnF1Dfj8ono67tv", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1425.8107096354167, + "y": 1320.40939512673, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 475.03417968750034, + "height": 79.30663117976157, + "seed": 66445648, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "KC5zECj3By5dDU8JFhAep" + } + ], + "updated": 1721980422672, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 810, + "versionNonce": 597409200, + "index": "b00", + "isDeleted": false, + "id": "KC5zECj3By5dDU8JFhAep", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1587.763779918353, + "y": 1347.7777356509237, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 151.1280391216278, + "height": 24.569950131374355, + "seed": 323827536, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980422672, + "link": null, + "locked": false, + "fontSize": 19.655960105099485, + "fontFamily": 1, + "text": "Launched phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "4ZMVPnrnF1Dfj8ono67tv", + "originalText": "Launched phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 771, + "versionNonce": 1263014832, + "index": "b01", + "isDeleted": false, + "id": "7Bq_OzmNwUc0GxjMxTYNY", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 265.25883719345677, + "y": 1666.5525788806733, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 1658.3805338541667, + "height": 0.078125, + "seed": 255347024, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1658.3805338541667, + 0.078125 + ] + ] + }, + { + "type": "line", + "version": 400, + "versionNonce": 1785339312, + "index": "b02", + "isDeleted": false, + "id": "OvebgcABs_rLQivf-TBk2", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 278.3545403184568, + "y": 1610.3123445056733, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1510121296, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 573, + "versionNonce": 750446512, + "index": "b03", + "isDeleted": false, + "id": "4C8GcmxoE4N2CEFpbetdn", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 769.7332140571524, + "y": 1606.5971383768026, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1158821200, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 856, + "versionNonce": 1046639024, + "index": "b04", + "isDeleted": false, + "id": "nHS8CykAzRlhhatMaNhMu", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1011.3251419415867, + "y": 1618.931674524432, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 364841808, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "arrow", + "version": 626, + "versionNonce": 109624240, + "index": "b05", + "isDeleted": false, + "id": "Fs9vTDdorvwlcYw_ubAa_", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1833.3903476101234, + "y": 1646.4256257556733, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 88.623046875, + "height": 0, + "seed": 643899728, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 88.623046875, + 0 + ] + ] + }, + { + "type": "text", + "version": 715, + "versionNonce": 1196803504, + "index": "b06", + "isDeleted": false, + "id": "l3WpHc1Tm8DmkYOar2yuc", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1854.7819491726234, + "y": 1622.5682038806733, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 40.63996636867523, + "height": 25, + "seed": 1179678544, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "time", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "time", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 674, + "versionNonce": 1039241136, + "index": "b07", + "isDeleted": false, + "id": "HVWEVkdCna3gjxJRN-dCZ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 222.7653476101235, + "y": 1547.7488679431735, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 227.99981439113617, + "height": 50, + "seed": 434441552, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgRegisterConsumer\nto get the consumer id", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgRegisterConsumer\nto get the consumer id", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 877, + "versionNonce": 1115953584, + "index": "b08", + "isDeleted": false, + "id": "jpeMZ5SS2jgAqO9FZB17B", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 672.7954074245766, + "y": 1496.999559674944, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 237.25982177257538, + "height": 100, + "seed": 2054611792, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "issue governance\nproposal with\nMsgInitializeConsumer\nand MsgUpdateconsumer", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "issue governance\nproposal with\nMsgInitializeConsumer\nand MsgUpdateconsumer", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 907, + "versionNonce": 1748329392, + "index": "b09", + "isDeleted": false, + "id": "zmw1PyM5vZzw3eZp9f19w", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 936.9607592922523, + "y": 1583.112840924944, + "strokeColor": "#e03131", + "backgroundColor": "transparent", + "width": 170.7798352241516, + "height": 25, + "seed": 1448999248, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "proposal rejected", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "proposal rejected", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1152, + "versionNonce": 489516464, + "index": "b0C", + "isDeleted": false, + "id": "ajHAAKi9tSoXcIkv3aA4L", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 277.09965750595677, + "y": 1665.9562654041108, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e7f5ff", + "width": 1646.6975911458337, + "height": 81.1279296875, + "seed": 948091728, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "2HQsEKAeWiKi5szJa8Io6" + } + ], + "updated": 1721980676778, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 916, + "versionNonce": 1251227568, + "index": "b0D", + "isDeleted": false, + "id": "2HQsEKAeWiKi5szJa8Io6", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1016.0985287529306, + "y": 1694.0202302478608, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 168.699848651886, + "height": 25, + "seed": 355389776, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Registered phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ajHAAKi9tSoXcIkv3aA4L", + "originalText": "Registered phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1323, + "versionNonce": 515241808, + "index": "b0E", + "isDeleted": false, + "id": "o16fHdthOp80uqAN-KkL2", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1015.8097812038734, + "y": 2025.532274518694, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffec99", + "width": 415.0227864583335, + "height": 81.1279296875, + "seed": 1877485392, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "348R4_XQcWAs6CAl4OV_w" + } + ], + "updated": 1721980415621, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1102, + "versionNonce": 1234865488, + "index": "b0F", + "isDeleted": false, + "id": "348R4_XQcWAs6CAl4OV_w", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1141.9412449352021, + "y": 2053.596239362444, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 162.75985899567604, + "height": 25, + "seed": 352763216, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Initialized phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "o16fHdthOp80uqAN-KkL2", + "originalText": "Initialized phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 897, + "versionNonce": 394027856, + "index": "b0M", + "isDeleted": false, + "id": "jAITNaSlDtSPpvQwpBfRJ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 267.98783052464313, + "y": 2020.76074945359, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 1658.3805338541667, + "height": 0.078125, + "seed": 124954448, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1658.3805338541667, + 0.078125 + ] + ] + }, + { + "type": "line", + "version": 504, + "versionNonce": 917731664, + "index": "b0N", + "isDeleted": false, + "id": "akYH8jPOSYYHRJ0kHn6SF", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 281.08353364964324, + "y": 1964.52051507859, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1463893328, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 677, + "versionNonce": 1251462992, + "index": "b0O", + "isDeleted": false, + "id": "Qds67yg8nIFlUKrTZNb8v", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 772.4622073883388, + "y": 1960.8053089497193, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 483201872, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "line", + "version": 960, + "versionNonce": 1266771280, + "index": "b0P", + "isDeleted": false, + "id": "jtzT1eH8RZn8QwNepmt_H", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1014.054135272773, + "y": 1973.1398450973488, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 778971472, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "arrow", + "version": 752, + "versionNonce": 1724398416, + "index": "b0Q", + "isDeleted": false, + "id": "8lhkFCwtbNTRFlmWeRE4n", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1836.1193409413095, + "y": 2000.63379632859, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 88.623046875, + "height": 0, + "seed": 1467776848, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 88.623046875, + 0 + ] + ] + }, + { + "type": "text", + "version": 819, + "versionNonce": 1589924176, + "index": "b0R", + "isDeleted": false, + "id": "CsZ965_KJ8mkVhd3JJHe6", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1857.5109425038095, + "y": 1976.77637445359, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 40.63996636867523, + "height": 25, + "seed": 944772432, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "time", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "time", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 778, + "versionNonce": 1791862608, + "index": "b0S", + "isDeleted": false, + "id": "VptrXV13wo5wjJkN_HnlZ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 225.49434094130987, + "y": 1901.9570385160905, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 227.99981439113617, + "height": 50, + "seed": 641788752, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgRegisterConsumer\nto get the consumer id", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgRegisterConsumer\nto get the consumer id", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1003, + "versionNonce": 389823824, + "index": "b0T", + "isDeleted": false, + "id": "i7B5C0pGmcgSuCqx5vRQP", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 675.524400755763, + "y": 1851.207730247861, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 237.25982177257538, + "height": 100, + "seed": 195494224, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "issue governance\nproposal with\nMsgInitializeConsumer\nand MsgUpdateconsumer", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "issue governance\nproposal with\nMsgInitializeConsumer\nand MsgUpdateconsumer", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1017, + "versionNonce": 623782224, + "index": "b0U", + "isDeleted": false, + "id": "KtxOQmQoRm5cuPDQBNvU5", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 939.6897526234386, + "y": 1937.321011497861, + "strokeColor": "#2f9e44", + "backgroundColor": "transparent", + "width": 156.959858417511, + "height": 25, + "seed": 1205491536, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980635662, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "proposal passes", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "proposal passes", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1270, + "versionNonce": 1806248272, + "index": "b0X", + "isDeleted": false, + "id": "aqECH_oHGd4F7Pq9jBCpa", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 279.82865083714313, + "y": 2020.1644359770276, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e7f5ff", + "width": 731.2353515625001, + "height": 81.1279296875, + "seed": 2041829712, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "J8GsOJGu4wkpH9e3dq06b" + } + ], + "updated": 1721980415621, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1034, + "versionNonce": 894926672, + "index": "b0Y", + "isDeleted": false, + "id": "J8GsOJGu4wkpH9e3dq06b", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 561.0964022924502, + "y": 2048.2284008207776, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 168.699848651886, + "height": 25, + "seed": 244068176, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Registered phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "aqECH_oHGd4F7Pq9jBCpa", + "originalText": "Registered phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 991, + "versionNonce": 2012467536, + "index": "b0Z", + "isDeleted": false, + "id": "jepmnNxu-8rBXJjZKYZKQ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1434.8150636276262, + "y": 2021.9498456357614, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1374274896, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980684670, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "text", + "version": 1224, + "versionNonce": 550960976, + "index": "b0a", + "isDeleted": false, + "id": "prbzcGXJPRqkOVsHpdbs4", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1320.214702789982, + "y": 2151.3216625395276, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 177.4198455810547, + "height": 75, + "seed": 1092918096, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980686051, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "spawnTime passed\nand at least one\nvalidator opted in", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "spawnTime passed\nand at least one\nvalidator opted in", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 1327, + "versionNonce": 1288511920, + "index": "b0b", + "isDeleted": false, + "id": "4_i6jup_6Cze3xommPSgL", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1494.9671535740297, + "y": 1916.495816185361, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 231.69981133937836, + "height": 50, + "seed": 1855238480, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980692762, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "MsgUpdateConsumer\nto change denylist, etc.", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "MsgUpdateConsumer\nto change denylist, etc.", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "line", + "version": 1250, + "versionNonce": 1557995440, + "index": "b0c", + "isDeleted": false, + "id": "G9GGcs9_A9FENDJhK85f5", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1581.264682461645, + "y": 1974.519486673957, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 0, + "height": 124.8681640625, + "seed": 1636960080, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721980691478, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 124.8681640625 + ] + ] + }, + { + "type": "rectangle", + "version": 1141, + "versionNonce": 1680731472, + "index": "b0d", + "isDeleted": false, + "id": "TuSGExogIwVLdWKpZuLEE", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1437.5394255767267, + "y": 2023.904675074647, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 475.03417968750034, + "height": 79.30663117976157, + "seed": 1987353936, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "Kha-a5kyL8kweb2LvlPtp" + } + ], + "updated": 1721980415621, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 936, + "versionNonce": 1218691920, + "index": "b0e", + "isDeleted": false, + "id": "Kha-a5kyL8kweb2LvlPtp", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1599.492495859663, + "y": 2051.2730155988406, + "strokeColor": "#1e1e1e", + "backgroundColor": "#a5d8ff", + "width": 151.1280391216278, + "height": 24.569950131374355, + "seed": 1049916240, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980415621, + "link": null, + "locked": false, + "fontSize": 19.655960105099485, + "fontFamily": 1, + "text": "Launched phase", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "TuSGExogIwVLdWKpZuLEE", + "originalText": "Launched phase", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "UyHfZ2VJGqV1pDsuTD9cV", + "type": "text", + "x": -108.94270833333303, + "y": 1338.8350902739019, + "width": 341.5998840332031, + "height": 70, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "groupIds": [], + "frameId": null, + "index": "b0f", + "roundness": null, + "seed": 723455312, + "version": 408, + "versionNonce": 396094800, + "isDeleted": false, + "boundElements": null, + "updated": 1721981143713, + "link": null, + "locked": false, + "text": "successful launch of an \nOpt In chain", + "fontSize": 28, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "successful launch of an \nOpt In chain", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 510, + "versionNonce": 1955709360, + "index": "b0g", + "isDeleted": false, + "id": "4n5NjjKLCJsk7c-7uAWhd", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": -50.64974466959666, + "y": 1661.4197256905686, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 263.73187255859375, + "height": 70, + "seed": 1223292336, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980676778, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "failed launch of a \nTop N chain", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "failed launch of a \nTop N chain", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "text", + "version": 577, + "versionNonce": 2112613712, + "index": "b0h", + "isDeleted": false, + "id": "vr9GdN-bw_UUQefiVts9a", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": -83.6536966959635, + "y": 2032.7738923572358, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 328.5238952636719, + "height": 70, + "seed": 1698232144, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1721980468104, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "successful launch of a \nTop N chain", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "successful launch of a \nTop N chain", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "udO72dQy2VH8wQm_dcFbx", + "type": "line", + "x": 290.74479166666686, + "y": 2111.0854564848396, + "width": 156.04817708333314, + "height": 104.58333333333394, + "angle": 0, + "strokeColor": "#e03131", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 60, + "groupIds": [], + "frameId": null, + "index": "b0l", + "roundness": { + "type": 2 + }, + "seed": 1863593392, + "version": 301, + "versionNonce": 1529007952, + "isDeleted": false, + "boundElements": null, + "updated": 1721981217963, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 156.04817708333314, + 104.58333333333394 + ] + ], + "lastCommittedPoint": null, + "startBinding": null, + "endBinding": null, + "startArrowhead": null, + "endArrowhead": null + }, + { + "type": "line", + "version": 598, + "versionNonce": 1734852016, + "index": "b0m", + "isDeleted": false, + "id": "zHhFHMZyTd9z3sepnFUy8", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 60, + "angle": 0, + "x": 1012.4072684983414, + "y": 2107.4292076232887, + "strokeColor": "#e03131", + "backgroundColor": "#b2f2bb", + "width": 205.91796875000023, + "height": 134.21875, + "seed": 1304021840, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1721981220095, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -205.91796875000023, + 134.21875 + ] + ] + }, + { + "id": "0kk2QokOsQCRZigvw5I2z", + "type": "text", + "x": 460.60807291666663, + "y": 2199.17139398484, + "width": 395.6397705078125, + "height": 140, + "angle": 0, + "strokeColor": "#e03131", + "backgroundColor": "#b2f2bb", + "fillStyle": "solid", + "strokeWidth": 4, + "strokeStyle": "dashed", + "roughness": 1, + "opacity": 60, + "groupIds": [], + "frameId": null, + "index": "b0n", + "roundness": null, + "seed": 1799721904, + "version": 219, + "versionNonce": 205377456, + "isDeleted": false, + "boundElements": null, + "updated": 1721981246158, + "link": null, + "locked": false, + "text": "NO MsgInitializeConsumer\nor MsgUpdateConsumer\nshould be executed as \ntransactions during this time", + "fontSize": 28, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "NO MsgInitializeConsumer\nor MsgUpdateConsumer\nshould be executed as \ntransactions during this time", + "autoResize": true, + "lineHeight": 1.25 + } + ], + "appState": { + "gridSize": null, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/docs/docs/adrs/figures/adr19_phases_of_a_consumer_chain.png b/docs/docs/adrs/figures/adr19_phases_of_a_consumer_chain.png new file mode 100644 index 0000000000..ce6eb8c451 Binary files /dev/null and b/docs/docs/adrs/figures/adr19_phases_of_a_consumer_chain.png differ diff --git a/docs/docs/adrs/intro.md b/docs/docs/adrs/intro.md index a1dac24771..c1a494f99e 100644 --- a/docs/docs/adrs/intro.md +++ b/docs/docs/adrs/intro.md @@ -41,12 +41,14 @@ To suggest an ADR, please make use of the [ADR template](https://github.com/cosm - [ADR 013: Slashing on the provider for consumer equivocation](./adr-013-equivocation-slashing.md) - [ADR 014: Epochs](./adr-014-epochs.md) - [ADR 015: Partial Set Security](./adr-015-partial-set-security.md) +- [ADR 017: ICS with Inactive Provider Validators](./adr-017-allowing-inactive-validators.md) +- [ADR 018: Remove VSCMatured Packets](./adr-018-remove-vscmatured.md) +- [ADR 18: Permissionless Interchain Security](./adr-019-permissionless-ics.md) ### Proposed - [ADR 011: Improving testing and increasing confidence](./adr-011-improving-test-confidence.md) - [ADR 016: Security aggregation](./adr-016-securityaggregation.md) -- [ADR 017: ICS with Inactive Provider Validators](./adr-017-allowing-inactive-validators.md) ### Rejected diff --git a/docs/docs/features/partial-set-security.md b/docs/docs/features/partial-set-security.md index 4e221583b5..b18de22b4e 100644 --- a/docs/docs/features/partial-set-security.md +++ b/docs/docs/features/partial-set-security.md @@ -4,7 +4,7 @@ sidebar_position: 6 # Partial Set Security -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: +Partial Set Security (PSS) is a complete revamp of the Hub's security offering. It allows consumer chains to leverage only a subset of validators from the provider chain, which offers more flexibility than the previous Replicated Security model. By introducing the top_N parameter, each consumer chain can choose the extent of security needed: * 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. @@ -12,22 +12,23 @@ Partial Set Security (PSS) allows consumer chains to leverage only a subset of v 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. -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. -However, 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. +Opt-In chains, on the other hand, are more flexible. Validators are never forced to validate these chains and simply opt in if they want to. At the moment, opt-in chains still require a governance proposal, but this will be removed in the next release, allowing chains to launch completely permissionlessly. However, 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. :::tip 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. ::: :::caution -Both Opt In and Top N chains currently require a governance proposal to be added to the provider chain. -For Top N chains, this is also the long term vision for how they are launched. +Top N chains always require a governance proposal because they force the top N +validators to run the chain. -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. +As a temporary measure, Opt In chains also require a governance proposal, but this will be removed in the next release, making Opt In chains completely permissionless. + +The reason Opt In chains currently require a governance prop is 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. 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. ::: :::tip A running Top N consumer chain might want to become an Opt-In chain or vice versa. This can be achieved by issuing a [`ConsumerModificationProposal`](./proposals.md#consumermodificationproposal). -::: \ No newline at end of file +::: diff --git a/docs/docs/frequently-asked-questions.md b/docs/docs/frequently-asked-questions.md index 27623d22f6..2183f74c26 100644 --- a/docs/docs/frequently-asked-questions.md +++ b/docs/docs/frequently-asked-questions.md @@ -134,4 +134,15 @@ By setting the commission rate ahead of time, they can make sure that they immed Yes, by issuing a [`ConsumerModificationProposal`](./features/proposals.md#consumermodificationproposal). ## Can a Top N consumer chain become Opt-In or vice versa? -Yes, by issuing a [`ConsumerModificationProposal`](./features/proposals.md#consumermodificationproposal). \ No newline at end of file +Yes, by issuing a [`ConsumerModificationProposal`](./features/proposals.md#consumermodificationproposal). + +## How do I know when the next validator update will be sent to the consumer chain? +Validator updates are sent to the consumer chain every `BlocksPerEpoch` blocks. +Keep in mind that depending on the status of relayers between the Hub and the consumer chain, +it might take a while for the validator update to be processed and applied on the consumer chain. + +To query how many blocks are left until the next epoch starts, +run the following command: +```bash +interchain-security-pd query provider blocks-until-next-epoch +``` \ No newline at end of file diff --git a/docs/docs/index.mdx b/docs/docs/index.mdx index 2086a4f384..576da1feee 100644 --- a/docs/docs/index.mdx +++ b/docs/docs/index.mdx @@ -6,9 +6,13 @@ import CardSection from '/src/components/Cards/CardSection'; import homeCards from '/src/components/Cards/card-data/home-cards'; -# Interchain Security Docs +# Cosmos Hub - Interchain Security -Welcome to the official Interchain Security module documentation for Cosmos-SDK based chains. +Welcome to the official documentation for the Cosmos Hub's Interchain Security - a platform for launching Cosmos-SDK chains. + +*The Cosmos Hub is the best place to launch a chain.* + +With the recent launch of [Partial Set Security](/features/partial-set-security) (PSS), it's easier than ever to leverage the Cosmos Hub validators, stake, and community for your chain. PSS provides powerful new capabilities for permissionlessly launching your chain and [shaping your validator set](/features/power-shaping). Here you can find information about Interchain Security, consumer chain development and instructions for validator onboarding. diff --git a/docs/docs/introduction/params.md b/docs/docs/introduction/params.md index 8d917b3070..3b52e772ab 100644 --- a/docs/docs/introduction/params.md +++ b/docs/docs/introduction/params.md @@ -61,21 +61,6 @@ CCVTimeoutPeriod may have different values on the provider and consumer chains. - `CCVTimeoutPeriod` on the provider **must** be larger than `ConsumerUnbondingPeriod` - `CCVTimeoutPeriod` on the consumer is initial set via the `ConsumerAdditionProposal` -### InitTimeoutPeriod -`InitTimeoutPeriod` is the maximum allowed duration for CCV channel initialization to execute. - -For any consumer chain, if the CCV channel is not established within `InitTimeoutPeriod` then the consumer chain will be removed and therefore will not be secured by the provider chain. - -The countdown starts when the `spawn_time` specified in the `ConsumerAdditionProposal` is reached. - -### VscTimeoutPeriod -`VscTimeoutPeriod` is the provider-side param that enables the provider to timeout VSC packets even when a consumer chain is not live. -If the `VscTimeoutPeriod` is ever reached for a consumer chain that chain will be considered not live and removed from interchain security. - -:::tip -`VscTimeoutPeriod` MUST be larger than the `ConsumerUnbondingPeriod`. -::: - ### BlocksPerDistributionTransmission `BlocksPerDistributionTransmission` is the number of blocks between rewards transfers from the consumer to the provider. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 7dcd1e5133..1f3b46069e 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -39,6 +39,7 @@ const config = { docs: { sidebarPath: require.resolve("./sidebars.js"), routeBasePath: "/", + lastVersion: "current", remarkPlugins: [remarkMath], rehypePlugins: [rehypeKatex], exclude: ["**/templates/*"], diff --git a/go.mod b/go.mod index 5a7eaa9368..6f5acbb8e5 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/spf13/cast v1.6.0 github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.9.0 - github.com/tidwall/gjson v1.17.1 + github.com/tidwall/gjson v1.17.2 golang.org/x/crypto v0.23.0 // indirect golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 golang.org/x/net v0.25.0 // indirect @@ -156,7 +156,7 @@ require ( cosmossdk.io/x/upgrade v0.1.1 github.com/cosmos/cosmos-db v1.0.2 github.com/cosmos/ibc-go/modules/capability v1.0.0 - github.com/cosmos/ibc-go/v8 v8.3.2 + github.com/cosmos/ibc-go/v8 v8.4.0 github.com/informalsystems/itf-go v0.0.1 github.com/spf13/viper v1.18.2 golang.org/x/mod v0.17.0 diff --git a/go.sum b/go.sum index a8880a7291..4180fc34ae 100644 --- a/go.sum +++ b/go.sum @@ -357,8 +357,8 @@ github.com/cosmos/iavl v1.1.2 h1:zL9FK7C4L/P4IF1Dm5fIwz0WXCnn7Bp1M2FxH0ayM7Y= github.com/cosmos/iavl v1.1.2/go.mod h1:jLeUvm6bGT1YutCaL2fIar/8vGUE8cPZvh/gXEWDaDM= github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE= github.com/cosmos/ibc-go/modules/capability v1.0.0/go.mod h1:D81ZxzjZAe0ZO5ambnvn1qedsFQ8lOwtqicG6liLBco= -github.com/cosmos/ibc-go/v8 v8.3.2 h1:8X1oHHKt2Bh9hcExWS89rntLaCKZp2EjFTUSxKlPhGI= -github.com/cosmos/ibc-go/v8 v8.3.2/go.mod h1:WVVIsG39jGrF9Cjggjci6LzySyWGloz194sjTxiGNIE= +github.com/cosmos/ibc-go/v8 v8.4.0 h1:K2PfX0AZ+1XKZytHGEMuSjQXG/MZshPb83RSTQt2+cE= +github.com/cosmos/ibc-go/v8 v8.4.0/go.mod h1:zh6x1osR0hNvEcFrC/lhGD08sMfQmr9wHVvZ/mRWMCs= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= @@ -998,8 +998,8 @@ github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2l github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= -github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= -github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.2 h1:YlBFFaxZdSXKP8zhqh5CRbk0wL7oCAU3D+JJLU5pE7U= +github.com/tidwall/gjson v1.17.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= diff --git a/proto/interchain_security/ccv/provider/v1/genesis.proto b/proto/interchain_security/ccv/provider/v1/genesis.proto index 80e9ee0cf8..f3c6d3da43 100644 --- a/proto/interchain_security/ccv/provider/v1/genesis.proto +++ b/proto/interchain_security/ccv/provider/v1/genesis.proto @@ -11,6 +11,21 @@ import "interchain_security/ccv/provider/v1/provider.proto"; // GenesisState defines the CCV provider chain genesis state message GenesisState { + // Reserve 3rd slot for removed unbonding_ops field + reserved 3; + + // Reserve 4th slot for removed mature_unbonding_ops field + reserved 4; + + // Reserve 11th slot for consumer_addrs_to_prune field + reserved 11; + + // Reserve 12th slot for removed init_timeout_timestamps field + reserved 12; + + // Reserve 13th slot for removed exported_vsc_send_timestamps field + reserved 13; + // strictly positive and set to 1 (DefaultValsetUpdateID) for a new chain uint64 valset_update_id = 1; // empty for a new chain @@ -19,11 +34,6 @@ message GenesisState { (gogoproto.moretags) = "yaml:\"consumer_states\"" ]; // empty for a new chain - repeated interchain_security.ccv.provider.v1.UnbondingOp unbonding_ops = 3 - [ (gogoproto.nullable) = false ]; - // empty for a new chain - interchain_security.ccv.provider.v1.MaturedUnbondingOps mature_unbonding_ops = 4; - // empty for a new chain repeated ValsetUpdateIdToHeight valset_update_id_to_height = 5 [ (gogoproto.nullable) = false ]; // empty for a new chain @@ -39,17 +49,12 @@ message GenesisState { // empty for a new chain repeated ValidatorByConsumerAddr validators_by_consumer_addr = 10 [ (gogoproto.nullable) = false ]; - // empty for a new chain - repeated ConsumerAddrsToPrune consumer_addrs_to_prune = 11 - [ (gogoproto.nullable) = false ]; - repeated interchain_security.ccv.provider.v1.InitTimeoutTimestamp init_timeout_timestamps = 12 - [ (gogoproto.nullable) = false ]; - - repeated interchain_security.ccv.provider.v1.ExportedVscSendTimestamp exported_vsc_send_timestamps = 13 + // empty for a new chain + repeated ConsumerAddrsToPruneV2 consumer_addrs_to_prune_v2 = 14 [ (gogoproto.nullable) = false ]; - repeated ConsensusValidator last_provider_consensus_validators = 14 + repeated ConsensusValidator last_provider_consensus_validators = 15 [ (gogoproto.nullable) = false ]; } @@ -57,6 +62,9 @@ message GenesisState { // // Note this type is only used internally to the provider CCV module. message ConsumerState { + // Reserve 8th slot for removed unbonding_ops_index field + reserved 8; + // ChainID defines the chain ID for the consumer chain string chain_id = 1; // ChannelID defines the IBC channel ID for the consumer chain @@ -73,10 +81,6 @@ message ConsumerState { repeated interchain_security.ccv.v1.ValidatorSetChangePacketData pending_valset_changes = 6 [ (gogoproto.nullable) = false ]; repeated string slash_downtime_ack = 7; - // UnbondingOpsIndex defines the unbonding operations waiting on this consumer - // chain - repeated interchain_security.ccv.provider.v1.VscUnbondingOps - unbonding_ops_index = 8 [ (gogoproto.nullable) = false ]; } // ValsetUpdateIdToHeight defines the genesis information for the mapping diff --git a/proto/interchain_security/ccv/provider/v1/provider.proto b/proto/interchain_security/ccv/provider/v1/provider.proto index 76adf80bd9..7e1836cf38 100644 --- a/proto/interchain_security/ccv/provider/v1/provider.proto +++ b/proto/interchain_security/ccv/provider/v1/provider.proto @@ -223,6 +223,12 @@ message GlobalSlashEntry { // Params defines the parameters for CCV Provider module message Params { + // Reserve 4th slot for removed init_timeout_period param + reserved 4; + + // Reserve 5th slot for removed vsc_timeout_period param + reserved 5; + // Reserve 8th slot for removed max throttled packet param reserved 8; @@ -233,16 +239,6 @@ message Params { // Sent IBC packets will timeout after this duration google.protobuf.Duration ccv_timeout_period = 3 [ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ]; - // The channel initialization (IBC channel opening handshake) will timeout - // after this duration - google.protobuf.Duration init_timeout_period = 4 - [ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ]; - // The VSC packets sent by the provider will timeout after this duration. - // Note that unlike ccv_timeout_period which is an IBC param, - // the vsc_timeout_period is a provider-side param that enables the provider - // to timeout VSC packets even when a consumer chain is not live. - google.protobuf.Duration vsc_timeout_period = 5 - [ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ]; // The period for which the slash meter is replenished google.protobuf.Duration slash_meter_replenish_period = 6 @@ -295,49 +291,12 @@ message ChannelToChain { string chain_id = 2; } -// VscUnbondingOps contains the IDs of unbonding operations that are waiting for -// at least one VSCMaturedPacket with vscID from a consumer chain -message VscUnbondingOps { - uint64 vsc_id = 1; - repeated uint64 unbonding_op_ids = 2; -} - -// UnbondingOp contains the ids of consumer chains that need to unbond before -// the unbonding operation with the given ID can unbond -message UnbondingOp { - uint64 id = 1; - // consumer chains that are still unbonding - repeated string unbonding_consumer_chains = 2; -} - -message InitTimeoutTimestamp { - string chain_id = 1; - uint64 timestamp = 2; -} - -message VscSendTimestamp { - uint64 vsc_id = 1; - google.protobuf.Timestamp timestamp = 2 - [ (gogoproto.stdtime) = true, (gogoproto.nullable) = false ]; -} - // ValidatorSetChangePackets is a pb list of ccv.ValidatorSetChangePacketData. message ValidatorSetChangePackets { repeated interchain_security.ccv.v1.ValidatorSetChangePacketData list = 1 [ (gogoproto.nullable) = false ]; } -// MaturedUnbondingOps defines a list of ids corresponding to ids of matured -// unbonding operations. -message MaturedUnbondingOps { repeated uint64 ids = 1; } - -// ExportedVscSendTimestamps is VscSendTimestamp with chainID info for exporting to genesis -message ExportedVscSendTimestamp { - string chain_id = 1; - repeated VscSendTimestamp vsc_send_timestamps = 2 - [ (gogoproto.nullable) = false ]; -} - // // Key assignment section // @@ -366,11 +325,12 @@ message ValidatorByConsumerAddr { bytes provider_addr = 3; } -// Used to serialize the ConsumerAddrsToPrune index from key assignment -// ConsumerAddrsToPrune: (chainID, vscID uint64) -> consumerAddrs AddressList -message ConsumerAddrsToPrune { +// Used to serialize the ConsumerAddrsToPruneV2 index from key assignment +// ConsumerAddrsToPruneV2: (chainID, pruneTs time.Time) -> consumerAddrs AddressList +message ConsumerAddrsToPruneV2 { string chain_id = 1; - uint64 vsc_id = 2; + google.protobuf.Timestamp prune_ts = 2 + [ (gogoproto.stdtime) = true, (gogoproto.nullable) = false ]; AddressList consumer_addrs = 3; } diff --git a/proto/interchain_security/ccv/provider/v1/query.proto b/proto/interchain_security/ccv/provider/v1/query.proto index 9ea3aa6bec..0051d83dd2 100644 --- a/proto/interchain_security/ccv/provider/v1/query.proto +++ b/proto/interchain_security/ccv/provider/v1/query.proto @@ -128,13 +128,6 @@ service Query { "/interchain_security/ccv/provider/consumer_commission_rate/{chain_id}/{provider_address}"; } - // QueryOldestUnconfirmedVsc returns the send timestamp of the oldest unconfirmed VSCPacket for a given chainID - rpc QueryOldestUnconfirmedVsc(QueryOldestUnconfirmedVscRequest) - returns (QueryOldestUnconfirmedVscResponse) { - option (google.api.http).get = - "/interchain_security/ccv/provider/oldest_unconfirmed_vsc/{chain_id}"; - } - // QueryConsumerValidators returns the latest set consumer-validator set for a given chainID // Note that this does not necessarily mean that the consumer chain is using this validator set at this exact moment // because a VSCPacket could be delayed to be delivered on the consumer chain. @@ -143,6 +136,14 @@ service Query { option (google.api.http).get = "/interchain_security/ccv/provider/consumer_validators/{chain_id}"; } + + // QueryBlocksUntilNextEpoch returns the number of blocks until the next epoch + // starts and validator updates are sent to the consumer chains + rpc QueryBlocksUntilNextEpoch(QueryBlocksUntilNextEpochRequest) + returns (QueryBlocksUntilNextEpochResponse) { + option (google.api.http).get = + "/interchain_security/ccv/provider/blocks_until_next_epoch"; + } } message QueryConsumerGenesisRequest { string chain_id = 1; } @@ -320,9 +321,9 @@ message QueryValidatorConsumerCommissionRateResponse { ]; } -message QueryOldestUnconfirmedVscRequest { string chain_id = 1; } +message QueryBlocksUntilNextEpochRequest { } -message QueryOldestUnconfirmedVscResponse { - interchain_security.ccv.provider.v1.VscSendTimestamp vsc_send_timestamp = 1 - [ (gogoproto.nullable) = false ]; +message QueryBlocksUntilNextEpochResponse { + // The number of blocks until the next epoch starts + uint64 blocks_until_next_epoch = 1; } diff --git a/proto/interchain_security/ccv/provider/v1/tx.proto b/proto/interchain_security/ccv/provider/v1/tx.proto index 6349f2a27a..b0f3fc58c2 100644 --- a/proto/interchain_security/ccv/provider/v1/tx.proto +++ b/proto/interchain_security/ccv/provider/v1/tx.proto @@ -289,7 +289,7 @@ message MsgSetConsumerCommissionRate { ]; // signer address string signer = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"]; - } +} message MsgSetConsumerCommissionRateResponse {} diff --git a/tests/e2e/action_rapid_test.go b/tests/e2e/action_rapid_test.go index b720d3557c..d0a9ede282 100644 --- a/tests/e2e/action_rapid_test.go +++ b/tests/e2e/action_rapid_test.go @@ -163,9 +163,9 @@ func GetStartSovereignChainActionGen() *rapid.Generator[StartSovereignChainActio }) } -func GetSubmitLegacyUpgradeProposalActionGen() *rapid.Generator[LegacyUpgradeProposalAction] { - return rapid.Custom(func(t *rapid.T) LegacyUpgradeProposalAction { - return LegacyUpgradeProposalAction{ +func GetSubmitLegacyUpgradeProposalActionGen() *rapid.Generator[UpgradeProposalAction] { + return rapid.Custom(func(t *rapid.T) UpgradeProposalAction { + return UpgradeProposalAction{ ChainID: GetChainIDGen().Draw(t, "ChainID"), UpgradeTitle: rapid.String().Draw(t, "UpgradeTitle"), Proposer: GetValidatorIDGen().Draw(t, "Proposer"), diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index b4cfd71dd4..2efd0b69e7 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -2395,7 +2395,7 @@ func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool } // Use: "opt-out [consumer-chain-id]", - optIn := fmt.Sprintf( + optOut := fmt.Sprintf( `%s tx provider opt-out %s --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, tr.testConfig.chainConfigs[ChainID("provi")].BinaryName, string(tr.testConfig.chainConfigs[action.Chain].ChainId), @@ -2408,7 +2408,7 @@ func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool cmd := target.ExecCommand( "/bin/bash", "-c", - optIn, + optOut, ) if verbose { @@ -2434,6 +2434,71 @@ func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool tr.waitBlocks(ChainID("provi"), 2, 30*time.Second) } +type SetConsumerCommissionRateAction struct { + Chain ChainID + Validator ValidatorID + CommissionRate float64 + + // depending on the execution, this action might throw an error (e.g., when no consumer chain exists) + ExpectError bool + ExpectedError string +} + +func (tr Chain) setConsumerCommissionRate(action SetConsumerCommissionRateAction, target ExecutionTarget, verbose bool) { + // Note: to get error response reported back from this command '--gas auto' needs to be set. + gas := "auto" + // Unfortunately, --gas auto does not work with CometMock. so when using CometMock, just use --gas 9000000 then + if tr.testConfig.useCometmock { + gas = "9000000" + } + + // Use: "set-consumer-commission-rate [consumer-chain-id] [commission-rate]" + setCommissionRate := fmt.Sprintf( + `%s tx provider set-consumer-commission-rate %s %f --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, + tr.testConfig.chainConfigs[ChainID("provi")].BinaryName, + string(tr.testConfig.chainConfigs[action.Chain].ChainId), + action.CommissionRate, + action.Validator, + tr.testConfig.chainConfigs[ChainID("provi")].ChainId, + tr.getValidatorHome(ChainID("provi"), action.Validator), + tr.getValidatorNode(ChainID("provi"), action.Validator), + gas, + ) + + cmd := target.ExecCommand( + "/bin/bash", "-c", + setCommissionRate, + ) + + if verbose { + fmt.Println("setConsumerCommissionRate cmd:", cmd.String()) + } + + bz, err := cmd.CombinedOutput() + if err != nil && !action.ExpectError { + log.Fatalf("unexpected error during commssion rate set - output: %s, err: %s", string(bz), err) + } + + if action.ExpectError && !tr.testConfig.useCometmock { // error report only works with --gas auto, which does not work with CometMock, so ignore + if err == nil || !strings.Contains(string(bz), action.ExpectedError) { + log.Fatalf("expected error not raised: expected: '%s', got '%s'", action.ExpectedError, (bz)) + } + + if verbose { + fmt.Printf("got expected error during commssion rate set | err: %s | output: %s \n", err, string(bz)) + } + } + + if !tr.testConfig.useCometmock { // error report only works with --gas auto, which does not work with CometMock, so ignore + if err != nil && verbose { + fmt.Printf("got error during commssion rate set | err: %s | output: %s \n", err, string(bz)) + } + } + + // wait for inclusion in a block -> '--broadcast-mode block' is deprecated + tr.waitBlocks(ChainID("provi"), 2, 30*time.Second) +} + // WaitTime waits for the given duration. // To make sure that the new timestamp is visible on-chain, it also waits until at least one block has been // produced on each chain after waiting. diff --git a/tests/e2e/actions_sovereign_chain.go b/tests/e2e/actions_sovereign_chain.go index 96d308ba57..0c8ccfae56 100644 --- a/tests/e2e/actions_sovereign_chain.go +++ b/tests/e2e/actions_sovereign_chain.go @@ -103,48 +103,91 @@ func (tr Chain) startSovereignChain( }, verbose) } -type LegacyUpgradeProposalAction struct { +type UpgradeProposalAction struct { ChainID ChainID UpgradeTitle string Proposer ValidatorID UpgradeHeight uint64 + Expedited bool } -func (tr *Chain) submitLegacyUpgradeProposal(action LegacyUpgradeProposalAction, verbose bool) { - submit := fmt.Sprintf( - `%s tx gov submit-legacy-proposal software-upgrade %s \ - --title %s \ - --deposit 10000000stake \ - --upgrade-height %s \ - --upgrade-info "perform changeover" \ - --description "perform changeover" \ - --gas 900000 \ - --from validator%s \ - --keyring-backend test \ - --chain-id %s \ - --home %s \ - --node %s \ - --no-validate \ - -y`, - tr.testConfig.chainConfigs[ChainID("sover")].BinaryName, - action.UpgradeTitle, - action.UpgradeTitle, - fmt.Sprint(action.UpgradeHeight), - action.Proposer, - tr.testConfig.chainConfigs[ChainID("sover")].ChainId, - tr.getValidatorHome(ChainID("sover"), action.Proposer), - tr.getValidatorNode(ChainID("sover"), action.Proposer), - ) - cmd := tr.target.ExecCommand("/bin/bash", "-c", submit) +func (tr *Chain) submitUpgradeProposal(action UpgradeProposalAction, verbose bool) { + + // Get authority address + binary := tr.testConfig.chainConfigs[ChainID("sover")].BinaryName + cmd := tr.target.ExecCommand(binary, + "query", "upgrade", "authority", + "--node", tr.getValidatorNode(ChainID("sover"), action.Proposer), + "-o", "json") + bz, err := cmd.CombinedOutput() + if err != nil { + log.Fatalf("failed running command '%s': %v", cmd, err) + } + + var authority struct { + Address string `json:"address"` + } + err = json.Unmarshal(bz, &authority) + if err != nil { + log.Fatalf("Failed getting authority: err=%v, data=%s", err, string(bz)) + } + + // Upgrade Proposal Content + metadata := "ipfs://CID" + deposit := "10000000stake" + summary := "my summary" + proposalJson := fmt.Sprintf(` +{ + "messages": [ + { + "@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade", + "authority": "%s", + "plan": { + "name": "sovereign-changeover", + "height": "%d", + "info": "my upgrade info", + "upgraded_client_state": null + } + } + ], + "metadata": "%s", + "title": "%s", + "summary": "%s", + "deposit": "%s", + "expedited": %t +}`, authority.Address, action.UpgradeHeight, metadata, action.UpgradeTitle, summary, deposit, action.Expedited) + + //#nosec G204 -- bypass unsafe quoting warning (no production code) + proposalPath := "/temp-proposal.json" + bz, err = tr.target.ExecCommand( + "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, proposalJson, proposalPath), + ).CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + // Submit Proposal + cmd = tr.target.ExecCommand(binary, + "tx", "gov", "submit-proposal", proposalPath, + "--gas", "900000", + "--from", "validator"+string(action.Proposer), + "--keyring-backend", "test", + "--chain-id", string(tr.testConfig.chainConfigs[ChainID("sover")].ChainId), + "--home", tr.getValidatorHome(ChainID("sover"), action.Proposer), + "--node", tr.getValidatorNode(ChainID("sover"), action.Proposer), + "-y") if verbose { - fmt.Println("submitUpgradeProposal cmd:", cmd.String()) + fmt.Println("Submit proposal:", cmd.String()) } - bz, err := cmd.CombinedOutput() + bz, err = cmd.CombinedOutput() if err != nil { log.Fatal(err, "\n", string(bz)) } + if verbose { + log.Println("Response to submit-proposal: ", string(bz)) + } tr.waitBlocks(action.ChainID, 1, 15*time.Second) } diff --git a/tests/e2e/json_utils.go b/tests/e2e/json_utils.go index e1e0b67fc6..4d7d2bbee7 100644 --- a/tests/e2e/json_utils.go +++ b/tests/e2e/json_utils.go @@ -217,7 +217,7 @@ func UnmarshalMapToActionType(rawAction json.RawMessage, actionTypeString string return a, nil } case "main.LegacyUpgradeProposalAction": - var a LegacyUpgradeProposalAction + var a UpgradeProposalAction err := json.Unmarshal(rawAction, &a) if err == nil { return a, nil diff --git a/tests/e2e/state.go b/tests/e2e/state.go index 064caa50f1..fba5e36c3a 100644 --- a/tests/e2e/state.go +++ b/tests/e2e/state.go @@ -139,6 +139,11 @@ func (tr Chain) GetChainState(chain ChainID, modelState ChainState) ChainState { chainState.InflationRateChange = &inflationRateChangeDirection } + if modelState.ConsumerCommissionRates != nil { + consumerCommissionRates := tr.GetConsumerCommissionRates(chain, *modelState.ConsumerCommissionRates) + chainState.ConsumerCommissionRates = &consumerCommissionRates + } + if modelState.ConsumerPendingPacketQueueSize != nil { pendingPacketQueueSize := tr.target.GetPendingPacketQueueSize(chain) chainState.ConsumerPendingPacketQueueSize = &pendingPacketQueueSize @@ -415,36 +420,39 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { noProposalRegex := regexp.MustCompile(`doesn't exist: key not found`) binaryName := tr.chainConfigs[chain].BinaryName - bz, err := tr.target.ExecCommand(binaryName, + cmd := tr.target.ExecCommand(binaryName, "query", "gov", "proposal", fmt.Sprint(proposal), `--node`, tr.GetQueryNode(chain), - `-o`, `json`, - ).CombinedOutput() + `-o`, `json`) + bz, err := cmd.CombinedOutput() + if err != nil { + log.Println("Error getting governance proposal", proposal, "\n\t cmd: ", cmd, "\n\t err:", err, "\n\t out: ", string(bz)) + } prop := TextProposal{} - + propRaw := string(bz) if err != nil { if noProposalRegex.Match(bz) { return prop } - log.Fatal(err, "\n", string(bz)) + log.Fatal(err, "\n", propRaw) } // for legacy proposal types submitted using "tx submit-legacyproposal" (cosmos-sdk/v1/MsgExecLegacyContent) - propType := gjson.Get(string(bz), `proposal.messages.0.value.content.type`).String() - rawContent := gjson.Get(string(bz), `proposal.messages.0.value.content.value`) + propType := gjson.Get(propRaw, `proposal.messages.0.value.content.type`).String() + rawContent := gjson.Get(propRaw, `proposal.messages.0.value.content.value`) // for current (>= v47) prop types submitted using "tx submit-proposal" if propType == "" { - propType = gjson.Get(string(bz), `proposal.messages.0.type`).String() - rawContent = gjson.Get(string(bz), `proposal.messages.0.value`) + propType = gjson.Get(propRaw, `proposal.messages.0.type`).String() + rawContent = gjson.Get(propRaw, `proposal.messages.0.value`) } - title := gjson.Get(string(bz), `proposal.title`).String() - deposit := gjson.Get(string(bz), `proposal.total_deposit.#(denom=="stake").amount`).Uint() - status := gjson.Get(string(bz), `proposal.status`).String() + title := gjson.Get(propRaw, `proposal.title`).String() + deposit := gjson.Get(propRaw, `proposal.total_deposit.#(denom=="stake").amount`).Uint() + status := gjson.Get(propRaw, `proposal.status`).String() switch propType { case "/cosmos.gov.v1beta1.TextProposal": @@ -480,6 +488,7 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { }, } case "/cosmos.upgrade.v1beta1.SoftwareUpgradeProposal": + case "cosmos-sdk/MsgSoftwareUpgrade": height := rawContent.Get("plan.height").Uint() title := rawContent.Get("plan.name").String() return UpgradeProposal{ @@ -510,7 +519,7 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { case "/ibc.applications.transfer.v1.MsgUpdateParams": var params IBCTransferParams if err := json.Unmarshal([]byte(rawContent.Get("params").String()), ¶ms); err != nil { - log.Fatal("cannot unmarshal ibc-transfer params: ", err, "\n", string(bz)) + log.Fatal("cannot unmarshal ibc-transfer params: ", err, "\n", propRaw) } return IBCTransferParamsProposal{ @@ -540,13 +549,13 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { return ParamsProposal{ Deposit: uint(deposit), Status: status, - Subspace: gjson.Get(string(bz), `messages.0.content.changes.0.subspace`).String(), - Key: gjson.Get(string(bz), `messages.0.content.changes.0.key`).String(), - Value: gjson.Get(string(bz), `messages.0.content.changes.0.value`).String(), + Subspace: gjson.Get(propRaw, `messages.0.content.changes.0.subspace`).String(), + Key: gjson.Get(propRaw, `messages.0.content.changes.0.key`).String(), + Value: gjson.Get(propRaw, `messages.0.content.changes.0.value`).String(), } } - log.Fatal("received unknown proposal type: ", propType, "proposal JSON:", string(bz)) + log.Fatal("received unknown proposal type: ", propType, "proposal JSON:", propRaw) return nil } @@ -1000,3 +1009,33 @@ func (tr Commands) GetQueryNodeIP(chain ChainID) string { } return fmt.Sprintf("%s.253", tr.chainConfigs[chain].IpPrefix) } + +// GetConsumerCommissionRate returns the commission rate of the given validator on the given consumerChain +func (tr Commands) GetConsumerCommissionRate(consumerChain ChainID, validator ValidatorID) float64 { + binaryName := tr.chainConfigs[ChainID("provi")].BinaryName + cmd := tr.target.ExecCommand(binaryName, + "query", "provider", "validator-consumer-commission-rate", + string(consumerChain), tr.validatorConfigs[validator].ValconsAddress, + `--node`, tr.GetQueryNode(ChainID("provi")), + `-o`, `json`, + ) + bz, err := cmd.CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + rate, err := strconv.ParseFloat(gjson.Get(string(bz), "rate").String(), 64) + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + return rate +} + +func (tr Chain) GetConsumerCommissionRates(chain ChainID, modelState map[ValidatorID]float64) map[ValidatorID]float64 { + actualState := map[ValidatorID]float64{} + for k := range modelState { + actualState[k] = tr.target.GetConsumerCommissionRate(chain, k) + } + + return actualState +} diff --git a/tests/e2e/steps_partial_set_security.go b/tests/e2e/steps_partial_set_security.go index 98316f45bb..80eff1aedd 100644 --- a/tests/e2e/steps_partial_set_security.go +++ b/tests/e2e/steps_partial_set_security.go @@ -29,6 +29,16 @@ func stepsOptInChain() []Step { }, }, }, + { + Action: SetConsumerCommissionRateAction{ + Chain: ChainID("consu"), + Validator: ValidatorID("bob"), + CommissionRate: 0.123, + ExpectError: true, + ExpectedError: "unknown consumer chain", + }, + State: State{}, + }, { Action: SubmitConsumerAdditionProposalAction{ Chain: ChainID("provi"), @@ -89,6 +99,31 @@ func stepsOptInChain() []Step { ValidatorID("carol"): {}, }, }, + ChainID("consu"): ChainState{ + // no consumer commission rates were set and hence we get + // the default (i.e., 0.1) commission rate the validators have on the provider + ConsumerCommissionRates: &map[ValidatorID]float64{ + ValidatorID("alice"): 0.1, + ValidatorID("bob"): 0.1, + ValidatorID("carol"): 0.1, + }, + }, + }, + }, + { + Action: SetConsumerCommissionRateAction{ + Chain: ChainID("consu"), + Validator: ValidatorID("bob"), + CommissionRate: 0.123, + }, + State: State{ + ChainID("consu"): ChainState{ + ConsumerCommissionRates: &map[ValidatorID]float64{ + ValidatorID("alice"): 0.1, + ValidatorID("bob"): 0.123, + ValidatorID("carol"): 0.1, + }, + }, }, }, { diff --git a/tests/e2e/steps_sovereign_changeover.go b/tests/e2e/steps_sovereign_changeover.go index 500120bbf0..ac6b7025cc 100644 --- a/tests/e2e/steps_sovereign_changeover.go +++ b/tests/e2e/steps_sovereign_changeover.go @@ -197,11 +197,12 @@ func stepRunSovereignChain() []Step { func stepsUpgradeChain() []Step { return []Step{ { - Action: LegacyUpgradeProposalAction{ + Action: UpgradeProposalAction{ ChainID: ChainID("sover"), UpgradeTitle: "sovereign-changeover", Proposer: ValidatorID("alice"), UpgradeHeight: 110, + Expedited: false, }, State: State{ ChainID("sover"): ChainState{ diff --git a/tests/e2e/test_driver.go b/tests/e2e/test_driver.go index 9c59411ac7..7a1996c01c 100644 --- a/tests/e2e/test_driver.go +++ b/tests/e2e/test_driver.go @@ -129,8 +129,8 @@ func (td *DefaultDriver) runAction(action interface{}) error { target.startChain(action, td.verbose) case StartSovereignChainAction: target.startSovereignChain(action, td.verbose) - case LegacyUpgradeProposalAction: - target.submitLegacyUpgradeProposal(action, td.verbose) + case UpgradeProposalAction: + target.submitUpgradeProposal(action, td.verbose) case WaitUntilBlockAction: target.waitUntilBlockOnChain(action) case ChangeoverChainAction: @@ -207,6 +207,8 @@ func (td *DefaultDriver) runAction(action interface{}) error { target.optIn(action, td.target, td.verbose) case OptOutAction: target.optOut(action, td.target, td.verbose) + case SetConsumerCommissionRateAction: + target.setConsumerCommissionRate(action, td.target, td.verbose) default: log.Fatalf("unknown action in testRun %s: %#v", td.testCfg.name, action) } diff --git a/tests/e2e/testlib/types.go b/tests/e2e/testlib/types.go index 725c4e6951..bd7996b988 100644 --- a/tests/e2e/testlib/types.go +++ b/tests/e2e/testlib/types.go @@ -38,6 +38,7 @@ type ChainCommands interface { GetValStakedTokens(chain ChainID, validatorAddress string) uint GetQueryNodeIP(chain ChainID) string GetInflationRate(chain ChainID) float64 + GetConsumerCommissionRate(chain ChainID, validator ValidatorID) float64 } // TODO: replace ExecutionTarget with new TargetDriver interface @@ -171,6 +172,7 @@ type ChainState struct { ClientsFrozenHeights *map[string]clienttypes.Height HasToValidate *map[ValidatorID][]ChainID // only relevant to provider chain InflationRateChange *int // whether the inflation rate between two blocks changes negatively (any negative number), is equal (0), or changes positively (any positive number) + ConsumerCommissionRates *map[ValidatorID]float64 } // custom marshal and unmarshal functions for the chainstate that convert proposals to/from the auxiliary type with type info diff --git a/tests/e2e/testnet-scripts/sovereign-genesis.json b/tests/e2e/testnet-scripts/sovereign-genesis.json index ba95b2fbce..bf7c881b1d 100644 --- a/tests/e2e/testnet-scripts/sovereign-genesis.json +++ b/tests/e2e/testnet-scripts/sovereign-genesis.json @@ -192,9 +192,20 @@ "threshold": "0.500000000000000000", "veto_threshold": "0.334000000000000000", "min_initial_deposit_ratio": "0.000000000000000000", + "proposal_cancel_ratio": "0.500000000000000000", + "proposal_cancel_dest": "", + "expedited_voting_period": "10s", + "expedited_threshold": "0.667000000000000000", + "expedited_min_deposit": [ + { + "denom": "stake", + "amount": "50000000" + } + ], "burn_vote_quorum": false, "burn_proposal_deposit_prevote": false, - "burn_vote_veto": true + "burn_vote_veto": true, + "min_deposit_ratio": "0.010000000000000000" } }, "ibc": { @@ -228,7 +239,16 @@ "send_sequences": [], "recv_sequences": [], "ack_sequences": [], - "next_channel_sequence": "0" + "next_channel_sequence": "0", + "params": { + "upgrade_timeout": { + "height": { + "revision_number": "0", + "revision_height": "0" + }, + "timestamp": "600000000000" + } + } } }, "mint": { diff --git a/tests/e2e/testnet-scripts/start-changeover.sh b/tests/e2e/testnet-scripts/start-changeover.sh index f41b6ce626..7d1bd7c2a9 100644 --- a/tests/e2e/testnet-scripts/start-changeover.sh +++ b/tests/e2e/testnet-scripts/start-changeover.sh @@ -179,7 +179,7 @@ QUERY_NODE_SUFFIX=$(echo "$VALIDATORS" | jq -r ".[0].ip_suffix") echo "NODE SUFFIX: $QUERY_NODE_SUFFIX" # poll for chain start set +e -until $BIN query block query block --type=height 0 --node "tcp://$CHAIN_IP_PREFIX.$QUERY_NODE_SUFFIX:26658" | grep -q -v '{"block_id":{"hash":"","parts":{"total":0,"hash":""}},"block":null}'; do sleep 0.3 ; done +until $BIN query block --type=height 0 --node "tcp://$CHAIN_IP_PREFIX.$QUERY_NODE_SUFFIX:26658" | grep -q -v '{"block_id":{"hash":"","parts":{"total":0,"hash":""}},"block":null}'; do sleep 0.3 ; done set -e echo "done!!!!!!!!" diff --git a/tests/e2e/v4/state.go b/tests/e2e/v4/state.go index e003b1bdf0..7f29859f8c 100644 --- a/tests/e2e/v4/state.go +++ b/tests/e2e/v4/state.go @@ -651,7 +651,11 @@ func (tr Commands) GetIBCTransferParams(chain ChainID) IBCTransferParams { } func (tr Commands) GetHasToValidate(validator ValidatorID) []ChainID { - panic("''GetHasToValidate' is not implemented in this version") + panic("'GetHasToValidate' is not implemented in this version") +} + +func (tr Commands) GetConsumerCommissionRate(chain ChainID, validator ValidatorID) float64 { + panic("'GetConsumerCommissionRate' is not implemented in this version") } func uintPtr(i uint) *uint { diff --git a/tests/integration/channel_init.go b/tests/integration/channel_init.go deleted file mode 100644 index e9a41c66f5..0000000000 --- a/tests/integration/channel_init.go +++ /dev/null @@ -1,96 +0,0 @@ -package integration - -// TestInitTimeout tests the init timeout -func (suite *CCVTestSuite) TestInitTimeout() { - testCases := []struct { - name string - handshake func() - removed bool - }{ - { - "init times out before INIT", func() {}, true, - }, - { - "init times out before TRY", func() { - // send ChanOpenInit - err := suite.path.EndpointA.ChanOpenInit() - suite.Require().NoError(err) - }, true, - }, - { - "init times out before ACK", func() { - // send ChanOpenInit - err := suite.path.EndpointA.ChanOpenInit() - suite.Require().NoError(err) - // send ChanOpenTry - err = suite.path.EndpointB.ChanOpenTry() - suite.Require().NoError(err) - }, true, - }, - { - "init times out before CONFIRM", func() { - // send ChanOpenInit - err := suite.path.EndpointA.ChanOpenInit() - suite.Require().NoError(err) - // send ChanOpenTry - err = suite.path.EndpointB.ChanOpenTry() - suite.Require().NoError(err) - // send ChanOpenAck - err = suite.path.EndpointA.ChanOpenAck() - suite.Require().NoError(err) - }, true, - }, - { - "init completes before timeout", func() { - // send ChanOpenInit - err := suite.path.EndpointA.ChanOpenInit() - suite.Require().NoError(err) - // send ChanOpenTry - err = suite.path.EndpointB.ChanOpenTry() - suite.Require().NoError(err) - // send ChanOpenAck - err = suite.path.EndpointA.ChanOpenAck() - suite.Require().NoError(err) - // send ChanOpenConfirm - err = suite.path.EndpointB.ChanOpenConfirm() - suite.Require().NoError(err) - }, false, - }, - } - - for i, tc := range testCases { - providerKeeper := suite.providerApp.GetProviderKeeper() - initTimeout := providerKeeper.GetParams(suite.providerCtx()).InitTimeoutPeriod - chainID := suite.consumerChain.ChainID - - // check that the init timeout timestamp is set - _, found := providerKeeper.GetInitTimeoutTimestamp(suite.providerCtx(), chainID) - suite.Require().True(found, "cannot find init timeout timestamp; test: %s", tc.name) - - // create connection - suite.coordinator.CreateConnections(suite.path) - - // channel opening handshake - tc.handshake() - - // call NextBlock - suite.providerChain.NextBlock() - - // increment time - incrementTime(suite, initTimeout) - - // check whether the chain was removed - _, found = providerKeeper.GetConsumerClientId(suite.providerCtx(), chainID) - suite.Require().Equal(!tc.removed, found, "unexpected outcome; test: %s", tc.name) - - if tc.removed { - // check if the chain was properly removed - suite.checkConsumerChainIsRemoved(chainID, false) - } - - if i+1 < len(testCases) { - // reset suite to reset provider client - suite.SetupTest() - } - } -} diff --git a/tests/integration/common.go b/tests/integration/common.go index cc8a0e86a5..46ef499d01 100644 --- a/tests/integration/common.go +++ b/tests/integration/common.go @@ -301,6 +301,7 @@ func relayAllCommittedPackets( // // Note that it is expected for the provider unbonding period // to be one day larger than the consumer unbonding period. +// TODO (mpoke) get rid of consumer unbonding period func incrementTimeByUnbondingPeriod(s *CCVTestSuite, chainType ChainType) { // Get unboding periods providerUnbondingPeriod, err := s.providerApp.GetTestStakingKeeper().UnbondingTime(s.providerCtx()) @@ -315,7 +316,7 @@ func incrementTimeByUnbondingPeriod(s *CCVTestSuite, chainType ChainType) { incrementTime(s, jumpPeriod) } -func checkStakingUnbondingOps(s *CCVTestSuite, id uint64, found, onHold bool, msgAndArgs ...interface{}) { +func checkStakingUnbondingOps(s *CCVTestSuite, id uint64, found bool, msgAndArgs ...interface{}) { stakingUnbondingOp, wasFound := getStakingUnbondingDelegationEntry(s.providerCtx(), s.providerApp.GetTestStakingKeeper(), id) s.Require().Equal( found, @@ -323,53 +324,15 @@ func checkStakingUnbondingOps(s *CCVTestSuite, id uint64, found, onHold bool, ms fmt.Sprintf("checkStakingUnbondingOps failed - getStakingUnbondingDelegationEntry; %s", msgAndArgs...), ) if wasFound { - s.Require().True( - onHold == (0 < stakingUnbondingOp.UnbondingOnHoldRefCount), - fmt.Sprintf("checkStakingUnbondingOps failed - onHold; %s", msgAndArgs...), - ) - } -} - -func checkCCVUnbondingOp(s *CCVTestSuite, providerCtx sdk.Context, chainID string, valUpdateID uint64, found bool, msgAndArgs ...interface{}) { - entries := s.providerApp.GetProviderKeeper().GetUnbondingOpsFromIndex(providerCtx, chainID, valUpdateID) - if found { - s.Require().NotEmpty(entries, fmt.Sprintf("checkCCVUnbondingOp failed - should not be empty; %s", msgAndArgs...)) - s.Require().Greater( - len(entries), - 0, - fmt.Sprintf("checkCCVUnbondingOp failed - no unbonding ops found; %s", msgAndArgs...), - ) - s.Require().Greater( - len(entries[0].UnbondingConsumerChains), - 0, - fmt.Sprintf("checkCCVUnbondingOp failed - unbonding op with no consumer chains; %s", msgAndArgs...), - ) + // make sure UnbondingOnHoldRefCount remains zero s.Require().Equal( - "testchain2", - entries[0].UnbondingConsumerChains[0], - fmt.Sprintf("checkCCVUnbondingOp failed - unbonding op with unexpected consumer chain; %s", msgAndArgs...), + int64(0), + stakingUnbondingOp.UnbondingOnHoldRefCount, + fmt.Sprintf("checkStakingUnbondingOps failed - UnbondingOnHoldRefCount; %s", msgAndArgs...), ) } } -// Checks that an expected amount of redelegations exist for a delegator -// via the staking keeper, then returns those redelegations. -func checkRedelegations(s *CCVTestSuite, delAddr sdk.AccAddress, - expect uint16, -) []stakingtypes.Redelegation { - redelegations, err := s.providerApp.GetTestStakingKeeper().GetRedelegations(s.providerCtx(), delAddr, 2) - s.Require().NoError(err) - s.Require().Len(redelegations, int(expect)) - return redelegations -} - -// Checks that a redelegation entry has a completion time equal to an expected time -func checkRedelegationEntryCompletionTime( - s *CCVTestSuite, entry stakingtypes.RedelegationEntry, expectedCompletion time.Time, -) { - s.Require().Equal(expectedCompletion, entry.CompletionTime) -} - func getStakingUnbondingDelegationEntry(ctx sdk.Context, k testutil.TestStakingKeeper, id uint64) (stakingUnbondingOp stakingtypes.UnbondingDelegationEntry, found bool) { stakingUbd, err := k.GetUnbondingDelegationByUnbondingID(ctx, id) if err != nil { diff --git a/tests/integration/slashing.go b/tests/integration/slashing.go index 70e1abb9c5..eab288deb3 100644 --- a/tests/integration/slashing.go +++ b/tests/integration/slashing.go @@ -106,14 +106,6 @@ func (s *CCVTestSuite) TestRelayAndApplyDowntimePacket() { // this call was added starging cosmos-sdk v0.50.x s.nextEpoch() - // VSC packets should have been sent from provider during block N to each consumer - expectedSentValsetUpdateId := valsetUpdateIdN - for _, bundle := range s.consumerBundles { - _, found := providerKeeper.GetVscSendTimestamp(s.providerCtx(), - bundle.Chain.ChainID, expectedSentValsetUpdateId) - s.Require().True(found) - } - s.nextEpoch() // Confirm the valset update Id was incremented twice on provider, @@ -124,6 +116,8 @@ func (s *CCVTestSuite) TestRelayAndApplyDowntimePacket() { // check that the validator was removed from the provider validator set by N + 2 s.Require().Len(s.providerChain.Vals.Validators, validatorsPerChain-1) + // VSC packets should have been sent from provider during block N to each consumer + expectedSentValsetUpdateId := valsetUpdateIdN for _, bundle := range s.consumerBundles { // Relay VSC packets from provider to each consumer relayAllCommittedPackets(s, s.providerChain, bundle.Path, diff --git a/tests/integration/stop_consumer.go b/tests/integration/stop_consumer.go index f7b2d6ef96..839bd10771 100644 --- a/tests/integration/stop_consumer.go +++ b/tests/integration/stop_consumer.go @@ -129,25 +129,12 @@ func (s *CCVTestSuite) TestStopConsumerOnChannelClosed() { func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, checkChannel bool) { channelID := s.path.EndpointB.ChannelID providerKeeper := s.providerApp.GetProviderKeeper() - providerStakingKeeper := s.providerApp.GetTestStakingKeeper() if checkChannel { // check channel's state is closed s.Require().Equal(channeltypes.CLOSED, s.path.EndpointB.GetChannel().State) } - // check UnbondingOps were deleted and undelegation entries aren't onHold - for _, unbondingOpsIndex := range providerKeeper.GetAllUnbondingOpIndexes(s.providerCtx(), chainID) { - _, found := providerKeeper.GetUnbondingOpIndex(s.providerCtx(), chainID, unbondingOpsIndex.VscId) - s.Require().False(found) - for _, ubdID := range unbondingOpsIndex.UnbondingOpIds { - _, found = providerKeeper.GetUnbondingOp(s.providerCtx(), unbondingOpsIndex.UnbondingOpIds[ubdID]) - s.Require().False(found) - ubd, _ := providerStakingKeeper.GetUnbondingDelegationByUnbondingID(s.providerCtx(), unbondingOpsIndex.UnbondingOpIds[ubdID]) - s.Require().Zero(ubd.Entries[ubdID].UnbondingOnHoldRefCount) - } - } - // verify consumer chain's states are removed _, found := providerKeeper.GetConsumerGenesis(s.providerCtx(), chainID) s.Require().False(found) diff --git a/tests/integration/unbonding.go b/tests/integration/unbonding.go index 6f027c3616..7316e6c7dd 100644 --- a/tests/integration/unbonding.go +++ b/tests/integration/unbonding.go @@ -1,529 +1,38 @@ package integration import ( - "time" - "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper" - ccv "github.com/cosmos/interchain-security/v5/x/ccv/types" ) -// TestUndelegationNormalOperation tests that undelegations complete after -// the unbonding period elapses on both the consumer and provider, without -// VSC packets timing out. -func (s *CCVTestSuite) TestUndelegationNormalOperation() { - unbondConsumer := func(expectedPackets int) { - // relay 1 VSC packet from provider to consumer - relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, expectedPackets) - // increment time so that the unbonding period ends on the consumer - incrementTimeByUnbondingPeriod(s, Consumer) - // relay 1 VSCMatured packet from consumer to provider - relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, expectedPackets) - } - - testCases := []struct { - name string - shareDiv int64 - unbond func(expBalance, balance math.Int) - }{ - { - "provider unbonding period elapses first", 2, func(expBalance, balance math.Int) { - // increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - - // check that onHold is true - checkStakingUnbondingOps(s, 1, true, true, "unbonding should be on hold") - - // check that the unbonding is not complete - s.Require().Equal(expBalance, balance, "unexpected balance after provider unbonding") - - // undelegation complete on consumer - unbondConsumer(1) - }, - }, - { - "consumer unbonding period elapses first", 2, func(expBalance, balance math.Int) { - // undelegation complete on consumer - unbondConsumer(1) - - // check that onHold is false - checkStakingUnbondingOps(s, 1, true, false, "unbonding should be not be on hold") - - // check that the unbonding is not complete - s.Require().Equal(expBalance, balance, "unexpected balance after consumer unbonding") - - // increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - }, - }, - { - "no valset changes", 1, func(expBalance, balance math.Int) { - // undelegation complete on consumer - unbondConsumer(1) - - // check that onHold is false - checkStakingUnbondingOps(s, 1, true, false, "unbonding should be not be on hold") - - // check that the unbonding is not complete - s.Require().Equal(expBalance, balance, "unexpected balance after consumer unbonding") - - // increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - }, - }, - } - - for i, tc := range testCases { - providerKeeper := s.providerApp.GetProviderKeeper() - consumerKeeper := s.consumerApp.GetConsumerKeeper() - stakingKeeper := s.providerApp.GetTestStakingKeeper() - - s.SetupCCVChannel(s.path) - - // set VSC timeout period to not trigger the removal of the consumer chain - providerUnbondingPeriod, err := stakingKeeper.UnbondingTime(s.providerCtx()) - s.Require().NoError(err) - consumerUnbondingPeriod := consumerKeeper.GetUnbondingPeriod(s.consumerCtx()) - providerKeeper.SetVscTimeoutPeriod(s.providerCtx(), providerUnbondingPeriod+consumerUnbondingPeriod+24*time.Hour) - - // delegate bondAmt and undelegate tc.shareDiv of it - bondAmt := math.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, tc.shareDiv) - // - check that staking unbonding op was created and onHold is true - checkStakingUnbondingOps(s, 1, true, true, "test: "+tc.name) - // - check that CCV unbonding op was created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true, "test: "+tc.name) - - // call NextBlock on the provider (which increments the height) - s.nextEpoch() - - // unbond both on provider and consumer and check that - // the balance remains unchanged in between - tc.unbond(initBalance.Sub(bondAmt), getBalance(s, s.providerCtx(), delAddr)) - - // check that the unbonding operation completed - // - check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false, "test: "+tc.name) - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false, "test: "+tc.name) - // - check that necessary delegated coins have been returned - unbondAmt := bondAmt.Sub(bondAmt.Quo(math.NewInt(tc.shareDiv))) - s.Require().Equal( - initBalance.Sub(unbondAmt), - getBalance(s, s.providerCtx(), delAddr), - "unexpected initial balance after unbonding; test: %s", tc.name, - ) - - if i+1 < len(testCases) { - // reset suite to reset provider client - s.SetupTest() - } - } -} - -// TestUndelegationVscTimeout tests that an undelegation -// completes after vscTimeoutPeriod even if it does not -// reach maturity on the consumer chain. In this case, -// the consumer chain is removed. -func (s *CCVTestSuite) TestUndelegationVscTimeout() { - providerKeeper := s.providerApp.GetProviderKeeper() - +// TestUndelegationCompletion tests that undelegations complete after +// the unbonding period elapses on the provider, regardless of the consumer's state +func (s *CCVTestSuite) TestUndelegationCompletion() { s.SetupCCVChannel(s.path) - // set VSC timeout period to trigger the removal of the consumer chain - vscTimeout := providerKeeper.GetVscTimeoutPeriod(s.providerCtx()) - - // delegate bondAmt and undelegate 1/2 of it + // delegate bondAmt and undelegate 1/4 of it bondAmt := math.NewInt(10000000) delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) - // - check that staking unbonding op was created and onHold is true - checkStakingUnbondingOps(s, 1, true, true) - // - check that CCV unbonding op was created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) + initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 4) + // - check that staking unbonding op was created + checkStakingUnbondingOps(s, 1, true) // call NextBlock on the provider (which increments the height) s.providerChain.NextBlock() - // increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - - // check that onHold is true - checkStakingUnbondingOps(s, 1, true, true, "unbonding should be on hold") - - // check that the unbonding is not complete - s.Require().Equal( - initBalance.Sub(bondAmt), - getBalance(s, s.providerCtx(), delAddr), - "unexpected balance after provider unbonding") - - // increment time - incrementTime(s, vscTimeout) - - // check whether the chain was removed - chainID := s.consumerChain.ChainID - _, found := providerKeeper.GetConsumerClientId(s.providerCtx(), chainID) - s.Require().Equal(false, found, "consumer chain was not removed") - - // check if the chain was properly removed - s.checkConsumerChainIsRemoved(chainID, true) + // unbond on provider + stakingKeeper := s.providerApp.GetTestStakingKeeper() + unbondingPeriod, err := stakingKeeper.UnbondingTime(s.providerCtx()) + s.Require().NoError(err) + incrementTime(s, unbondingPeriod) // check that the unbonding operation completed - // - check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false) + checkStakingUnbondingOps(s, valsetUpdateID, false) // - check that necessary delegated coins have been returned - unbondAmt := bondAmt.Sub(bondAmt.Quo(math.NewInt(2))) + unbondAmt := bondAmt.Quo(math.NewInt(4)) + stillBondedAmt := bondAmt.Sub(unbondAmt) s.Require().Equal( - initBalance.Sub(unbondAmt), + initBalance.Sub(stillBondedAmt), getBalance(s, s.providerCtx(), delAddr), - "unexpected initial balance after VSC timeout", + "unexpected initial balance after unbonding; test: %s", ) } - -// TestUndelegationDuringInit checks that before the CCV channel is established -// - no undelegations can complete, even if the provider unbonding period elapses -// - all the VSC packets are stored in state as pending -// - if the channel handshake times out, then the undelegation completes -func (s *CCVTestSuite) TestUndelegationDuringInit() { - testCases := []struct { - name string - updateInitTimeoutTimestamp func(*providerkeeper.Keeper, time.Duration) - removed bool - }{ - { - "channel handshake completes after unbonding period", func(pk *providerkeeper.Keeper, pUnbondingPeriod time.Duration) { - // change the init timeout timestamp for this consumer chain - // to make sure the chain is not removed before the unbonding period elapses - ts := s.providerCtx().BlockTime().Add(pUnbondingPeriod + 24*time.Hour) - pk.SetInitTimeoutTimestamp(s.providerCtx(), s.consumerChain.ChainID, uint64(ts.UnixNano())) - }, false, - }, - { - "channel handshake times out before unbonding period", func(pk *providerkeeper.Keeper, pUnbondingPeriod time.Duration) { - // change the init timeout timestamp for this consumer chain - // to make sure the chain is removed before the unbonding period elapses - ts := s.providerCtx().BlockTime().Add(pUnbondingPeriod - 24*time.Hour) - pk.SetInitTimeoutTimestamp(s.providerCtx(), s.consumerChain.ChainID, uint64(ts.UnixNano())) - }, true, - }, - } - - for i, tc := range testCases { - providerKeeper := s.providerApp.GetProviderKeeper() - stakingKeeper := s.providerApp.GetTestStakingKeeper() - - // delegate bondAmt and undelegate 1/2 of it - bondAmt := math.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) - // - check that staking unbonding op was created and onHold is true - checkStakingUnbondingOps(s, 1, true, true, "test: "+tc.name) - // - check that CCV unbonding op was created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true, "test: "+tc.name) - - // get provider unbonding period - providerUnbondingPeriod, err := stakingKeeper.UnbondingTime(s.providerCtx()) - s.Require().NoError(err) - // update init timeout timestamp - tc.updateInitTimeoutTimestamp(&providerKeeper, providerUnbondingPeriod) - - s.nextEpoch() - - // check that the VSC packet is stored in state as pending - pendingVSCs := providerKeeper.GetPendingVSCPackets(s.providerCtx(), s.consumerChain.ChainID) - s.Require().Lenf(pendingVSCs, 1, "no pending VSC packet found; test: %s", tc.name) - - // delegate again to create another VSC packet - delegate(s, delAddr, bondAmt) - - s.nextEpoch() - - // check that the VSC packet is stored in state as pending - pendingVSCs = providerKeeper.GetPendingVSCPackets(s.providerCtx(), s.consumerChain.ChainID) - s.Require().Lenf(pendingVSCs, 2, "only one pending VSC packet found; test: %s", tc.name) - - // increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - - // check whether the unbonding op is still there and onHold is true - checkStakingUnbondingOps(s, 1, !tc.removed, true, "test: "+tc.name) - - if !tc.removed { - // check that unbonding has not yet completed, i.e., the initBalance - // is still lower by the bond amount, because it has been taken out of - // the delegator's account - s.Require().Equal( - initBalance.Sub(bondAmt).Sub(bondAmt), - getBalance(s, s.providerCtx(), delAddr), - "unexpected initial balance before unbonding; test: %s", tc.name, - ) - - // complete CCV channel setup - s.SetupCCVChannel(s.path) - s.nextEpoch() - - // relay VSC packets from provider to consumer - relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 2) - - // increment time so that the unbonding period ends on the consumer - incrementTimeByUnbondingPeriod(s, Consumer) - - // relay VSCMatured packets from consumer to provider - relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 2) - - // check that the unbonding operation completed - // - check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false, "test: "+tc.name) - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false, "test: "+tc.name) - // - check that one quarter the delegated coins have been returned - s.Require().Equal( - initBalance.Sub(bondAmt).Sub(bondAmt.Quo(math.NewInt(2))), - getBalance(s, s.providerCtx(), delAddr), - "unexpected initial balance after unbonding; test: %s", tc.name, - ) - } - - if i+1 < len(testCases) { - // reset suite to reset provider client - s.SetupTest() - } - } -} - -// Bond some tokens on provider -// Unbond them to create unbonding op -// Check unbonding ops on both sides -// Advance time so that provider's unbonding op completes -// Check that unbonding has completed in provider staking -func (s *CCVTestSuite) TestUnbondingNoConsumer() { - providerKeeper := s.providerApp.GetProviderKeeper() - providerStakingKeeper := s.providerApp.GetTestStakingKeeper() - - // remove all consumer chains, which were already started during setup - for chainID := range s.consumerBundles { - err := providerKeeper.StopConsumerChain(s.providerCtx(), chainID, true) - s.Require().NoError(err) - } - - // delegate bondAmt and undelegate 1/2 of it - bondAmt := math.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) - // - check that staking unbonding op was created and onHold is FALSE - checkStakingUnbondingOps(s, 1, true, false) - // - check that CCV unbonding op was NOT created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) - - // increment time so that the unbonding period ends on the provider; - // cannot use incrementTimeByUnbondingPeriod() since it tries - // to also update the provider's client on the consumer - providerUnbondingPeriod, err := providerStakingKeeper.UnbondingTime(s.providerCtx()) - s.Require().NoError(err) - s.coordinator.IncrementTimeBy(providerUnbondingPeriod + time.Hour) - - // call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // check that the unbonding operation completed - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false) - // - check that half the coins have been returned - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt.Quo(math.NewInt(2))))) -} - -// TestRedelegationNoConsumer tests a redelegate transaction -// submitted on a provider chain with no consumers -func (s *CCVTestSuite) TestRedelegationNoConsumer() { - providerKeeper := s.providerApp.GetProviderKeeper() - stakingKeeper := s.providerApp.GetTestStakingKeeper() - - // stop the consumer chain, which was already started during setup - err := providerKeeper.StopConsumerChain(s.providerCtx(), s.consumerChain.ChainID, true) - s.Require().NoError(err) - - // Setup delegator, bond amount, and src/dst validators - bondAmt := math.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - _, srcVal := s.getValByIdx(0) - _, dstVal := s.getValByIdx(1) - - delegateAndRedelegate( - s, - delAddr, - srcVal, - dstVal, - bondAmt, - ) - - // 1 redelegation record should exist for original delegator - redelegations := checkRedelegations(s, delAddr, 1) - - // Check that the only entry has appropriate maturation time, the unbonding period from now - unbondingTime, err := stakingKeeper.UnbondingTime(s.providerCtx()) - s.Require().NoError(err) - checkRedelegationEntryCompletionTime( - s, - redelegations[0].Entries[0], - s.providerCtx().BlockTime().Add(unbondingTime), - ) - - // required before call to incrementTimeByUnbondingPeriod or else a panic - // occurs in ibc-go because trusted validators don't match last trusted. - s.providerChain.NextBlock() - - // Increment time so that the unbonding period passes on the provider - incrementTimeByUnbondingPeriod(s, Provider) - - // Call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // No redelegation records should exist for original delegator anymore - checkRedelegations(s, delAddr, 0) -} - -// TestRedelegationWithConsumer tests a redelegate transaction submitted on a provider chain -// when the unbonding period elapses first on the provider chain -func (s *CCVTestSuite) TestRedelegationProviderFirst() { - s.SetupCCVChannel(s.path) - s.SetupTransferChannel() - - providerKeeper := s.providerApp.GetProviderKeeper() - consumerKeeper := s.consumerApp.GetConsumerKeeper() - stakingKeeper := s.providerApp.GetTestStakingKeeper() - - // set VSC timeout period to not trigger the removal of the consumer chain - providerUnbondingPeriod, err := stakingKeeper.UnbondingTime(s.providerCtx()) - s.Require().NoError(err) - consumerUnbondingPeriod := consumerKeeper.GetUnbondingPeriod(s.consumerCtx()) - providerKeeper.SetVscTimeoutPeriod(s.providerCtx(), providerUnbondingPeriod+consumerUnbondingPeriod+24*time.Hour) - - // Setup delegator, bond amount, and src/dst validators - bondAmt := math.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - _, srcVal := s.getValByIdx(0) - _, dstVal := s.getValByIdx(1) - - delegateAndRedelegate( - s, - delAddr, - srcVal, - dstVal, - bondAmt, - ) - - // 1 redelegation record should exist for original delegator - redelegations := checkRedelegations(s, delAddr, 1) - - // Check that the only entry has appropriate maturation time, the unbonding period from now - unbondingTime, err := stakingKeeper.UnbondingTime(s.providerCtx()) - s.Require().NoError(err) - checkRedelegationEntryCompletionTime( - s, - redelegations[0].Entries[0], - s.providerCtx().BlockTime().Add(unbondingTime), - ) - - // Save the current valset update ID - valsetUpdateID := providerKeeper.GetValidatorSetUpdateId(s.providerCtx()) - - // Check that CCV unbonding op was created from AfterUnbondingInitiated hook - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) - - // move forward by an epoch to be able to relay VSC packets - s.nextEpoch() - - // Relay 2 VSC packets from provider to consumer (original delegation, and redelegation) - relayAllCommittedPackets(s, s.providerChain, s.path, - ccv.ProviderPortID, s.path.EndpointB.ChannelID, 2) - - // Increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - - // 1 redelegation record should still exist for original delegator on provider - checkRedelegations(s, delAddr, 1) - - // CCV unbonding op should also still exist - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) - - // Increment time so that the unbonding period ends on the consumer - incrementTimeByUnbondingPeriod(s, Consumer) - - // Relay 2 VSCMatured packets from consumer to provider (original delegation and redelegation) - relayAllCommittedPackets(s, s.consumerChain, - s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 2) - - // - // Check that the redelegation operation has now completed on provider - // - - // Redelegation record should be deleted for original delegator - checkRedelegations(s, delAddr, 0) - - // Check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) -} - -// This test reproduces a fixed bug when an inactive validator enters back into the active set. -// It used to cause a panic in the provider module hook called by AfterUnbondingInitiated -// during the staking module EndBlock. -func (s *CCVTestSuite) TestTooManyLastValidators() { - sk := s.providerApp.GetTestStakingKeeper() - pk := s.providerApp.GetProviderKeeper() - - getLastValsFn := func(ctx sdk.Context) []stakingtypes.Validator { - lastVals, err := pk.GetLastBondedValidators(s.providerCtx()) - s.Require().NoError(err) - return lastVals - } - - // get current staking params - p, err := sk.GetParams(s.providerCtx()) - s.Require().NoError(err) - - // get validators, which are all active at the moment - vals, err := sk.GetAllValidators(s.providerCtx()) - s.Require().NoError(err) - - s.Require().Equal(len(vals), len(getLastValsFn(s.providerCtx()))) - - // jail a validator - val := vals[0] - consAddr, err := val.GetConsAddr() - s.Require().NoError(err) - sk.Jail(s.providerCtx(), consAddr) - - // save the current number of bonded vals - lastVals := getLastValsFn(s.providerCtx()) - - // pass one block to apply the validator set changes - // (calls ApplyAndReturnValidatorSetUpdates in the the staking module EndBlock) - s.providerChain.NextBlock() - - // verify that the number of bonded validators is decreased by one - s.Require().Equal(len(lastVals)-1, len(getLastValsFn(s.providerCtx()))) - - // update maximum validator to equal the number of bonded validators - p.MaxValidators = uint32(len(getLastValsFn(s.providerCtx()))) - sk.SetParams(s.providerCtx(), p) - - // pass one block to apply validator set changes - s.providerChain.NextBlock() - - // unjail validator - // Note that since validators are sorted in descending order, the unjailed validator - // enters the active set again since it's ranked first by voting power. - sk.Unjail(s.providerCtx(), consAddr) - - // pass another block to update the validator set - // which causes a panic due to a GetLastValidator call in - // ApplyAndReturnValidatorSetUpdates where the staking module has a inconsistent state - s.Require().NotPanics(s.providerChain.NextBlock) - s.Require().NotPanics(func() { sk.ApplyAndReturnValidatorSetUpdates(s.providerCtx()) }) - s.Require().NotPanics(func() { getLastValsFn(s.providerCtx()) }) -} diff --git a/tests/mbt/driver/mbt_test.go b/tests/mbt/driver/mbt_test.go index 70fded614a..35ea2f4e1f 100644 --- a/tests/mbt/driver/mbt_test.go +++ b/tests/mbt/driver/mbt_test.go @@ -520,8 +520,6 @@ func RunItfTrace(t *testing.T, path string) { for _, consumerChainID := range actualRunningConsumerChainIDs { ComparePacketQueues(t, driver, currentModelState, consumerChainID, timeOffset) } - // compare that the sent packets on the proider match the model - CompareSentPacketsOnProvider(driver, currentModelState, timeOffset) // ensure that the jailed validators are the same in the model and the system, // and that the jail end times are the same, in particular @@ -784,30 +782,6 @@ func CompareValSet(modelValSet map[string]itf.Expr, systemValSet map[string]int6 return nil } -func CompareSentPacketsOnProvider(driver *Driver, currentModelState map[string]itf.Expr, timeOffset time.Time) { - for _, consumerChainID := range driver.runningConsumerChainIDs() { - vscSendTimestamps := driver.providerKeeper().GetAllVscSendTimestamps(driver.providerCtx(), string(consumerChainID)) - - actualVscSendTimestamps := make([]time.Time, 0) - for _, vscSendTimestamp := range vscSendTimestamps { - actualVscSendTimestamps = append(actualVscSendTimestamps, vscSendTimestamp.Timestamp) - } - - modelVscSendTimestamps := VscSendTimestamps(currentModelState, string(consumerChainID)) - - for i, modelVscSendTimestamp := range modelVscSendTimestamps { - actualTimeWithOffset := actualVscSendTimestamps[i].Unix() - timeOffset.Unix() - require.Equal( - driver.t, - modelVscSendTimestamp, - actualTimeWithOffset, - "Vsc send timestamps do not match for consumer %v", - consumerChainID, - ) - } - } -} - func CompareJailedValidators( driver *Driver, currentModelState map[string]itf.Expr, diff --git a/tests/mbt/driver/setup.go b/tests/mbt/driver/setup.go index acdae7554b..d9e658c030 100644 --- a/tests/mbt/driver/setup.go +++ b/tests/mbt/driver/setup.go @@ -438,8 +438,6 @@ func (s *Driver) setupProvider( providerChain := newChain(s.t, params, s.coordinator, icstestingutils.ProviderAppIniter, "provider", valSet, signers, nodes, valNames) s.coordinator.Chains["provider"] = providerChain - // set the VscTimeout - s.providerKeeper().SetVscTimeoutPeriod(s.ctx("provider"), params.VscTimeout) // set the CcvTimeoutPeriod providerParams := s.providerKeeper().GetParams(s.ctx("provider")) providerParams.CcvTimeoutPeriod = params.CcvTimeout[ChainId(providerChain.ChainID)] diff --git a/testutil/integration/debug_test.go b/testutil/integration/debug_test.go index d26246dcf5..022cc71429 100644 --- a/testutil/integration/debug_test.go +++ b/testutil/integration/debug_test.go @@ -49,14 +49,6 @@ func findAndCallMethod(t *testing.T, suite any, methodName string) { method.Func.Call([]reflect.Value{reflect.ValueOf(suite)}) } -// -// Channel init tests -// - -func TestInitTimeout(t *testing.T) { - runCCVTestByName(t, "TestInitTimeout") -} - // // Consumer democracy tests // @@ -201,28 +193,8 @@ func TestSlashAllValidators(t *testing.T) { // Unbonding tests // -func TestUndelegationNormalOperation(t *testing.T) { - runCCVTestByName(t, "TestUndelegationNormalOperation") -} - -func TestUndelegationVscTimeout(t *testing.T) { - runCCVTestByName(t, "TestUndelegationVscTimeout") -} - -func TestUndelegationDuringInit(t *testing.T) { - runCCVTestByName(t, "TestUndelegationDuringInit") -} - -func TestUnbondingNoConsumer(t *testing.T) { - runCCVTestByName(t, "TestUnbondingNoConsumer") -} - -func TestRedelegationNoConsumer(t *testing.T) { - runCCVTestByName(t, "TestRedelegationNoConsumer") -} - -func TestRedelegationProviderFirst(t *testing.T) { - runCCVTestByName(t, "TestRedelegationProviderFirst") +func TestUndelegationCompletion(t *testing.T) { + runCCVTestByName(t, "TestUndelegationCompletion") } // diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index 06553b7efa..72a59a1207 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -211,13 +211,6 @@ func GetNewSlashPacketData() types.SlashPacketData { } } -// Obtains vsc matured packet data with a newly generated key -func GetNewVSCMaturedPacketData() types.VSCMaturedPacketData { - b := make([]byte, 8) - _, _ = rand.Read(b) - return types.VSCMaturedPacketData{ValsetUpdateId: binary.BigEndian.Uint64(b)} -} - // SetupForStoppingConsumerChain registers expected mock calls and corresponding state setup // which assert that a consumer chain was properly setup to be later stopped from `StopConsumerChain`. // Note: This function only setups and tests that we correctly setup a consumer chain that we could later stop when @@ -259,10 +252,6 @@ func TestProviderStateIsCleanedAfterConsumerChainIsStopped(t *testing.T, ctx sdk require.False(t, found) acks := providerKeeper.GetSlashAcks(ctx, expectedChainID) require.Empty(t, acks) - _, found = providerKeeper.GetInitTimeoutTimestamp(ctx, expectedChainID) - require.False(t, found) - - require.Empty(t, providerKeeper.GetAllVscSendTimestamps(ctx, expectedChainID)) // in case the chain was successfully stopped, it should not contain a Top N associated to it _, found = providerKeeper.GetTopN(ctx, expectedChainID) diff --git a/x/ccv/provider/client/cli/query.go b/x/ccv/provider/client/cli/query.go index 697fccbb76..84fbff3fd0 100644 --- a/x/ccv/provider/client/cli/query.go +++ b/x/ccv/provider/client/cli/query.go @@ -39,7 +39,7 @@ func NewQueryCmd() *cobra.Command { cmd.AddCommand(CmdConsumerValidators()) cmd.AddCommand(CmdConsumerChainsValidatorHasToValidate()) cmd.AddCommand(CmdValidatorConsumerCommissionRate()) - cmd.AddCommand(CmdOldestUnconfirmedVsc()) + cmd.AddCommand(CmdBlocksUntilNextEpoch()) return cmd } @@ -570,11 +570,11 @@ $ %s validator-consumer-commission-rate foochain %s1gghjut3ccd8ay0zduzj64hwre2fx return cmd } -func CmdOldestUnconfirmedVsc() *cobra.Command { +func CmdBlocksUntilNextEpoch() *cobra.Command { cmd := &cobra.Command{ - Use: "oldest_unconfirmed_vsc [chainid]", - Short: "Query the send timestamp of the oldest unconfirmed VSCPacket by chain id", - Args: cobra.ExactArgs(1), + Use: "blocks-until-next-epoch", + Short: "Query the number of blocks until the next epoch begins and validator updates are sent to consumer chains", + Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { @@ -582,13 +582,13 @@ func CmdOldestUnconfirmedVsc() *cobra.Command { } queryClient := types.NewQueryClient(clientCtx) - req := types.QueryOldestUnconfirmedVscRequest{ChainId: args[0]} - res, err := queryClient.QueryOldestUnconfirmedVsc(cmd.Context(), &req) + req := &types.QueryBlocksUntilNextEpochRequest{} + res, err := queryClient.QueryBlocksUntilNextEpoch(cmd.Context(), req) if err != nil { return err } - return clientCtx.PrintProto(&res.VscSendTimestamp) + return clientCtx.PrintProto(res) }, } diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index eadb3a7e57..4011a36a79 100644 --- a/x/ccv/provider/client/cli/tx.go +++ b/x/ccv/provider/client/cli/tx.go @@ -325,7 +325,8 @@ func NewSetConsumerCommissionRateCmd() *cobra.Command { if err != nil { return err } - msg := types.NewMsgSetConsumerCommissionRate(args[0], commission, sdk.ValAddress(providerValAddr)) + signer := clientCtx.GetFromAddress().String() + msg := types.NewMsgSetConsumerCommissionRate(args[0], commission, sdk.ValAddress(providerValAddr), signer) if err := msg.ValidateBasic(); err != nil { return err } diff --git a/x/ccv/provider/ibc_module.go b/x/ccv/provider/ibc_module.go index f91f69e618..b41512e98a 100644 --- a/x/ccv/provider/ibc_module.go +++ b/x/ccv/provider/ibc_module.go @@ -197,13 +197,8 @@ func (am AppModule) OnRecvPacket( var err error switch consumerPacket.Type { case ccv.VscMaturedPacket: - // handle VSCMaturedPacket - data := *consumerPacket.GetVscMaturedPacketData() - err = am.keeper.OnRecvVSCMaturedPacket(ctx, packet, data) - if err == nil { - logger.Info("successfully handled VSCMaturedPacket", "sequence", packet.Sequence) - eventAttributes = append(eventAttributes, sdk.NewAttribute(ccv.AttributeValSetUpdateID, strconv.Itoa(int(data.ValsetUpdateId)))) - } + // ignore VSCMaturedPacket + err = nil case ccv.SlashPacket: // handle SlashPacket var ackResult ccv.PacketAckResult diff --git a/x/ccv/provider/ibc_module_test.go b/x/ccv/provider/ibc_module_test.go index fdae2a03ba..58573d3e3b 100644 --- a/x/ccv/provider/ibc_module_test.go +++ b/x/ccv/provider/ibc_module_test.go @@ -31,7 +31,7 @@ func TestOnChanOpenInit(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx( t, keeperParams) defer ctrl.Finish() - providerModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace) + providerModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace, keeperParams.StoreKey) // OnChanOpenInit must error for provider even with correct arguments _, err := providerModule.OnChanOpenInit( @@ -119,7 +119,7 @@ func TestOnChanOpenTry(t *testing.T) { keeperParams := testkeeper.NewInMemKeeperParams(t) providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx( t, keeperParams) - providerModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace) + providerModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace, keeperParams.StoreKey) providerKeeper.SetPort(ctx, ccv.ProviderPortID) providerKeeper.SetConsumerClientId(ctx, "consumerChainID", "clientIDToConsumer") @@ -190,7 +190,7 @@ func TestOnChanOpenAck(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx( t, keeperParams) defer ctrl.Finish() - providerModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace) + providerModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace, keeperParams.StoreKey) // OnChanOpenAck must error for provider even with correct arguments err := providerModule.OnChanOpenAck( @@ -312,7 +312,7 @@ func TestOnChanOpenConfirm(t *testing.T) { providerKeeper.SetChainToChannel(ctx, "consumerChainID", "existingChannelID") } - providerModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace) + providerModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace, keeperParams.StoreKey) err := providerModule.OnChanOpenConfirm(ctx, "providerPortID", "channelID") diff --git a/x/ccv/provider/keeper/genesis.go b/x/ccv/provider/keeper/genesis.go index a2a64267dd..04f38c817d 100644 --- a/x/ccv/provider/keeper/genesis.go +++ b/x/ccv/provider/keeper/genesis.go @@ -41,15 +41,6 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) []abc p := prop k.SetPendingConsumerRemovalProp(ctx, &p) } - for _, ubdOp := range genState.UnbondingOps { - k.SetUnbondingOp(ctx, ubdOp) - } - - // Note that MatureUnbondingOps aren't stored across blocks, but it - // might be used after implementing standalone to consumer transition - if genState.MatureUnbondingOps != nil { - k.AppendMaturedUnbondingOps(ctx, genState.MatureUnbondingOps.Ids) - } // Set initial state for each consumer chain for _, cs := range genState.ConsumerStates { @@ -60,9 +51,6 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) []abc // the ConsumerGenesis validated in ConsumerState.Validate(). panic(fmt.Errorf("consumer chain genesis could not be persisted: %w", err)) } - for _, ubdOpIndex := range cs.UnbondingOpsIndex { - k.SetUnbondingOpIndex(ctx, chainID, ubdOpIndex.GetVscId(), ubdOpIndex.GetUnbondingOpIds()) - } // check if the CCV channel was established if cs.ChannelId != "" { k.SetChannelToChain(ctx, cs.ChannelId, chainID) @@ -86,20 +74,10 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) []abc k.SetValidatorByConsumerAddr(ctx, item.ChainId, consumerAddr, providerAddr) } - for _, item := range genState.ConsumerAddrsToPrune { + for _, item := range genState.ConsumerAddrsToPruneV2 { for _, addr := range item.ConsumerAddrs.Addresses { consumerAddr := types.NewConsumerConsAddress(addr) - k.AppendConsumerAddrsToPrune(ctx, item.ChainId, item.VscId, consumerAddr) - } - } - - for _, item := range genState.InitTimeoutTimestamps { - k.SetInitTimeoutTimestamp(ctx, item.ChainId, item.Timestamp) - } - - for _, item := range genState.ExportedVscSendTimestamps { - for _, vscSendTimestamp := range item.VscSendTimestamps { - k.SetVscSendTimestamp(ctx, item.ChainId, vscSendTimestamp.VscId, vscSendTimestamp.Timestamp) + k.AppendConsumerAddrsToPrune(ctx, item.ChainId, item.PruneTs, consumerAddr) } } @@ -153,7 +131,6 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { // get a list of all registered consumer chains registeredChainIDs := k.GetAllRegisteredConsumerChainIDs(ctx) - var exportedVscSendTimestamps []types.ExportedVscSendTimestamp // export states for each consumer chains var consumerStates []types.ConsumerState for _, chainID := range registeredChainIDs { @@ -168,10 +145,9 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { // initial consumer chain states cs := types.ConsumerState{ - ChainId: chainID, - ClientId: clientID, - ConsumerGenesis: gen, - UnbondingOpsIndex: k.GetAllUnbondingOpIndexes(ctx, chainID), + ChainId: chainID, + ClientId: clientID, + ConsumerGenesis: gen, } // try to find channel id for the current consumer chain @@ -187,13 +163,10 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { cs.PendingValsetChanges = k.GetPendingVSCPackets(ctx, chainID) consumerStates = append(consumerStates, cs) - - vscSendTimestamps := k.GetAllVscSendTimestamps(ctx, chainID) - exportedVscSendTimestamps = append(exportedVscSendTimestamps, types.ExportedVscSendTimestamp{ChainId: chainID, VscSendTimestamps: vscSendTimestamps}) } // ConsumerAddrsToPrune are added only for registered consumer chains - consumerAddrsToPrune := []types.ConsumerAddrsToPrune{} + consumerAddrsToPrune := []types.ConsumerAddrsToPruneV2{} for _, chainID := range registeredChainIDs { consumerAddrsToPrune = append(consumerAddrsToPrune, k.GetAllConsumerAddrsToPrune(ctx, chainID)...) } @@ -209,16 +182,12 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { k.GetValidatorSetUpdateId(ctx), k.GetAllValsetUpdateBlockHeights(ctx), consumerStates, - k.GetAllUnbondingOps(ctx), - &types.MaturedUnbondingOps{Ids: k.GetMaturedUnbondingOps(ctx)}, k.GetAllPendingConsumerAdditionProps(ctx), k.GetAllPendingConsumerRemovalProps(ctx), params, k.GetAllValidatorConsumerPubKeys(ctx, nil), k.GetAllValidatorsByConsumerAddr(ctx, nil), consumerAddrsToPrune, - k.GetAllInitTimeoutTimestamps(ctx), - exportedVscSendTimestamps, lastProviderConsensusValSet, ) } diff --git a/x/ccv/provider/keeper/genesis_test.go b/x/ccv/provider/keeper/genesis_test.go index e2f73eca53..230f3cefdc 100644 --- a/x/ccv/provider/keeper/genesis_test.go +++ b/x/ccv/provider/keeper/genesis_test.go @@ -1,7 +1,6 @@ package keeper_test import ( - "sort" "testing" "time" @@ -27,7 +26,6 @@ func TestInitAndExportGenesis(t *testing.T) { expClientID := "client" oneHourFromNow := time.Now().UTC().Add(time.Hour) initHeight, vscID := uint64(5), uint64(1) - ubdIndex := []uint64{0, 1, 2} params := providertypes.DefaultParams() // create validator keys and addresses for key assignment @@ -41,32 +39,6 @@ func TestInitAndExportGenesis(t *testing.T) { consumerTmPubKey := consumerCryptoId.TMProtoCryptoPublicKey() consumerConsAddr := consumerCryptoId.ConsumerConsAddress() - initTimeoutTimeStamps := []providertypes.InitTimeoutTimestamp{ - {ChainId: cChainIDs[0], Timestamp: uint64(time.Now().UTC().UnixNano()) + 10}, - {ChainId: cChainIDs[1], Timestamp: uint64(time.Now().UTC().UnixNano()) + 15}, - } - - now := time.Now().UTC() - exportedVscSendTimeStampsC0 := providertypes.ExportedVscSendTimestamp{ - ChainId: "c0", - VscSendTimestamps: []providertypes.VscSendTimestamp{ - {VscId: 1, Timestamp: now.Add(time.Hour)}, - {VscId: 2, Timestamp: now.Add(2 * time.Hour)}, - }, - } - - exportedVscSendTimeStampsC1 := providertypes.ExportedVscSendTimestamp{ - ChainId: "c1", - VscSendTimestamps: []providertypes.VscSendTimestamp{ - {VscId: 1, Timestamp: now.Add(-time.Hour)}, - {VscId: 2, Timestamp: now.Add(time.Hour)}, - }, - } - - var exportedVscSendTimeStampsAll []providertypes.ExportedVscSendTimestamp - exportedVscSendTimeStampsAll = append(exportedVscSendTimeStampsAll, exportedVscSendTimeStampsC0) - exportedVscSendTimeStampsAll = append(exportedVscSendTimeStampsAll, exportedVscSendTimeStampsC1) - // at genesis, the validator has 100 power lastProviderConsensusValidators := []providertypes.ConsensusValidator{{ ProviderConsAddr: provAddr.Address, @@ -84,9 +56,6 @@ func TestInitAndExportGenesis(t *testing.T) { "channel", initHeight, *ccv.DefaultConsumerGenesisState(), - []providertypes.VscUnbondingOps{ - {VscId: vscID, UnbondingOpIds: ubdIndex}, - }, []ccv.ValidatorSetChangePacketData{}, []string{"slashedValidatorConsAddress"}, ), @@ -96,16 +65,10 @@ func TestInitAndExportGenesis(t *testing.T) { "", 0, *ccv.DefaultConsumerGenesisState(), - nil, []ccv.ValidatorSetChangePacketData{{ValsetUpdateId: vscID}}, nil, ), }, - []providertypes.UnbondingOp{{ - Id: vscID, - UnbondingConsumerChains: []string{cChainIDs[0]}, - }}, - &providertypes.MaturedUnbondingOps{Ids: ubdIndex}, []providertypes.ConsumerAdditionProposal{{ ChainId: cChainIDs[0], SpawnTime: oneHourFromNow, @@ -129,15 +92,13 @@ func TestInitAndExportGenesis(t *testing.T) { ConsumerAddr: consumerConsAddr.ToSdkConsAddr(), }, }, - []providertypes.ConsumerAddrsToPrune{ + []providertypes.ConsumerAddrsToPruneV2{ { ChainId: cChainIDs[0], - VscId: vscID, + PruneTs: oneHourFromNow, ConsumerAddrs: &providertypes.AddressList{Addresses: [][]byte{consumerConsAddr.ToSdkConsAddr()}}, }, }, - initTimeoutTimeStamps, - exportedVscSendTimeStampsAll, lastProviderConsensusValidators, ) @@ -179,11 +140,6 @@ func TestInitAndExportGenesis(t *testing.T) { require.Equal(t, expectedCandidate, pk.GetSlashMeterReplenishTimeCandidate(ctx)) // check local provider chain states - ubdOps, found := pk.GetUnbondingOp(ctx, vscID) - require.True(t, found) - require.Equal(t, provGenesis.UnbondingOps[0], ubdOps) - matureUbdOps := pk.GetMaturedUnbondingOps(ctx) - require.Equal(t, ubdIndex, matureUbdOps) chainID, found := pk.GetChannelToChain(ctx, provGenesis.ConsumerStates[0].ChannelId) require.True(t, found) require.Equal(t, cChainIDs[0], chainID) @@ -216,7 +172,7 @@ func TestInitAndExportGenesis(t *testing.T) { require.True(t, found) require.Equal(t, provAddr, providerAddr) - addrs := pk.GetConsumerAddrsToPrune(ctx, cChainIDs[0], vscID) + addrs := pk.GetConsumerAddrsToPrune(ctx, cChainIDs[0], oneHourFromNow) // Expect same list as what was provided in provGenesis expectedAddrList := providertypes.AddressList{Addresses: [][]byte{consumerConsAddr.ToSdkConsAddr()}} require.Equal(t, expectedAddrList, addrs) @@ -226,24 +182,6 @@ func TestInitAndExportGenesis(t *testing.T) { // check the exported genesis require.Equal(t, provGenesis, pk.ExportGenesis(ctx)) - - initTimeoutTimestampInStore := pk.GetAllInitTimeoutTimestamps(ctx) - sort.Slice(initTimeoutTimestampInStore, func(i, j int) bool { - return initTimeoutTimestampInStore[i].Timestamp < initTimeoutTimestampInStore[j].Timestamp - }) - require.Equal(t, initTimeoutTimestampInStore, initTimeoutTimeStamps) - - vscSendTimestampsC0InStore := pk.GetAllVscSendTimestamps(ctx, cChainIDs[0]) - sort.Slice(vscSendTimestampsC0InStore, func(i, j int) bool { - return vscSendTimestampsC0InStore[i].VscId < vscSendTimestampsC0InStore[j].VscId - }) - require.Equal(t, vscSendTimestampsC0InStore, exportedVscSendTimeStampsC0.VscSendTimestamps) - - vscSendTimestampsC1InStore := pk.GetAllVscSendTimestamps(ctx, cChainIDs[1]) - sort.Slice(vscSendTimestampsC1InStore, func(i, j int) bool { - return vscSendTimestampsC1InStore[i].VscId < vscSendTimestampsC1InStore[j].VscId - }) - require.Equal(t, vscSendTimestampsC1InStore, exportedVscSendTimeStampsC1.VscSendTimestamps) } func assertConsumerChainStates(t *testing.T, ctx sdk.Context, pk keeper.Keeper, consumerStates ...providertypes.ConsumerState) { @@ -274,12 +212,6 @@ func assertConsumerChainStates(t *testing.T, ctx sdk.Context, pk keeper.Keeper, require.Equal(t, expVSC, gotVSC) } - for _, ubdOpIdx := range cs.UnbondingOpsIndex { - ubdIndex, found := pk.GetUnbondingOpIndex(ctx, chainID, ubdOpIdx.VscId) - require.True(t, found) - require.Equal(t, ubdOpIdx.UnbondingOpIds, ubdIndex) - } - require.Equal(t, cs.SlashDowntimeAck, pk.GetSlashAcks(ctx, chainID)) } } diff --git a/x/ccv/provider/keeper/grpc_query.go b/x/ccv/provider/keeper/grpc_query.go index e8df558a75..20c644ea60 100644 --- a/x/ccv/provider/keeper/grpc_query.go +++ b/x/ccv/provider/keeper/grpc_query.go @@ -463,33 +463,12 @@ func (k Keeper) QueryValidatorConsumerCommissionRate(goCtx context.Context, req return res, nil } -func (k Keeper) QueryOldestUnconfirmedVsc(goCtx context.Context, req *types.QueryOldestUnconfirmedVscRequest) (*types.QueryOldestUnconfirmedVscResponse, error) { +// QueryBlocksUntilNextEpoch returns the number of blocks until the next epoch +func (k Keeper) QueryBlocksUntilNextEpoch(goCtx context.Context, req *types.QueryBlocksUntilNextEpochRequest) (*types.QueryBlocksUntilNextEpochResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - if req == nil { - return nil, status.Errorf(codes.InvalidArgument, "empty request") - } - - if req.ChainId == "" { - return nil, status.Errorf(codes.InvalidArgument, "invalid request: chain id cannot be empty") - } - - if _, consumerRegistered := k.GetConsumerClientId(ctx, req.ChainId); !consumerRegistered { - return nil, status.Error( - codes.NotFound, - errorsmod.Wrap(types.ErrUnknownConsumerChainId, req.ChainId).Error(), - ) - } - - // Note that GetFirstVscSendTimestamp returns the send timestamp of the oldest - // unconfirmed VSCPacket as these timestamps are deleted when handling VSCMaturedPackets - ts, found := k.GetFirstVscSendTimestamp(ctx, req.ChainId) - if !found { - return nil, status.Error( - codes.NotFound, - errorsmod.Wrap(types.ErrNoUnconfirmedVSCPacket, req.ChainId).Error(), - ) - } + // Calculate the blocks until the next epoch + blocksUntilNextEpoch := k.BlocksUntilNextEpoch(ctx) - return &types.QueryOldestUnconfirmedVscResponse{VscSendTimestamp: ts}, nil + return &types.QueryBlocksUntilNextEpochResponse{BlocksUntilNextEpoch: uint64(blocksUntilNextEpoch)}, nil } diff --git a/x/ccv/provider/keeper/grpc_query_test.go b/x/ccv/provider/keeper/grpc_query_test.go index a3dfce14a0..183fed198a 100644 --- a/x/ccv/provider/keeper/grpc_query_test.go +++ b/x/ccv/provider/keeper/grpc_query_test.go @@ -3,7 +3,6 @@ package keeper_test import ( "fmt" "testing" - "time" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" @@ -68,49 +67,6 @@ func TestQueryAllPairsValConAddrByConsumerChainID(t *testing.T) { require.Equal(t, &expectedResult, response.PairValConAddr[0]) } -func TestQueryOldestUnconfirmedVsc(t *testing.T) { - chainID := consumer - - pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - now := time.Now().UTC() - pk.SetVscSendTimestamp(ctx, chainID, 2, now) - pk.SetVscSendTimestamp(ctx, chainID, 1, now) - pk.SetConsumerClientId(ctx, chainID, "client-1") - - // Request is nil - _, err := pk.QueryOldestUnconfirmedVsc(ctx, nil) - require.Error(t, err) - - // Request with chainId is empty - _, err = pk.QueryOldestUnconfirmedVsc(ctx, &types.QueryOldestUnconfirmedVscRequest{}) - require.Error(t, err) - - // Request with chainId is invalid - _, err = pk.QueryOldestUnconfirmedVsc(ctx, &types.QueryOldestUnconfirmedVscRequest{ChainId: "invalidChainId"}) - require.Error(t, err) - - // Request is valid - response, err := pk.QueryOldestUnconfirmedVsc(ctx, &types.QueryOldestUnconfirmedVscRequest{ChainId: chainID}) - require.NoError(t, err) - expectedResult := types.VscSendTimestamp{ - VscId: 1, - Timestamp: now, - } - require.Equal(t, expectedResult, response.VscSendTimestamp) - - // Make sure that the oldest is queried - pk.DeleteVscSendTimestamp(ctx, chainID, 1) - response, err = pk.QueryOldestUnconfirmedVsc(ctx, &types.QueryOldestUnconfirmedVscRequest{ChainId: chainID}) - require.NoError(t, err) - expectedResult = types.VscSendTimestamp{ - VscId: 2, - Timestamp: now, - } - require.Equal(t, expectedResult, response.VscSendTimestamp) -} - func TestQueryConsumerChainOptedInValidators(t *testing.T) { chainID := "chainID" diff --git a/x/ccv/provider/keeper/hooks.go b/x/ccv/provider/keeper/hooks.go index e0b4a066c6..15d5d0e769 100644 --- a/x/ccv/provider/keeper/hooks.go +++ b/x/ccv/provider/keeper/hooks.go @@ -33,105 +33,7 @@ func (k *Keeper) Hooks() Hooks { // staking hooks // -// This stores a record of each unbonding op from staking, allowing us to track which consumer chains have unbonded func (h Hooks) AfterUnbondingInitiated(goCtx context.Context, id uint64) error { - var consumerChainIDS []string - - ctx := sdk.UnwrapSDKContext(goCtx) - - // get validator address from unbonding operation - unbondingType, err := h.k.stakingKeeper.GetUnbondingType(ctx, id) - vadAddrBech32 := "" - if err != nil { - ctx.Logger().Error("undefined type for unbonding operation: id: %d: %s", id, err) - return nil - } - - switch unbondingType { - case stakingtypes.UnbondingType_UnbondingDelegation: - ubd, err := h.k.stakingKeeper.GetUnbondingDelegationByUnbondingID(ctx, id) - if err != nil { - ctx.Logger().Error("unfound ubonding delegation for unbonding id: %d: %s", id, err) - return nil - } - vadAddrBech32 = ubd.ValidatorAddress - case stakingtypes.UnbondingType_Redelegation: - red, err := h.k.stakingKeeper.GetRedelegationByUnbondingID(ctx, id) - if err != nil { - ctx.Logger().Error("unfound relegation for unbonding operation id: %d: %s", id, err) - return nil - } - vadAddrBech32 = red.ValidatorSrcAddress - case stakingtypes.UnbondingType_ValidatorUnbonding: - val, err := h.k.stakingKeeper.GetValidatorByUnbondingID(ctx, id) - if err != nil { - ctx.Logger().Error("unfound validator for unbonding operation id: %d: %s", id, err) - return nil - } - vadAddrBech32 = val.OperatorAddress - default: - ctx.Logger().Error("invalid unbonding operation type: %s", unbondingType) - return nil - } - - valAddr, err := sdk.ValAddressFromBech32(vadAddrBech32) - if err != nil { - ctx.Logger().Error(err.Error()) - return nil - } - - validator, err := h.k.stakingKeeper.GetValidator(ctx, valAddr) - if err != nil { - ctx.Logger().Error("unfound validator for validator address: %s: %s", vadAddrBech32, err) - return nil - } - - consAddr, err := validator.GetConsAddr() - if err != nil { - ctx.Logger().Error(err.Error()) - return nil - } - - // get all consumers where the validator is in the validator set - for _, chainID := range h.k.GetAllRegisteredConsumerChainIDs(ctx) { - if h.k.IsConsumerValidator(ctx, chainID, providertypes.NewProviderConsAddress(consAddr)) { - consumerChainIDS = append(consumerChainIDS, chainID) - } - } - - if len(consumerChainIDS) == 0 { - // Do not put the unbonding op on hold if there are no consumer chains - return nil - } - - valsetUpdateID := h.k.GetValidatorSetUpdateId(ctx) - unbondingOp := providertypes.UnbondingOp{ - Id: id, - UnbondingConsumerChains: consumerChainIDS, - } - - // Add to indexes - for _, consumerChainID := range consumerChainIDS { - index, _ := h.k.GetUnbondingOpIndex(ctx, consumerChainID, valsetUpdateID) - index = append(index, id) - h.k.SetUnbondingOpIndex(ctx, consumerChainID, valsetUpdateID, index) - } - - h.k.SetUnbondingOp(ctx, unbondingOp) - - // Call back into staking to tell it to stop this op from unbonding when the unbonding period is complete - if err := h.k.stakingKeeper.PutUnbondingOnHold(ctx, id); err != nil { - // If there was an error putting the unbonding on hold, panic to end execution for - // the current tx and prevent committal of this invalid state. - // - // Note: that in the case of a validator unbonding, AfterUnbondingInitiated is called - // from staking.EndBlock, thus the following panic would halt the chain. - - // In this case PutUnbondingOnHold fails if either the unbonding operation was - // not found or the UnbondingOnHoldRefCount is negative. In either cases, - // the state of the x/staking module of cosmos-sdk is invalid. - panic(fmt.Errorf("unbonding could not be put on hold: %w", err)) - } return nil } diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index 447f9fe2a5..6d8e0f4175 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -430,8 +430,6 @@ func (k Keeper) SetConsumerChain(ctx sdk.Context, channelID string) error { k.SetChannelToChain(ctx, channelID, chainID) // - set current block height for the consumer chain initialization k.SetInitChainHeight(ctx, chainID, uint64(ctx.BlockHeight())) - // - remove init timeout timestamp - k.DeleteInitTimeoutTimestamp(ctx, chainID) // emit event on successful addition ctx.EventManager().EmitEvent( @@ -447,261 +445,6 @@ func (k Keeper) SetConsumerChain(ctx sdk.Context, channelID string) error { return nil } -// SetUnbondingOp sets the UnbondingOp by its unique ID -func (k Keeper) SetUnbondingOp(ctx sdk.Context, unbondingOp types.UnbondingOp) { - store := ctx.KVStore(k.storeKey) - bz, err := unbondingOp.Marshal() - if err != nil { - // An error here would indicate something is very wrong, - // unbondingOp is either instantiated in AfterUnbondingInitiated, - // updated correctly by RemoveConsumerFromUnbondingOp, - // or set during InitGenesis. - panic(fmt.Errorf("unbonding op could not be marshaled: %w", err)) - } - store.Set(types.UnbondingOpKey(unbondingOp.Id), bz) -} - -// GetUnbondingOp gets a UnbondingOp by its unique ID -func (k Keeper) GetUnbondingOp(ctx sdk.Context, id uint64) (types.UnbondingOp, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.UnbondingOpKey(id)) - if bz == nil { - return types.UnbondingOp{}, false - } - - var unbondingOp types.UnbondingOp - if err := unbondingOp.Unmarshal(bz); err != nil { - // An error here would indicate something is very wrong, - // the UnbondingOp is assumed to be correctly serialized in SetUnbondingOp. - panic(fmt.Errorf("failed to unmarshal UnbondingOp: %w", err)) - } - - return unbondingOp, true -} - -// DeleteUnbondingOp deletes a UnbondingOp given its ID -func (k Keeper) DeleteUnbondingOp(ctx sdk.Context, id uint64) { - store := ctx.KVStore(k.storeKey) - store.Delete(types.UnbondingOpKey(id)) -} - -// GetAllUnbondingOps gets all UnbondingOps, where each UnbondingOp consists -// of its unique ID and a list of consumer chainIDs that the unbonding operation -// is waiting on. -// -// Note that UnbondingOps are stored under keys with the following format: -// UnbondingOpKeyPrefix | ID -// Thus, the iteration is in ascending order of IDs. -func (k Keeper) GetAllUnbondingOps(ctx sdk.Context) (ops []types.UnbondingOp) { - store := ctx.KVStore(k.storeKey) - iterator := storetypes.KVStorePrefixIterator(store, types.UnbondingOpKeyPrefix()) - - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - id := binary.BigEndian.Uint64(iterator.Key()[1:]) - bz := iterator.Value() - if bz == nil { - // An error here would indicate something is very wrong, - // the UnbondingOp is assumed to be correctly set in SetUnbondingOp. - panic(fmt.Errorf("unbonding operation is nil for id %d", id)) - } - var unbondingOp types.UnbondingOp - if err := unbondingOp.Unmarshal(bz); err != nil { - // An error here would indicate something is very wrong, - // the UnbondingOp is assumed to be correctly serialized in SetUnbondingOp. - panic(fmt.Errorf("failed to unmarshal UnbondingOp: %w", err)) - } - - ops = append(ops, unbondingOp) - } - - return ops -} - -// RemoveConsumerFromUnbondingOp removes a consumer chain ID that the unbonding op with 'id' is waiting on. -// The method returns true if the unbonding op can complete. In this case the record is removed from store. -// The method panics if the unbonding op with 'id' is not found. -func (k Keeper) RemoveConsumerFromUnbondingOp(ctx sdk.Context, id uint64, chainID string) (canComplete bool) { - // Get the unbonding op from store - unbondingOp, found := k.GetUnbondingOp(ctx, id) - if !found { - panic(fmt.Errorf("internal state corrupted; could not find UnbondingOp with ID %d", id)) - } - - // Remove consumer chain ID from unbonding op - var numRemoved int - unbondingOp.UnbondingConsumerChains, numRemoved = removeStringFromSlice(unbondingOp.UnbondingConsumerChains, chainID) - if numRemoved > 0 { - k.Logger(ctx).Debug("unbonding operation matured on consumer", "chainID", chainID, "opID", id) - - if len(unbondingOp.UnbondingConsumerChains) == 0 { - // Delete unbonding op - k.DeleteUnbondingOp(ctx, id) - // No more consumer chains; the unbonding op can complete - canComplete = true - } else { - // Update unbonding op in store - k.SetUnbondingOp(ctx, unbondingOp) - } - } - return -} - -func removeStringFromSlice(slice []string, x string) (newSlice []string, numRemoved int) { - for _, y := range slice { - if x != y { - newSlice = append(newSlice, y) - } - } - - return newSlice, len(slice) - len(newSlice) -} - -// SetUnbondingOpIndex sets the IDs of unbonding operations that are waiting for -// a VSCMaturedPacket with vscID from a consumer with chainID -func (k Keeper) SetUnbondingOpIndex(ctx sdk.Context, chainID string, vscID uint64, ids []uint64) { - store := ctx.KVStore(k.storeKey) - - vscUnbondingOps := types.VscUnbondingOps{ - VscId: vscID, - UnbondingOpIds: ids, - } - bz, err := vscUnbondingOps.Marshal() - if err != nil { - // An error here would indicate something is very wrong, - // vscUnbondingOps is instantiated in this method and should be able to be marshaled. - panic(fmt.Errorf("failed to marshal VscUnbondingOps: %w", err)) - } - - store.Set(types.UnbondingOpIndexKey(chainID, vscID), bz) -} - -// GetAllUnbondingOpIndexes gets all unbonding indexes for a given chain id, -// i.e., all the IDs of unbonding operations that are waiting for -// VSCMaturedPackets from a consumer with chainID. -// -// Note that the unbonding indexes for a given chainID are stored under keys with the following format: -// UnbondingOpIndexKeyPrefix | len(chainID) | chainID | vscID -// Thus, the returned array is in ascending order of vscIDs. -func (k Keeper) GetAllUnbondingOpIndexes(ctx sdk.Context, chainID string) (indexes []types.VscUnbondingOps) { - store := ctx.KVStore(k.storeKey) - bytePrefix := types.UnbondingOpIndexKeyPrefix() - iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(bytePrefix, chainID)) - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - var vscUnbondingOps types.VscUnbondingOps - if err := vscUnbondingOps.Unmarshal(iterator.Value()); err != nil { - // An error here would indicate something is very wrong, - // the VscUnbondingOps are assumed to be correctly serialized in SetUnbondingOpIndex. - panic(fmt.Errorf("failed to unmarshal VscUnbondingOps: %w", err)) - } - - indexes = append(indexes, types.VscUnbondingOps{ - VscId: vscUnbondingOps.GetVscId(), - UnbondingOpIds: vscUnbondingOps.GetUnbondingOpIds(), - }) - } - - return indexes -} - -// GetUnbondingOpIndex gets the IDs of unbonding operations that are waiting for -// a VSCMaturedPacket with vscID from a consumer with chainID -func (k Keeper) GetUnbondingOpIndex(ctx sdk.Context, chainID string, vscID uint64) ([]uint64, bool) { - store := ctx.KVStore(k.storeKey) - - bz := store.Get(types.UnbondingOpIndexKey(chainID, vscID)) - if bz == nil { - return []uint64{}, false - } - - var vscUnbondingOps types.VscUnbondingOps - if err := vscUnbondingOps.Unmarshal(bz); err != nil { - // An error here would indicate something is very wrong, - // the VscUnbondingOps are assumed to be correctly serialized in SetUnbondingOpIndex. - panic(fmt.Errorf("failed to unmarshal VscUnbondingOps: %w", err)) - } - - return vscUnbondingOps.GetUnbondingOpIds(), true -} - -// DeleteUnbondingOpIndex deletes the IDs of unbonding operations that are waiting for -// a VSCMaturedPacket with vscID from a consumer with chainID -func (k Keeper) DeleteUnbondingOpIndex(ctx sdk.Context, chainID string, vscID uint64) { - store := ctx.KVStore(k.storeKey) - store.Delete(types.UnbondingOpIndexKey(chainID, vscID)) -} - -// GetUnbondingOpsFromIndex gets the unbonding ops waiting for a given chainID and vscID -func (k Keeper) GetUnbondingOpsFromIndex(ctx sdk.Context, chainID string, valsetUpdateID uint64) (entries []types.UnbondingOp) { - ids, found := k.GetUnbondingOpIndex(ctx, chainID, valsetUpdateID) - if !found { - return entries - } - for _, id := range ids { - entry, found := k.GetUnbondingOp(ctx, id) - if !found { - // An error here would indicate something is very wrong. - // Every UnbondingOpIndex is assumed to have the corresponding UnbondingOps set in store. - // This is done in AfterUnbondingInitiated and InitGenesis. - panic("did not find UnbondingOp according to index- index was probably not correctly updated") - } - entries = append(entries, entry) - } - - return entries -} - -// GetMaturedUnbondingOps returns the list of matured unbonding operation ids -func (k Keeper) GetMaturedUnbondingOps(ctx sdk.Context) (ids []uint64) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.MaturedUnbondingOpsKey()) - if bz == nil { - // Note that every call to ConsumeMaturedUnbondingOps - // deletes the MaturedUnbondingOpsKey, which means that - // the first call to GetMaturedUnbondingOps after that - // will enter this branch. - return nil - } - - var ops types.MaturedUnbondingOps - if err := ops.Unmarshal(bz); err != nil { - // An error here would indicate something is very wrong, - // the MaturedUnbondingOps are assumed to be correctly serialized in AppendMaturedUnbondingOps. - panic(fmt.Errorf("failed to unmarshal MaturedUnbondingOps: %w", err)) - } - return ops.GetIds() -} - -// AppendMaturedUnbondingOps adds a list of ids to the list of matured unbonding operation ids -func (k Keeper) AppendMaturedUnbondingOps(ctx sdk.Context, ids []uint64) { - if len(ids) == 0 { - return - } - existingIds := k.GetMaturedUnbondingOps(ctx) - maturedOps := types.MaturedUnbondingOps{ - Ids: append(existingIds, ids...), - } - - store := ctx.KVStore(k.storeKey) - bz, err := maturedOps.Marshal() - if err != nil { - // An error here would indicate something is very wrong, - // maturedOps is instantiated in this method and should be able to be marshaled. - panic(fmt.Sprintf("failed to marshal matured unbonding operations: %s", err)) - } - store.Set(types.MaturedUnbondingOpsKey(), bz) -} - -// ConsumeMaturedUnbondingOps empties and returns list of matured unbonding operation ids (if it exists) -func (k Keeper) ConsumeMaturedUnbondingOps(ctx sdk.Context) []uint64 { - ids := k.GetMaturedUnbondingOps(ctx) - store := ctx.KVStore(k.storeKey) - store.Delete(types.MaturedUnbondingOpsKey()) - return ids -} - // Retrieves the underlying client state corresponding to a connection ID. func (k Keeper) getUnderlyingClient(ctx sdk.Context, connectionID string) ( clientID string, tmClient *ibctmtypes.ClientState, err error, @@ -959,175 +702,6 @@ func (k Keeper) DeleteConsumerClientId(ctx sdk.Context, chainID string) { store.Delete(types.ChainToClientKey(chainID)) } -// SetInitTimeoutTimestamp sets the init timeout timestamp for the given chain ID -func (k Keeper) SetInitTimeoutTimestamp(ctx sdk.Context, chainID string, ts uint64) { - store := ctx.KVStore(k.storeKey) - tsBytes := make([]byte, 8) - binary.BigEndian.PutUint64(tsBytes, ts) - store.Set(types.InitTimeoutTimestampKey(chainID), tsBytes) -} - -// GetInitTimeoutTimestamp returns the init timeout timestamp for the given chain ID. -// This method is used only in testing. -func (k Keeper) GetInitTimeoutTimestamp(ctx sdk.Context, chainID string) (uint64, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.InitTimeoutTimestampKey(chainID)) - if bz == nil { - return 0, false - } - return binary.BigEndian.Uint64(bz), true -} - -// DeleteInitTimeoutTimestamp removes from the store the init timeout timestamp for the given chainID. -func (k Keeper) DeleteInitTimeoutTimestamp(ctx sdk.Context, chainID string) { - store := ctx.KVStore(k.storeKey) - store.Delete(types.InitTimeoutTimestampKey(chainID)) -} - -// GetAllInitTimeoutTimestamps gets all init timeout timestamps in the store. -// -// Note that the init timeout timestamps are stored under keys with the following format: -// InitTimeoutTimestampKeyPrefix | chainID -// Thus, the returned array is in ascending order of chainIDs (NOT in timestamp order). -func (k Keeper) GetAllInitTimeoutTimestamps(ctx sdk.Context) (initTimeoutTimestamps []types.InitTimeoutTimestamp) { - store := ctx.KVStore(k.storeKey) - iterator := storetypes.KVStorePrefixIterator(store, types.InitTimeoutTimestampKeyPrefix()) - - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - chainID := string(iterator.Key()[1:]) - ts := binary.BigEndian.Uint64(iterator.Value()) - - initTimeoutTimestamps = append(initTimeoutTimestamps, types.InitTimeoutTimestamp{ - ChainId: chainID, - Timestamp: ts, - }) - } - - return initTimeoutTimestamps -} - -// SetVscSendTimestamp sets the VSC send timestamp -// for a VSCPacket with ID vscID sent to a chain with ID chainID -func (k Keeper) SetVscSendTimestamp( - ctx sdk.Context, - chainID string, - vscID uint64, - timestamp time.Time, -) { - store := ctx.KVStore(k.storeKey) - - // Convert timestamp into bytes for storage - timeBz := sdk.FormatTimeBytes(timestamp) - - store.Set(types.VscSendingTimestampKey(chainID, vscID), timeBz) -} - -// GetVscSendTimestamp returns a VSC send timestamp by chainID and vscID -// -// Note: This method is used only for testing. -func (k Keeper) GetVscSendTimestamp(ctx sdk.Context, chainID string, vscID uint64) (time.Time, bool) { - store := ctx.KVStore(k.storeKey) - - timeBz := store.Get(types.VscSendingTimestampKey(chainID, vscID)) - if timeBz == nil { - return time.Time{}, false - } - - ts, err := sdk.ParseTimeBytes(timeBz) - if err != nil { - return time.Time{}, false - } - return ts, true -} - -// DeleteVscSendTimestamp removes from the store a specific VSC send timestamp -// for the given chainID and vscID. -func (k Keeper) DeleteVscSendTimestamp(ctx sdk.Context, chainID string, vscID uint64) { - store := ctx.KVStore(k.storeKey) - store.Delete(types.VscSendingTimestampKey(chainID, vscID)) -} - -// GetAllVscSendTimestamps gets an array of all the vsc send timestamps of the given chainID. -// -// Note that the vsc send timestamps of a given chainID are stored under keys with the following format: -// VscSendTimestampKeyPrefix | len(chainID) | chainID | vscID -// Thus, the iteration is in ascending order of vscIDs, and as a result in send timestamp order. -func (k Keeper) GetAllVscSendTimestamps(ctx sdk.Context, chainID string) (vscSendTimestamps []types.VscSendTimestamp) { - store := ctx.KVStore(k.storeKey) - iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.VscSendingTimestampKeyPrefix(), chainID)) - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - _, vscID, err := types.ParseVscSendingTimestampKey(iterator.Key()) - if err != nil { - // An error here would indicate something is very wrong, - // the store key is assumed to be correctly serialized in SetVscSendTimestamp. - panic(fmt.Errorf("failed to parse VscSendTimestampKey: %w", err)) - } - ts, err := sdk.ParseTimeBytes(iterator.Value()) - if err != nil { - // An error here would indicate something is very wrong, - // the timestamp is assumed to be correctly serialized in SetVscSendTimestamp. - panic(fmt.Errorf("failed to parse timestamp value: %w", err)) - } - - vscSendTimestamps = append(vscSendTimestamps, types.VscSendTimestamp{ - VscId: vscID, - Timestamp: ts, - }) - } - - return vscSendTimestamps -} - -// DeleteVscSendTimestampsForConsumer deletes all VSC send timestamps for a given consumer chain -func (k Keeper) DeleteVscSendTimestampsForConsumer(ctx sdk.Context, consumerChainID string) { - store := ctx.KVStore(k.storeKey) - iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.VscSendingTimestampKeyPrefix(), consumerChainID)) - - defer iterator.Close() - - keysToDel := [][]byte{} - for ; iterator.Valid(); iterator.Next() { - keysToDel = append(keysToDel, iterator.Key()) - } - - // Delete data for this consumer - for _, key := range keysToDel { - store.Delete(key) - } -} - -// GetFirstVscSendTimestamp gets the vsc send timestamp with the lowest vscID for the given chainID. -func (k Keeper) GetFirstVscSendTimestamp(ctx sdk.Context, chainID string) (vscSendTimestamp types.VscSendTimestamp, found bool) { - store := ctx.KVStore(k.storeKey) - iterator := storetypes.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.VscSendingTimestampKeyPrefix(), chainID)) - defer iterator.Close() - - if iterator.Valid() { - _, vscID, err := types.ParseVscSendingTimestampKey(iterator.Key()) - if err != nil { - // An error here would indicate something is very wrong, - // the store key is assumed to be correctly serialized in SetVscSendTimestamp. - panic(fmt.Errorf("failed to parse VscSendTimestampKey: %w", err)) - } - ts, err := sdk.ParseTimeBytes(iterator.Value()) - if err != nil { - // An error here would indicate something is very wrong, - // the timestamp is assumed to be correctly serialized in SetVscSendTimestamp. - panic(fmt.Errorf("failed to parse timestamp value: %w", err)) - } - - return types.VscSendTimestamp{ - VscId: vscID, - Timestamp: ts, - }, true - } - - return types.VscSendTimestamp{}, false -} - // SetSlashLog updates validator's slash log for a consumer chain // If an entry exists for a given validator address, at least one // double signing slash packet was received by the provider from at least one consumer chain @@ -1670,3 +1244,11 @@ func (k Keeper) DeleteAllowInactiveValidators( store := ctx.KVStore(k.storeKey) store.Delete(types.AllowInactiveValidatorsKey(chainID)) } + +func (k Keeper) UnbondingCanComplete(ctx sdk.Context, id uint64) error { + return k.stakingKeeper.UnbondingCanComplete(ctx, id) +} + +func (k Keeper) UnbondingTime(ctx sdk.Context) (time.Duration, error) { + return k.stakingKeeper.UnbondingTime(ctx) +} diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 0949fa4317..b4bd76041a 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -5,7 +5,6 @@ import ( "fmt" "sort" "testing" - "time" "cosmossdk.io/math" ibctesting "github.com/cosmos/ibc-go/v8/testing" @@ -225,175 +224,6 @@ func TestInitHeight(t *testing.T) { } } -// TestGetAllUnbondingOpIndexes tests GetAllUnbondingOpIndexes behavior correctness -func TestGetAllUnbondingOpIndexes(t *testing.T) { - pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - ops := []types.VscUnbondingOps{ - { - VscId: 2, - UnbondingOpIds: []uint64{4, 5, 6, 7}, - }, - { - VscId: 1, - UnbondingOpIds: []uint64{1, 2, 3}, - }, - { - VscId: 4, - UnbondingOpIds: []uint64{10}, - }, - { - VscId: 3, - UnbondingOpIds: []uint64{8, 9}, - }, - } - // sorting by CrossChainValidator.Address - expectedGetAllOrder := ops - sort.Slice(expectedGetAllOrder, func(i, j int) bool { - return expectedGetAllOrder[i].VscId < expectedGetAllOrder[j].VscId - }) - - pk.SetUnbondingOpIndex(ctx, "chain-2", 1, []uint64{1, 2, 3}) - for _, op := range ops { - pk.SetUnbondingOpIndex(ctx, "chain-1", op.VscId, op.UnbondingOpIds) - } - - // iterate and check all results are returned in the expected order - result := pk.GetAllUnbondingOpIndexes(ctx, "chain-1") - require.Len(t, result, len(ops)) - require.Equal(t, result, expectedGetAllOrder) -} - -func TestMaturedUnbondingOps(t *testing.T) { - providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - ids := providerKeeper.GetMaturedUnbondingOps(ctx) - require.Nil(t, ids) - - unbondingOpIds := []uint64{0, 1, 2, 3, 4, 5, 6} - providerKeeper.AppendMaturedUnbondingOps(ctx, unbondingOpIds) - - ids = providerKeeper.ConsumeMaturedUnbondingOps(ctx) - require.Equal(t, len(unbondingOpIds), len(ids)) - for i := 0; i < len(unbondingOpIds); i++ { - require.Equal(t, unbondingOpIds[i], ids[i]) - } -} - -func TestInitTimeoutTimestamp(t *testing.T) { - pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - now := time.Now().UTC() - nsNow := uint64(now.UnixNano()) - timeoutTimestamps := []types.InitTimeoutTimestamp{ - { - ChainId: "chain-2", - Timestamp: nsNow, - }, - { - ChainId: "chain-1", - Timestamp: nsNow + 10, - }, - { - ChainId: "chain-4", - Timestamp: nsNow - 10, - }, - { - ChainId: "chain-3", - Timestamp: nsNow, - }, - } - - expectedGetAllOrder := timeoutTimestamps - // sorting by ChainId - sort.Slice(expectedGetAllOrder, func(i, j int) bool { - return expectedGetAllOrder[i].ChainId < expectedGetAllOrder[j].ChainId - }) - - _, found := pk.GetInitTimeoutTimestamp(ctx, timeoutTimestamps[0].ChainId) - require.False(t, found) - - for _, tt := range timeoutTimestamps { - pk.SetInitTimeoutTimestamp(ctx, tt.ChainId, tt.Timestamp) - } - - for _, tt := range timeoutTimestamps { - _, found := pk.GetInitTimeoutTimestamp(ctx, tt.ChainId) - require.True(t, found) - } - - // iterate and check all results are returned in the expected order - result := pk.GetAllInitTimeoutTimestamps(ctx) - require.Len(t, result, len(timeoutTimestamps)) - require.Equal(t, result, expectedGetAllOrder) - - pk.DeleteInitTimeoutTimestamp(ctx, timeoutTimestamps[0].ChainId) - _, found = pk.GetInitTimeoutTimestamp(ctx, timeoutTimestamps[0].ChainId) - require.False(t, found) -} - -// TestVscSendTimestamp tests the set, deletion, and iteration methods for VSC timeout timestamps -func TestVscSendTimestamp(t *testing.T) { - providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - now := time.Now().UTC() - - testCases := []struct { - chainID string - ts time.Time - vscID uint64 - }{ - {chainID: "chain", ts: now.Add(2 * time.Hour), vscID: 2}, - {chainID: "chain", ts: now.Add(time.Hour), vscID: 1}, - {chainID: "chain", ts: now.Add(time.Hour), vscID: 3}, - // this is not possible since the ts is the timestamp of sending, - // which means it must be in the same order as vscIDs, - // but it still worth testing - {chainID: "chain", ts: now.Add(-time.Hour), vscID: 4}, - {chainID: "chain1", ts: now.Add(time.Hour), vscID: 1}, - {chainID: "chain2", ts: now.Add(time.Hour), vscID: 1}, - } - chainID := testCases[0].chainID - expectedGetAllOrder := []types.VscSendTimestamp{} - for _, tc := range testCases { - if tc.chainID == chainID { - expectedGetAllOrder = append(expectedGetAllOrder, types.VscSendTimestamp{VscId: tc.vscID, Timestamp: tc.ts}) - } - } - // sorting by vscID - sort.Slice(expectedGetAllOrder, func(i, j int) bool { - return expectedGetAllOrder[i].VscId < expectedGetAllOrder[j].VscId - }) - - require.Empty(t, providerKeeper.GetAllVscSendTimestamps(ctx, chainID)) - - for _, tc := range testCases { - providerKeeper.SetVscSendTimestamp(ctx, tc.chainID, tc.vscID, tc.ts) - } - - // iterate and check all results are returned in the expected order - vscSendTimestamps := providerKeeper.GetAllVscSendTimestamps(ctx, chainID) - require.Equal(t, expectedGetAllOrder, vscSendTimestamps) - - vscSendTimestamp, found := providerKeeper.GetFirstVscSendTimestamp(ctx, chainID) - require.True(t, found) - require.Equal(t, vscSendTimestamp, expectedGetAllOrder[0]) - - // delete first VSC send timestamp - providerKeeper.DeleteVscSendTimestamp(ctx, chainID, vscSendTimestamp.VscId) - for _, vst := range providerKeeper.GetAllVscSendTimestamps(ctx, chainID) { - require.NotEqual(t, vscSendTimestamp, vst) - } - - // delete all VSC send timestamps - providerKeeper.DeleteVscSendTimestampsForConsumer(ctx, chainID) - require.Empty(t, providerKeeper.GetAllVscSendTimestamps(ctx, chainID)) -} - func TestGetAllRegisteredConsumerChainIDs(t *testing.T) { pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() @@ -434,92 +264,6 @@ func TestGetAllChannelToChains(t *testing.T) { require.Equal(t, expectedGetAllOrder, result) } -// TestGetAllUnbondingOps tests GetAllUnbondingOps behaviour correctness -func TestGetAllUnbondingOps(t *testing.T) { - pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - ops := []types.UnbondingOp{ - { - Id: 2, - UnbondingConsumerChains: []string{"chain-2", "chain-1"}, - }, - { - Id: 1, - UnbondingConsumerChains: []string{"chain-1", "chain-2"}, - }, - { - Id: 4, - UnbondingConsumerChains: []string{"chain-2"}, - }, - { - Id: 3, - UnbondingConsumerChains: []string{"chain-3", "chain-1", "chain-2"}, - }, - } - expectedGetAllOrder := ops - // sorting by Id - sort.Slice(expectedGetAllOrder, func(i, j int) bool { - return expectedGetAllOrder[i].Id < expectedGetAllOrder[j].Id - }) - - for _, op := range ops { - pk.SetUnbondingOp(ctx, op) - } - - // iterate and check all results are returned - result := pk.GetAllUnbondingOps(ctx) - require.Len(t, result, len(ops)) - require.Equal(t, expectedGetAllOrder, result) -} - -// TestRemoveConsumerFromUnbondingOp tests RemoveConsumerFromUnbondingOp behaviour correctness -func TestRemoveConsumerFromUnbondingOp(t *testing.T) { - pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - var expectedID uint64 = 1 - expectedUnbondingOp := types.UnbondingOp{ - Id: expectedID, - UnbondingConsumerChains: []string{"chain-3", "chain-1", "chain-2"}, - } - - pk.SetUnbondingOp(ctx, expectedUnbondingOp) - - canComplete := pk.RemoveConsumerFromUnbondingOp(ctx, expectedID, "chain-1") - require.False(t, canComplete) - unbondingOp, found := pk.GetUnbondingOp(ctx, expectedID) - require.True(t, found) - expectedChainIDs := []string{"chain-3", "chain-2"} - require.Equal(t, expectedChainIDs, unbondingOp.UnbondingConsumerChains) - - canComplete = pk.RemoveConsumerFromUnbondingOp(ctx, expectedID, "chain-2") - require.False(t, canComplete) - unbondingOp, found = pk.GetUnbondingOp(ctx, expectedID) - require.True(t, found) - expectedChainIDs = []string{"chain-3"} - require.Equal(t, expectedChainIDs, unbondingOp.UnbondingConsumerChains) - - // check that it doesn't panic when calling with same chain ID - canComplete = pk.RemoveConsumerFromUnbondingOp(ctx, expectedID, "chain-2") - require.False(t, canComplete) - unbondingOp, found = pk.GetUnbondingOp(ctx, expectedID) - require.True(t, found) - require.Equal(t, expectedChainIDs, unbondingOp.UnbondingConsumerChains) - - canComplete = pk.RemoveConsumerFromUnbondingOp(ctx, expectedID, "chain-3") - require.True(t, canComplete) - unbondingOp, found = pk.GetUnbondingOp(ctx, expectedID) - require.False(t, found) - require.Empty(t, unbondingOp.UnbondingConsumerChains) - - // check that it panics when calling with wrong chain IDs - require.Panics(t, func() { - canComplete = pk.RemoveConsumerFromUnbondingOp(ctx, expectedID, "some_chain") - require.False(t, canComplete) - }) -} - // TestSetSlashLog tests slash log getter and setter methods func TestSetSlashLog(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) diff --git a/x/ccv/provider/keeper/key_assignment.go b/x/ccv/provider/keeper/key_assignment.go index dd0868b9a2..23dd20109d 100644 --- a/x/ccv/provider/keeper/key_assignment.go +++ b/x/ccv/provider/keeper/key_assignment.go @@ -3,6 +3,7 @@ package keeper import ( "encoding/base64" "fmt" + "time" errorsmod "cosmossdk.io/errors" storetypes "cosmossdk.io/store/types" @@ -104,7 +105,7 @@ func (k Keeper) SetValidatorConsumerPubKey( // If chainID is nil, it returns all the validators public keys assigned for all consumer chains // // Note that the validators public keys assigned for a consumer chain are stored under keys -// with the following format: UnbondingOpIndexKeyPrefix | len(chainID) | chainID | providerAddress +// with the following format: ConsumerValidatorsBytePrefix | len(chainID) | chainID | providerAddress // Thus, the returned array is // - in ascending order of providerAddresses, if chainID is not nil; // - in undetermined order, if chainID is nil. @@ -235,16 +236,22 @@ func (k Keeper) DeleteValidatorByConsumerAddr(ctx sdk.Context, chainID string, c } // AppendConsumerAddrsToPrune appends a consumer validator address to the list of consumer addresses -// that can be pruned once the VSCMaturedPacket with vscID is received. +// that can be pruned once the block time is at least pruneTs. // // The following invariant needs to hold: // For each consumer address cAddr in ValidatorByConsumerAddr, // - either there exists a provider address pAddr in ValidatorConsumerPubKey, // s.t. hash(ValidatorConsumerPubKey(pAddr)) = cAddr -// - or there exists a vscID in ConsumerAddrsToPrune s.t. cAddr in ConsumerAddrsToPrune(vscID) -func (k Keeper) AppendConsumerAddrsToPrune(ctx sdk.Context, chainID string, vscID uint64, consumerAddr types.ConsumerConsAddress) { +// - or there exists a timestamp in ConsumerAddrsToPrune s.t. cAddr in ConsumerAddrsToPrune(timestamp) +func (k Keeper) AppendConsumerAddrsToPrune( + ctx sdk.Context, + chainID string, + pruneTs time.Time, + consumerAddr types.ConsumerConsAddress, +) { store := ctx.KVStore(k.storeKey) - bz := store.Get(types.ConsumerAddrsToPruneKey(chainID, vscID)) + storeKey := types.ConsumerAddrsToPruneV2Key(chainID, pruneTs) + bz := store.Get(storeKey) var consumerAddrsToPrune types.AddressList if bz != nil { err := consumerAddrsToPrune.Unmarshal(bz) @@ -261,18 +268,19 @@ func (k Keeper) AppendConsumerAddrsToPrune(ctx sdk.Context, chainID string, vscI // consumerAddrsToPrune is instantiated in this method and should be able to be marshaled. panic(err) } - store.Set(types.ConsumerAddrsToPruneKey(chainID, vscID), bz) + store.Set(storeKey, bz) } -// GetConsumerAddrsToPrune returns the list of consumer addresses -// that can be pruned once the VSCMaturedPacket with vscID is received +// GetConsumerAddrsToPrune returns the list of consumer addresses to prune stored under timestamp ts. +// Note that this method is only used in testing. func (k Keeper) GetConsumerAddrsToPrune( ctx sdk.Context, chainID string, - vscID uint64, + ts time.Time, ) (consumerAddrsToPrune types.AddressList) { store := ctx.KVStore(k.storeKey) - bz := store.Get(types.ConsumerAddrsToPruneKey(chainID, vscID)) + + bz := store.Get(types.ConsumerAddrsToPruneV2Key(chainID, ts)) if bz == nil { return } @@ -285,19 +293,78 @@ func (k Keeper) GetConsumerAddrsToPrune( return } -// GetAllConsumerAddrsToPrune gets all consumer addresses that can be pruned for a given chainID. +// ConsumeConsumerAddrsToPrune returns the list of consumer addresses that can be pruned at timestamp ts. +// The returned addresses are removed from the store. // // Note that the list of all consumer addresses is stored under keys with the following format: -// ConsumerAddrsToPruneKeyPrefix | len(chainID) | chainID | vscID -// Thus, the returned array is in ascending order of vscIDs. -func (k Keeper) GetAllConsumerAddrsToPrune(ctx sdk.Context, chainID string) (consumerAddrsToPrune []types.ConsumerAddrsToPrune) { +// ConsumerAddrsToPruneV2BytePrefix | len(chainID) | chainID | timestamp +// Thus, this method returns all the consumer addresses stored under keys in the following range: +// (ConsumerAddrsToPruneV2BytePrefix | len(chainID) | chainID | ts') where ts' <= ts +func (k Keeper) ConsumeConsumerAddrsToPrune( + ctx sdk.Context, + chainID string, + ts time.Time, +) (consumerAddrsToPrune types.AddressList) { store := ctx.KVStore(k.storeKey) - consumerAddrsToPruneKeyPrefix := types.ConsumerAddrsToPruneKeyPrefix() + consumerAddrsToPruneKeyPrefix := types.ConsumerAddrsToPruneV2KeyPrefix() + startPrefix := types.ChainIdWithLenKey(consumerAddrsToPruneKeyPrefix, chainID) + iterator := store.Iterator(startPrefix, + storetypes.InclusiveEndBytes(types.ConsumerAddrsToPruneV2Key(chainID, ts))) + defer iterator.Close() + + var keysToDel [][]byte + for ; iterator.Valid(); iterator.Next() { + // Sanity check + if _, pruneTs, err := types.ParseChainIdAndTsKey(consumerAddrsToPruneKeyPrefix, iterator.Key()); err != nil { + // An error here would indicate something is very wrong, + // store keys are assumed to be correctly serialized in AppendConsumerAddrsToPrune. + k.Logger(ctx).Error("ParseChainIdAndTsKey failed", + "key", string(iterator.Key()), + "error", err.Error(), + ) + continue + } else if pruneTs.After(ts) { + // An error here would indicate something is wrong the iterator + k.Logger(ctx).Error("iterator in ConsumeConsumerAddrsToPrune failed", "key", string(iterator.Key())) + continue + } + + keysToDel = append(keysToDel, iterator.Key()) + + var addrs types.AddressList + if err := addrs.Unmarshal(iterator.Value()); err != nil { + // An error here would indicate something is very wrong, + // the list of consumer addresses is assumed to be correctly serialized in AppendConsumerAddrsToPrune. + k.Logger(ctx).Error("unmarshaling in ConsumeConsumerAddrsToPrune failed", + "key", string(iterator.Key()), + "error", err.Error(), + ) + continue + } + + consumerAddrsToPrune.Addresses = append(consumerAddrsToPrune.Addresses, addrs.Addresses...) + } + + for _, delKey := range keysToDel { + store.Delete(delKey) + } + + return +} + +// GetAllConsumerAddrsToPrune gets all consumer addresses that can be eventually pruned for a given chainID. +// +// Note that the list of all consumer addresses is stored under keys with the following format: +// ConsumerAddrsToPruneV2BytePrefix | len(chainID) | chainID | timestamp +// Thus, the returned array is in ascending order of timestamps. +func (k Keeper) GetAllConsumerAddrsToPrune(ctx sdk.Context, chainID string) (consumerAddrsToPrune []types.ConsumerAddrsToPruneV2) { + store := ctx.KVStore(k.storeKey) + consumerAddrsToPruneKeyPrefix := types.ConsumerAddrsToPruneV2KeyPrefix() iteratorPrefix := types.ChainIdWithLenKey(consumerAddrsToPruneKeyPrefix, chainID) iterator := storetypes.KVStorePrefixIterator(store, iteratorPrefix) defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - _, vscID, err := types.ParseChainIdAndUintIdKey(consumerAddrsToPruneKeyPrefix, iterator.Key()) + _, ts, err := types.ParseChainIdAndTsKey(consumerAddrsToPruneKeyPrefix, iterator.Key()) if err != nil { // An error here would indicate something is very wrong, // store keys are assumed to be correctly serialized in AppendConsumerAddrsToPrune. @@ -311,8 +378,8 @@ func (k Keeper) GetAllConsumerAddrsToPrune(ctx sdk.Context, chainID string) (con panic(err) } - consumerAddrsToPrune = append(consumerAddrsToPrune, types.ConsumerAddrsToPrune{ - VscId: vscID, + consumerAddrsToPrune = append(consumerAddrsToPrune, types.ConsumerAddrsToPruneV2{ + PruneTs: ts, ConsumerAddrs: &addrs, ChainId: chainID, }) @@ -321,10 +388,10 @@ func (k Keeper) GetAllConsumerAddrsToPrune(ctx sdk.Context, chainID string) (con return consumerAddrsToPrune } -// DeleteConsumerAddrsToPrune deletes the list of consumer addresses mapped to a given VSC ID -func (k Keeper) DeleteConsumerAddrsToPrune(ctx sdk.Context, chainID string, vscID uint64) { +// DeleteConsumerAddrsToPruneV2 deletes the list of consumer addresses mapped to a timestamp +func (k Keeper) DeleteConsumerAddrsToPrune(ctx sdk.Context, chainID string, pruneTs time.Time) { store := ctx.KVStore(k.storeKey) - store.Delete(types.ConsumerAddrsToPruneKey(chainID, vscID)) + store.Delete(types.ConsumerAddrsToPruneV2Key(chainID, pruneTs)) } // AssignConsumerKey assigns the consumerKey to the validator with providerAddr @@ -395,13 +462,16 @@ func (k Keeper) AssignConsumerKey( // check whether the consumer chain is already registered, // i.e., a client to the consumer was already created if _, consumerRegistered := k.GetConsumerClientId(ctx, chainID); consumerRegistered { - // mark the old consumer address as prunable once the VSCMaturedPacket - // for the current VSC ID is received; - // note: this state is removed on receiving the VSCMaturedPacket + // mark the old consumer address as prunable once UnbondingPeriod elapses; + // note: this state is removed on EndBlock + unbondingPeriod, err := k.stakingKeeper.UnbondingTime(ctx) + if err != nil { + return err + } k.AppendConsumerAddrsToPrune( ctx, chainID, - k.GetValidatorSetUpdateId(ctx), + ctx.BlockTime().Add(unbondingPeriod), oldConsumerAddr, ) } else { @@ -442,8 +512,10 @@ func (k Keeper) GetProviderAddrFromConsumerAddr( // PruneKeyAssignments prunes the consumer addresses no longer needed // as they cannot be referenced in slash requests (by a correct consumer) -func (k Keeper) PruneKeyAssignments(ctx sdk.Context, chainID string, vscID uint64) { - consumerAddrs := k.GetConsumerAddrsToPrune(ctx, chainID, vscID) +func (k Keeper) PruneKeyAssignments(ctx sdk.Context, chainID string) { + now := ctx.BlockTime() + + consumerAddrs := k.ConsumeConsumerAddrsToPrune(ctx, chainID, now) for _, addrBz := range consumerAddrs.Addresses { consumerAddr := types.NewConsumerConsAddress(addrBz) k.DeleteValidatorByConsumerAddr(ctx, chainID, consumerAddr) @@ -452,8 +524,6 @@ func (k Keeper) PruneKeyAssignments(ctx sdk.Context, chainID string, vscID uint6 "consumer consensus addr", consumerAddr.String(), ) } - - k.DeleteConsumerAddrsToPrune(ctx, chainID, vscID) } // DeleteKeyAssignments deletes all the state needed for key assignments on a consumer chain @@ -472,7 +542,7 @@ func (k Keeper) DeleteKeyAssignments(ctx sdk.Context, chainID string) { // delete ValidatorConsumerPubKey for _, consumerAddrsToPrune := range k.GetAllConsumerAddrsToPrune(ctx, chainID) { - k.DeleteConsumerAddrsToPrune(ctx, chainID, consumerAddrsToPrune.VscId) + k.DeleteConsumerAddrsToPrune(ctx, chainID, consumerAddrsToPrune.PruneTs) } } diff --git a/x/ccv/provider/keeper/key_assignment_test.go b/x/ccv/provider/keeper/key_assignment_test.go index 4a3b566c01..7dbec09f40 100644 --- a/x/ccv/provider/keeper/key_assignment_test.go +++ b/x/ccv/provider/keeper/key_assignment_test.go @@ -189,25 +189,52 @@ func TestGetAllValidatorsByConsumerAddr(t *testing.T) { func TestConsumerAddrsToPruneCRUD(t *testing.T) { chainID := consumer - consumerAddr := types.NewConsumerConsAddress([]byte("consumerAddr1")) - vscID := uint64(1) + consumerAddr1 := types.NewConsumerConsAddress([]byte("consumerAddr1")) + consumerAddr2 := types.NewConsumerConsAddress([]byte("consumerAddr2")) keeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - addrsToPrune := keeper.GetConsumerAddrsToPrune(ctx, chainID, vscID).Addresses + ts1 := ctx.BlockTime() + ts2 := ts1.Add(time.Hour) + + addrsToPrune := keeper.GetConsumerAddrsToPrune(ctx, chainID, ts1).Addresses require.Empty(t, addrsToPrune) - keeper.AppendConsumerAddrsToPrune(ctx, chainID, vscID, consumerAddr) + keeper.AppendConsumerAddrsToPrune(ctx, chainID, ts1, consumerAddr1) + + addrsToPrune = keeper.GetConsumerAddrsToPrune(ctx, chainID, ts1).Addresses + require.NotEmpty(t, addrsToPrune, "addresses to prune is empty") + require.Len(t, addrsToPrune, 1, "addresses to prune is not len 1") + require.Equal(t, addrsToPrune[0], consumerAddr1.ToSdkConsAddr().Bytes()) + + keeper.AppendConsumerAddrsToPrune(ctx, chainID, ts2, consumerAddr2) - addrsToPrune = keeper.GetConsumerAddrsToPrune(ctx, chainID, vscID).Addresses + addrsToPrune = keeper.GetConsumerAddrsToPrune(ctx, chainID, ts2).Addresses require.NotEmpty(t, addrsToPrune, "addresses to prune is empty") require.Len(t, addrsToPrune, 1, "addresses to prune is not len 1") - require.Equal(t, addrsToPrune[0], consumerAddr.ToSdkConsAddr().Bytes()) + require.Equal(t, addrsToPrune[0], consumerAddr2.ToSdkConsAddr().Bytes()) + + keeper.DeleteConsumerAddrsToPrune(ctx, chainID, ts1) + addrsToPrune = keeper.GetConsumerAddrsToPrune(ctx, chainID, ts1).Addresses + require.Empty(t, addrsToPrune, "addresses to prune was returned") + addrsToPrune = keeper.GetConsumerAddrsToPrune(ctx, chainID, ts2).Addresses + require.NotEmpty(t, addrsToPrune, "addresses to prune is empty") + require.Len(t, addrsToPrune, 1, "addresses to prune is not len 1") + require.Equal(t, addrsToPrune[0], consumerAddr2.ToSdkConsAddr().Bytes()) + + keeper.AppendConsumerAddrsToPrune(ctx, chainID, ts1, consumerAddr1) - keeper.DeleteConsumerAddrsToPrune(ctx, chainID, vscID) - addrsToPrune = keeper.GetConsumerAddrsToPrune(ctx, chainID, vscID).Addresses + addrsToPrune = keeper.ConsumeConsumerAddrsToPrune(ctx, chainID, ts1).Addresses + require.NotEmpty(t, addrsToPrune, "addresses to prune was returned") + require.Len(t, addrsToPrune, 1, "addresses to prune is not len 1") + require.Equal(t, addrsToPrune[0], consumerAddr1.ToSdkConsAddr().Bytes()) + addrsToPrune = keeper.GetConsumerAddrsToPrune(ctx, chainID, ts1).Addresses require.Empty(t, addrsToPrune, "addresses to prune was returned") + addrsToPrune = keeper.GetConsumerAddrsToPrune(ctx, chainID, ts2).Addresses + require.NotEmpty(t, addrsToPrune, "addresses to prune is empty") + require.Len(t, addrsToPrune, 1, "addresses to prune is not len 1") + require.Equal(t, addrsToPrune[0], consumerAddr2.ToSdkConsAddr().Bytes()) } func TestGetAllConsumerAddrsToPrune(t *testing.T) { @@ -219,7 +246,7 @@ func TestGetAllConsumerAddrsToPrune(t *testing.T) { chainIDs := []string{"consumer-1", "consumer-2", "consumer-3"} numAssignments := 10 - testAssignments := []types.ConsumerAddrsToPrune{} + testAssignments := []types.ConsumerAddrsToPruneV2{} for i := 0; i < numAssignments; i++ { consumerAddresses := types.AddressList{} for j := 0; j < 2*(i+1); j++ { @@ -227,9 +254,9 @@ func TestGetAllConsumerAddrsToPrune(t *testing.T) { consumerAddresses.Addresses = append(consumerAddresses.Addresses, addr) } testAssignments = append(testAssignments, - types.ConsumerAddrsToPrune{ + types.ConsumerAddrsToPruneV2{ ChainId: chainIDs[rng.Intn(len(chainIDs))], - VscId: rng.Uint64(), + PruneTs: time.Now().UTC(), ConsumerAddrs: &consumerAddresses, }, ) @@ -248,21 +275,21 @@ func TestGetAllConsumerAddrsToPrune(t *testing.T) { break } } - expectedGetAllOrder := []types.ConsumerAddrsToPrune{} + expectedGetAllOrder := []types.ConsumerAddrsToPruneV2{} for _, assignment := range testAssignments { if assignment.ChainId == chainID { expectedGetAllOrder = append(expectedGetAllOrder, assignment) } } - // sorting by ConsumerAddrsToPrune.VscId + // sorting by ConsumerAddrsToPrune.PruneTs sort.Slice(expectedGetAllOrder, func(i, j int) bool { - return expectedGetAllOrder[i].VscId < expectedGetAllOrder[j].VscId + return expectedGetAllOrder[i].PruneTs.Before(expectedGetAllOrder[j].PruneTs) }) for _, assignment := range testAssignments { for _, addr := range assignment.ConsumerAddrs.Addresses { consumerAddr := types.NewConsumerConsAddress(addr) - pk.AppendConsumerAddrsToPrune(ctx, assignment.ChainId, assignment.VscId, consumerAddr) + pk.AppendConsumerAddrsToPrune(ctx, assignment.ChainId, assignment.PruneTs, consumerAddr) } } @@ -277,7 +304,7 @@ func checkCorrectPruningProperty(ctx sdk.Context, k providerkeeper.Keeper, chain For each consumer address cAddr in ValidatorByConsumerAddr, - either there exists a provider address pAddr in ValidatorConsumerPubKey, s.t. hash(ValidatorConsumerPubKey(pAddr)) = cAddr - - or there exists a vscID in ConsumerAddrsToPrune s.t. cAddr in ConsumerAddrsToPrune(vscID) + - or there exists a timestamp in ConsumerAddrsToPrune s.t. cAddr in ConsumerAddrsToPrune(timestamp) */ willBePruned := map[string]bool{} for _, consAddrToPrune := range k.GetAllConsumerAddrsToPrune(ctx, chainID) { @@ -293,6 +320,7 @@ func checkCorrectPruningProperty(ctx sdk.Context, k providerkeeper.Keeper, chain // Address will be pruned, everything is fine. continue } + // Try to find a validator who has this consumer address currently assigned isCurrentlyAssigned := false for _, valconsPubKey := range k.GetAllValidatorConsumerPubKeys(ctx, &valByConsAddr.ChainId) { @@ -388,6 +416,7 @@ func TestAssignConsensusKeyForConsumerChain(t *testing.T) { mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, consumerIdentities[1].SDKValConsAddress(), ).Return(stakingtypes.Validator{}, stakingtypes.ErrNoValidatorFound), + mocks.MockStakingKeeper.EXPECT().UnbondingTime(ctx), ) }, doActions: func(sdkCtx sdk.Context, k providerkeeper.Keeper) { @@ -714,11 +743,6 @@ func TestSimulatedAssignmentsAndUpdateApplication(t *testing.T) { providerValset := CreateValSet(providerIDS) // NOTE: consumer must have space for provider identities because default key assignments are to provider keys consumerValset := CreateValSet(assignableIDS) - // For each validator on the consumer, record the corresponding provider - // address as looked up on the provider using GetProviderAddrFromConsumerAddr - // at a given vscid. - // consumer consAddr -> vscid -> provider consAddr - historicSlashQueries := map[string]map[uint64]string{} // Sanity check that the validator set update is initialised to 0, for clarity. require.Equal(t, k.GetValidatorSetUpdateId(ctx), uint64(0)) @@ -791,9 +815,14 @@ func TestSimulatedAssignmentsAndUpdateApplication(t *testing.T) { } } + // Set the unbonding time to 60s so that a key is prunable after 60s + unbondingTimeInNs := 60 * time.Second // 60 seconds + mocks.MockStakingKeeper.EXPECT().UnbondingTime(gomock.Any()).Return(unbondingTimeInNs, nil).AnyTimes() + // The consumer chain has not yet been registered // Apply some randomly generated key assignments assignments := getAssignments() + applyAssignments(assignments) // And generate a random provider valset which, in the real system, will // be put into the consumer genesis. @@ -804,15 +833,15 @@ func TestSimulatedAssignmentsAndUpdateApplication(t *testing.T) { // Register the consumer chain k.SetConsumerClientId(ctx, ChainID, "") - // Analogous to the last vscid received from the consumer in a maturity - // Used to check the correct pruning property - greatestPrunedVSCID := -1 + // Set the greatest block time up to which keys have been pruned. At the beginning, no pruning has taken + // place, so we set `greatestPrunedBlockTime` to 0, and set the current block time to 1. + greatestPrunedBlockTime := int64(0) + ctx = ctx.WithBlockTime(time.Unix(0, 1)) // Simulate a number of 'blocks' // Each block consists of a number of random key assignment tx's // and a random set of validator power updates for block := 0; block < NUM_BLOCKS_PER_EXECUTION; block++ { - stakingUpdates = getStakingUpdates() assignments = getAssignments() @@ -820,13 +849,14 @@ func TestSimulatedAssignmentsAndUpdateApplication(t *testing.T) { applyAssignments(assignments) applyUpdatesAndIncrementVSCID(stakingUpdates) - // Randomly fast forward the greatest pruned VSCID. This simulates - // delivery of maturity packets from the consumer chain. - prunedVscid := greatestPrunedVSCID + - // +1 and -1 because id was incremented (-1), (+1) to make upper bound inclusive - rng.Intn(int(k.GetValidatorSetUpdateId(ctx))+1-1-greatestPrunedVSCID) - k.PruneKeyAssignments(ctx, ChainID, uint64(prunedVscid)) - greatestPrunedVSCID = prunedVscid + // prune all keys that can be pruned up to the current block time + greatestPrunedBlockTime = ctx.BlockTime().UnixNano() + k.PruneKeyAssignments(ctx, ChainID) + + // Increase the block time by a small random amount up to UnbondingTime / 10. We do not increase the block time + // by UnbondingTime so that in the upcoming iteration of this `for` loop (i.e., new block), not all the keys + // previously (in this current block) set to be prunable are pruned. + ctx = ctx.WithBlockTime(time.Unix(0, ctx.BlockTime().UnixNano()+rng.Int63n(unbondingTimeInNs.Nanoseconds())/10)) /* @@ -882,20 +912,25 @@ func TestSimulatedAssignmentsAndUpdateApplication(t *testing.T) { Property: Pruning (bounded storage) Check that all keys have been or will eventually be pruned. */ - require.True(t, checkCorrectPruningProperty(ctx, k, ChainID)) /* Property: Correct Consumer Initiated Slash Lookup - Check that since the last pruning, it has never been possible to query - two different provider addresses from the same consumer address. + Check that since the last pruning took place, it has never been possible to have + two different provider addresses for the same consumer address. We know that the queried provider address was correct at least once, from checking the validator set replication property. These two facts together guarantee that the slash lookup is always correct. */ - // Build up the historicSlashQueries data structure + // For each validator on the consumer, record the corresponding provider + // address as looked up on the provider using `GetProviderAddrFromConsumerAddr` + // at a given block time. + // consumer consAddr -> block time -> provider consAddr + consumerAddrToBlockTimeToProviderAddr := map[string]map[uint64]string{} + + // Build up the consumerAddrToBlockTimeToProviderAddr data structure for i := range consumerValset.identities { // For each active validator on the consumer chain consC := consumerValset.identities[i].ConsumerConsAddress() @@ -903,28 +938,25 @@ func TestSimulatedAssignmentsAndUpdateApplication(t *testing.T) { // Get the provider who assigned the key consP := k.GetProviderAddrFromConsumerAddr(ctx, ChainID, consC) - if _, found := historicSlashQueries[consC.String()]; !found { - historicSlashQueries[consC.String()] = map[uint64]string{} + if _, found := consumerAddrToBlockTimeToProviderAddr[consC.String()]; !found { + consumerAddrToBlockTimeToProviderAddr[consC.String()] = map[uint64]string{} } - vscid := k.GetValidatorSetUpdateId(ctx) - 1 // -1 since it was incremented before - // Record the slash query result obtained at this block - historicSlashQueries[consC.String()][vscid] = consP.String() + consumerAddrToBlockTimeToProviderAddr[consC.String()][uint64(ctx.BlockTime().UnixNano())] = consP.String() } } - // Check that, for each address known the consumer at some block - // with vscid st. greatestPrunedVSCID < vscid, there were never - // conflicting slash query results. - for _, vscidToConsP := range historicSlashQueries { + // Check that, for each consumer address known at some block with blockTime st. greatestPrunedBlockTime < blockTime, + // there were never two providers with this consumer address. + for _, blockTimeToProviderAddr := range consumerAddrToBlockTimeToProviderAddr { seen := map[string]bool{} - for vscid, consP := range vscidToConsP { - if uint64(greatestPrunedVSCID) < vscid { - // The provider would have returned + for blockTime, consP := range blockTimeToProviderAddr { + if uint64(greatestPrunedBlockTime) < blockTime { seen[consP] = true } } - // No conflicts. + // Having len(seen) >= 2 implies that we had at least 2 different provider addresses that at some point + // had the exact same consumer address since the last pruning took place. This should not be possible! require.True(t, len(seen) < 2) } diff --git a/x/ccv/provider/keeper/params.go b/x/ccv/provider/keeper/params.go index b1a30ed4a4..9feb274189 100644 --- a/x/ccv/provider/keeper/params.go +++ b/x/ccv/provider/keeper/params.go @@ -30,25 +30,6 @@ func (k Keeper) GetCCVTimeoutPeriod(ctx sdk.Context) time.Duration { return params.CcvTimeoutPeriod } -// GetInitTimeoutPeriod returns the init timeout period -func (k Keeper) GetInitTimeoutPeriod(ctx sdk.Context) time.Duration { - params := k.GetParams(ctx) - return params.InitTimeoutPeriod -} - -// GetVscTimeoutPeriod returns the vsc timeout period -func (k Keeper) GetVscTimeoutPeriod(ctx sdk.Context) time.Duration { - params := k.GetParams(ctx) - return params.VscTimeoutPeriod -} - -// SetVscTimeoutPeriod sets the vsc timeout period -func (k Keeper) SetVscTimeoutPeriod(ctx sdk.Context, period time.Duration) { - params := k.GetParams(ctx) - params.VscTimeoutPeriod = period - k.SetParams(ctx, params) -} - // GetSlashMeterReplenishPeriod returns the period in which: // Once the slash meter becomes not-full, the slash meter is replenished after this period. func (k Keeper) GetSlashMeterReplenishPeriod(ctx sdk.Context) time.Duration { diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go index bd2e451254..947122b221 100644 --- a/x/ccv/provider/keeper/params_test.go +++ b/x/ccv/provider/keeper/params_test.go @@ -41,8 +41,6 @@ func TestParams(t *testing.T) { ), "0.25", 7*24*time.Hour, - 5*time.Hour, - 10*time.Minute, time.Hour, "0.4", sdk.Coin{ diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index 28d28f3af9..30d29c5b0e 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -2,7 +2,6 @@ package keeper import ( "fmt" - "strconv" "time" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -143,10 +142,6 @@ func (k Keeper) CreateConsumerClient(ctx sdk.Context, prop *types.ConsumerAdditi } k.SetConsumerClientId(ctx, chainID, clientID) - // add the init timeout timestamp for this consumer chain - ts := ctx.BlockTime().Add(k.GetParams(ctx).InitTimeoutPeriod) - k.SetInitTimeoutTimestamp(ctx, chainID, uint64(ts.UnixNano())) - k.Logger(ctx).Info("consumer chain registered (client created)", "chainID", chainID, "clientID", clientID, @@ -159,7 +154,6 @@ func (k Keeper) CreateConsumerClient(ctx sdk.Context, prop *types.ConsumerAdditi sdk.NewAttribute(ccv.AttributeChainID, chainID), sdk.NewAttribute(clienttypes.AttributeKeyClientID, clientID), sdk.NewAttribute(types.AttributeInitialHeight, prop.InitialHeight.String()), - sdk.NewAttribute(types.AttributeInitializationTimeout, strconv.Itoa(int(ts.UnixNano()))), sdk.NewAttribute(types.AttributeTrustingPeriod, clientState.TrustingPeriod.String()), sdk.NewAttribute(types.AttributeUnbondingPeriod, clientState.UnbondingPeriod.String()), ), @@ -184,7 +178,6 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan boo // clean up states k.DeleteConsumerClientId(ctx, chainID) k.DeleteConsumerGenesis(ctx, chainID) - k.DeleteInitTimeoutTimestamp(ctx, chainID) // Note: this call panics if the key assignment state is invalid k.DeleteKeyAssignments(ctx, chainID) k.DeleteMinimumPowerInTopN(ctx, chainID) @@ -209,9 +202,6 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan boo } k.DeleteChainToChannel(ctx, chainID) k.DeleteChannelToChain(ctx, channelID) - - // delete VSC send timestamps - k.DeleteVscSendTimestampsForConsumer(ctx, chainID) } // delete consumer commission rate @@ -224,26 +214,6 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, closeChan boo k.DeleteSlashAcks(ctx, chainID) k.DeletePendingVSCPackets(ctx, chainID) - // release unbonding operations - for _, unbondingOpsIndex := range k.GetAllUnbondingOpIndexes(ctx, chainID) { - // iterate over the unbonding operations for the current VSC ID - var maturedIds []uint64 - for _, id := range unbondingOpsIndex.UnbondingOpIds { - // Remove consumer chain ID from unbonding op record. - // Note that RemoveConsumerFromUnbondingOp cannot panic here - // as it is expected that for all UnbondingOpIds in every - // VscUnbondingOps returned by GetAllUnbondingOpIndexes - // there is an unbonding op in store that can be retrieved - // via via GetUnbondingOp. - if k.RemoveConsumerFromUnbondingOp(ctx, id, chainID) { - // Store id of matured unbonding op for later completion of unbonding in staking module - maturedIds = append(maturedIds, id) - } - } - k.AppendMaturedUnbondingOps(ctx, maturedIds) - k.DeleteUnbondingOpIndex(ctx, chainID, unbondingOpsIndex.VscId) - } - k.DeleteTopN(ctx, chainID) k.DeleteValidatorsPowerCap(ctx, chainID) k.DeleteValidatorSetCap(ctx, chainID) diff --git a/x/ccv/provider/keeper/proposal_test.go b/x/ccv/provider/keeper/proposal_test.go index d18a06f5ab..670db4e100 100644 --- a/x/ccv/provider/keeper/proposal_test.go +++ b/x/ccv/provider/keeper/proposal_test.go @@ -654,8 +654,6 @@ func TestMakeConsumerGenesis(t *testing.T) { // They must be populated with reasonable values to satisfy SetParams though. TrustingPeriodFraction: providertypes.DefaultTrustingPeriodFraction, CcvTimeoutPeriod: ccvtypes.DefaultCCVTimeoutPeriod, - InitTimeoutPeriod: providertypes.DefaultInitTimeoutPeriod, - VscTimeoutPeriod: providertypes.DefaultVscTimeoutPeriod, SlashMeterReplenishPeriod: providertypes.DefaultSlashMeterReplenishPeriod, SlashMeterReplenishFraction: providertypes.DefaultSlashMeterReplenishFraction, ConsumerRewardDenomRegistrationFee: sdk.Coin{ diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index b5ffecf919..6381793a0f 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -20,96 +20,6 @@ import ( ccv "github.com/cosmos/interchain-security/v5/x/ccv/types" ) -// OnRecvVSCMaturedPacket handles a VSCMatured packet and returns a no-op result ack. -func (k Keeper) OnRecvVSCMaturedPacket( - ctx sdk.Context, - packet channeltypes.Packet, - data ccv.VSCMaturedPacketData, -) error { - // check that the channel is established, panic if not - chainID, found := k.GetChannelToChain(ctx, packet.DestinationChannel) - if !found { - // VSCMatured packet was sent on a channel different than any of the established CCV channels; - // this should never happen - k.Logger(ctx).Error("VSCMaturedPacket received on unknown channel", - "channelID", packet.DestinationChannel, - ) - panic(fmt.Errorf("VSCMaturedPacket received on unknown channel %s", packet.DestinationChannel)) - } - - // validate packet data upon receiving - if err := data.Validate(); err != nil { - return errorsmod.Wrapf(err, "error validating VSCMaturedPacket data") - } - - k.HandleVSCMaturedPacket(ctx, chainID, data) - - k.Logger(ctx).Info("VSCMaturedPacket handled", - "chainID", chainID, - "vscID", data.ValsetUpdateId, - ) - - return nil -} - -// HandleVSCMaturedPacket handles a VSCMatured packet. -// -// Note: This method should only panic for a system critical error like a -// failed marshal/unmarshal, or persistence of critical data. -func (k Keeper) HandleVSCMaturedPacket(ctx sdk.Context, chainID string, data ccv.VSCMaturedPacketData) { - // iterate over the unbonding operations mapped to (chainID, data.ValsetUpdateId) - var maturedIds []uint64 - for _, unbondingOp := range k.GetUnbondingOpsFromIndex(ctx, chainID, data.ValsetUpdateId) { - // Remove consumer chain ID from unbonding op record. - // Note that RemoveConsumerFromUnbondingOp cannot panic here - // as all the unbonding ops returned by GetUnbondingOpsFromIndex - // are retrieved via GetUnbondingOp. - if k.RemoveConsumerFromUnbondingOp(ctx, unbondingOp.Id, chainID) { - // Store id of matured unbonding op for later completion of unbonding in staking module - maturedIds = append(maturedIds, unbondingOp.Id) - } - } - k.AppendMaturedUnbondingOps(ctx, maturedIds) - - // clean up index - k.DeleteUnbondingOpIndex(ctx, chainID, data.ValsetUpdateId) - - // remove the VSC timeout timestamp for this chainID and vscID - k.DeleteVscSendTimestamp(ctx, chainID, data.ValsetUpdateId) - - // prune previous consumer validator address that are no longer needed - k.PruneKeyAssignments(ctx, chainID, data.ValsetUpdateId) - - k.Logger(ctx).Info("VSCMaturedPacket handled", - "chainID", chainID, - "vscID", data.ValsetUpdateId, - ) -} - -// CompleteMaturedUnbondingOps attempts to complete all matured unbonding operations -func (k Keeper) completeMaturedUnbondingOps(ctx sdk.Context) { - for _, id := range k.ConsumeMaturedUnbondingOps(ctx) { - // Attempt to complete unbonding in staking module - err := k.stakingKeeper.UnbondingCanComplete(ctx, id) - if err != nil { - if errors.Is(err, stakingtypes.ErrNoUnbondingDelegation) { - // The unbonding was not found. - unbondingType, errGet := k.stakingKeeper.GetUnbondingType(ctx, id) - if errGet == nil && unbondingType == stakingtypes.UnbondingType_UnbondingDelegation { - // If this is an unbonding delegation, it may have been removed - // after through a CancelUnbondingDelegation message - k.Logger(ctx).Debug("unbonding delegation was already removed:", "unbondingID", id) - continue - } - } - // UnbondingCanComplete failing means that the state of the x/staking module - // of cosmos-sdk is invalid. An exception is the case handled above - panic(fmt.Sprintf("could not complete unbonding op: %s", err.Error())) - } - k.Logger(ctx).Debug("unbonding operation matured on all consumers", "opID", id) - } -} - // OnAcknowledgementPacket handles acknowledgments for sent VSC packets func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, ack channeltypes.Acknowledgement) error { if err := ack.GetError(); err != "" { @@ -155,9 +65,6 @@ func (k Keeper) EndBlockVSU(ctx sdk.Context) ([]abci.ValidatorUpdate, error) { // to compute the minimum power in the top N valUpdates := k.ProviderValidatorUpdates(ctx) - // notify the staking module to complete all matured unbonding ops - k.completeMaturedUnbondingOps(ctx) - if ctx.BlockHeight()%k.GetBlocksPerEpoch(ctx) == 0 { // only queue and send VSCPackets at the boundaries of an epoch @@ -214,6 +121,19 @@ func (k Keeper) ProviderValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate return valUpdates } +// BlocksUntilNextEpoch returns the number of blocks until the next epoch starts +// Returns 0 if VSCPackets are sent in the current block, +// which is done in the first block of each epoch. +func (k Keeper) BlocksUntilNextEpoch(ctx sdk.Context) int64 { + blocksSinceEpochStart := ctx.BlockHeight() % k.GetBlocksPerEpoch(ctx) + + if blocksSinceEpochStart == 0 { + return 0 + } else { + return int64(k.GetBlocksPerEpoch(ctx) - blocksSinceEpochStart) + } +} + // SendVSCPackets iterates over all registered consumers and sends pending // VSC packets to the chains with established CCV channels. // If the CCV channel is not established for a consumer chain, @@ -258,10 +178,6 @@ func (k Keeper) SendVSCPacketsToChain(ctx sdk.Context, chainID, channelID string } return } - // set the VSC send timestamp for this packet; - // note that the VSC send timestamp are set when the packets - // are actually sent over IBC - k.SetVscSendTimestamp(ctx, chainID, data.ValsetUpdateId, ctx.BlockTime()) } k.DeletePendingVSCPackets(ctx, chainID) } @@ -311,11 +227,8 @@ func (k Keeper) QueueVSCPackets(ctx sdk.Context) { valUpdates := DiffValidators(currentValidators, nextValidators) k.SetConsumerValSet(ctx, chainID, nextValidators) - // check whether there are changes in the validator set; - // note that this also entails unbonding operations - // w/o changes in the voting power of the validators in the validator set - unbondingOps := k.GetUnbondingOpsFromIndex(ctx, chainID, valUpdateID) - if len(valUpdates) != 0 || len(unbondingOps) != 0 { + // check whether there are changes in the validator set + if len(valUpdates) != 0 { // construct validator set change packet data packet := ccv.NewValidatorSetChangePacketData(valUpdates, valUpdateID, k.ConsumeSlashAcks(ctx, chainID)) k.AppendPendingVSCPackets(ctx, chainID, packet) @@ -323,7 +236,6 @@ func (k Keeper) QueueVSCPackets(ctx sdk.Context) { "chainID", chainID, "vscID", valUpdateID, "len updates", len(valUpdates), - "len unbonding ops", len(unbondingOps), ) } } @@ -354,6 +266,11 @@ func (k Keeper) EndBlockCIS(ctx sdk.Context) { valUpdateID := k.GetValidatorSetUpdateId(ctx) k.SetValsetUpdateBlockHeight(ctx, valUpdateID, blockHeight) k.Logger(ctx).Debug("vscID was mapped to block height", "vscID", valUpdateID, "height", blockHeight) + + // prune previous consumer validator addresses that are no longer needed + for _, chainID := range k.GetAllRegisteredConsumerChainIDs(ctx) { + k.PruneKeyAssignments(ctx, chainID) + } } // OnRecvSlashPacket delivers a received slash packet, validates it and @@ -478,7 +395,7 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, chainID string, data ccv.Slas // Obtain provider chain consensus address using the consumer chain consensus address providerConsAddr := k.GetProviderAddrFromConsumerAddr(ctx, chainID, consumerConsAddr) - k.Logger(ctx).Debug("handling slash packet", + k.Logger(ctx).Debug("HandleSlashPacket", "chainID", chainID, "consumer cons addr", consumerConsAddr.String(), "provider cons addr", providerConsAddr.String(), @@ -497,10 +414,10 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, chainID string, data ccv.Slas // stakingKeeper.Slash() panics otherwise if validator.IsUnbonded() { // if validator is not found or is unbonded, drop slash packet and log error. - // Note that it is impossible for the validator to be not found or unbonded if both the provider - // and the consumer are following the protocol. Thus if this branch is taken then one or both - // chains is incorrect, but it is impossible to tell which. - k.Logger(ctx).Error("validator already unbonded", "validator", providerConsAddr.String()) + k.Logger(ctx).Info( + "HandleSlashPacket - slash packet dropped because validator not found or is unbonded", + "provider cons addr", providerConsAddr.String(), + ) return } @@ -508,7 +425,7 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, chainID string, data ccv.Slas if k.slashingKeeper.IsTombstoned(ctx, providerConsAddr.ToSdkConsAddr()) { // Log and drop packet if validator is tombstoned. k.Logger(ctx).Info( - "slash packet dropped because validator is already tombstoned", + "HandleSlashPacket - slash packet dropped because validator is already tombstoned", "provider cons addr", providerConsAddr.String(), ) return @@ -516,7 +433,10 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, chainID string, data ccv.Slas infractionHeight, found := k.getMappedInfractionHeight(ctx, chainID, data.ValsetUpdateId) if !found { - k.Logger(ctx).Error("infraction height not found. But was found during slash packet validation") + k.Logger(ctx).Error( + "HandleSlashPacket - infraction height not found. But was found during slash packet validation", + "vscID", data.ValsetUpdateId, + ) // drop packet return } @@ -535,7 +455,7 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, chainID string, data ccv.Slas k.Logger(ctx).Error("failed to jail vaidator", providerConsAddr.ToSdkConsAddr().String(), "err", err.Error()) return } - k.Logger(ctx).Info("validator jailed", "provider cons addr", providerConsAddr.String()) + k.Logger(ctx).Info("HandleSlashPacket - validator jailed", "provider cons addr", providerConsAddr.String()) jailDuration, err := k.slashingKeeper.DowntimeJailDuration(ctx) if err != nil { k.Logger(ctx).Error("failed to get jail duration", "err", err.Error()) @@ -561,60 +481,6 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, chainID string, data ccv.Slas ) } -// EndBlockCCR contains the EndBlock logic needed for -// the Consumer Chain Removal sub-protocol -func (k Keeper) EndBlockCCR(ctx sdk.Context) { - currentTime := ctx.BlockTime() - currentTimeUint64 := uint64(currentTime.UnixNano()) - - for _, initTimeoutTimestamp := range k.GetAllInitTimeoutTimestamps(ctx) { - if currentTimeUint64 > initTimeoutTimestamp.Timestamp { - // initTimeout expired - // stop the consumer chain and unlock the unbonding. - // Note that the CCV channel was not established, - // thus closeChan is irrelevant - k.Logger(ctx).Info("about to remove timed out consumer chain - chain was not initialised", - "chainID", initTimeoutTimestamp.ChainId) - err := k.StopConsumerChain(ctx, initTimeoutTimestamp.ChainId, false) - if err != nil { - if errors.Is(err, providertypes.ErrConsumerChainNotFound) { - // consumer chain not found - continue - } - panic(fmt.Errorf("consumer chain failed to stop: %w", err)) - } - } - } - - for _, channelToChain := range k.GetAllChannelToChains(ctx) { - // Check if the first vscSendTimestamp in iterator + VscTimeoutPeriod - // exceed the current block time. - // Checking the first send timestamp for each chain is sufficient since - // timestamps are ordered by vsc ID. - // Note: GetFirstVscSendTimestamp panics if the internal state is invalid - vscSendTimestamp, found := k.GetFirstVscSendTimestamp(ctx, channelToChain.ChainId) - if found { - timeoutTimestamp := vscSendTimestamp.Timestamp.Add(k.GetParams(ctx).VscTimeoutPeriod) - if currentTime.After(timeoutTimestamp) { - // vscTimeout expired - // stop the consumer chain and release unbondings - k.Logger(ctx).Info("about to remove timed out consumer chain - VSCPacket timed out", - "chainID", channelToChain.ChainId, - "vscID", vscSendTimestamp.VscId, - ) - err := k.StopConsumerChain(ctx, channelToChain.ChainId, true) - if err != nil { - if errors.Is(err, providertypes.ErrConsumerChainNotFound) { - // consumer chain not found - continue - } - panic(fmt.Errorf("consumer chain failed to stop: %w", err)) - } - } - } - } -} - // getMappedInfractionHeight gets the infraction height mapped from val set ID for the given chain ID func (k Keeper) getMappedInfractionHeight(ctx sdk.Context, chainID string, valsetUpdateID uint64, diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index 8771194aeb..dad58c994b 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -12,9 +12,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -134,27 +132,6 @@ func TestQueueVSCPacketsDoesNotResetConsumerValidatorsHeights(t *testing.T) { require.Equal(t, chainHeight, cv.JoinHeight, "the consumer validator's height was not correctly set") } -// TestOnRecvVSCMaturedPacket tests the OnRecvVSCMaturedPacket method of the keeper. -// -// Note: Handling logic itself is not tested here. -func TestOnRecvVSCMaturedPacket(t *testing.T) { - providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - providerKeeper.SetParams(ctx, providertypes.DefaultParams()) - - // Set channel to chain (faking multiple established channels) - providerKeeper.SetChannelToChain(ctx, "channel-1", "chain-1") - providerKeeper.SetChannelToChain(ctx, "channel-2", "chain-2") - - // Execute on recv for chain-1, confirm v1 result ack is returned - err := executeOnRecvVSCMaturedPacket(t, &providerKeeper, ctx, "channel-1", 1) - require.NoError(t, err) - - // Now queue a slash packet data instance for chain-2, confirm v1 result ack is returned - err = executeOnRecvVSCMaturedPacket(t, &providerKeeper, ctx, "channel-2", 2) - require.NoError(t, err) -} - // TestOnRecvDowntimeSlashPacket tests the OnRecvSlashPacket method specifically for downtime slash packets. func TestOnRecvDowntimeSlashPacket(t *testing.T) { providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) @@ -258,22 +235,6 @@ func TestOnRecvDoubleSignSlashPacket(t *testing.T) { require.False(t, providerKeeper.GetSlashLog(ctx, randomAddress)) } -func executeOnRecvVSCMaturedPacket(t *testing.T, providerKeeper *keeper.Keeper, ctx sdk.Context, - channelID string, ibcSeqNum uint64, -) error { - t.Helper() - // Instantiate vsc matured packet data and bytes - data := testkeeper.GetNewVSCMaturedPacketData() - dataBz, err := data.Marshal() - require.NoError(t, err) - - return providerKeeper.OnRecvVSCMaturedPacket( - ctx, - channeltypes.NewPacket(dataBz, ibcSeqNum, "srcPort", "srcChan", "provider-port", channelID, clienttypes.Height{}, 1), - data, - ) -} - func executeOnRecvSlashPacket(t *testing.T, providerKeeper *keeper.Keeper, ctx sdk.Context, channelID string, ibcSeqNum uint64, packetData ccv.SlashPacketData, ) (ccv.PacketAckResult, error) { @@ -510,184 +471,6 @@ func TestHandleSlashPacket(t *testing.T) { } } -// TestHandleVSCMaturedPacket tests the handling of VSCMatured packets. -// Note that this method also tests the behaviour of AfterUnbondingInitiated. -func TestHandleVSCMaturedPacket(t *testing.T) { - pk, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - // Init vscID - pk.SetValidatorSetUpdateId(ctx, 1) - - // Start first unbonding without any consumers registered - var unbondingOpId uint64 = 1 - gomock.InOrder( - mocks.MockStakingKeeper.EXPECT().GetUnbondingType(ctx, unbondingOpId).Return(stakingtypes.UnbondingType_Undefined, stakingtypes.ErrNoUnbondingType), - ) - - err := pk.Hooks().AfterUnbondingInitiated(ctx, unbondingOpId) - require.NoError(t, err) - // Check that no unbonding op was stored - _, found := pk.GetUnbondingOp(ctx, unbondingOpId) - require.False(t, found) - - // Increment vscID - pk.IncrementValidatorSetUpdateId(ctx) - require.Equal(t, uint64(2), pk.GetValidatorSetUpdateId(ctx)) - - // Register first consumer - pk.SetConsumerClientId(ctx, "chain-1", "client-1") - - // Create 2 validators - vals := []stakingtypes.Validator{} - valsPk := []cryptotypes.PubKey{} - for i := 0; i < 2; i++ { - pubkey, err := cryptocodec.FromTmPubKeyInterface(cryptotestutil.NewCryptoIdentityFromIntSeed(54321 + i).TMCryptoPubKey()) - require.NoError(t, err) - valsPk = append(valsPk, pubkey) - pkAny, err := codectypes.NewAnyWithValue(pubkey) - require.NoError(t, err) - vals = append(vals, stakingtypes.Validator{ConsensusPubkey: pkAny}) - } - - // Opt-in one validator to consumer - pk.SetConsumerValidator(ctx, "chain-1", providertypes.ConsensusValidator{ProviderConsAddr: valsPk[0].Address()}) - - // Start second unbonding - unbondingOpId = 2 - gomock.InOrder( - mocks.MockStakingKeeper.EXPECT().GetUnbondingType(ctx, unbondingOpId).Return(stakingtypes.UnbondingType_UnbondingDelegation, nil), - mocks.MockStakingKeeper.EXPECT().GetUnbondingDelegationByUnbondingID(ctx, unbondingOpId).Return( - stakingtypes.UnbondingDelegation{ - ValidatorAddress: sdk.ValAddress([]byte{1}).String(), - }, nil), - mocks.MockStakingKeeper.EXPECT().GetValidator(ctx, sdk.ValAddress([]byte{1})). - Return(vals[0], nil), - mocks.MockStakingKeeper.EXPECT().PutUnbondingOnHold(ctx, unbondingOpId).Return(nil), - ) - err = pk.Hooks().AfterUnbondingInitiated(ctx, unbondingOpId) - require.NoError(t, err) - // Check that an unbonding op was stored - expectedChains := []string{"chain-1"} - unbondingOp, found := pk.GetUnbondingOp(ctx, unbondingOpId) - require.True(t, found) - require.Equal(t, unbondingOpId, unbondingOp.Id) - require.Equal(t, expectedChains, unbondingOp.UnbondingConsumerChains) - // Check that the unbonding op index was stored - expectedUnbondingOpIds := []uint64{unbondingOpId} - ids, found := pk.GetUnbondingOpIndex(ctx, "chain-1", pk.GetValidatorSetUpdateId(ctx)) - require.True(t, found) - require.Equal(t, expectedUnbondingOpIds, ids) - - // Increment vscID - pk.IncrementValidatorSetUpdateId(ctx) - require.Equal(t, uint64(3), pk.GetValidatorSetUpdateId(ctx)) - - // Registered second consumer - pk.SetConsumerClientId(ctx, "chain-2", "client-2") - - // Opt-in both validators to second consumer - pk.SetConsumerValidator(ctx, "chain-2", providertypes.ConsensusValidator{ProviderConsAddr: valsPk[0].Address()}) - pk.SetConsumerValidator(ctx, "chain-2", providertypes.ConsensusValidator{ProviderConsAddr: valsPk[1].Address()}) - - // Start third and fourth unbonding - unbondingOpIds := []uint64{3, 4} - for _, id := range unbondingOpIds { - gomock.InOrder( - mocks.MockStakingKeeper.EXPECT().GetUnbondingType(ctx, id).Return(stakingtypes.UnbondingType_Redelegation, nil), - mocks.MockStakingKeeper.EXPECT().GetRedelegationByUnbondingID(ctx, id).Return( - stakingtypes.Redelegation{ - ValidatorSrcAddress: sdk.ValAddress([]byte{1}).String(), - }, nil), - mocks.MockStakingKeeper.EXPECT().GetValidator(ctx, sdk.ValAddress([]byte{1})). - Return(vals[0], nil), - mocks.MockStakingKeeper.EXPECT().PutUnbondingOnHold(ctx, id).Return(nil), - ) - err = pk.Hooks().AfterUnbondingInitiated(ctx, id) - require.NoError(t, err) - } - // Check that the unbonding ops were stored - expectedChains = []string{"chain-1", "chain-2"} - for _, id := range unbondingOpIds { - unbondingOp, found = pk.GetUnbondingOp(ctx, id) - require.True(t, found) - require.Equal(t, id, unbondingOp.Id) - require.Equal(t, expectedChains, unbondingOp.UnbondingConsumerChains) - } - // Check that the unbonding op index was stored - for _, chainID := range expectedChains { - ids, found := pk.GetUnbondingOpIndex(ctx, chainID, pk.GetValidatorSetUpdateId(ctx)) - require.True(t, found) - require.Equal(t, unbondingOpIds, ids) - } - - // Increment vscID - pk.IncrementValidatorSetUpdateId(ctx) - require.Equal(t, uint64(4), pk.GetValidatorSetUpdateId(ctx)) - - // Start fith unbonding - unbondingOpId = 5 - gomock.InOrder( - mocks.MockStakingKeeper.EXPECT().GetUnbondingType(ctx, unbondingOpId).Return(stakingtypes.UnbondingType_ValidatorUnbonding, nil), - mocks.MockStakingKeeper.EXPECT().GetValidatorByUnbondingID(ctx, unbondingOpId).Return( - stakingtypes.Validator{ - OperatorAddress: sdk.ValAddress([]byte{1}).String(), - }, nil), - mocks.MockStakingKeeper.EXPECT().GetValidator(ctx, sdk.ValAddress([]byte{1})). - Return(vals[1], nil), - mocks.MockStakingKeeper.EXPECT().PutUnbondingOnHold(ctx, unbondingOpId).Return(nil), - ) - err = pk.Hooks().AfterUnbondingInitiated(ctx, unbondingOpId) - require.NoError(t, err) - - // Check that an unbonding op was stored for chain-2 only - // since it's the only consumer the unbonding validator has opted-in to - expectedChains = []string{"chain-2"} - unbondingOp, found = pk.GetUnbondingOp(ctx, unbondingOpId) - require.True(t, found) - require.Equal(t, unbondingOpId, unbondingOp.Id) - require.Equal(t, expectedChains, unbondingOp.UnbondingConsumerChains) - - // Handle VSCMatured packet from chain-1 for vscID 1. - // Note that no VSCPacket was sent as the chain was not yet registered, - // but the code should still work - pk.HandleVSCMaturedPacket(ctx, "chain-1", ccv.VSCMaturedPacketData{ValsetUpdateId: 1}) - require.Empty(t, pk.ConsumeMaturedUnbondingOps(ctx)) - - // Handle VSCMatured packet from chain-1 for vscID 2. - pk.HandleVSCMaturedPacket(ctx, "chain-1", ccv.VSCMaturedPacketData{ValsetUpdateId: 2}) - // Check that the unbonding operation with ID=2 can complete - require.Equal(t, []uint64{2}, pk.ConsumeMaturedUnbondingOps(ctx)) - // Check that the unbonding op index was removed - _, found = pk.GetUnbondingOpIndex(ctx, "chain-1", 2) - require.False(t, found) - - // Handle VSCMatured packet from chain-2 for vscID 3. - pk.HandleVSCMaturedPacket(ctx, "chain-2", ccv.VSCMaturedPacketData{ValsetUpdateId: 3}) - // Check that the unbonding operations with IDs 3 and 4 no longer wait for chain-2 - expectedChains = []string{"chain-1"} - unbondingOpIds = []uint64{3, 4} - for _, id := range unbondingOpIds { - unbondingOp, found := pk.GetUnbondingOp(ctx, id) - require.True(t, found) - require.Equal(t, id, unbondingOp.Id) - require.Equal(t, expectedChains, unbondingOp.UnbondingConsumerChains) - } - // Check that no unbonding operation can complete - require.Empty(t, pk.ConsumeMaturedUnbondingOps(ctx)) - // Check that the unbonding op index was removed - _, found = pk.GetUnbondingOpIndex(ctx, "chain-2", 3) - require.False(t, found) - - // Handle VSCMatured packet from chain-1 for vscID 3. - pk.HandleVSCMaturedPacket(ctx, "chain-1", ccv.VSCMaturedPacketData{ValsetUpdateId: 3}) - // Check that the unbonding operations with IDs 3 and 4 can complete - require.Equal(t, unbondingOpIds, pk.ConsumeMaturedUnbondingOps(ctx)) - // Check that the unbonding op index was removed - _, found = pk.GetUnbondingOpIndex(ctx, "chain-1", 3) - require.False(t, found) -} - // TestSendVSCPacketsToChainFailure tests the SendVSCPacketsToChain method failing func TestSendVSCPacketsToChainFailure(t *testing.T) { // Keeper setup @@ -1004,3 +787,39 @@ func TestQueueVSCPacketsWithPowerCapping(t *testing.T) { require.Equal(t, expectedQueuedVSCPackets, actualQueuedVSCPackets) } + +// TestBlocksUntilNextEpoch tests the `BlocksUntilNextEpoch` method +func TestBlocksUntilNextEpoch(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + // 10 blocks constitute an epoch + params := providertypes.DefaultParams() + params.BlocksPerEpoch = 10 + providerKeeper.SetParams(ctx, params) + + // with block height of 1 we expect 9 blocks until the next epoch + ctx = ctx.WithBlockHeight(1) + require.Equal(t, int64(9), providerKeeper.BlocksUntilNextEpoch(ctx)) + + // with block height of 5 we expect 5 blocks until the next epoch + ctx = ctx.WithBlockHeight(5) + require.Equal(t, int64(5), providerKeeper.BlocksUntilNextEpoch(ctx)) + + // with block height of 10 we expect 0 blocks until the next epoch, since + // this epoch is the one where we send the VSC packet + ctx = ctx.WithBlockHeight(10) + require.Equal(t, int64(0), providerKeeper.BlocksUntilNextEpoch(ctx)) + + // with block height of 11 we expect 9 blocks until the next epoch + ctx = ctx.WithBlockHeight(11) + require.Equal(t, int64(9), providerKeeper.BlocksUntilNextEpoch(ctx)) + + // with block height of 15 we expect 5 blocks until the next epoch + ctx = ctx.WithBlockHeight(15) + require.Equal(t, int64(5), providerKeeper.BlocksUntilNextEpoch(ctx)) + + // with block height of 19 we expect 1 block until the next epoch + ctx = ctx.WithBlockHeight(19) + require.Equal(t, int64(1), providerKeeper.BlocksUntilNextEpoch(ctx)) +} diff --git a/x/ccv/provider/keeper/throttle_legacy.go b/x/ccv/provider/keeper/throttle_legacy.go deleted file mode 100644 index 604f3a08c4..0000000000 --- a/x/ccv/provider/keeper/throttle_legacy.go +++ /dev/null @@ -1,111 +0,0 @@ -package keeper - -import ( - "fmt" - - storetypes "cosmossdk.io/store/types" - sdktypes "github.com/cosmos/cosmos-sdk/types" - - providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types" - ccvtypes "github.com/cosmos/interchain-security/v5/x/ccv/types" -) - -// Pending packet data type enum, used to encode the type of packet data stored at each entry in the mutual queue. -// Note this type is copy/pasted from throttle v1 code. -const ( - slashPacketData byte = iota - vscMaturedPacketData -) - -// Deprecated: LegacyGetAllThrottledPacketData is deprecated for ICS >= v4.0.0. -// LegacyGetAllThrottledPacketData returns all throttled packet data that was queued on the provider for a given consumer chain. -func (k Keeper) LegacyGetAllThrottledPacketData(ctx sdktypes.Context, consumerChainID string) ( - slashData []ccvtypes.SlashPacketData, vscMaturedData []ccvtypes.VSCMaturedPacketData, -) { - slashData = []ccvtypes.SlashPacketData{} - vscMaturedData = []ccvtypes.VSCMaturedPacketData{} - - store := ctx.KVStore(k.storeKey) - iteratorPrefix := providertypes.ChainIdWithLenKey(providertypes.ThrottledPacketDataKeyPrefix(), consumerChainID) - iterator := storetypes.KVStorePrefixIterator(store, iteratorPrefix) - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - bz := iterator.Value() - switch bz[0] { - case slashPacketData: - d := ccvtypes.SlashPacketData{} - if err := d.Unmarshal(bz[1:]); err != nil { - k.Logger(ctx).Error(fmt.Sprintf("failed to unmarshal slash packet data: %v", err)) - continue - } - slashData = append(slashData, d) - case vscMaturedPacketData: - d := ccvtypes.VSCMaturedPacketData{} - if err := d.Unmarshal(bz[1:]); err != nil { - k.Logger(ctx).Error(fmt.Sprintf("failed to unmarshal vsc matured packet data: %v", err)) - continue - } - vscMaturedData = append(vscMaturedData, d) - default: - k.Logger(ctx).Error(fmt.Sprintf("invalid packet data type: %v", bz[0])) - continue - } - } - - return slashData, vscMaturedData -} - -// Deprecated: LegacyDeleteThrottledPacketDataForConsumer is deprecated for ICS >= v4.0.0. -// LegacyDeleteThrottledPacketDataForConsumer removes all throttled packet data that was queued on the provider for a given consumer chain. -func (k Keeper) LegacyDeleteThrottledPacketDataForConsumer(ctx sdktypes.Context, consumerChainID string) { - store := ctx.KVStore(k.storeKey) - iteratorPrefix := providertypes.ChainIdWithLenKey(providertypes.ThrottledPacketDataKeyPrefix(), consumerChainID) - iterator := storetypes.KVStorePrefixIterator(store, iteratorPrefix) - defer iterator.Close() - - keysToDel := [][]byte{} - for ; iterator.Valid(); iterator.Next() { - keysToDel = append(keysToDel, iterator.Key()) - } - // Delete data for this consumer - for _, key := range keysToDel { - store.Delete(key) - } - - // Delete size of data queue for this consumer - store.Delete(providertypes.ThrottledPacketDataSizeKey(consumerChainID)) -} - -// Deprecated: LegacyQueueThrottledPacketData is deprecated for ICS >= v4.0.0. -// LegacyQueueThrottledPacketData queues throttled packet data for a given consumer chain on the provider. -// The method should not be used because the provider does not process throttled packet data anymore. -func (k Keeper) LegacyQueueThrottledPacketData( - ctx sdktypes.Context, consumerChainID string, ibcSeqNum uint64, packetData interface{}, -) error { - store := ctx.KVStore(k.storeKey) - - var bz []byte - var err error - switch data := packetData.(type) { - case ccvtypes.SlashPacketData: - bz, err = data.Marshal() - if err != nil { - return fmt.Errorf("failed to marshal slash packet data: %v", err) - } - bz = append([]byte{slashPacketData}, bz...) - case ccvtypes.VSCMaturedPacketData: - bz, err = data.Marshal() - if err != nil { - return fmt.Errorf("failed to marshal vsc matured packet data: %v", err) - } - bz = append([]byte{vscMaturedPacketData}, bz...) - default: - // Indicates a developer error, this method should only be called - // by tests, QueueThrottledSlashPacketData, or QueueThrottledVSCMaturedPacketData. - panic(fmt.Sprintf("unexpected packet data type: %T", data)) - } - - store.Set(providertypes.ThrottledPacketDataKey(consumerChainID, ibcSeqNum), bz) - return nil -} diff --git a/x/ccv/provider/migrations/migrator.go b/x/ccv/provider/migrations/migrator.go index b031f9705b..4678fe83cd 100644 --- a/x/ccv/provider/migrations/migrator.go +++ b/x/ccv/provider/migrations/migrator.go @@ -1,30 +1,38 @@ package migrations import ( + "fmt" + storetypes "cosmossdk.io/store/types" - "github.com/cosmos/cosmos-sdk/codec" sdktypes "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper" - v3 "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations/v3" v4 "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations/v4" v5 "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations/v5" v6 "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations/v6" v7 "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations/v7" + v8 "github.com/cosmos/interchain-security/v5/x/ccv/provider/migrations/v8" ) // Migrator is a struct for handling in-place store migrations. type Migrator struct { providerKeeper providerkeeper.Keeper paramSpace paramtypes.Subspace - cdc codec.BinaryCodec storeKey storetypes.StoreKey } // NewMigrator returns a new Migrator. -func NewMigrator(providerKeeper providerkeeper.Keeper, paramSpace paramtypes.Subspace) Migrator { - return Migrator{providerKeeper: providerKeeper, paramSpace: paramSpace} +func NewMigrator( + providerKeeper providerkeeper.Keeper, + paramSpace paramtypes.Subspace, + storeKey storetypes.StoreKey, +) Migrator { + return Migrator{ + providerKeeper: providerKeeper, + paramSpace: paramSpace, + storeKey: storeKey, + } } // Migrating consensus version 1 to 2 is a no-op. @@ -32,12 +40,16 @@ func NewMigrator(providerKeeper providerkeeper.Keeper, paramSpace paramtypes.Sub // First run provider@v2.x.y in production to migrate from consensus version 1 to 2. // Then, in order to migrate to consensus version 3, first upgrade to provider@v3.x.y. func (m Migrator) Migrate1to2(ctx sdktypes.Context) error { - return nil + return fmt.Errorf("state migration failed: " + + "first run provider@v2.x.y in production to migrate from consensus version 1 to 2; " + + "then, in order to migrate to consensus version 3, first upgrade to provider@v3.x.y") } // Migrate2to3 migrates x/ccvprovider state from consensus version 2 to 3. +// First run provider@v4.0.x in production to migrate from consensus version 2 to 3. func (m Migrator) Migrate2to3(ctx sdktypes.Context) error { - return v3.MigrateQueuedPackets(ctx, m.providerKeeper) + return fmt.Errorf("state migration failed: " + + "first run provider@v4.0.x in production to migrate from consensus version 2 to 3") } // Migrate3to4 migrates x/ccvprovider state from consensus version 3 to 4. @@ -54,7 +66,8 @@ func (m Migrator) Migrate4to5(ctx sdktypes.Context) error { return nil } -// Migrate5to6 consists of setting the `NumberOfEpochsToStartReceivingRewards` param, as well as +// Migrate5to6 migrates x/ccvprovider state from consensus version 5 to 6. +// It consists of setting the `NumberOfEpochsToStartReceivingRewards` param, as well as // computing and storing the minimal power in the top N for all registered consumer chains. func (m Migrator) Migrate5to6(ctx sdktypes.Context) error { v6.MigrateParams(ctx, m.paramSpace) @@ -67,3 +80,19 @@ func (m Migrator) Migrate5to6(ctx sdktypes.Context) error { func (m Migrator) Migrate6to7(ctx sdktypes.Context) error { return v7.MigrateLegacyParams(ctx, m.providerKeeper, m.paramSpace) } + +// Migrate7to8 migrates x/ccvprovider state from consensus version 7 to 8. +// The migration consists of the following actions: +// - complete the outstanding paused unbonding ops waiting for VSCMaturedPackets from consumer chains +// - migrate the ConsumerAddrsToPrune index to ConsumerAddrsToPruneV2 +// - cleanup deprecated state +func (m Migrator) Migrate7to8(ctx sdktypes.Context) error { + store := ctx.KVStore(m.storeKey) + v8.CompleteUnbondingOps(ctx, store, m.providerKeeper) + if err := v8.MigrateConsumerAddrsToPrune(ctx, store, m.providerKeeper); err != nil { + return err + } + v8.CleanupState(store) + + return nil +} diff --git a/x/ccv/provider/migrations/v3/migration_test.go b/x/ccv/provider/migrations/v3/migration_test.go deleted file mode 100644 index 56d6b617d9..0000000000 --- a/x/ccv/provider/migrations/v3/migration_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package v3 - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - - testutil "github.com/cosmos/interchain-security/v5/testutil/keeper" -) - -func TestMigrate2To3(t *testing.T) { - providerKeeper, ctx, ctrl, _ := testutil.GetProviderKeeperAndCtx(t, testutil.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - // Set consumer client ids to mock consumers being connected to provider - providerKeeper.SetConsumerClientId(ctx, "chain-1", "client-1") - providerKeeper.SetConsumerClientId(ctx, "chain-2", "client-2") - providerKeeper.SetConsumerClientId(ctx, "chain-3", "client-3") - - // Queue some data for chain-1 - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-1", 66, testutil.GetNewSlashPacketData()) - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-1", 67, testutil.GetNewVSCMaturedPacketData()) - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-1", 68, testutil.GetNewSlashPacketData()) - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-1", 69, testutil.GetNewVSCMaturedPacketData()) - - // Queue some data for chain-2 - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-2", 789, testutil.GetNewVSCMaturedPacketData()) - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-2", 790, testutil.GetNewSlashPacketData()) - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-2", 791, testutil.GetNewVSCMaturedPacketData()) - - // Queue some data for chain-3 - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-3", 123, testutil.GetNewSlashPacketData()) - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-3", 124, testutil.GetNewVSCMaturedPacketData()) - providerKeeper.LegacyQueueThrottledPacketData( - ctx, "chain-3", 125, testutil.GetNewVSCMaturedPacketData()) - - // Confirm getter methods return expected values - slash1, vscm1 := providerKeeper.LegacyGetAllThrottledPacketData(ctx, "chain-1") - require.Len(t, slash1, 2) - require.Len(t, vscm1, 2) - - slash2, vscm2 := providerKeeper.LegacyGetAllThrottledPacketData(ctx, "chain-2") - require.Len(t, slash2, 1) - require.Len(t, vscm2, 2) - - slash3, vscm3 := providerKeeper.LegacyGetAllThrottledPacketData(ctx, "chain-3") - require.Len(t, slash3, 1) - require.Len(t, vscm3, 2) - - // Set vsc send timestamp for every queued vsc matured packet, - // as a way to assert that the vsc matured packets are handled in the migration. - // - // That is, timestamp should exist before a vsc matured packet is handled, - // and deleted after handling. - for _, data := range vscm1 { - providerKeeper.SetVscSendTimestamp(ctx, "chain-1", data.ValsetUpdateId, time.Now()) - } - for _, data := range vscm2 { - providerKeeper.SetVscSendTimestamp(ctx, "chain-2", data.ValsetUpdateId, time.Now()) - } - for _, data := range vscm3 { - providerKeeper.SetVscSendTimestamp(ctx, "chain-3", data.ValsetUpdateId, time.Now()) - } - - // Confirm timestamps are set - for _, data := range vscm1 { - _, found := providerKeeper.GetVscSendTimestamp(ctx, "chain-1", data.ValsetUpdateId) - require.True(t, found) - } - for _, data := range vscm2 { - _, found := providerKeeper.GetVscSendTimestamp(ctx, "chain-2", data.ValsetUpdateId) - require.True(t, found) - } - for _, data := range vscm3 { - _, found := providerKeeper.GetVscSendTimestamp(ctx, "chain-3", data.ValsetUpdateId) - require.True(t, found) - } - - // Run migration - err := MigrateQueuedPackets(ctx, providerKeeper) - require.NoError(t, err) - - // Confirm throttled data is now deleted - slash1, vscm1 = providerKeeper.LegacyGetAllThrottledPacketData(ctx, "chain-1") - require.Empty(t, slash1) - require.Empty(t, vscm1) - slash2, vscm2 = providerKeeper.LegacyGetAllThrottledPacketData(ctx, "chain-2") - require.Empty(t, slash2) - require.Empty(t, vscm2) - slash3, vscm3 = providerKeeper.LegacyGetAllThrottledPacketData(ctx, "chain-3") - require.Empty(t, slash3) - require.Empty(t, vscm3) - - // Confirm timestamps are deleted, meaning vsc matured packets were handled - for _, data := range vscm1 { - _, found := providerKeeper.GetVscSendTimestamp(ctx, "chain-1", data.ValsetUpdateId) - require.False(t, found) - } - for _, data := range vscm2 { - _, found := providerKeeper.GetVscSendTimestamp(ctx, "chain-2", data.ValsetUpdateId) - require.False(t, found) - } - for _, data := range vscm3 { - _, found := providerKeeper.GetVscSendTimestamp(ctx, "chain-3", data.ValsetUpdateId) - require.False(t, found) - } -} diff --git a/x/ccv/provider/migrations/v3/migrations.go b/x/ccv/provider/migrations/v3/migrations.go deleted file mode 100644 index 8c17000b0b..0000000000 --- a/x/ccv/provider/migrations/v3/migrations.go +++ /dev/null @@ -1,25 +0,0 @@ -package v3 - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - - providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper" -) - -// MigrateQueuedPackets processes all queued packet data for all consumer chains that were stored -// on the provider in the v2 consensus version (jail throttling v1). -func MigrateQueuedPackets(ctx sdk.Context, k providerkeeper.Keeper) error { - for _, consumerChainID := range k.GetAllRegisteredConsumerChainIDs(ctx) { - slashData, vscmData := k.LegacyGetAllThrottledPacketData(ctx, consumerChainID) - if len(slashData) > 0 { - k.Logger(ctx).Error(fmt.Sprintf("slash data being dropped: %v", slashData)) - } - for _, data := range vscmData { - k.HandleVSCMaturedPacket(ctx, consumerChainID, data) - } - k.LegacyDeleteThrottledPacketDataForConsumer(ctx, consumerChainID) - } - return nil -} diff --git a/x/ccv/provider/migrations/v7/legacy_params.go b/x/ccv/provider/migrations/v7/legacy_params.go index 46bb2c99b4..05e0cea59e 100644 --- a/x/ccv/provider/migrations/v7/legacy_params.go +++ b/x/ccv/provider/migrations/v7/legacy_params.go @@ -32,20 +32,6 @@ func getCCVTimeoutPeriod(ctx sdk.Context, paramSpace ccvtypes.LegacyParamSubspac return p } -// getInitTimeoutPeriod returns the init timeout period -func getInitTimeoutPeriod(ctx sdk.Context, paramSpace ccvtypes.LegacyParamSubspace) time.Duration { - var p time.Duration - paramSpace.Get(ctx, types.KeyInitTimeoutPeriod, &p) - return p -} - -// getVscTimeoutPeriod returns the vsc timeout period -func getVscTimeoutPeriod(ctx sdk.Context, paramSpace ccvtypes.LegacyParamSubspace) time.Duration { - var p time.Duration - paramSpace.Get(ctx, types.KeyVscTimeoutPeriod, &p) - return p -} - // getSlashMeterReplenishPeriod returns the period in which: // Once the slash meter becomes not-full, the slash meter is replenished after this period. func getSlashMeterReplenishPeriod(ctx sdk.Context, paramSpace ccvtypes.LegacyParamSubspace) time.Duration { @@ -88,8 +74,6 @@ func GetParamsLegacy(ctx sdk.Context, paramspace ccvtypes.LegacyParamSubspace) t getTemplateClient(ctx, paramspace), getTrustingPeriodFraction(ctx, paramspace), getCCVTimeoutPeriod(ctx, paramspace), - getInitTimeoutPeriod(ctx, paramspace), - getVscTimeoutPeriod(ctx, paramspace), getSlashMeterReplenishPeriod(ctx, paramspace), getSlashMeterReplenishFraction(ctx, paramspace), getConsumerRewardDenomRegistrationFee(ctx, paramspace), diff --git a/x/ccv/provider/migrations/v7/migrations_test.go b/x/ccv/provider/migrations/v7/migrations_test.go index f4ee763263..4b983205cc 100644 --- a/x/ccv/provider/migrations/v7/migrations_test.go +++ b/x/ccv/provider/migrations/v7/migrations_test.go @@ -23,8 +23,6 @@ func TestMigrateParams(t *testing.T) { inMemParams.ParamsSubspace.Set(ctx, providertypes.KeyTemplateClient, defaultParams.TemplateClient) inMemParams.ParamsSubspace.Set(ctx, providertypes.KeyTrustingPeriodFraction, defaultParams.TrustingPeriodFraction) inMemParams.ParamsSubspace.Set(ctx, ccvtypes.KeyCCVTimeoutPeriod, defaultParams.CcvTimeoutPeriod) - inMemParams.ParamsSubspace.Set(ctx, providertypes.KeyInitTimeoutPeriod, defaultParams.InitTimeoutPeriod) - inMemParams.ParamsSubspace.Set(ctx, providertypes.KeyVscTimeoutPeriod, defaultParams.VscTimeoutPeriod) inMemParams.ParamsSubspace.Set(ctx, providertypes.KeySlashMeterReplenishPeriod, defaultParams.SlashMeterReplenishPeriod) inMemParams.ParamsSubspace.Set(ctx, providertypes.KeySlashMeterReplenishFraction, defaultParams.SlashMeterReplenishFraction) inMemParams.ParamsSubspace.Set(ctx, providertypes.KeyConsumerRewardDenomRegistrationFee, defaultParams.ConsumerRewardDenomRegistrationFee) diff --git a/x/ccv/provider/migrations/v8/migrations.go b/x/ccv/provider/migrations/v8/migrations.go new file mode 100644 index 0000000000..cdf299f91f --- /dev/null +++ b/x/ccv/provider/migrations/v8/migrations.go @@ -0,0 +1,120 @@ +package v8 + +import ( + "encoding/binary" + "time" + + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper" + providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types" +) + +const ( + LegacyUnbondingOpBytePrefix = byte(11) + LegacyConsumerAddrsToPruneBytePrefix = byte(25) + LegacyMaturedUnbondingOpsByteKey = byte(1) + LegacyUnbondingOpIndexBytePrefix = byte(12) + LegacyInitTimeoutTimestampBytePrefix = byte(8) + LegacyVscSendTimestampBytePrefix = byte(18) + LegacyVSCMaturedHandledThisBlockBytePrefix = byte(28) +) + +// CompleteUnbondingOps completes all unbonding operations. +// Note that it must be executed before CleanupState. +func CompleteUnbondingOps(ctx sdk.Context, store storetypes.KVStore, pk providerkeeper.Keeper) { + iterator := storetypes.KVStorePrefixIterator(store, []byte{LegacyUnbondingOpBytePrefix}) + defer func() { + if err := iterator.Close(); err != nil { + pk.Logger(ctx).Error("Failed to close iterator", "error", err) + } + }() + + for ; iterator.Valid(); iterator.Next() { + id := binary.BigEndian.Uint64(iterator.Key()[1:]) + if err := pk.UnbondingCanComplete(ctx, id); err != nil { + pk.Logger(ctx).Error("UnbondingCanComplete failed", "unbondingID", id, "error", err.Error()) + } + } +} + +// MigrateConsumerAddrsToPrune migrates the ConsumerAddrsToPrune index to ConsumerAddrsToPruneV2. +// Note: This migration must be done before removing the VscSendTimestamp index +func MigrateConsumerAddrsToPrune(ctx sdk.Context, store storetypes.KVStore, pk providerkeeper.Keeper) error { + iterator := storetypes.KVStorePrefixIterator(store, []byte{LegacyConsumerAddrsToPruneBytePrefix}) + defer iterator.Close() + + unbondingPeriod, err := pk.UnbondingTime(ctx) + if err != nil { + return err + } + + for ; iterator.Valid(); iterator.Next() { + chainID, vscID, err := providertypes.ParseChainIdAndUintIdKey(LegacyConsumerAddrsToPruneBytePrefix, iterator.Key()) + if err != nil { + pk.Logger(ctx).Error("ParseChainIdAndUintIdKey failed while migrating ConsumerAddrsToPrune", + "key", string(iterator.Key()), + "error", err.Error(), + ) + continue + } + // use the VscSendTimestamp index to compute the timestamp after which this consumer address can be pruned + vscSendTimestampKey := providertypes.ChainIdAndUintIdKey(LegacyVscSendTimestampBytePrefix, chainID, vscID) + var sentTime time.Time + if timeBz := store.Get(vscSendTimestampKey); timeBz != nil { + if ts, err := sdk.ParseTimeBytes(timeBz); err == nil { + sentTime = ts + } else { + pk.Logger(ctx).Error("MigrateConsumerAddrsToPrune failed parsing VSC send timestamp key", "error", err.Error()) + continue + } + } else { + pk.Logger(ctx).Error( + "MigrateConsumerAddrsToPrune cannot find VSC send timestamp", + "chainID", chainID, + "vscID", vscID, + ) + continue + } + pruneAfterTs := sentTime.Add(unbondingPeriod).UTC() + + var addrs providertypes.AddressList + err = addrs.Unmarshal(iterator.Value()) + if err != nil { + pk.Logger(ctx).Error("MigrateConsumerAddrsToPrune failed unmarshaling data from store", "key", string(iterator.Value())) + continue + } + + for _, addr := range addrs.Addresses { + consumerAddr := providertypes.NewConsumerConsAddress(addr) + pk.AppendConsumerAddrsToPrune(ctx, chainID, pruneAfterTs, consumerAddr) + } + } + + return nil +} + +// CleanupState removes deprecated state +func CleanupState(store storetypes.KVStore) { + removePrefix(store, LegacyMaturedUnbondingOpsByteKey) + removePrefix(store, LegacyUnbondingOpBytePrefix) + removePrefix(store, LegacyUnbondingOpIndexBytePrefix) + removePrefix(store, LegacyInitTimeoutTimestampBytePrefix) + removePrefix(store, LegacyVscSendTimestampBytePrefix) + removePrefix(store, LegacyVSCMaturedHandledThisBlockBytePrefix) + removePrefix(store, LegacyConsumerAddrsToPruneBytePrefix) +} + +func removePrefix(store storetypes.KVStore, prefix byte) { + iterator := storetypes.KVStorePrefixIterator(store, []byte{prefix}) + defer iterator.Close() + + var keysToDel [][]byte + for ; iterator.Valid(); iterator.Next() { + keysToDel = append(keysToDel, iterator.Key()) + } + for _, delKey := range keysToDel { + store.Delete(delKey) + } +} diff --git a/x/ccv/provider/migrations/v8/migrations_test.go b/x/ccv/provider/migrations/v8/migrations_test.go new file mode 100644 index 0000000000..8c23fccc64 --- /dev/null +++ b/x/ccv/provider/migrations/v8/migrations_test.go @@ -0,0 +1,140 @@ +package v8 + +import ( + "testing" + "time" + + "github.com/golang/mock/gomock" + + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + testutil "github.com/cosmos/interchain-security/v5/testutil/keeper" + providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types" + "github.com/stretchr/testify/require" +) + +func legacyConsumerAddrsToPruneKey(chainID string, vscID uint64) []byte { + return providertypes.ChainIdAndUintIdKey(LegacyConsumerAddrsToPruneBytePrefix, chainID, vscID) +} + +func legacyAppendConsumerAddrsToPrune( + store storetypes.KVStore, + chainID string, + vscID uint64, + consumerAddr providertypes.ConsumerConsAddress, +) { + bz := store.Get(legacyConsumerAddrsToPruneKey(chainID, vscID)) + var consumerAddrsToPrune providertypes.AddressList + if bz != nil { + err := consumerAddrsToPrune.Unmarshal(bz) + if err != nil { + // An error here would indicate something is very wrong, + // the data bytes are assumed to be correctly serialized by previous calls to this method. + panic(err) + } + } + consumerAddrsToPrune.Addresses = append(consumerAddrsToPrune.Addresses, consumerAddr.ToSdkConsAddr()) + bz, err := consumerAddrsToPrune.Marshal() + if err != nil { + // An error here would indicate something is very wrong, + // consumerAddrsToPrune is instantiated in this method and should be able to be marshaled. + panic(err) + } + store.Set(legacyConsumerAddrsToPruneKey(chainID, vscID), bz) +} + +func legacyVscSendingTimestampKey(chainID string, vscID uint64) []byte { + return providertypes.ChainIdAndUintIdKey(LegacyVscSendTimestampBytePrefix, chainID, vscID) +} + +func legacySetVscSendTimestamp( + store storetypes.KVStore, + chainID string, + vscID uint64, + timestamp time.Time, +) { + // Convert timestamp into bytes for storage + timeBz := sdk.FormatTimeBytes(timestamp) + + store.Set(legacyVscSendingTimestampKey(chainID, vscID), timeBz) +} + +func TestMigrateConsumerAddrsToPrune(t *testing.T) { + t.Helper() + inMemParams := testutil.NewInMemKeeperParams(t) + pk, ctx, ctrl, mocks := testutil.GetProviderKeeperAndCtx(t, inMemParams) + defer ctrl.Finish() + + store := ctx.KVStore(inMemParams.StoreKey) + + consumerAddrsToPrune := []struct { + chainId string + vscId uint64 + address providertypes.ConsumerConsAddress + }{ + {"chain-1", 1, providertypes.NewConsumerConsAddress([]byte{0x01})}, + {"chain-1", 1, providertypes.NewConsumerConsAddress([]byte{0x02})}, + {"chain-2", 1, providertypes.NewConsumerConsAddress([]byte{0x03})}, + {"chain-1", 2, providertypes.NewConsumerConsAddress([]byte{0x04})}, + {"chain-1", 3, providertypes.NewConsumerConsAddress([]byte{0x05})}, + } + for _, x := range consumerAddrsToPrune { + legacyAppendConsumerAddrsToPrune(store, x.chainId, x.vscId, x.address) + } + + ts1 := time.Now().UTC() + ts2 := ts1.Add(time.Minute).UTC() + ts3 := ts2.Add(time.Hour).UTC() + vscSendTimestamps := []struct { + chainId string + vscId uint64 + ts time.Time + }{ + {"chain-1", 1, ts1}, + {"chain-1", 2, ts2}, + {"chain-1", 3, ts3}, + {"chain-2", 1, ts1}, + } + for _, x := range vscSendTimestamps { + legacySetVscSendTimestamp(store, x.chainId, x.vscId, x.ts) + } + + gomock.InOrder( + mocks.MockStakingKeeper.EXPECT().UnbondingTime(ctx).Times(2), + ) + + unbondingPeriod, err := pk.UnbondingTime(ctx) + require.NoError(t, err) + + err = MigrateConsumerAddrsToPrune(ctx, store, pk) + require.NoError(t, err) + + consumerAddrs := pk.GetAllConsumerAddrsToPrune(ctx, "chain-1") + require.Len(t, consumerAddrs, 3) + // two addresses with ts1 + require.Equal(t, ts1.Add(unbondingPeriod).UTC(), consumerAddrs[0].PruneTs) + require.Len(t, consumerAddrs[0].ConsumerAddrs.Addresses, 2) + consumerAddr := providertypes.NewConsumerConsAddress(consumerAddrs[0].ConsumerAddrs.Addresses[0]) + require.Equal(t, consumerAddrsToPrune[0].address, consumerAddr) + consumerAddr = providertypes.NewConsumerConsAddress(consumerAddrs[0].ConsumerAddrs.Addresses[1]) + require.Equal(t, consumerAddrsToPrune[1].address, consumerAddr) + // one address with ts2 + require.Equal(t, ts2.Add(unbondingPeriod).UTC(), consumerAddrs[1].PruneTs) + require.Len(t, consumerAddrs[1].ConsumerAddrs.Addresses, 1) + consumerAddr = providertypes.NewConsumerConsAddress(consumerAddrs[1].ConsumerAddrs.Addresses[0]) + require.Equal(t, consumerAddrsToPrune[3].address, consumerAddr) + // one address with ts3 + require.Equal(t, ts3.Add(unbondingPeriod).UTC(), consumerAddrs[2].PruneTs) + require.Len(t, consumerAddrs[2].ConsumerAddrs.Addresses, 1) + consumerAddr = providertypes.NewConsumerConsAddress(consumerAddrs[2].ConsumerAddrs.Addresses[0]) + require.Equal(t, consumerAddrsToPrune[4].address, consumerAddr) + + consumerAddrs = pk.GetAllConsumerAddrsToPrune(ctx, "chain-2") + require.Len(t, consumerAddrs, 1) + // one address with ts1 + require.Equal(t, ts1.Add(unbondingPeriod).UTC(), consumerAddrs[0].PruneTs) + require.Len(t, consumerAddrs[0].ConsumerAddrs.Addresses, 1) + consumerAddr = providertypes.NewConsumerConsAddress(consumerAddrs[0].ConsumerAddrs.Addresses[0]) + require.Equal(t, consumerAddrsToPrune[2].address, consumerAddr) + +} diff --git a/x/ccv/provider/module.go b/x/ccv/provider/module.go index 3deb4adaf9..320a135a69 100644 --- a/x/ccv/provider/module.go +++ b/x/ccv/provider/module.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" "cosmossdk.io/core/appmodule" - + storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -105,13 +105,15 @@ type AppModule struct { AppModuleBasic keeper *keeper.Keeper paramSpace paramtypes.Subspace + storeKey storetypes.StoreKey } // NewAppModule creates a new provider module -func NewAppModule(k *keeper.Keeper, paramSpace paramtypes.Subspace) AppModule { +func NewAppModule(k *keeper.Keeper, paramSpace paramtypes.Subspace, storeKey storetypes.StoreKey) AppModule { return AppModule{ keeper: k, paramSpace: paramSpace, + storeKey: storeKey, } } @@ -125,7 +127,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { providertypes.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) providertypes.RegisterQueryServer(cfg.QueryServer(), am.keeper) - migrator := migrations.NewMigrator(*am.keeper, am.paramSpace) + migrator := migrations.NewMigrator(*am.keeper, am.paramSpace, am.storeKey) if err := cfg.RegisterMigration(providertypes.ModuleName, 2, migrator.Migrate2to3); err != nil { panic(fmt.Sprintf("failed to register migrator for %s: %s -- from 2 -> 3", providertypes.ModuleName, err)) } @@ -136,10 +138,13 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { panic(fmt.Sprintf("failed to register migrator for %s: %s -- from 4 -> 5", providertypes.ModuleName, err)) } if err := cfg.RegisterMigration(providertypes.ModuleName, 5, migrator.Migrate5to6); err != nil { - panic(fmt.Sprintf("failed to register migrator for %s: %s", providertypes.ModuleName, err)) + panic(fmt.Sprintf("failed to register migrator for %s: %s -- from 5 -> 6", providertypes.ModuleName, err)) } if err := cfg.RegisterMigration(providertypes.ModuleName, 6, migrator.Migrate6to7); err != nil { - panic(fmt.Sprintf("failed to register migrator for %s: %s", providertypes.ModuleName, err)) + panic(fmt.Sprintf("failed to register migrator for %s: %s -- from 6 -> 7", providertypes.ModuleName, err)) + } + if err := cfg.RegisterMigration(providertypes.ModuleName, 7, migrator.Migrate7to8); err != nil { + panic(fmt.Sprintf("failed to register migrator for %s: %s -- from 7 -> 8", providertypes.ModuleName, err)) } } @@ -162,7 +167,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 7 } +func (AppModule) ConsensusVersion() uint64 { return 8 } // BeginBlock implements the AppModule interface func (am AppModule) BeginBlock(ctx context.Context) error { @@ -186,8 +191,6 @@ func (am AppModule) EndBlock(ctx context.Context) ([]abci.ValidatorUpdate, error // EndBlock logic needed for the Consumer Initiated Slashing sub-protocol. // Important: EndBlockCIS must be called before EndBlockVSU am.keeper.EndBlockCIS(sdkCtx) - // EndBlock logic needed for the Consumer Chain Removal sub-protocol - am.keeper.EndBlockCCR(sdkCtx) // EndBlock logic needed for the Validator Set Update sub-protocol return am.keeper.EndBlockVSU(sdkCtx) } diff --git a/x/ccv/provider/module_test.go b/x/ccv/provider/module_test.go index 5e8584f15b..3c406f1cc8 100644 --- a/x/ccv/provider/module_test.go +++ b/x/ccv/provider/module_test.go @@ -99,22 +99,18 @@ func TestInitGenesis(t *testing.T) { keeperParams := testkeeper.NewInMemKeeperParams(t) providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) - appModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace) + appModule := provider.NewAppModule(&providerKeeper, *keeperParams.ParamsSubspace, keeperParams.StoreKey) genState := types.NewGenesisState( providerKeeper.GetValidatorSetUpdateId(ctx), nil, tc.consumerStates, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ) cdc := keeperParams.Cdc diff --git a/x/ccv/provider/types/consumer.go b/x/ccv/provider/types/consumer.go index 02651ac03e..37c286422f 100644 --- a/x/ccv/provider/types/consumer.go +++ b/x/ccv/provider/types/consumer.go @@ -10,7 +10,6 @@ func NewConsumerStates( channelID string, initialHeight uint64, genesis ccv.ConsumerGenesisState, - unbondingOpsIndexes []VscUnbondingOps, pendingValsetChanges []ccv.ValidatorSetChangePacketData, slashDowntimeAck []string, ) ConsumerState { @@ -19,7 +18,6 @@ func NewConsumerStates( ClientId: clientID, ChannelId: channelID, InitialHeight: initialHeight, - UnbondingOpsIndex: unbondingOpsIndexes, PendingValsetChanges: pendingValsetChanges, ConsumerGenesis: genesis, SlashDowntimeAck: slashDowntimeAck, diff --git a/x/ccv/provider/types/events.go b/x/ccv/provider/types/events.go index 8701821c52..9abcba7836 100644 --- a/x/ccv/provider/types/events.go +++ b/x/ccv/provider/types/events.go @@ -12,7 +12,6 @@ const ( EventTypeOptOut = "opt_out" AttributeInfractionHeight = "infraction_height" AttributeInitialHeight = "initial_height" - AttributeInitializationTimeout = "initialization_timeout" AttributeTrustingPeriod = "trusting_period" AttributeUnbondingPeriod = "unbonding_period" AttributeProviderValidatorAddress = "provider_validator_address" diff --git a/x/ccv/provider/types/genesis.go b/x/ccv/provider/types/genesis.go index 345bd20537..ae47f2987c 100644 --- a/x/ccv/provider/types/genesis.go +++ b/x/ccv/provider/types/genesis.go @@ -16,32 +16,24 @@ func NewGenesisState( vscID uint64, vscIdToHeights []ValsetUpdateIdToHeight, consumerStates []ConsumerState, - unbondingOps []UnbondingOp, - matureUbdOps *MaturedUnbondingOps, additionProposals []ConsumerAdditionProposal, removalProposals []ConsumerRemovalProposal, params Params, validatorConsumerPubkeys []ValidatorConsumerPubKey, validatorsByConsumerAddr []ValidatorByConsumerAddr, - consumerAddrsToPrune []ConsumerAddrsToPrune, - initTimeoutTimestamps []InitTimeoutTimestamp, - exportedVscSendTimestamps []ExportedVscSendTimestamp, + consumerAddrsToPrune []ConsumerAddrsToPruneV2, lastProviderConsensusValidators []ConsensusValidator, ) *GenesisState { return &GenesisState{ ValsetUpdateId: vscID, ValsetUpdateIdToHeight: vscIdToHeights, ConsumerStates: consumerStates, - UnbondingOps: unbondingOps, - MatureUnbondingOps: matureUbdOps, ConsumerAdditionProposals: additionProposals, ConsumerRemovalProposals: removalProposals, Params: params, ValidatorConsumerPubkeys: validatorConsumerPubkeys, ValidatorsByConsumerAddr: validatorsByConsumerAddr, - ConsumerAddrsToPrune: consumerAddrsToPrune, - InitTimeoutTimestamps: initTimeoutTimestamps, - ExportedVscSendTimestamps: exportedVscSendTimestamps, + ConsumerAddrsToPruneV2: consumerAddrsToPrune, LastProviderConsensusValidators: lastProviderConsensusValidators, } } @@ -59,12 +51,6 @@ func (gs GenesisState) Validate() error { return errorsmod.Wrap(ccv.ErrInvalidGenesis, "valset update ID cannot be equal to zero") } - for _, ubdOp := range gs.UnbondingOps { - if err := gs.ValidateUnbondingOp(ubdOp); err != nil { - return err - } - } - for _, prop := range gs.ConsumerAdditionProposals { if err := prop.ValidateBasic(); err != nil { return errorsmod.Wrap(ccv.ErrInvalidGenesis, err.Error()) @@ -96,7 +82,7 @@ func (gs GenesisState) Validate() error { if err := KeyAssignmentValidateBasic(gs.ValidatorConsumerPubkeys, gs.ValidatorsByConsumerAddr, - gs.ConsumerAddrsToPrune, + gs.ConsumerAddrsToPruneV2, ); err != nil { return err } @@ -104,38 +90,6 @@ func (gs GenesisState) Validate() error { return nil } -func (gs GenesisState) ValidateUnbondingOp(ubdOp UnbondingOp) error { - if len(ubdOp.UnbondingConsumerChains) == 0 { - return errorsmod.Wrap(ccv.ErrInvalidGenesis, "unbonding operations cannot have an empty consumer chain list") - } - - // Check that the ID is set correctly in the UnbondingOpsIndex - for _, chainID := range ubdOp.UnbondingConsumerChains { - found := false - - // Find consumer state for this consumer chain - for _, cs := range gs.ConsumerStates { - if cs.ChainId != chainID { - continue - } - for _, vscUnbondingOps := range cs.UnbondingOpsIndex { - for _, id := range vscUnbondingOps.GetUnbondingOpIds() { - if id == ubdOp.Id { - found = true - break - } - } - } - } - if !found { - return errorsmod.Wrap(ccv.ErrInvalidGenesis, - fmt.Sprintf("unbonding operation without UnbondingOpsIndex, opID=%d, chainID=%s", ubdOp.Id, chainID)) - } - } - - return nil -} - // Validate performs a consumer state validation returning an error upon any failure. // It ensures that the chain id, client id and consumer genesis states are valid and non-empty. func (cs ConsumerState) Validate() error { @@ -169,15 +123,6 @@ func (cs ConsumerState) Validate() error { } } - for _, ubdOpIdx := range cs.UnbondingOpsIndex { - if ubdOpIdx.VscId == 0 { - return fmt.Errorf("UnbondingOpsIndex vscID cannot be equal to zero") - } - if len(ubdOpIdx.UnbondingOpIds) == 0 { - return fmt.Errorf("unbonding operation index cannot be empty: %#v", ubdOpIdx) - } - } - return nil } diff --git a/x/ccv/provider/types/genesis.pb.go b/x/ccv/provider/types/genesis.pb.go index 78d2aec6fb..6d000eb8d9 100644 --- a/x/ccv/provider/types/genesis.pb.go +++ b/x/ccv/provider/types/genesis.pb.go @@ -31,10 +31,6 @@ type GenesisState struct { // empty for a new chain ConsumerStates []ConsumerState `protobuf:"bytes,2,rep,name=consumer_states,json=consumerStates,proto3" json:"consumer_states" yaml:"consumer_states"` // empty for a new chain - UnbondingOps []UnbondingOp `protobuf:"bytes,3,rep,name=unbonding_ops,json=unbondingOps,proto3" json:"unbonding_ops"` - // empty for a new chain - MatureUnbondingOps *MaturedUnbondingOps `protobuf:"bytes,4,opt,name=mature_unbonding_ops,json=matureUnbondingOps,proto3" json:"mature_unbonding_ops,omitempty"` - // empty for a new chain ValsetUpdateIdToHeight []ValsetUpdateIdToHeight `protobuf:"bytes,5,rep,name=valset_update_id_to_height,json=valsetUpdateIdToHeight,proto3" json:"valset_update_id_to_height"` // empty for a new chain ConsumerAdditionProposals []ConsumerAdditionProposal `protobuf:"bytes,6,rep,name=consumer_addition_proposals,json=consumerAdditionProposals,proto3" json:"consumer_addition_proposals"` @@ -46,10 +42,8 @@ type GenesisState struct { // empty for a new chain ValidatorsByConsumerAddr []ValidatorByConsumerAddr `protobuf:"bytes,10,rep,name=validators_by_consumer_addr,json=validatorsByConsumerAddr,proto3" json:"validators_by_consumer_addr"` // empty for a new chain - ConsumerAddrsToPrune []ConsumerAddrsToPrune `protobuf:"bytes,11,rep,name=consumer_addrs_to_prune,json=consumerAddrsToPrune,proto3" json:"consumer_addrs_to_prune"` - InitTimeoutTimestamps []InitTimeoutTimestamp `protobuf:"bytes,12,rep,name=init_timeout_timestamps,json=initTimeoutTimestamps,proto3" json:"init_timeout_timestamps"` - ExportedVscSendTimestamps []ExportedVscSendTimestamp `protobuf:"bytes,13,rep,name=exported_vsc_send_timestamps,json=exportedVscSendTimestamps,proto3" json:"exported_vsc_send_timestamps"` - LastProviderConsensusValidators []ConsensusValidator `protobuf:"bytes,14,rep,name=last_provider_consensus_validators,json=lastProviderConsensusValidators,proto3" json:"last_provider_consensus_validators"` + ConsumerAddrsToPruneV2 []ConsumerAddrsToPruneV2 `protobuf:"bytes,14,rep,name=consumer_addrs_to_prune_v2,json=consumerAddrsToPruneV2,proto3" json:"consumer_addrs_to_prune_v2"` + LastProviderConsensusValidators []ConsensusValidator `protobuf:"bytes,15,rep,name=last_provider_consensus_validators,json=lastProviderConsensusValidators,proto3" json:"last_provider_consensus_validators"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -99,20 +93,6 @@ func (m *GenesisState) GetConsumerStates() []ConsumerState { return nil } -func (m *GenesisState) GetUnbondingOps() []UnbondingOp { - if m != nil { - return m.UnbondingOps - } - return nil -} - -func (m *GenesisState) GetMatureUnbondingOps() *MaturedUnbondingOps { - if m != nil { - return m.MatureUnbondingOps - } - return nil -} - func (m *GenesisState) GetValsetUpdateIdToHeight() []ValsetUpdateIdToHeight { if m != nil { return m.ValsetUpdateIdToHeight @@ -155,23 +135,9 @@ func (m *GenesisState) GetValidatorsByConsumerAddr() []ValidatorByConsumerAddr { return nil } -func (m *GenesisState) GetConsumerAddrsToPrune() []ConsumerAddrsToPrune { +func (m *GenesisState) GetConsumerAddrsToPruneV2() []ConsumerAddrsToPruneV2 { if m != nil { - return m.ConsumerAddrsToPrune - } - return nil -} - -func (m *GenesisState) GetInitTimeoutTimestamps() []InitTimeoutTimestamp { - if m != nil { - return m.InitTimeoutTimestamps - } - return nil -} - -func (m *GenesisState) GetExportedVscSendTimestamps() []ExportedVscSendTimestamp { - if m != nil { - return m.ExportedVscSendTimestamps + return m.ConsumerAddrsToPruneV2 } return nil } @@ -201,9 +167,6 @@ type ConsumerState struct { // consumer chain PendingValsetChanges []types.ValidatorSetChangePacketData `protobuf:"bytes,6,rep,name=pending_valset_changes,json=pendingValsetChanges,proto3" json:"pending_valset_changes"` SlashDowntimeAck []string `protobuf:"bytes,7,rep,name=slash_downtime_ack,json=slashDowntimeAck,proto3" json:"slash_downtime_ack,omitempty"` - // UnbondingOpsIndex defines the unbonding operations waiting on this consumer - // chain - UnbondingOpsIndex []VscUnbondingOps `protobuf:"bytes,8,rep,name=unbonding_ops_index,json=unbondingOpsIndex,proto3" json:"unbonding_ops_index"` } func (m *ConsumerState) Reset() { *m = ConsumerState{} } @@ -288,13 +251,6 @@ func (m *ConsumerState) GetSlashDowntimeAck() []string { return nil } -func (m *ConsumerState) GetUnbondingOpsIndex() []VscUnbondingOps { - if m != nil { - return m.UnbondingOpsIndex - } - return nil -} - // ValsetUpdateIdToHeight defines the genesis information for the mapping // of each valset update id to a block height type ValsetUpdateIdToHeight struct { @@ -360,67 +316,59 @@ func init() { } var fileDescriptor_48411d9c7900d48e = []byte{ - // 951 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x5f, 0x6f, 0x1b, 0xc5, - 0x17, 0xcd, 0x26, 0x6e, 0x1a, 0x4f, 0xfe, 0xfc, 0xf2, 0x1b, 0x82, 0xbb, 0x49, 0xc0, 0x89, 0x8c, - 0x2a, 0x45, 0x02, 0xec, 0x26, 0x80, 0x28, 0x7f, 0xfa, 0xd0, 0xb4, 0x08, 0x2c, 0x84, 0xb0, 0x9c, - 0x34, 0x48, 0xe5, 0x61, 0x34, 0x9e, 0x1d, 0xd9, 0xd3, 0xac, 0x67, 0x56, 0x73, 0x67, 0x37, 0xb1, - 0x10, 0x52, 0x11, 0x3c, 0xf1, 0xc4, 0xc7, 0xea, 0x63, 0x1f, 0x79, 0xa1, 0x42, 0xc9, 0x37, 0xe0, - 0x13, 0xa0, 0x9d, 0x9d, 0xdd, 0xac, 0x53, 0xa7, 0xb2, 0x79, 0x4a, 0x3c, 0x67, 0xee, 0x39, 0xe7, - 0xce, 0x9d, 0xbd, 0x77, 0xd0, 0xbe, 0x90, 0x86, 0x6b, 0x36, 0xa0, 0x42, 0x12, 0xe0, 0x2c, 0xd6, - 0xc2, 0x8c, 0x5a, 0x8c, 0x25, 0xad, 0x48, 0xab, 0x44, 0x04, 0x5c, 0xb7, 0x92, 0xfd, 0x56, 0x9f, - 0x4b, 0x0e, 0x02, 0x9a, 0x91, 0x56, 0x46, 0xe1, 0xf7, 0x26, 0x84, 0x34, 0x19, 0x4b, 0x9a, 0x79, - 0x48, 0x33, 0xd9, 0xdf, 0xda, 0xe8, 0xab, 0xbe, 0xb2, 0xfb, 0x5b, 0xe9, 0x7f, 0x59, 0xe8, 0xd6, - 0xbd, 0x9b, 0xd4, 0x92, 0xfd, 0x16, 0x0c, 0xa8, 0xe6, 0x01, 0x61, 0x4a, 0x42, 0x3c, 0xe4, 0xda, - 0x45, 0xdc, 0x7d, 0x43, 0xc4, 0x99, 0xd0, 0xdc, 0x6d, 0x3b, 0x98, 0x26, 0x8d, 0xc2, 0x9f, 0x8d, - 0x69, 0xfc, 0xb5, 0x82, 0x56, 0xbe, 0xce, 0x32, 0x3b, 0x32, 0xd4, 0x70, 0xbc, 0x87, 0xd6, 0x13, - 0x1a, 0x02, 0x37, 0x24, 0x8e, 0x02, 0x6a, 0x38, 0x11, 0x81, 0xef, 0xed, 0x7a, 0x7b, 0x95, 0xee, - 0x5a, 0xb6, 0xfe, 0xc4, 0x2e, 0xb7, 0x03, 0xfc, 0x13, 0xfa, 0x5f, 0xee, 0x93, 0x40, 0x1a, 0x0b, - 0xfe, 0xfc, 0xee, 0xc2, 0xde, 0xf2, 0xc1, 0x41, 0x73, 0x8a, 0xc3, 0x69, 0x3e, 0x72, 0xb1, 0x56, - 0xf6, 0xb0, 0xfe, 0xe2, 0xd5, 0xce, 0xdc, 0x3f, 0xaf, 0x76, 0x6a, 0x23, 0x3a, 0x0c, 0x3f, 0x6f, - 0x5c, 0x23, 0x6e, 0x74, 0xd7, 0x58, 0x79, 0x3b, 0xe0, 0x1f, 0xd1, 0x6a, 0x2c, 0x7b, 0x4a, 0x06, - 0x42, 0xf6, 0x89, 0x8a, 0xc0, 0x5f, 0xb0, 0xd2, 0xf7, 0xa6, 0x92, 0x7e, 0x92, 0x47, 0x7e, 0x1f, - 0x1d, 0x56, 0x52, 0xe1, 0xee, 0x4a, 0x7c, 0xb5, 0x04, 0xf8, 0x19, 0xda, 0x18, 0x52, 0x13, 0x6b, - 0x4e, 0xc6, 0x35, 0x2a, 0xbb, 0xde, 0xde, 0xf2, 0xc1, 0xfd, 0xa9, 0x34, 0xbe, 0xb3, 0x04, 0x41, - 0x49, 0x0a, 0xba, 0x38, 0x63, 0x2d, 0xaf, 0xe1, 0x9f, 0xd1, 0xd6, 0xf5, 0xf3, 0x26, 0x46, 0x91, - 0x01, 0x17, 0xfd, 0x81, 0xf1, 0x6f, 0xd9, 0xac, 0xbe, 0x98, 0x4a, 0xf1, 0x64, 0xac, 0x3c, 0xc7, - 0xea, 0x1b, 0x4b, 0xe1, 0x12, 0xac, 0x25, 0x13, 0x51, 0xfc, 0xab, 0x87, 0xb6, 0x8b, 0xc3, 0xa6, - 0x41, 0x20, 0x8c, 0x50, 0x92, 0x44, 0x5a, 0x45, 0x0a, 0x68, 0x08, 0xfe, 0xa2, 0x35, 0xf0, 0x60, - 0xa6, 0x8a, 0x3e, 0x74, 0x34, 0x1d, 0xc7, 0xe2, 0x2c, 0x6c, 0xb2, 0x1b, 0x70, 0xc0, 0xcf, 0x3d, - 0xb4, 0x55, 0xb8, 0xd0, 0x7c, 0xa8, 0x12, 0x1a, 0x96, 0x4c, 0xdc, 0xb6, 0x26, 0xbe, 0x9c, 0xc9, - 0x44, 0x37, 0x63, 0xb9, 0xe6, 0xc1, 0x67, 0x93, 0x61, 0xc0, 0x6d, 0xb4, 0x18, 0x51, 0x4d, 0x87, - 0xe0, 0x2f, 0xd9, 0x2a, 0xbf, 0x3f, 0x95, 0x5a, 0xc7, 0x86, 0x38, 0x72, 0x47, 0x60, 0xb3, 0x49, - 0x68, 0x28, 0x02, 0x6a, 0x94, 0x2e, 0xbe, 0x65, 0x12, 0xc5, 0xbd, 0x53, 0x3e, 0x02, 0xbf, 0x3a, - 0x43, 0x36, 0x27, 0x39, 0x4d, 0x9e, 0x56, 0x27, 0xee, 0x7d, 0xcb, 0x47, 0x79, 0x36, 0xc9, 0x04, - 0x38, 0xd5, 0xc0, 0xbf, 0x78, 0x68, 0xbb, 0x00, 0x81, 0xf4, 0x46, 0xa4, 0x5c, 0x64, 0xed, 0xa3, - 0xff, 0xe2, 0xe1, 0x70, 0x54, 0xaa, 0xb0, 0x7e, 0xcd, 0x03, 0x8c, 0xe3, 0x38, 0x41, 0x77, 0xc6, - 0x44, 0x21, 0xbd, 0xd7, 0x91, 0x8e, 0x25, 0xf7, 0x97, 0xad, 0xfc, 0x67, 0xb3, 0xde, 0x2a, 0x0d, - 0xc7, 0xaa, 0x93, 0x12, 0x38, 0xed, 0x0d, 0x36, 0x01, 0xc3, 0x67, 0xe8, 0x8e, 0x90, 0xc2, 0x10, - 0x23, 0x86, 0x5c, 0xc5, 0xd9, 0x5f, 0x30, 0x74, 0x18, 0x81, 0xbf, 0x32, 0x83, 0x6e, 0x5b, 0x0a, - 0x73, 0x9c, 0x51, 0x1c, 0xe7, 0x0c, 0x4e, 0xf7, 0x6d, 0x31, 0x01, 0x03, 0xfc, 0x9b, 0x87, 0xde, - 0xe1, 0xe7, 0x91, 0xd2, 0x86, 0x07, 0x24, 0x01, 0x46, 0x80, 0xcb, 0xa0, 0x2c, 0xbf, 0x3a, 0xc3, - 0xc7, 0xf4, 0x95, 0x23, 0x3a, 0x01, 0x76, 0xc4, 0x65, 0x70, 0xdd, 0xc2, 0x26, 0xbf, 0x01, 0x07, - 0xfc, 0xbb, 0x87, 0x1a, 0x21, 0x05, 0x43, 0x72, 0x3a, 0x5b, 0x7b, 0x2e, 0x21, 0x06, 0x72, 0x55, - 0x2c, 0x7f, 0xcd, 0x9a, 0xf9, 0x74, 0xea, 0x1a, 0x58, 0x82, 0xab, 0xbb, 0x90, 0xd9, 0xd8, 0x49, - 0x85, 0x3a, 0x6e, 0xe7, 0xeb, 0xbb, 0xa0, 0xf1, 0xbc, 0x82, 0x56, 0xc7, 0x3a, 0x3d, 0xde, 0x44, - 0x4b, 0x99, 0x9a, 0x1b, 0x2c, 0xd5, 0xee, 0x6d, 0xfb, 0xbb, 0x1d, 0xe0, 0x77, 0x11, 0x62, 0x03, - 0x2a, 0x25, 0x0f, 0x53, 0x70, 0xde, 0x82, 0x55, 0xb7, 0xd2, 0x0e, 0xf0, 0x36, 0xaa, 0xb2, 0x50, - 0x70, 0x69, 0x52, 0x74, 0xc1, 0xa2, 0x4b, 0xd9, 0x42, 0x3b, 0xc0, 0x77, 0xd1, 0x5a, 0x5a, 0x15, - 0x41, 0xc3, 0xbc, 0x77, 0x56, 0xec, 0xd4, 0x5a, 0x75, 0xab, 0xae, 0xdf, 0x51, 0xb4, 0x5e, 0x5c, - 0x4a, 0x37, 0xd1, 0xfd, 0x5b, 0xf6, 0x83, 0xbf, 0x79, 0x74, 0x94, 0x2e, 0x61, 0x79, 0x54, 0xba, - 0x23, 0x28, 0x86, 0xa0, 0xc3, 0xb0, 0x41, 0xb5, 0x88, 0x67, 0x43, 0xc3, 0x75, 0xf6, 0x34, 0x85, - 0x3e, 0xcf, 0x9b, 0xe9, 0xfd, 0x37, 0x09, 0x15, 0x47, 0x77, 0xc4, 0xcd, 0x23, 0x1b, 0xd6, 0xa1, - 0xec, 0x94, 0x9b, 0xc7, 0xd4, 0xd0, 0xfc, 0xd6, 0x3b, 0xf6, 0xac, 0xdf, 0x67, 0x9b, 0x00, 0x7f, - 0x80, 0x30, 0x84, 0x14, 0x06, 0x24, 0x50, 0x67, 0x32, 0xbd, 0x73, 0x84, 0xb2, 0x53, 0xdb, 0x39, - 0xab, 0xdd, 0x75, 0x8b, 0x3c, 0x76, 0xc0, 0x43, 0x76, 0x8a, 0x9f, 0xa1, 0xb7, 0xc6, 0x46, 0x1b, - 0x11, 0x32, 0xe0, 0xe7, 0xfe, 0x92, 0x35, 0xf8, 0xf1, 0x74, 0x6d, 0x01, 0x58, 0x79, 0x90, 0x39, - 0x73, 0xff, 0x2f, 0x0f, 0xd2, 0x76, 0x4a, 0xda, 0x78, 0x8a, 0x6a, 0x93, 0x47, 0xd3, 0x0c, 0x6f, - 0x8d, 0x1a, 0x5a, 0x74, 0x55, 0x9d, 0xb7, 0xb8, 0xfb, 0x75, 0xf8, 0xc3, 0x8b, 0x8b, 0xba, 0xf7, - 0xf2, 0xa2, 0xee, 0xfd, 0x7d, 0x51, 0xf7, 0xfe, 0xb8, 0xac, 0xcf, 0xbd, 0xbc, 0xac, 0xcf, 0xfd, - 0x79, 0x59, 0x9f, 0x7b, 0xfa, 0xa0, 0x2f, 0xcc, 0x20, 0xee, 0x35, 0x99, 0x1a, 0xb6, 0x98, 0x82, - 0xa1, 0x82, 0xd6, 0x55, 0x56, 0x1f, 0x16, 0xcf, 0xa3, 0xe4, 0x93, 0xd6, 0xf9, 0xf8, 0x1b, 0xc9, - 0x8c, 0x22, 0x0e, 0xbd, 0x45, 0xfb, 0x3c, 0xfa, 0xe8, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x54, - 0xf5, 0x38, 0x0c, 0x1b, 0x0a, 0x00, 0x00, + // 823 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0x41, 0x8f, 0xdb, 0x44, + 0x14, 0x8e, 0x37, 0xde, 0xd4, 0x99, 0xdd, 0xa4, 0xd6, 0xa8, 0x8a, 0xdc, 0xac, 0xc8, 0xae, 0x82, + 0x2a, 0x45, 0x02, 0xe2, 0x26, 0x08, 0x81, 0x80, 0x1e, 0x9a, 0x56, 0x82, 0x84, 0x4b, 0x94, 0x96, + 0x45, 0xea, 0x65, 0x34, 0x19, 0x8f, 0x92, 0x51, 0x1c, 0x8f, 0xe5, 0x19, 0xbb, 0x44, 0x08, 0x09, + 0xc4, 0x8d, 0x13, 0x67, 0xfe, 0x09, 0xff, 0xa0, 0xc7, 0x1e, 0x39, 0xad, 0xd0, 0xee, 0x3f, 0xe0, + 0x17, 0x20, 0x8f, 0xc7, 0xde, 0x64, 0x37, 0xbb, 0x4a, 0xb8, 0x25, 0xf3, 0xbd, 0xf7, 0xbd, 0xef, + 0xbd, 0x19, 0x7f, 0x0f, 0xf4, 0x58, 0x20, 0x69, 0x44, 0xe6, 0x98, 0x05, 0x48, 0x50, 0x12, 0x47, + 0x4c, 0xae, 0x5c, 0x42, 0x12, 0x37, 0x8c, 0x78, 0xc2, 0x3c, 0x1a, 0xb9, 0x49, 0xcf, 0x9d, 0xd1, + 0x80, 0x0a, 0x26, 0xba, 0x61, 0xc4, 0x25, 0x87, 0x1f, 0x6e, 0x49, 0xe9, 0x12, 0x92, 0x74, 0xf3, + 0x94, 0x6e, 0xd2, 0x6b, 0x3e, 0x9a, 0xf1, 0x19, 0x57, 0xf1, 0x6e, 0xfa, 0x2b, 0x4b, 0x6d, 0x3e, + 0xbd, 0xab, 0x5a, 0xd2, 0x73, 0xc5, 0x1c, 0x47, 0xd4, 0x43, 0x84, 0x07, 0x22, 0x5e, 0xd2, 0x48, + 0x67, 0x3c, 0xb9, 0x27, 0xe3, 0x2d, 0x8b, 0xa8, 0x0e, 0xeb, 0xef, 0xd2, 0x46, 0xa1, 0x4f, 0xe5, + 0xb4, 0xff, 0xaa, 0x82, 0xe3, 0x6f, 0xb2, 0xce, 0x5e, 0x49, 0x2c, 0x29, 0xec, 0x00, 0x3b, 0xc1, + 0xbe, 0xa0, 0x12, 0xc5, 0xa1, 0x87, 0x25, 0x45, 0xcc, 0x73, 0x8c, 0x33, 0xa3, 0x63, 0x4e, 0xea, + 0xd9, 0xf9, 0xf7, 0xea, 0x78, 0xe8, 0xc1, 0x9f, 0xc0, 0xc3, 0x5c, 0x27, 0x12, 0x69, 0xae, 0x70, + 0x0e, 0xce, 0xca, 0x9d, 0xa3, 0x7e, 0xbf, 0xbb, 0xc3, 0x70, 0xba, 0x2f, 0x74, 0xae, 0x2a, 0x3b, + 0x68, 0xbd, 0xbb, 0x38, 0x2d, 0xfd, 0x7b, 0x71, 0xda, 0x58, 0xe1, 0xa5, 0xff, 0x65, 0xfb, 0x06, + 0x71, 0x7b, 0x52, 0x27, 0xeb, 0xe1, 0x02, 0xfe, 0x0c, 0x9a, 0x37, 0x65, 0x22, 0xc9, 0xd1, 0x9c, + 0xb2, 0xd9, 0x5c, 0x3a, 0x87, 0x4a, 0xc7, 0x57, 0x3b, 0xe9, 0x38, 0xdf, 0xe8, 0xea, 0x35, 0xff, + 0x56, 0x51, 0x0c, 0xcc, 0x54, 0xd0, 0xa4, 0x91, 0x6c, 0x45, 0xe1, 0x6f, 0x06, 0x38, 0x29, 0x34, + 0x62, 0xcf, 0x63, 0x92, 0xf1, 0x00, 0x85, 0x11, 0x0f, 0xb9, 0xc0, 0xbe, 0x70, 0x2a, 0x4a, 0xc0, + 0xb3, 0xbd, 0x06, 0xf1, 0x5c, 0xd3, 0x8c, 0x35, 0x8b, 0x96, 0xf0, 0x98, 0xdc, 0x81, 0x0b, 0xf8, + 0x8b, 0x01, 0x9a, 0x85, 0x8a, 0x88, 0x2e, 0x79, 0x82, 0xfd, 0x35, 0x11, 0x0f, 0x94, 0x88, 0xaf, + 0xf7, 0x12, 0x31, 0xc9, 0x58, 0x6e, 0x68, 0x70, 0xc8, 0x76, 0x58, 0xc0, 0x21, 0xa8, 0x84, 0x38, + 0xc2, 0x4b, 0xe1, 0x58, 0x67, 0x46, 0xe7, 0xa8, 0xff, 0xd1, 0x4e, 0xd5, 0xc6, 0x2a, 0x45, 0x93, + 0x6b, 0x02, 0xd5, 0x4d, 0x82, 0x7d, 0xe6, 0x61, 0xc9, 0xa3, 0xe2, 0x13, 0x40, 0x61, 0x3c, 0x5d, + 0xd0, 0x95, 0x70, 0xaa, 0x7b, 0x74, 0x73, 0x9e, 0xd3, 0xe4, 0x6d, 0x8d, 0xe3, 0xe9, 0x77, 0x74, + 0x95, 0x77, 0x93, 0x6c, 0x81, 0xd3, 0x1a, 0xf0, 0x57, 0x03, 0x9c, 0x14, 0xa0, 0x40, 0xd3, 0x15, + 0x5a, 0xbf, 0xe4, 0xc8, 0x01, 0xff, 0x47, 0xc3, 0x60, 0xb5, 0x76, 0xc3, 0xd1, 0x2d, 0x0d, 0x62, + 0x13, 0x4f, 0x5f, 0xf6, 0x46, 0x51, 0x91, 0xbe, 0xeb, 0x30, 0x8a, 0x03, 0x8a, 0x92, 0xbe, 0x53, + 0xdf, 0xe3, 0x65, 0xaf, 0xd3, 0x8a, 0xd7, 0x7c, 0x9c, 0x72, 0x9c, 0xf7, 0xf3, 0x97, 0x4d, 0xb6, + 0xa2, 0xf0, 0x77, 0x03, 0xb4, 0x7d, 0x2c, 0x24, 0xca, 0x99, 0xd4, 0x08, 0x68, 0x20, 0x62, 0x81, + 0xae, 0x35, 0x3b, 0x0f, 0x95, 0x8e, 0xcf, 0x77, 0xd6, 0xa1, 0x08, 0xae, 0x47, 0x92, 0x69, 0x38, + 0x4d, 0x0b, 0x8d, 0x75, 0xe4, 0xed, 0x28, 0x31, 0x32, 0xad, 0xb2, 0x6d, 0x8e, 0x4c, 0xcb, 0xb4, + 0x0f, 0x47, 0xa6, 0x75, 0x64, 0x1f, 0x8f, 0x4c, 0xeb, 0xd8, 0xae, 0x8d, 0x4c, 0xab, 0x66, 0xd7, + 0xdb, 0x7f, 0x96, 0x41, 0x6d, 0xc3, 0x45, 0xe0, 0x63, 0x60, 0x65, 0x5a, 0xb4, 0x69, 0x55, 0x27, + 0x0f, 0xd4, 0xff, 0xa1, 0x07, 0x3f, 0x00, 0x80, 0xcc, 0x71, 0x10, 0x50, 0x3f, 0x05, 0x0f, 0x14, + 0x58, 0xd5, 0x27, 0x43, 0x0f, 0x9e, 0x80, 0x2a, 0xf1, 0x19, 0x0d, 0x64, 0x8a, 0x96, 0x15, 0x6a, + 0x65, 0x07, 0x43, 0x0f, 0x3e, 0x01, 0x75, 0x16, 0x30, 0xc9, 0xb0, 0x9f, 0x1b, 0x8c, 0xa9, 0x1c, + 0xb1, 0xa6, 0x4f, 0xb5, 0x29, 0x60, 0x60, 0x17, 0x37, 0xa7, 0xb7, 0x85, 0x73, 0xa8, 0xbe, 0x8a, + 0xa7, 0x77, 0xce, 0x69, 0xed, 0x9a, 0xd6, 0x6d, 0x58, 0x0f, 0xa8, 0x30, 0x58, 0x8d, 0x41, 0x09, + 0x1a, 0x21, 0x0d, 0x3c, 0x16, 0xcc, 0x90, 0xb6, 0xbf, 0xb4, 0x85, 0x19, 0xcd, 0x1d, 0xe7, 0x8b, + 0xfb, 0x0a, 0x15, 0x83, 0x7d, 0x45, 0xe5, 0x0b, 0x95, 0x36, 0xc6, 0x64, 0x41, 0xe5, 0x4b, 0x2c, + 0xb1, 0x2e, 0xf8, 0x48, 0xb3, 0x67, 0xa6, 0x98, 0x05, 0x09, 0xf8, 0x31, 0x80, 0xc2, 0xc7, 0x62, + 0x8e, 0x3c, 0xfe, 0x36, 0x90, 0x6c, 0x49, 0x11, 0x26, 0x0b, 0x65, 0x2f, 0xd5, 0x89, 0xad, 0x90, + 0x97, 0x1a, 0x78, 0x4e, 0x16, 0x23, 0xd3, 0xb2, 0xec, 0x6a, 0xfb, 0x0d, 0x68, 0x6c, 0x77, 0xd6, + 0x3d, 0x36, 0x4c, 0x03, 0x54, 0xf4, 0xbc, 0x0f, 0x14, 0xae, 0xff, 0x0d, 0x7e, 0x78, 0x77, 0xd9, + 0x32, 0xde, 0x5f, 0xb6, 0x8c, 0x7f, 0x2e, 0x5b, 0xc6, 0x1f, 0x57, 0xad, 0xd2, 0xfb, 0xab, 0x56, + 0xe9, 0xef, 0xab, 0x56, 0xe9, 0xcd, 0xb3, 0x19, 0x93, 0xf3, 0x78, 0xda, 0x25, 0x7c, 0xe9, 0x12, + 0x2e, 0x96, 0x5c, 0xb8, 0xd7, 0x03, 0xf9, 0xa4, 0x58, 0x8a, 0xc9, 0x67, 0xee, 0x8f, 0x9b, 0x9b, + 0x51, 0xae, 0x42, 0x2a, 0xa6, 0x15, 0xb5, 0x14, 0x3f, 0xfd, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x90, + 0x3e, 0xd5, 0xfb, 0x11, 0x08, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -454,27 +402,13 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenesis(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x72 - } - } - if len(m.ExportedVscSendTimestamps) > 0 { - for iNdEx := len(m.ExportedVscSendTimestamps) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ExportedVscSendTimestamps[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x6a + dAtA[i] = 0x7a } } - if len(m.InitTimeoutTimestamps) > 0 { - for iNdEx := len(m.InitTimeoutTimestamps) - 1; iNdEx >= 0; iNdEx-- { + if len(m.ConsumerAddrsToPruneV2) > 0 { + for iNdEx := len(m.ConsumerAddrsToPruneV2) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.InitTimeoutTimestamps[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.ConsumerAddrsToPruneV2[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -482,21 +416,7 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenesis(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x62 - } - } - if len(m.ConsumerAddrsToPrune) > 0 { - for iNdEx := len(m.ConsumerAddrsToPrune) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ConsumerAddrsToPrune[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x5a + dAtA[i] = 0x72 } } if len(m.ValidatorsByConsumerAddr) > 0 { @@ -579,32 +499,6 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x2a } } - if m.MatureUnbondingOps != nil { - { - size, err := m.MatureUnbondingOps.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - if len(m.UnbondingOps) > 0 { - for iNdEx := len(m.UnbondingOps) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.UnbondingOps[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - } if len(m.ConsumerStates) > 0 { for iNdEx := len(m.ConsumerStates) - 1; iNdEx >= 0; iNdEx-- { { @@ -647,20 +541,6 @@ func (m *ConsumerState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.UnbondingOpsIndex) > 0 { - for iNdEx := len(m.UnbondingOpsIndex) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.UnbondingOpsIndex[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x42 - } - } if len(m.SlashDowntimeAck) > 0 { for iNdEx := len(m.SlashDowntimeAck) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.SlashDowntimeAck[iNdEx]) @@ -782,16 +662,6 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } - if len(m.UnbondingOps) > 0 { - for _, e := range m.UnbondingOps { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if m.MatureUnbondingOps != nil { - l = m.MatureUnbondingOps.Size() - n += 1 + l + sovGenesis(uint64(l)) - } if len(m.ValsetUpdateIdToHeight) > 0 { for _, e := range m.ValsetUpdateIdToHeight { l = e.Size() @@ -824,20 +694,8 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } - if len(m.ConsumerAddrsToPrune) > 0 { - for _, e := range m.ConsumerAddrsToPrune { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.InitTimeoutTimestamps) > 0 { - for _, e := range m.InitTimeoutTimestamps { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.ExportedVscSendTimestamps) > 0 { - for _, e := range m.ExportedVscSendTimestamps { + if len(m.ConsumerAddrsToPruneV2) > 0 { + for _, e := range m.ConsumerAddrsToPruneV2 { l = e.Size() n += 1 + l + sovGenesis(uint64(l)) } @@ -886,12 +744,6 @@ func (m *ConsumerState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } - if len(m.UnbondingOpsIndex) > 0 { - for _, e := range m.UnbondingOpsIndex { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } return n } @@ -998,76 +850,6 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UnbondingOps", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.UnbondingOps = append(m.UnbondingOps, UnbondingOp{}) - if err := m.UnbondingOps[len(m.UnbondingOps)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MatureUnbondingOps", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.MatureUnbondingOps == nil { - m.MatureUnbondingOps = &MaturedUnbondingOps{} - } - if err := m.MatureUnbondingOps.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ValsetUpdateIdToHeight", wireType) @@ -1271,77 +1053,9 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 11: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsumerAddrsToPrune", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ConsumerAddrsToPrune = append(m.ConsumerAddrsToPrune, ConsumerAddrsToPrune{}) - if err := m.ConsumerAddrsToPrune[len(m.ConsumerAddrsToPrune)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 12: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field InitTimeoutTimestamps", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.InitTimeoutTimestamps = append(m.InitTimeoutTimestamps, InitTimeoutTimestamp{}) - if err := m.InitTimeoutTimestamps[len(m.InitTimeoutTimestamps)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 13: + case 14: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ExportedVscSendTimestamps", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ConsumerAddrsToPruneV2", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1368,12 +1082,12 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ExportedVscSendTimestamps = append(m.ExportedVscSendTimestamps, ExportedVscSendTimestamp{}) - if err := m.ExportedVscSendTimestamps[len(m.ExportedVscSendTimestamps)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.ConsumerAddrsToPruneV2 = append(m.ConsumerAddrsToPruneV2, ConsumerAddrsToPruneV2{}) + if err := m.ConsumerAddrsToPruneV2[len(m.ConsumerAddrsToPruneV2)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 14: + case 15: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field LastProviderConsensusValidators", wireType) } @@ -1671,40 +1385,6 @@ func (m *ConsumerState) Unmarshal(dAtA []byte) error { } m.SlashDowntimeAck = append(m.SlashDowntimeAck, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UnbondingOpsIndex", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.UnbondingOpsIndex = append(m.UnbondingOpsIndex, VscUnbondingOps{}) - if err := m.UnbondingOpsIndex[len(m.UnbondingOpsIndex)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/ccv/provider/types/genesis_test.go b/x/ccv/provider/types/genesis_test.go index e949f87b91..86e4dbe2e5 100644 --- a/x/ccv/provider/types/genesis_test.go +++ b/x/ccv/provider/types/genesis_test.go @@ -35,15 +35,11 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id", ConsumerGenesis: getInitialConsumerGenesis(t, "chainid-1")}}, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), true, }, @@ -60,15 +56,11 @@ func TestValidateGenesisState(t *testing.T) { }, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), true, }, @@ -80,13 +72,9 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id", ConsumerGenesis: getInitialConsumerGenesis(t, "chainid-1")}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, 30*time.Minute, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), - nil, - nil, + types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), nil, nil, nil, @@ -102,13 +90,9 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, 30*time.Minute, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), - nil, - nil, + types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), nil, nil, nil, @@ -124,13 +108,9 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, 30*time.Minute, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), - nil, - nil, + types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), nil, nil, nil, @@ -144,15 +124,11 @@ func TestValidateGenesisState(t *testing.T) { types.DefaultValsetUpdateID, nil, nil, - []types.UnbondingOp{{UnbondingConsumerChains: nil}}, - nil, nil, nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, 30*time.Minute, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), - nil, - nil, + types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), nil, nil, nil, @@ -168,14 +144,10 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id"}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, 0, clienttypes.Height{}, nil, []string{"ibc", "upgradedIBCState"}), types.DefaultTrustingPeriodFraction, ccv.DefaultCCVTimeoutPeriod, - types.DefaultInitTimeoutPeriod, - types.DefaultVscTimeoutPeriod, types.DefaultSlashMeterReplenishPeriod, types.DefaultSlashMeterReplenishFraction, sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), @@ -183,8 +155,6 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, nil, - nil, - nil, ), false, }, @@ -196,14 +166,10 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id"}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), "0.0", // 0 trusting period fraction here ccv.DefaultCCVTimeoutPeriod, - types.DefaultInitTimeoutPeriod, - types.DefaultVscTimeoutPeriod, types.DefaultSlashMeterReplenishPeriod, types.DefaultSlashMeterReplenishFraction, sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), @@ -211,8 +177,6 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, nil, - nil, - nil, ), false, }, @@ -224,14 +188,10 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id"}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), types.DefaultTrustingPeriodFraction, 0, // 0 ccv timeout here - types.DefaultInitTimeoutPeriod, - types.DefaultVscTimeoutPeriod, types.DefaultSlashMeterReplenishPeriod, types.DefaultSlashMeterReplenishFraction, sdk.Coin{Denom: "stake", Amount: math.NewInt(1000000)}, 600, 24, 180), @@ -239,8 +199,6 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, nil, - nil, - nil, ), false, }, @@ -252,14 +210,10 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id"}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), types.DefaultTrustingPeriodFraction, ccv.DefaultCCVTimeoutPeriod, - 0, // 0 init timeout here - types.DefaultVscTimeoutPeriod, types.DefaultSlashMeterReplenishPeriod, types.DefaultSlashMeterReplenishFraction, sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), @@ -267,8 +221,6 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, nil, - nil, - nil, ), false, }, @@ -280,14 +232,10 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id"}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), types.DefaultTrustingPeriodFraction, ccv.DefaultCCVTimeoutPeriod, - types.DefaultInitTimeoutPeriod, - 0, // 0 vsc timeout here types.DefaultSlashMeterReplenishPeriod, types.DefaultSlashMeterReplenishFraction, sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), @@ -295,8 +243,6 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, nil, - nil, - nil, ), false, }, @@ -308,14 +254,10 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id"}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), types.DefaultTrustingPeriodFraction, ccv.DefaultCCVTimeoutPeriod, - types.DefaultInitTimeoutPeriod, - types.DefaultVscTimeoutPeriod, 0, // 0 slash meter replenish period here types.DefaultSlashMeterReplenishFraction, sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), @@ -323,8 +265,6 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, nil, - nil, - nil, ), false, }, @@ -336,14 +276,10 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id"}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), types.DefaultTrustingPeriodFraction, ccv.DefaultCCVTimeoutPeriod, - types.DefaultInitTimeoutPeriod, - types.DefaultVscTimeoutPeriod, types.DefaultSlashMeterReplenishPeriod, "1.15", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 600, 24, 180), @@ -351,8 +287,6 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, nil, - nil, - nil, ), false, }, @@ -364,15 +298,11 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "", ChannelId: "channelid", ClientId: "client-id"}}, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), false, }, @@ -384,15 +314,11 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid", ChannelId: "ivnalidChannel{}", ClientId: "client-id"}}, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), false, }, @@ -404,15 +330,11 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid", ChannelId: "channel-0", ClientId: ""}}, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), false, }, @@ -424,15 +346,11 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid", ChannelId: "channel-0", ClientId: "abc", ConsumerGenesis: getInitialConsumerGenesis(t, "chainid")}}, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), false, }, @@ -447,15 +365,11 @@ func TestValidateGenesisState(t *testing.T) { }}, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), false, }, @@ -471,15 +385,11 @@ func TestValidateGenesisState(t *testing.T) { }}, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), false, }, @@ -495,15 +405,11 @@ func TestValidateGenesisState(t *testing.T) { }}, nil, nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), false, }, @@ -523,180 +429,11 @@ func TestValidateGenesisState(t *testing.T) { }}, nil, nil, - nil, - nil, - types.DefaultParams(), - nil, - nil, - nil, - nil, - nil, - nil, - ), - false, - }, - { - "invalid consumer state UnbondingOpsIndex - zero vscID", - types.NewGenesisState( - types.DefaultValsetUpdateID, - nil, - []types.ConsumerState{ - { - ChainId: "chainid", - ChannelId: "channel-0", - ClientId: "client-id", - ConsumerGenesis: getInitialConsumerGenesis(t, "chainid"), - UnbondingOpsIndex: []types.VscUnbondingOps{{}}, - }, - }, - nil, - nil, - nil, - nil, - types.DefaultParams(), - nil, - nil, - nil, - nil, - nil, - nil, - ), - false, - }, - { - "invalid consumer state UnbondingOpsIndex - no IDs", - types.NewGenesisState( - types.DefaultValsetUpdateID, - nil, - []types.ConsumerState{ - { - ChainId: "chainid", - ChannelId: "channel-0", - ClientId: "client-id", - ConsumerGenesis: getInitialConsumerGenesis(t, "chainid"), - UnbondingOpsIndex: []types.VscUnbondingOps{{VscId: 1}}, - }, - }, - nil, - nil, - nil, - nil, - types.DefaultParams(), - nil, - nil, - nil, - nil, - nil, - nil, - ), - false, - }, - { - "invalid consumer state UnbondingOp - no matching UnbondingOpsIndex", - types.NewGenesisState( - types.DefaultValsetUpdateID, - nil, - []types.ConsumerState{ - { - ChainId: "chainid", - ChannelId: "channel-0", - ClientId: "client-id", - ConsumerGenesis: getInitialConsumerGenesis(t, "chainid"), - UnbondingOpsIndex: []types.VscUnbondingOps{ - { - VscId: 1, - }, - }, - }, - }, - []types.UnbondingOp{ - { - Id: 13, - UnbondingConsumerChains: []string{"chainid"}, - }, - }, - nil, - nil, - nil, - types.DefaultParams(), - nil, - nil, - nil, - nil, - nil, - nil, - ), - false, - }, - { - "invalid consumer state UnbondingOp - no matching UnbondingOpsIndex 2", - types.NewGenesisState( - types.DefaultValsetUpdateID, - nil, - []types.ConsumerState{ - { - ChainId: "chainid", - ChannelId: "channel-0", - ClientId: "client-id", - ConsumerGenesis: getInitialConsumerGenesis(t, "chainid"), - UnbondingOpsIndex: []types.VscUnbondingOps{ - { - VscId: 1, - UnbondingOpIds: []uint64{13}, - }, - }, - }, - { - ChainId: "chainid-2", - ChannelId: "channel-0", - ClientId: "client-id", - ConsumerGenesis: getInitialConsumerGenesis(t, "chainid-2"), - UnbondingOpsIndex: []types.VscUnbondingOps{ - { - VscId: 1, - }, - }, - }, - }, - []types.UnbondingOp{ - { - Id: 13, - UnbondingConsumerChains: []string{"chainid", "chainid-2"}, - }, - }, - nil, - nil, - nil, - types.DefaultParams(), - nil, - nil, - nil, - nil, - nil, - nil, - ), - false, - }, - { - "invalid consumer state unbonding operation operation 2", - types.NewGenesisState( - types.DefaultValsetUpdateID, - nil, - []types.ConsumerState{{ - ChainId: "chainid", ChannelId: "channel-0", ClientId: "client-id", - UnbondingOpsIndex: []types.VscUnbondingOps{{VscId: 1}}, - }}, - nil, - nil, - nil, - nil, types.DefaultParams(), nil, nil, nil, nil, - nil, - nil, ), false, }, @@ -708,13 +445,9 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id", ConsumerGenesis: getInitialConsumerGenesis(t, "chainid-1")}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, 30*time.Minute, time.Hour, "0.1", sdk.Coin{Denom: "st", Amount: math.NewInt(10000000)}, 600, 24, 180), - nil, - nil, + types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "st", Amount: math.NewInt(10000000)}, 600, 24, 180), nil, nil, nil, @@ -730,13 +463,9 @@ func TestValidateGenesisState(t *testing.T) { []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid", ClientId: "client-id", ConsumerGenesis: getInitialConsumerGenesis(t, "chainid-1")}}, nil, nil, - nil, - nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, 30*time.Minute, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(-1000000)}, 600, 24, 180), - nil, - nil, + types.DefaultTrustingPeriodFraction, time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(-1000000)}, 600, 24, 180), nil, nil, nil, diff --git a/x/ccv/provider/types/key_assignment.go b/x/ccv/provider/types/key_assignment.go index ee403e1e49..7149ebc6cc 100644 --- a/x/ccv/provider/types/key_assignment.go +++ b/x/ccv/provider/types/key_assignment.go @@ -67,7 +67,7 @@ func (c *ConsumerConsAddress) String() string { func KeyAssignmentValidateBasic( assignedKeys []ValidatorConsumerPubKey, byConsumerAddrs []ValidatorByConsumerAddr, - consumerAddrsToPrune []ConsumerAddrsToPrune, + consumerAddrsToPrune []ConsumerAddrsToPruneV2, ) error { for _, e := range assignedKeys { if strings.TrimSpace(e.ChainId) == "" { @@ -95,7 +95,6 @@ func KeyAssignmentValidateBasic( if strings.TrimSpace(e.ChainId) == "" { return errorsmod.Wrap(ccvtypes.ErrInvalidGenesis, "consumer chain id must not be blank") } - // Don't check e.vscid, it's an unsigned integer for _, a := range e.ConsumerAddrs.Addresses { if err := sdk.VerifyAddressFormat(a); err != nil { return errorsmod.Wrap(ccvtypes.ErrInvalidGenesis, fmt.Sprintf("invalid consumer address: %s", a)) diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index 9be7fabf7a..54821e8427 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -41,7 +41,7 @@ const ( PortKeyName = "PortKey" - MaturedUnbondingOpsKeyName = "MaturedUnbondingOpsKey" + DeprecatedMaturedUnbondingOpsKeyName = "DeprecatedMaturedUnbondingOpsKey" ValidatorSetUpdateIdKeyName = "ValidatorSetUpdateIdKey" @@ -55,15 +55,15 @@ const ( ChainToClientKeyName = "ChainToClientKey" - InitTimeoutTimestampKeyName = "InitTimeoutTimestampKey" + DeprecatedInitTimeoutTimestampKeyName = "DeprecatedInitTimeoutTimestampKey" PendingCAPKeyName = "PendingCAPKey" PendingCRPKeyName = "PendingCRPKey" - UnbondingOpKeyName = "UnbondingOpKey" + DeprecatedUnbondingOpKeyName = "DeprecatedUnbondingOpKey" - UnbondingOpIndexKeyName = "UnbondingOpIndexKey" + DeprecatedUnbondingOpIndexKeyName = "DeprecatedUnbondingOpIndexKey" ValsetUpdateBlockHeightKeyName = "ValsetUpdateBlockHeightKey" @@ -75,7 +75,7 @@ const ( PendingVSCsKeyName = "PendingVSCsKey" - VscSendTimestampKeyName = "VscSendTimestampKey" + DeprecatedVscSendTimestampKeyName = "DeprecatedVscSendTimestampKey" ThrottledPacketDataSizeKeyName = "ThrottledPacketDataSizeKey" @@ -87,15 +87,15 @@ const ( ValidatorsByConsumerAddrKeyName = "ValidatorsByConsumerAddrKey" - KeyAssignmentReplacementsKeyName = "DeprecatedKeyAssignmentReplacementsKey" + DeprecatedKeyAssignmentReplacementsKeyName = "DeprecatedKeyAssignmentReplacementsKey" - ConsumerAddrsToPruneKeyName = "ConsumerAddrsToPruneKey" + DeprecatedConsumerAddrsToPruneKeyName = "DeprecatedConsumerAddrsToPruneKey" SlashLogKeyName = "SlashLogKey" ConsumerRewardDenomsKeyName = "ConsumerRewardDenomsKey" - VSCMaturedHandledThisBlockKeyName = "VSCMaturedHandledThisBlockKey" + DeprecatedVSCMaturedHandledThisBlockKeyName = "DeprecatedVSCMaturedHandledThisBlockKey" EquivocationEvidenceMinHeightKeyName = "EquivocationEvidenceMinHeightKey" @@ -126,6 +126,8 @@ const ( MinStakeKeyName = "MinStakeKey" AllowInactiveValidatorsKeyName = "AllowInactiveValidatorsKey" + + ConsumerAddrsToPruneV2KeyName = "ConsumerAddrsToPruneV2Key" ) // getKeyPrefixes returns a constant map of all the byte prefixes for existing keys @@ -142,7 +144,9 @@ func getKeyPrefixes() map[string]byte { // MaturedUnbondingOpsKey is the key that stores the list of all unbonding operations ids // that have matured from a consumer chain perspective, // i.e., no longer waiting on the unbonding period to elapse on any consumer chain - MaturedUnbondingOpsKeyName: 1, + // NOTE: This prefix is deprecated, but left in place to avoid state migrations + // [DEPRECATED] + DeprecatedMaturedUnbondingOpsKeyName: 1, // ValidatorSetUpdateIdKey is the key that stores the current validator set update id ValidatorSetUpdateIdKeyName: 2, @@ -166,7 +170,9 @@ func getKeyPrefixes() map[string]byte { // InitTimeoutTimestampKey is the key for storing // the init timeout timestamp for a given consumer chainID. - InitTimeoutTimestampKeyName: 8, + // NOTE: This prefix is deprecated, but left in place to avoid state migrations + // [DEPRECATED] + DeprecatedInitTimeoutTimestampKeyName: 8, // PendingCAPKey is the key for storing pending consumer addition proposals before the spawn time occurs. // The key includes the BigEndian timestamp to allow for efficient chronological iteration @@ -178,11 +184,15 @@ func getKeyPrefixes() map[string]byte { // UnbondingOpKey is the key that stores a record of all the ids of consumer chains that // need to unbond before a given unbonding operation can unbond on this chain. - UnbondingOpKeyName: 11, + // NOTE: This prefix is deprecated, but left in place to avoid state migrations + // [DEPRECATED] + DeprecatedUnbondingOpKeyName: 11, // UnbondingOpIndexKey is key of the index for looking up which unbonding // operations are waiting for a given consumer chain to unbond - UnbondingOpIndexKeyName: 12, + // NOTE: This prefix is deprecated, but left in place to avoid state migrations + // [DEPRECATED] + DeprecatedUnbondingOpIndexKeyName: 12, // ValsetUpdateBlockHeightKey is the key for storing the mapping from vscIDs to block heights ValsetUpdateBlockHeightKeyName: 13, @@ -202,7 +212,9 @@ func getKeyPrefixes() map[string]byte { // VscSendTimestampKey is the key for storing // the list of VSC sending timestamps for a given consumer chainID. - VscSendTimestampKeyName: 18, + // NOTE: This prefix is deprecated, but left in place to avoid state migrations + // [DEPRECATED] + DeprecatedVscSendTimestampKeyName: 18, // ThrottledPacketDataSizeKey is the key for storing the size of chain-specific throttled packet data queues ThrottledPacketDataSizeKeyName: 19, @@ -223,11 +235,13 @@ func getKeyPrefixes() map[string]byte { // DeprecatedKeyAssignmentReplacementsKey was the key used to store the key assignments that needed to be replaced in the current block // NOTE: This prefix is deprecated, but left in place to avoid consumer state migrations // [DEPRECATED] - KeyAssignmentReplacementsKeyName: 24, + DeprecatedKeyAssignmentReplacementsKeyName: 24, // ConsumerAddrsToPruneKey is the key for storing the mapping from VSC ids // to consumer validators addresses needed for pruning - ConsumerAddrsToPruneKeyName: 25, + // NOTE: This prefix is deprecated, but left in place to avoid consumer state migrations + // [DEPRECATED] + DeprecatedConsumerAddrsToPruneKeyName: 25, // SlashLogKey is the key for storing the mapping from provider address to boolean // denoting whether the provider address has committed any double signign infractions @@ -238,7 +252,9 @@ func getKeyPrefixes() map[string]byte { // VSCMaturedHandledThisBlockKey is the key for storing the number of vsc matured packets // handled in the current block - VSCMaturedHandledThisBlockKeyName: 28, + // NOTE: This prefix is deprecated, but left in place to avoid state migrations + // [DEPRECATED] + DeprecatedVSCMaturedHandledThisBlockKeyName: 28, // EquivocationEvidenceMinHeightKey is the key for storing the mapping from consumer chain IDs // to the minimum height of a valid consumer equivocation evidence @@ -287,16 +303,20 @@ func getKeyPrefixes() map[string]byte { // minimum power required to be in the top N per consumer chain. MinimumPowerInTopNKeyName: 40, + // ConsumerAddrsToPruneV2Key is the key for storing + // consumer validators addresses that need to be pruned. + ConsumerAddrsToPruneV2KeyName: 41, + // LastProviderConsensusValsPrefix is the byte prefix for storing the last validator set // sent to the consensus engine of the provider chain - LastProviderConsensusValsKeyName: 41, + LastProviderConsensusValsKeyName: 42, // MinStakeKey is the byte prefix for storing the mapping from consumer chains to the minimum stake required to be a validator on the consumer chain - MinStakeKeyName: 42, + MinStakeKeyName: 43, // AllowInactiveValidatorsKey is the byte prefix for storing the mapping from consumer chains to the boolean value // that determines whether inactive validators can validate on that chain - AllowInactiveValidatorsKeyName: 43, + AllowInactiveValidatorsKeyName: 44, // NOTE: DO NOT ADD NEW BYTE PREFIXES HERE WITHOUT ADDING THEM TO TestPreserveBytePrefix() IN keys_test.go } @@ -355,11 +375,6 @@ func PortKey() []byte { return []byte{mustGetKeyPrefix(PortKeyName)} } -// MaturedUnbondingOpsKey returns the key for storing the list of matured unbonding operations. -func MaturedUnbondingOpsKey() []byte { - return []byte{mustGetKeyPrefix(MaturedUnbondingOpsKeyName)} -} - // ValidatorSetUpdateIdKey is the key that stores the current validator set update id func ValidatorSetUpdateIdKey() []byte { return []byte{mustGetKeyPrefix(ValidatorSetUpdateIdKeyName)} @@ -400,16 +415,6 @@ func ChainToClientKey(chainID string) []byte { return append(ChainToClientKeyPrefix(), []byte(chainID)...) } -// InitTimeoutTimestampKeyPrefix returns the key prefix for storing the init timeout timestamps -func InitTimeoutTimestampKeyPrefix() []byte { - return []byte{mustGetKeyPrefix(InitTimeoutTimestampKeyName)} -} - -// InitTimeoutTimestampKey returns the key under which the init timeout timestamp for the given chainID is stored. -func InitTimeoutTimestampKey(chainID string) []byte { - return append(InitTimeoutTimestampKeyPrefix(), []byte(chainID)...) -} - // PendingCAPKeyPrefix returns the key prefix for storing a pending consumer addition proposal func PendingCAPKeyPrefix() []byte { return []byte{mustGetKeyPrefix(PendingCAPKeyName)} @@ -448,36 +453,6 @@ func PendingCRPKey(timestamp time.Time, chainID string) []byte { ) } -// UnbondingOpKeyPrefix returns the key prefix that stores a record of all the ids of consumer chains that -// need to unbond before a given unbonding operation can unbond on this chain. -func UnbondingOpKeyPrefix() []byte { - return []byte{mustGetKeyPrefix(UnbondingOpKeyName)} -} - -// UnbondingOpKey returns the key that stores a record of all the ids of consumer chains that -// need to unbond before a given unbonding operation can unbond on this chain. -func UnbondingOpKey(id uint64) []byte { - bz := make([]byte, 8) - binary.BigEndian.PutUint64(bz, id) - return append(UnbondingOpKeyPrefix(), bz...) -} - -// UnbondingOpIndexKeyPrefix returns the key prefix for storing an unbonding op index -func UnbondingOpIndexKeyPrefix() byte { - return mustGetKeyPrefix(UnbondingOpIndexKeyName) -} - -// UnbondingOpIndexKey returns the key for storing an unbonding op index -func UnbondingOpIndexKey(chainID string, vscID uint64) []byte { - return ChainIdAndUintIdKey(UnbondingOpIndexKeyPrefix(), chainID, vscID) -} - -// ParseUnbondingOpIndexKey parses an unbonding op index key for VSC ID -// Removes the prefix + chainID from index key and returns only the key part. -func ParseUnbondingOpIndexKey(key []byte) (string, uint64, error) { - return ParseChainIdAndUintIdKey(UnbondingOpIndexKeyPrefix(), key) -} - // ValsetUpdateBlockHeightKeyPrefix returns the key prefix that storing the mapping from valset update ID to block height func ValsetUpdateBlockHeightKeyPrefix() []byte { return []byte{mustGetKeyPrefix(ValsetUpdateBlockHeightKeyName)} @@ -512,23 +487,6 @@ func PendingVSCsKey(chainID string) []byte { return append([]byte{mustGetKeyPrefix(PendingVSCsKeyName)}, []byte(chainID)...) } -// VscSendingTimestampKeyPrefix returns the key for storing the sending timestamp of VSCPackets -func VscSendingTimestampKeyPrefix() byte { - return mustGetKeyPrefix(VscSendTimestampKeyName) -} - -// VscSendingTimestampKey returns the key under which the -// sending timestamp of the VSCPacket with vsc ID is stored -func VscSendingTimestampKey(chainID string, vscID uint64) []byte { - return ChainIdAndUintIdKey(VscSendingTimestampKeyPrefix(), chainID, vscID) -} - -// ParseVscTimeoutTimestampKey returns chain ID and vsc ID -// for a VscSendingTimestampKey or an error if unparsable -func ParseVscSendingTimestampKey(bz []byte) (string, uint64, error) { - return ParseChainIdAndUintIdKey(VscSendingTimestampKeyPrefix(), bz) -} - // ThrottledPacketDataSizeKey returns the key storing the size of the throttled packet data queue for a given chain ID func ThrottledPacketDataSizeKey(consumerChainID string) []byte { return append([]byte{mustGetKeyPrefix(ThrottledPacketDataSizeKeyName)}, []byte(consumerChainID)...) @@ -625,27 +583,11 @@ func ValidatorsByConsumerAddrKey(chainID string, addr ConsumerConsAddress) []byt return ChainIdAndConsAddrKey(ValidatorsByConsumerAddrKeyPrefix(), chainID, addr.ToSdkConsAddr()) } -// ConsumerAddrsToPruneKeyPrefix returns the key prefix for storing the -// mapping from VSC ids to consumer validators addresses -func ConsumerAddrsToPruneKeyPrefix() byte { - return mustGetKeyPrefix(ConsumerAddrsToPruneKeyName) -} - -// ConsumerAddrsToPruneKey returns the key for storing the -// mapping from VSC ids to consumer validators addresses -func ConsumerAddrsToPruneKey(chainID string, vscID uint64) []byte { - return ChainIdAndUintIdKey(ConsumerAddrsToPruneKeyPrefix(), chainID, vscID) -} - // SlashLogKey returns the key to a validator's slash log func SlashLogKey(providerAddr ProviderConsAddress) []byte { return append([]byte{mustGetKeyPrefix(SlashLogKeyName)}, providerAddr.ToSdkConsAddr().Bytes()...) } -func VSCMaturedHandledThisBlockKey() []byte { - return []byte{mustGetKeyPrefix(VSCMaturedHandledThisBlockKeyName)} -} - // ConsumerRewardDenomsKeyPrefix returns the key prefix for storing consumer reward denoms func ConsumerRewardDenomsKeyPrefix() []byte { return []byte{mustGetKeyPrefix(ConsumerRewardDenomsKeyName)} @@ -796,6 +738,20 @@ func AllowInactiveValidatorsKey(chainID string) []byte { return ChainIdWithLenKey(mustGetKeyPrefix(AllowInactiveValidatorsKeyName), chainID) } +// ConsumerAddrsToPruneV2KeyPrefix returns the key prefix for storing the consumer validators +// addresses that need to be pruned. These are stored as a +// (chainID, ts) -> (consumer_address1, consumer_address2, ...) mapping, where ts is the +// timestamp at which the consumer validators addresses can be pruned. +func ConsumerAddrsToPruneV2KeyPrefix() byte { + return mustGetKeyPrefix(ConsumerAddrsToPruneV2KeyName) +} + +// ConsumerAddrsToPruneV2Key returns the key for storing the consumer validators +// addresses that need to be pruned. +func ConsumerAddrsToPruneV2Key(chainID string, pruneTs time.Time) []byte { + return ChainIdAndTsKey(ConsumerAddrsToPruneV2KeyPrefix(), chainID, pruneTs) +} + // NOTE: DO NOT ADD FULLY DEFINED KEY FUNCTIONS WITHOUT ADDING THEM TO getAllFullyDefinedKeys() IN keys_test.go // diff --git a/x/ccv/provider/types/keys_test.go b/x/ccv/provider/types/keys_test.go index 4fd7fb4877..e970cc6d91 100644 --- a/x/ccv/provider/types/keys_test.go +++ b/x/ccv/provider/types/keys_test.go @@ -27,89 +27,91 @@ func TestNoDuplicates(t *testing.T) { // Test that the value of all byte prefixes is preserved func TestPreserveBytePrefix(t *testing.T) { i := 0 - require.Equal(t, uint8(0xFF), providertypes.ParametersKey()[0]) + require.Equal(t, byte(0xFF), providertypes.ParametersKey()[0]) i++ - require.Equal(t, uint8(0), providertypes.PortKey()[0]) + require.Equal(t, byte(0), providertypes.PortKey()[0]) i++ - require.Equal(t, uint8(1), providertypes.MaturedUnbondingOpsKey()[0]) + // reserve 1 as deprecated i++ - require.Equal(t, uint8(2), providertypes.ValidatorSetUpdateIdKey()[0]) + require.Equal(t, byte(2), providertypes.ValidatorSetUpdateIdKey()[0]) i++ - require.Equal(t, uint8(3), providertypes.SlashMeterKey()[0]) + require.Equal(t, byte(3), providertypes.SlashMeterKey()[0]) i++ - require.Equal(t, uint8(4), providertypes.SlashMeterReplenishTimeCandidateKey()[0]) + require.Equal(t, byte(4), providertypes.SlashMeterReplenishTimeCandidateKey()[0]) i++ - require.Equal(t, uint8(5), providertypes.ChainToChannelKey("chainID")[0]) + require.Equal(t, byte(5), providertypes.ChainToChannelKey("chainID")[0]) i++ - require.Equal(t, uint8(6), providertypes.ChannelToChainKeyPrefix()[0]) + require.Equal(t, byte(6), providertypes.ChannelToChainKeyPrefix()[0]) i++ - require.Equal(t, uint8(7), providertypes.ChainToClientKeyPrefix()[0]) + require.Equal(t, byte(7), providertypes.ChainToClientKeyPrefix()[0]) i++ - require.Equal(t, uint8(8), providertypes.InitTimeoutTimestampKeyPrefix()[0]) + // reserve 8 as deprecated i++ - require.Equal(t, uint8(9), providertypes.PendingCAPKeyPrefix()[0]) + require.Equal(t, byte(9), providertypes.PendingCAPKeyPrefix()[0]) i++ - require.Equal(t, uint8(10), providertypes.PendingCRPKeyPrefix()[0]) + require.Equal(t, byte(10), providertypes.PendingCRPKeyPrefix()[0]) i++ - require.Equal(t, uint8(11), providertypes.UnbondingOpKeyPrefix()[0]) + // reserve 11 as deprecated i++ - require.Equal(t, uint8(12), providertypes.UnbondingOpIndexKeyPrefix()) + // reserve 12 as deprecated i++ - require.Equal(t, uint8(13), providertypes.ValsetUpdateBlockHeightKeyPrefix()[0]) + require.Equal(t, byte(13), providertypes.ValsetUpdateBlockHeightKeyPrefix()[0]) i++ - require.Equal(t, uint8(14), providertypes.ConsumerGenesisKey("chainID")[0]) + require.Equal(t, byte(14), providertypes.ConsumerGenesisKey("chainID")[0]) i++ - require.Equal(t, uint8(15), providertypes.SlashAcksKey("chainID")[0]) + require.Equal(t, byte(15), providertypes.SlashAcksKey("chainID")[0]) i++ - require.Equal(t, uint8(16), providertypes.InitChainHeightKey("chainID")[0]) + require.Equal(t, byte(16), providertypes.InitChainHeightKey("chainID")[0]) i++ - require.Equal(t, uint8(17), providertypes.PendingVSCsKey("chainID")[0]) + require.Equal(t, byte(17), providertypes.PendingVSCsKey("chainID")[0]) i++ - require.Equal(t, uint8(18), providertypes.VscSendingTimestampKeyPrefix()) + // reserve 18 as deprecated i++ - require.Equal(t, uint8(19), providertypes.ThrottledPacketDataSizeKey("chainID")[0]) + require.Equal(t, byte(19), providertypes.ThrottledPacketDataSizeKey("chainID")[0]) i++ - require.Equal(t, uint8(20), providertypes.ThrottledPacketDataKeyPrefix()) + require.Equal(t, byte(20), providertypes.ThrottledPacketDataKeyPrefix()) i++ - require.Equal(t, uint8(21), providertypes.GlobalSlashEntryKeyPrefix()[0]) + require.Equal(t, byte(21), providertypes.GlobalSlashEntryKeyPrefix()[0]) i++ - require.Equal(t, uint8(22), providertypes.ConsumerValidatorsKeyPrefix()) + require.Equal(t, byte(22), providertypes.ConsumerValidatorsKeyPrefix()) i++ - require.Equal(t, uint8(23), providertypes.ValidatorsByConsumerAddrKeyPrefix()) + require.Equal(t, byte(23), providertypes.ValidatorsByConsumerAddrKeyPrefix()) i++ // reserve 24 as deprecated i++ - require.Equal(t, uint8(25), providertypes.ConsumerAddrsToPruneKeyPrefix()) + // reserve 25 as deprecated i++ - require.Equal(t, uint8(26), providertypes.SlashLogKey(providertypes.NewProviderConsAddress([]byte{0x05}))[0]) + require.Equal(t, byte(26), providertypes.SlashLogKey(providertypes.NewProviderConsAddress([]byte{0x05}))[0]) i++ - require.Equal(t, uint8(27), providertypes.ConsumerRewardDenomsKeyPrefix()[0]) + require.Equal(t, byte(27), providertypes.ConsumerRewardDenomsKeyPrefix()[0]) i++ - require.Equal(t, uint8(28), providertypes.VSCMaturedHandledThisBlockKey()[0]) + // reserve 28 as deprecated i++ - require.Equal(t, uint8(29), providertypes.EquivocationEvidenceMinHeightKey("chainID")[0]) + require.Equal(t, byte(29), providertypes.EquivocationEvidenceMinHeightKey("chainID")[0]) i++ - require.Equal(t, uint8(30), providertypes.ProposedConsumerChainKeyPrefix()[0]) + require.Equal(t, byte(30), providertypes.ProposedConsumerChainKeyPrefix()[0]) i++ - require.Equal(t, uint8(31), providertypes.ConsumerValidatorKeyPrefix()) + require.Equal(t, byte(31), providertypes.ConsumerValidatorKeyPrefix()) i++ - require.Equal(t, uint8(32), providertypes.OptedInKeyPrefix()) + require.Equal(t, byte(32), providertypes.OptedInKeyPrefix()) i++ - require.Equal(t, uint8(33), providertypes.TopNKey("chainID")[0]) + require.Equal(t, byte(33), providertypes.TopNKey("chainID")[0]) i++ - require.Equal(t, uint8(34), providertypes.ValidatorsPowerCapKey("chainID")[0]) + require.Equal(t, byte(34), providertypes.ValidatorsPowerCapKey("chainID")[0]) i++ - require.Equal(t, uint8(35), providertypes.ValidatorSetCapKey("chainID")[0]) + require.Equal(t, byte(35), providertypes.ValidatorSetCapKey("chainID")[0]) i++ - require.Equal(t, uint8(36), providertypes.AllowlistKeyPrefix()) + require.Equal(t, byte(36), providertypes.AllowlistKeyPrefix()) i++ - require.Equal(t, uint8(37), providertypes.DenylistKeyPrefix()) + require.Equal(t, byte(37), providertypes.DenylistKeyPrefix()) i++ - require.Equal(t, uint8(38), providertypes.ConsumerRewardsAllocationKey("chainID")[0]) + require.Equal(t, byte(38), providertypes.ConsumerRewardsAllocationKey("chainID")[0]) i++ - require.Equal(t, uint8(39), providertypes.ConsumerCommissionRateKeyPrefix()) + require.Equal(t, byte(39), providertypes.ConsumerCommissionRateKeyPrefix()) i++ - require.Equal(t, uint8(40), providertypes.MinimumPowerInTopNKey("chainID")[0]) + require.Equal(t, byte(40), providertypes.MinimumPowerInTopNKey("chainID")[0]) + i++ + require.Equal(t, byte(41), providertypes.ConsumerAddrsToPruneV2KeyPrefix()) i++ require.Equal(t, uint8(41), providertypes.LastProviderConsensusValsPrefix()) i++ @@ -149,32 +151,25 @@ func getAllFullyDefinedKeys() [][]byte { return [][]byte{ providertypes.ParametersKey(), providertypes.PortKey(), - providertypes.MaturedUnbondingOpsKey(), providertypes.ValidatorSetUpdateIdKey(), providertypes.SlashMeterKey(), providertypes.SlashMeterReplenishTimeCandidateKey(), providertypes.ChainToChannelKey("chainID"), providertypes.ChannelToChainKey("channelID"), providertypes.ChainToClientKey("chainID"), - providertypes.InitTimeoutTimestampKey("chainID"), providertypes.PendingCAPKey(time.Time{}, "chainID"), providertypes.PendingCRPKey(time.Time{}, "chainID"), - providertypes.UnbondingOpKey(7), - providertypes.UnbondingOpIndexKey("chainID", 7), providertypes.ValsetUpdateBlockHeightKey(7), providertypes.ConsumerGenesisKey("chainID"), providertypes.SlashAcksKey("chainID"), providertypes.InitChainHeightKey("chainID"), providertypes.PendingVSCsKey("chainID"), - providertypes.VscSendingTimestampKey("chainID", 8), providertypes.ThrottledPacketDataSizeKey("chainID"), providertypes.ThrottledPacketDataKey("chainID", 88), providertypes.GlobalSlashEntryKey(providertypes.GlobalSlashEntry{}), providertypes.ConsumerValidatorsKey("chainID", providertypes.NewProviderConsAddress([]byte{0x05})), providertypes.ValidatorsByConsumerAddrKey("chainID", providertypes.NewConsumerConsAddress([]byte{0x05})), - providertypes.ConsumerAddrsToPruneKey("chainID", 88), providertypes.SlashLogKey(providertypes.NewProviderConsAddress([]byte{0x05})), - providertypes.VSCMaturedHandledThisBlockKey(), providertypes.ConsumerRewardDenomsKey("uatom"), providertypes.EquivocationEvidenceMinHeightKey("chainID"), providertypes.ProposedConsumerChainKey(1), @@ -188,6 +183,7 @@ func getAllFullyDefinedKeys() [][]byte { providertypes.ConsumerRewardsAllocationKey("chainID"), providertypes.ConsumerCommissionRateKey("chainID", providertypes.NewProviderConsAddress([]byte{0x05})), providertypes.MinimumPowerInTopNKey("chainID"), + providertypes.ConsumerAddrsToPruneV2Key("chainID", time.Time{}), providertypes.LastProviderConsensusValidatorKey([]byte{0x05}), providertypes.MinStakeKey("chainID"), providertypes.AllowInactiveValidatorsKey("chainID"), @@ -339,7 +335,6 @@ func TestKeysWithPrefixAndId(t *testing.T) { providertypes.ChainToChannelKey, providertypes.ChannelToChainKey, providertypes.ChainToClientKey, - providertypes.InitTimeoutTimestampKey, providertypes.ConsumerGenesisKey, providertypes.SlashAcksKey, providertypes.InitChainHeightKey, @@ -364,7 +359,6 @@ func TestKeysWithPrefixAndId(t *testing.T) { func TestKeysWithUint64Payload(t *testing.T) { funcs := []func(uint64) []byte{ - providertypes.UnbondingOpKey, providertypes.ValsetUpdateBlockHeightKey, } diff --git a/x/ccv/provider/types/msg.go b/x/ccv/provider/types/msg.go index 4fdd560548..c47c62e0a0 100644 --- a/x/ccv/provider/types/msg.go +++ b/x/ccv/provider/types/msg.go @@ -423,11 +423,12 @@ func (msg MsgOptOut) ValidateBasic() error { } // NewMsgSetConsumerCommissionRate creates a new MsgSetConsumerCommissionRate msg instance. -func NewMsgSetConsumerCommissionRate(chainID string, commission math.LegacyDec, providerValidatorAddress sdk.ValAddress) *MsgSetConsumerCommissionRate { +func NewMsgSetConsumerCommissionRate(chainID string, commission math.LegacyDec, providerValidatorAddress sdk.ValAddress, signer string) *MsgSetConsumerCommissionRate { return &MsgSetConsumerCommissionRate{ ChainId: chainID, Rate: commission, ProviderAddr: providerValidatorAddress.String(), + Signer: signer, } } diff --git a/x/ccv/provider/types/params.go b/x/ccv/provider/types/params.go index 659cd554d0..3fddd002a1 100644 --- a/x/ccv/provider/types/params.go +++ b/x/ccv/provider/types/params.go @@ -24,12 +24,6 @@ const ( // as UnbondingPeriod * TrustingPeriodFraction DefaultTrustingPeriodFraction = "0.66" - // DefaultInitTimeoutPeriod defines the init timeout period - DefaultInitTimeoutPeriod = 7 * 24 * time.Hour - - // DefaultVscTimeoutPeriod defines the VSC timeout period - DefaultVscTimeoutPeriod = 5 * 7 * 24 * time.Hour - // DefaultSlashMeterReplenishPeriod defines the default period for which the slash gas meter is replenished DefaultSlashMeterReplenishPeriod = time.Hour @@ -66,8 +60,6 @@ const ( var ( KeyTemplateClient = []byte("TemplateClient") KeyTrustingPeriodFraction = []byte("TrustingPeriodFraction") - KeyInitTimeoutPeriod = []byte("InitTimeoutPeriod") - KeyVscTimeoutPeriod = []byte("VscTimeoutPeriod") KeySlashMeterReplenishPeriod = []byte("SlashMeterReplenishPeriod") KeySlashMeterReplenishFraction = []byte("SlashMeterReplenishFraction") KeyConsumerRewardDenomRegistrationFee = []byte("ConsumerRewardDenomRegistrationFee") @@ -86,8 +78,6 @@ func NewParams( cs *ibctmtypes.ClientState, trustingPeriodFraction string, ccvTimeoutPeriod time.Duration, - initTimeoutPeriod time.Duration, - vscTimeoutPeriod time.Duration, slashMeterReplenishPeriod time.Duration, slashMeterReplenishFraction string, consumerRewardDenomRegistrationFee sdk.Coin, @@ -99,8 +89,6 @@ func NewParams( TemplateClient: cs, TrustingPeriodFraction: trustingPeriodFraction, CcvTimeoutPeriod: ccvTimeoutPeriod, - InitTimeoutPeriod: initTimeoutPeriod, - VscTimeoutPeriod: vscTimeoutPeriod, SlashMeterReplenishPeriod: slashMeterReplenishPeriod, SlashMeterReplenishFraction: slashMeterReplenishFraction, ConsumerRewardDenomRegistrationFee: consumerRewardDenomRegistrationFee, @@ -127,8 +115,6 @@ func DefaultParams() Params { ), DefaultTrustingPeriodFraction, ccvtypes.DefaultCCVTimeoutPeriod, - DefaultInitTimeoutPeriod, - DefaultVscTimeoutPeriod, DefaultSlashMeterReplenishPeriod, DefaultSlashMeterReplenishFraction, // Defining this inline because it's not possible to define a constant of type sdk.Coin. @@ -157,12 +143,6 @@ func (p Params) Validate() error { if err := ccvtypes.ValidateDuration(p.CcvTimeoutPeriod); err != nil { return fmt.Errorf("ccv timeout period is invalid: %s", err) } - if err := ccvtypes.ValidateDuration(p.InitTimeoutPeriod); err != nil { - return fmt.Errorf("init timeout period is invalid: %s", err) - } - if err := ccvtypes.ValidateDuration(p.VscTimeoutPeriod); err != nil { - return fmt.Errorf("vsc timeout period is invalid: %s", err) - } if err := ccvtypes.ValidateDuration(p.SlashMeterReplenishPeriod); err != nil { return fmt.Errorf("slash meter replenish period is invalid: %s", err) } @@ -191,8 +171,6 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { paramtypes.NewParamSetPair(KeyTemplateClient, p.TemplateClient, ValidateTemplateClient), paramtypes.NewParamSetPair(KeyTrustingPeriodFraction, p.TrustingPeriodFraction, ccvtypes.ValidateStringFraction), paramtypes.NewParamSetPair(ccvtypes.KeyCCVTimeoutPeriod, p.CcvTimeoutPeriod, ccvtypes.ValidateDuration), - paramtypes.NewParamSetPair(KeyInitTimeoutPeriod, p.InitTimeoutPeriod, ccvtypes.ValidateDuration), - paramtypes.NewParamSetPair(KeyVscTimeoutPeriod, p.VscTimeoutPeriod, ccvtypes.ValidateDuration), paramtypes.NewParamSetPair(KeySlashMeterReplenishPeriod, p.SlashMeterReplenishPeriod, ccvtypes.ValidateDuration), paramtypes.NewParamSetPair(KeySlashMeterReplenishFraction, p.SlashMeterReplenishFraction, ccvtypes.ValidateStringFraction), paramtypes.NewParamSetPair(KeyConsumerRewardDenomRegistrationFee, p.ConsumerRewardDenomRegistrationFee, ValidateCoin), diff --git a/x/ccv/provider/types/params_test.go b/x/ccv/provider/types/params_test.go index 515a4b28c7..12bfee81a0 100644 --- a/x/ccv/provider/types/params_test.go +++ b/x/ccv/provider/types/params_test.go @@ -25,43 +25,37 @@ func TestValidateParams(t *testing.T) { {"custom valid params", types.NewParams( ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.33", time.Hour, time.Hour, time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), true}, + "0.33", time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), true}, {"custom invalid params", types.NewParams( ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, 0, clienttypes.Height{}, nil, []string{"ibc", "upgradedIBCState"}), - "0.33", time.Hour, time.Hour, time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, + "0.33", time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, {"blank client", types.NewParams(&ibctmtypes.ClientState{}, - "0.33", time.Hour, time.Hour, time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, - {"nil client", types.NewParams(nil, "0.33", time.Hour, time.Hour, time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, + "0.33", time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, + {"nil client", types.NewParams(nil, "0.33", time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, // Check if "0.00" is valid or if a zero dec TrustFraction needs to return an error {"0 trusting period fraction", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.00", time.Hour, time.Hour, time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), true}, + "0.00", time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), true}, {"0 ccv timeout period", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.33", 0, time.Hour, time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, - {"0 init timeout period", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, - time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.33", time.Hour, 0, time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, - {"0 vsc timeout period", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, - time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.33", time.Hour, time.Hour, 0, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, + "0.33", 0, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, {"0 slash meter replenish period", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.33", time.Hour, time.Hour, 24*time.Hour, 0, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, + "0.33", time.Hour, 0, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, {"slash meter replenish fraction over 1", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.33", time.Hour, time.Hour, 24*time.Hour, time.Hour, "1.5", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, + "0.33", time.Hour, time.Hour, "1.5", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, {"invalid consumer reward denom registration fee denom", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.33", time.Hour, time.Hour, 24*time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "st", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, + "0.33", time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "st", Amount: math.NewInt(10000000)}, 1000, 24, 180), false}, {"invalid consumer reward denom registration fee amount", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.33", time.Hour, time.Hour, 24*time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(-10000000)}, 1000, 24, 180), false}, + "0.33", time.Hour, time.Hour, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(-10000000)}, 1000, 24, 180), false}, {"invalid number of epochs to start receiving rewards", types.NewParams( ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}), - "0.33", time.Hour, time.Hour, time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 0, 180), false}, + "0.33", time.Hour, 30*time.Minute, "0.1", sdk.Coin{Denom: "stake", Amount: math.NewInt(10000000)}, 1000, 0, 180), false}, } for _, tc := range testCases { diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index 1199216292..7c30781221 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -601,14 +601,6 @@ type Params struct { TrustingPeriodFraction string `protobuf:"bytes,2,opt,name=trusting_period_fraction,json=trustingPeriodFraction,proto3" json:"trusting_period_fraction,omitempty"` // Sent IBC packets will timeout after this duration CcvTimeoutPeriod time.Duration `protobuf:"bytes,3,opt,name=ccv_timeout_period,json=ccvTimeoutPeriod,proto3,stdduration" json:"ccv_timeout_period"` - // The channel initialization (IBC channel opening handshake) will timeout - // after this duration - InitTimeoutPeriod time.Duration `protobuf:"bytes,4,opt,name=init_timeout_period,json=initTimeoutPeriod,proto3,stdduration" json:"init_timeout_period"` - // The VSC packets sent by the provider will timeout after this duration. - // Note that unlike ccv_timeout_period which is an IBC param, - // the vsc_timeout_period is a provider-side param that enables the provider - // to timeout VSC packets even when a consumer chain is not live. - VscTimeoutPeriod time.Duration `protobuf:"bytes,5,opt,name=vsc_timeout_period,json=vscTimeoutPeriod,proto3,stdduration" json:"vsc_timeout_period"` // The period for which the slash meter is replenished SlashMeterReplenishPeriod time.Duration `protobuf:"bytes,6,opt,name=slash_meter_replenish_period,json=slashMeterReplenishPeriod,proto3,stdduration" json:"slash_meter_replenish_period"` // The fraction of total voting power that is replenished to the slash meter @@ -680,20 +672,6 @@ func (m *Params) GetCcvTimeoutPeriod() time.Duration { return 0 } -func (m *Params) GetInitTimeoutPeriod() time.Duration { - if m != nil { - return m.InitTimeoutPeriod - } - return 0 -} - -func (m *Params) GetVscTimeoutPeriod() time.Duration { - if m != nil { - return m.VscTimeoutPeriod - } - return 0 -} - func (m *Params) GetSlashMeterReplenishPeriod() time.Duration { if m != nil { return m.SlashMeterReplenishPeriod @@ -974,219 +952,6 @@ func (m *ChannelToChain) GetChainId() string { return "" } -// VscUnbondingOps contains the IDs of unbonding operations that are waiting for -// at least one VSCMaturedPacket with vscID from a consumer chain -type VscUnbondingOps struct { - VscId uint64 `protobuf:"varint,1,opt,name=vsc_id,json=vscId,proto3" json:"vsc_id,omitempty"` - UnbondingOpIds []uint64 `protobuf:"varint,2,rep,packed,name=unbonding_op_ids,json=unbondingOpIds,proto3" json:"unbonding_op_ids,omitempty"` -} - -func (m *VscUnbondingOps) Reset() { *m = VscUnbondingOps{} } -func (m *VscUnbondingOps) String() string { return proto.CompactTextString(m) } -func (*VscUnbondingOps) ProtoMessage() {} -func (*VscUnbondingOps) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{12} -} -func (m *VscUnbondingOps) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *VscUnbondingOps) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_VscUnbondingOps.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *VscUnbondingOps) XXX_Merge(src proto.Message) { - xxx_messageInfo_VscUnbondingOps.Merge(m, src) -} -func (m *VscUnbondingOps) XXX_Size() int { - return m.Size() -} -func (m *VscUnbondingOps) XXX_DiscardUnknown() { - xxx_messageInfo_VscUnbondingOps.DiscardUnknown(m) -} - -var xxx_messageInfo_VscUnbondingOps proto.InternalMessageInfo - -func (m *VscUnbondingOps) GetVscId() uint64 { - if m != nil { - return m.VscId - } - return 0 -} - -func (m *VscUnbondingOps) GetUnbondingOpIds() []uint64 { - if m != nil { - return m.UnbondingOpIds - } - return nil -} - -// UnbondingOp contains the ids of consumer chains that need to unbond before -// the unbonding operation with the given ID can unbond -type UnbondingOp struct { - Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - // consumer chains that are still unbonding - UnbondingConsumerChains []string `protobuf:"bytes,2,rep,name=unbonding_consumer_chains,json=unbondingConsumerChains,proto3" json:"unbonding_consumer_chains,omitempty"` -} - -func (m *UnbondingOp) Reset() { *m = UnbondingOp{} } -func (m *UnbondingOp) String() string { return proto.CompactTextString(m) } -func (*UnbondingOp) ProtoMessage() {} -func (*UnbondingOp) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{13} -} -func (m *UnbondingOp) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *UnbondingOp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_UnbondingOp.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *UnbondingOp) XXX_Merge(src proto.Message) { - xxx_messageInfo_UnbondingOp.Merge(m, src) -} -func (m *UnbondingOp) XXX_Size() int { - return m.Size() -} -func (m *UnbondingOp) XXX_DiscardUnknown() { - xxx_messageInfo_UnbondingOp.DiscardUnknown(m) -} - -var xxx_messageInfo_UnbondingOp proto.InternalMessageInfo - -func (m *UnbondingOp) GetId() uint64 { - if m != nil { - return m.Id - } - return 0 -} - -func (m *UnbondingOp) GetUnbondingConsumerChains() []string { - if m != nil { - return m.UnbondingConsumerChains - } - return nil -} - -type InitTimeoutTimestamp struct { - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` -} - -func (m *InitTimeoutTimestamp) Reset() { *m = InitTimeoutTimestamp{} } -func (m *InitTimeoutTimestamp) String() string { return proto.CompactTextString(m) } -func (*InitTimeoutTimestamp) ProtoMessage() {} -func (*InitTimeoutTimestamp) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{14} -} -func (m *InitTimeoutTimestamp) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *InitTimeoutTimestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_InitTimeoutTimestamp.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *InitTimeoutTimestamp) XXX_Merge(src proto.Message) { - xxx_messageInfo_InitTimeoutTimestamp.Merge(m, src) -} -func (m *InitTimeoutTimestamp) XXX_Size() int { - return m.Size() -} -func (m *InitTimeoutTimestamp) XXX_DiscardUnknown() { - xxx_messageInfo_InitTimeoutTimestamp.DiscardUnknown(m) -} - -var xxx_messageInfo_InitTimeoutTimestamp proto.InternalMessageInfo - -func (m *InitTimeoutTimestamp) GetChainId() string { - if m != nil { - return m.ChainId - } - return "" -} - -func (m *InitTimeoutTimestamp) GetTimestamp() uint64 { - if m != nil { - return m.Timestamp - } - return 0 -} - -type VscSendTimestamp struct { - VscId uint64 `protobuf:"varint,1,opt,name=vsc_id,json=vscId,proto3" json:"vsc_id,omitempty"` - Timestamp time.Time `protobuf:"bytes,2,opt,name=timestamp,proto3,stdtime" json:"timestamp"` -} - -func (m *VscSendTimestamp) Reset() { *m = VscSendTimestamp{} } -func (m *VscSendTimestamp) String() string { return proto.CompactTextString(m) } -func (*VscSendTimestamp) ProtoMessage() {} -func (*VscSendTimestamp) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{15} -} -func (m *VscSendTimestamp) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *VscSendTimestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_VscSendTimestamp.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *VscSendTimestamp) XXX_Merge(src proto.Message) { - xxx_messageInfo_VscSendTimestamp.Merge(m, src) -} -func (m *VscSendTimestamp) XXX_Size() int { - return m.Size() -} -func (m *VscSendTimestamp) XXX_DiscardUnknown() { - xxx_messageInfo_VscSendTimestamp.DiscardUnknown(m) -} - -var xxx_messageInfo_VscSendTimestamp proto.InternalMessageInfo - -func (m *VscSendTimestamp) GetVscId() uint64 { - if m != nil { - return m.VscId - } - return 0 -} - -func (m *VscSendTimestamp) GetTimestamp() time.Time { - if m != nil { - return m.Timestamp - } - return time.Time{} -} - // ValidatorSetChangePackets is a pb list of ccv.ValidatorSetChangePacketData. type ValidatorSetChangePackets struct { List []types3.ValidatorSetChangePacketData `protobuf:"bytes,1,rep,name=list,proto3" json:"list"` @@ -1196,7 +961,7 @@ func (m *ValidatorSetChangePackets) Reset() { *m = ValidatorSetChangePac func (m *ValidatorSetChangePackets) String() string { return proto.CompactTextString(m) } func (*ValidatorSetChangePackets) ProtoMessage() {} func (*ValidatorSetChangePackets) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{16} + return fileDescriptor_f22ec409a72b7b72, []int{12} } func (m *ValidatorSetChangePackets) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1232,105 +997,6 @@ func (m *ValidatorSetChangePackets) GetList() []types3.ValidatorSetChangePacketD return nil } -// MaturedUnbondingOps defines a list of ids corresponding to ids of matured -// unbonding operations. -type MaturedUnbondingOps struct { - Ids []uint64 `protobuf:"varint,1,rep,packed,name=ids,proto3" json:"ids,omitempty"` -} - -func (m *MaturedUnbondingOps) Reset() { *m = MaturedUnbondingOps{} } -func (m *MaturedUnbondingOps) String() string { return proto.CompactTextString(m) } -func (*MaturedUnbondingOps) ProtoMessage() {} -func (*MaturedUnbondingOps) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{17} -} -func (m *MaturedUnbondingOps) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MaturedUnbondingOps) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MaturedUnbondingOps.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MaturedUnbondingOps) XXX_Merge(src proto.Message) { - xxx_messageInfo_MaturedUnbondingOps.Merge(m, src) -} -func (m *MaturedUnbondingOps) XXX_Size() int { - return m.Size() -} -func (m *MaturedUnbondingOps) XXX_DiscardUnknown() { - xxx_messageInfo_MaturedUnbondingOps.DiscardUnknown(m) -} - -var xxx_messageInfo_MaturedUnbondingOps proto.InternalMessageInfo - -func (m *MaturedUnbondingOps) GetIds() []uint64 { - if m != nil { - return m.Ids - } - return nil -} - -// ExportedVscSendTimestamps is VscSendTimestamp with chainID info for exporting to genesis -type ExportedVscSendTimestamp struct { - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - VscSendTimestamps []VscSendTimestamp `protobuf:"bytes,2,rep,name=vsc_send_timestamps,json=vscSendTimestamps,proto3" json:"vsc_send_timestamps"` -} - -func (m *ExportedVscSendTimestamp) Reset() { *m = ExportedVscSendTimestamp{} } -func (m *ExportedVscSendTimestamp) String() string { return proto.CompactTextString(m) } -func (*ExportedVscSendTimestamp) ProtoMessage() {} -func (*ExportedVscSendTimestamp) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{18} -} -func (m *ExportedVscSendTimestamp) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ExportedVscSendTimestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ExportedVscSendTimestamp.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ExportedVscSendTimestamp) XXX_Merge(src proto.Message) { - xxx_messageInfo_ExportedVscSendTimestamp.Merge(m, src) -} -func (m *ExportedVscSendTimestamp) XXX_Size() int { - return m.Size() -} -func (m *ExportedVscSendTimestamp) XXX_DiscardUnknown() { - xxx_messageInfo_ExportedVscSendTimestamp.DiscardUnknown(m) -} - -var xxx_messageInfo_ExportedVscSendTimestamp proto.InternalMessageInfo - -func (m *ExportedVscSendTimestamp) GetChainId() string { - if m != nil { - return m.ChainId - } - return "" -} - -func (m *ExportedVscSendTimestamp) GetVscSendTimestamps() []VscSendTimestamp { - if m != nil { - return m.VscSendTimestamps - } - return nil -} - type KeyAssignmentReplacement struct { ProviderAddr []byte `protobuf:"bytes,1,opt,name=provider_addr,json=providerAddr,proto3" json:"provider_addr,omitempty"` PrevCKey *crypto.PublicKey `protobuf:"bytes,2,opt,name=prev_c_key,json=prevCKey,proto3" json:"prev_c_key,omitempty"` @@ -1341,7 +1007,7 @@ func (m *KeyAssignmentReplacement) Reset() { *m = KeyAssignmentReplaceme func (m *KeyAssignmentReplacement) String() string { return proto.CompactTextString(m) } func (*KeyAssignmentReplacement) ProtoMessage() {} func (*KeyAssignmentReplacement) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{19} + return fileDescriptor_f22ec409a72b7b72, []int{13} } func (m *KeyAssignmentReplacement) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1404,7 +1070,7 @@ func (m *ValidatorConsumerPubKey) Reset() { *m = ValidatorConsumerPubKey func (m *ValidatorConsumerPubKey) String() string { return proto.CompactTextString(m) } func (*ValidatorConsumerPubKey) ProtoMessage() {} func (*ValidatorConsumerPubKey) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{20} + return fileDescriptor_f22ec409a72b7b72, []int{14} } func (m *ValidatorConsumerPubKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1467,7 +1133,7 @@ func (m *ValidatorByConsumerAddr) Reset() { *m = ValidatorByConsumerAddr func (m *ValidatorByConsumerAddr) String() string { return proto.CompactTextString(m) } func (*ValidatorByConsumerAddr) ProtoMessage() {} func (*ValidatorByConsumerAddr) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{21} + return fileDescriptor_f22ec409a72b7b72, []int{15} } func (m *ValidatorByConsumerAddr) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1517,26 +1183,26 @@ func (m *ValidatorByConsumerAddr) GetProviderAddr() []byte { return nil } -// Used to serialize the ConsumerAddrsToPrune index from key assignment -// ConsumerAddrsToPrune: (chainID, vscID uint64) -> consumerAddrs AddressList -type ConsumerAddrsToPrune struct { +// Used to serialize the ConsumerAddrsToPruneV2 index from key assignment +// ConsumerAddrsToPruneV2: (chainID, pruneTs time.Time) -> consumerAddrs AddressList +type ConsumerAddrsToPruneV2 struct { ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - VscId uint64 `protobuf:"varint,2,opt,name=vsc_id,json=vscId,proto3" json:"vsc_id,omitempty"` + PruneTs time.Time `protobuf:"bytes,2,opt,name=prune_ts,json=pruneTs,proto3,stdtime" json:"prune_ts"` ConsumerAddrs *AddressList `protobuf:"bytes,3,opt,name=consumer_addrs,json=consumerAddrs,proto3" json:"consumer_addrs,omitempty"` } -func (m *ConsumerAddrsToPrune) Reset() { *m = ConsumerAddrsToPrune{} } -func (m *ConsumerAddrsToPrune) String() string { return proto.CompactTextString(m) } -func (*ConsumerAddrsToPrune) ProtoMessage() {} -func (*ConsumerAddrsToPrune) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{22} +func (m *ConsumerAddrsToPruneV2) Reset() { *m = ConsumerAddrsToPruneV2{} } +func (m *ConsumerAddrsToPruneV2) String() string { return proto.CompactTextString(m) } +func (*ConsumerAddrsToPruneV2) ProtoMessage() {} +func (*ConsumerAddrsToPruneV2) Descriptor() ([]byte, []int) { + return fileDescriptor_f22ec409a72b7b72, []int{16} } -func (m *ConsumerAddrsToPrune) XXX_Unmarshal(b []byte) error { +func (m *ConsumerAddrsToPruneV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ConsumerAddrsToPrune) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ConsumerAddrsToPruneV2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ConsumerAddrsToPrune.Marshal(b, m, deterministic) + return xxx_messageInfo_ConsumerAddrsToPruneV2.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1546,33 +1212,33 @@ func (m *ConsumerAddrsToPrune) XXX_Marshal(b []byte, deterministic bool) ([]byte return b[:n], nil } } -func (m *ConsumerAddrsToPrune) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConsumerAddrsToPrune.Merge(m, src) +func (m *ConsumerAddrsToPruneV2) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsumerAddrsToPruneV2.Merge(m, src) } -func (m *ConsumerAddrsToPrune) XXX_Size() int { +func (m *ConsumerAddrsToPruneV2) XXX_Size() int { return m.Size() } -func (m *ConsumerAddrsToPrune) XXX_DiscardUnknown() { - xxx_messageInfo_ConsumerAddrsToPrune.DiscardUnknown(m) +func (m *ConsumerAddrsToPruneV2) XXX_DiscardUnknown() { + xxx_messageInfo_ConsumerAddrsToPruneV2.DiscardUnknown(m) } -var xxx_messageInfo_ConsumerAddrsToPrune proto.InternalMessageInfo +var xxx_messageInfo_ConsumerAddrsToPruneV2 proto.InternalMessageInfo -func (m *ConsumerAddrsToPrune) GetChainId() string { +func (m *ConsumerAddrsToPruneV2) GetChainId() string { if m != nil { return m.ChainId } return "" } -func (m *ConsumerAddrsToPrune) GetVscId() uint64 { +func (m *ConsumerAddrsToPruneV2) GetPruneTs() time.Time { if m != nil { - return m.VscId + return m.PruneTs } - return 0 + return time.Time{} } -func (m *ConsumerAddrsToPrune) GetConsumerAddrs() *AddressList { +func (m *ConsumerAddrsToPruneV2) GetConsumerAddrs() *AddressList { if m != nil { return m.ConsumerAddrs } @@ -1602,7 +1268,7 @@ func (m *ConsensusValidator) Reset() { *m = ConsensusValidator{} } func (m *ConsensusValidator) String() string { return proto.CompactTextString(m) } func (*ConsensusValidator) ProtoMessage() {} func (*ConsensusValidator) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{23} + return fileDescriptor_f22ec409a72b7b72, []int{17} } func (m *ConsensusValidator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1670,7 +1336,7 @@ func (m *ConsumerRewardsAllocation) Reset() { *m = ConsumerRewardsAlloca func (m *ConsumerRewardsAllocation) String() string { return proto.CompactTextString(m) } func (*ConsumerRewardsAllocation) ProtoMessage() {} func (*ConsumerRewardsAllocation) Descriptor() ([]byte, []int) { - return fileDescriptor_f22ec409a72b7b72, []int{24} + return fileDescriptor_f22ec409a72b7b72, []int{18} } func (m *ConsumerRewardsAllocation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1719,17 +1385,11 @@ func init() { proto.RegisterType((*ConsumerRemovalProposals)(nil), "interchain_security.ccv.provider.v1.ConsumerRemovalProposals") proto.RegisterType((*AddressList)(nil), "interchain_security.ccv.provider.v1.AddressList") proto.RegisterType((*ChannelToChain)(nil), "interchain_security.ccv.provider.v1.ChannelToChain") - proto.RegisterType((*VscUnbondingOps)(nil), "interchain_security.ccv.provider.v1.VscUnbondingOps") - proto.RegisterType((*UnbondingOp)(nil), "interchain_security.ccv.provider.v1.UnbondingOp") - proto.RegisterType((*InitTimeoutTimestamp)(nil), "interchain_security.ccv.provider.v1.InitTimeoutTimestamp") - proto.RegisterType((*VscSendTimestamp)(nil), "interchain_security.ccv.provider.v1.VscSendTimestamp") proto.RegisterType((*ValidatorSetChangePackets)(nil), "interchain_security.ccv.provider.v1.ValidatorSetChangePackets") - proto.RegisterType((*MaturedUnbondingOps)(nil), "interchain_security.ccv.provider.v1.MaturedUnbondingOps") - proto.RegisterType((*ExportedVscSendTimestamp)(nil), "interchain_security.ccv.provider.v1.ExportedVscSendTimestamp") proto.RegisterType((*KeyAssignmentReplacement)(nil), "interchain_security.ccv.provider.v1.KeyAssignmentReplacement") proto.RegisterType((*ValidatorConsumerPubKey)(nil), "interchain_security.ccv.provider.v1.ValidatorConsumerPubKey") proto.RegisterType((*ValidatorByConsumerAddr)(nil), "interchain_security.ccv.provider.v1.ValidatorByConsumerAddr") - proto.RegisterType((*ConsumerAddrsToPrune)(nil), "interchain_security.ccv.provider.v1.ConsumerAddrsToPrune") + proto.RegisterType((*ConsumerAddrsToPruneV2)(nil), "interchain_security.ccv.provider.v1.ConsumerAddrsToPruneV2") proto.RegisterType((*ConsensusValidator)(nil), "interchain_security.ccv.provider.v1.ConsensusValidator") proto.RegisterType((*ConsumerRewardsAllocation)(nil), "interchain_security.ccv.provider.v1.ConsumerRewardsAllocation") } @@ -1739,141 +1399,129 @@ func init() { } var fileDescriptor_f22ec409a72b7b72 = []byte{ - // 2138 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0xcb, 0x6f, 0x1b, 0xc7, - 0x19, 0xd7, 0x8a, 0x94, 0x44, 0x0e, 0xf5, 0x1c, 0x29, 0xf1, 0x4a, 0x51, 0x29, 0x7a, 0x53, 0xbb, - 0x6c, 0x5c, 0x93, 0x91, 0x83, 0x00, 0x86, 0xdb, 0x20, 0x90, 0x28, 0x27, 0x96, 0x5d, 0xdb, 0xca, - 0x4a, 0x95, 0xd1, 0xf4, 0xb0, 0x18, 0xce, 0x8e, 0xc8, 0xa9, 0x76, 0x77, 0xd6, 0x33, 0xc3, 0xb5, - 0x79, 0xe9, 0xb9, 0x28, 0x50, 0x20, 0xbd, 0x05, 0xbd, 0x34, 0xed, 0xa9, 0xe8, 0xa9, 0x87, 0xa2, - 0x7f, 0x40, 0x4f, 0x41, 0x2f, 0xcd, 0xb1, 0xa7, 0xa4, 0xb0, 0x0f, 0x3d, 0xf4, 0x0f, 0xe8, 0xb5, - 0x98, 0xd9, 0x27, 0xa9, 0x47, 0x68, 0xa4, 0xb9, 0x48, 0xdc, 0xef, 0xf1, 0x9b, 0x6f, 0x66, 0xbe, - 0xc7, 0x6f, 0x17, 0xdc, 0xa2, 0x81, 0x24, 0x1c, 0xf7, 0x11, 0x0d, 0x1c, 0x41, 0xf0, 0x80, 0x53, - 0x39, 0x6c, 0x63, 0x1c, 0xb5, 0x43, 0xce, 0x22, 0xea, 0x12, 0xde, 0x8e, 0xb6, 0xb3, 0xdf, 0xad, - 0x90, 0x33, 0xc9, 0xe0, 0x9b, 0xe7, 0xf8, 0xb4, 0x30, 0x8e, 0x5a, 0x99, 0x5d, 0xb4, 0xbd, 0x71, - 0xed, 0x22, 0xe0, 0x68, 0xbb, 0xfd, 0x8c, 0x72, 0x12, 0x63, 0x6d, 0xac, 0xf5, 0x58, 0x8f, 0xe9, - 0x9f, 0x6d, 0xf5, 0x2b, 0x91, 0x6e, 0xf5, 0x18, 0xeb, 0x79, 0xa4, 0xad, 0x9f, 0xba, 0x83, 0x93, - 0xb6, 0xa4, 0x3e, 0x11, 0x12, 0xf9, 0x61, 0x62, 0x50, 0x1f, 0x37, 0x70, 0x07, 0x1c, 0x49, 0xca, - 0x82, 0x14, 0x80, 0x76, 0x71, 0x1b, 0x33, 0x4e, 0xda, 0xd8, 0xa3, 0x24, 0x90, 0x6a, 0xd5, 0xf8, - 0x57, 0x62, 0xd0, 0x56, 0x06, 0x1e, 0xed, 0xf5, 0x65, 0x2c, 0x16, 0x6d, 0x49, 0x02, 0x97, 0x70, - 0x9f, 0xc6, 0xc6, 0xf9, 0x53, 0xe2, 0xb0, 0x59, 0xd0, 0x63, 0x3e, 0x0c, 0x25, 0x6b, 0x9f, 0x92, - 0xa1, 0x48, 0xb4, 0xd7, 0x31, 0x13, 0x3e, 0x13, 0x6d, 0xa2, 0xf6, 0x1f, 0x60, 0xd2, 0x8e, 0xb6, - 0xbb, 0x44, 0xa2, 0xed, 0x4c, 0x90, 0xc6, 0x9d, 0xd8, 0x75, 0x91, 0xc8, 0x6d, 0x30, 0xa3, 0x69, - 0xdc, 0xeb, 0xb1, 0xde, 0x89, 0x4f, 0x24, 0x7e, 0x48, 0x54, 0x2b, 0xc8, 0xa7, 0x01, 0x6b, 0xeb, - 0xbf, 0xb1, 0xc8, 0xfa, 0x6f, 0x05, 0x98, 0x1d, 0x16, 0x88, 0x81, 0x4f, 0xf8, 0x8e, 0xeb, 0x52, - 0x75, 0x00, 0x07, 0x9c, 0x85, 0x4c, 0x20, 0x0f, 0xae, 0x81, 0x19, 0x49, 0xa5, 0x47, 0x4c, 0xa3, - 0x61, 0x34, 0xab, 0x76, 0xfc, 0x00, 0x1b, 0xa0, 0xe6, 0x12, 0x81, 0x39, 0x0d, 0x95, 0xb1, 0x39, - 0xad, 0x75, 0x45, 0x11, 0x5c, 0x07, 0x95, 0xf8, 0xd6, 0xa8, 0x6b, 0x96, 0xb4, 0x7a, 0x4e, 0x3f, - 0xef, 0xbb, 0xf0, 0x43, 0xb0, 0x48, 0x03, 0x2a, 0x29, 0xf2, 0x9c, 0x3e, 0x51, 0x67, 0x67, 0x96, - 0x1b, 0x46, 0xb3, 0x76, 0x6b, 0xa3, 0x45, 0xbb, 0xb8, 0xa5, 0x8e, 0xbb, 0x95, 0x1c, 0x72, 0xb4, - 0xdd, 0xba, 0xa7, 0x2d, 0x76, 0xcb, 0x9f, 0x7f, 0xb9, 0x35, 0x65, 0x2f, 0x24, 0x7e, 0xb1, 0x10, - 0x5e, 0x05, 0xf3, 0x3d, 0x12, 0x10, 0x41, 0x85, 0xd3, 0x47, 0xa2, 0x6f, 0xce, 0x34, 0x8c, 0xe6, - 0xbc, 0x5d, 0x4b, 0x64, 0xf7, 0x90, 0xe8, 0xc3, 0x2d, 0x50, 0xeb, 0xd2, 0x00, 0xf1, 0x61, 0x6c, - 0x31, 0xab, 0x2d, 0x40, 0x2c, 0xd2, 0x06, 0x1d, 0x00, 0x44, 0x88, 0x9e, 0x05, 0x8e, 0xca, 0x0d, - 0x73, 0x2e, 0x09, 0x24, 0xce, 0x8b, 0x56, 0x9a, 0x17, 0xad, 0xa3, 0x34, 0x71, 0x76, 0x2b, 0x2a, - 0x90, 0x4f, 0xbe, 0xda, 0x32, 0xec, 0xaa, 0xf6, 0x53, 0x1a, 0xf8, 0x08, 0x2c, 0x0f, 0x82, 0x2e, - 0x0b, 0x5c, 0x1a, 0xf4, 0x9c, 0x90, 0x70, 0xca, 0x5c, 0xb3, 0xa2, 0xa1, 0xd6, 0xcf, 0x40, 0xed, - 0x25, 0x29, 0x16, 0x23, 0x7d, 0xaa, 0x90, 0x96, 0x32, 0xe7, 0x03, 0xed, 0x0b, 0x3f, 0x02, 0x10, - 0xe3, 0x48, 0x87, 0xc4, 0x06, 0x32, 0x45, 0xac, 0x4e, 0x8e, 0xb8, 0x8c, 0x71, 0x74, 0x14, 0x7b, - 0x27, 0x90, 0x3f, 0x03, 0x57, 0x24, 0x47, 0x81, 0x38, 0x21, 0x7c, 0x1c, 0x17, 0x4c, 0x8e, 0xfb, - 0x5a, 0x8a, 0x31, 0x0a, 0x7e, 0x0f, 0x34, 0x70, 0x92, 0x40, 0x0e, 0x27, 0x2e, 0x15, 0x92, 0xd3, - 0xee, 0x40, 0xf9, 0x3a, 0x27, 0x1c, 0x61, 0x9d, 0x23, 0x35, 0x9d, 0x04, 0xf5, 0xd4, 0xce, 0x1e, - 0x31, 0xfb, 0x20, 0xb1, 0x82, 0x8f, 0xc1, 0x77, 0xbb, 0x1e, 0xc3, 0xa7, 0x42, 0x05, 0xe7, 0x8c, - 0x20, 0xe9, 0xa5, 0x7d, 0x2a, 0x84, 0x42, 0x9b, 0x6f, 0x18, 0xcd, 0x92, 0x7d, 0x35, 0xb6, 0x3d, - 0x20, 0x7c, 0xaf, 0x60, 0x79, 0x54, 0x30, 0x84, 0x37, 0x01, 0xec, 0x53, 0x21, 0x19, 0xa7, 0x18, - 0x79, 0x0e, 0x09, 0x24, 0xa7, 0x44, 0x98, 0x0b, 0xda, 0x7d, 0x25, 0xd7, 0xdc, 0x8d, 0x15, 0xf0, - 0x3e, 0xb8, 0x7a, 0xe1, 0xa2, 0x0e, 0xee, 0xa3, 0x20, 0x20, 0x9e, 0xb9, 0xa8, 0xb7, 0xb2, 0xe5, - 0x5e, 0xb0, 0x66, 0x27, 0x36, 0x83, 0xab, 0x60, 0x46, 0xb2, 0xd0, 0x79, 0x64, 0x2e, 0x35, 0x8c, - 0xe6, 0x82, 0x5d, 0x96, 0x2c, 0x7c, 0x04, 0xdf, 0x06, 0x6b, 0x11, 0xf2, 0xa8, 0x8b, 0x24, 0xe3, - 0xc2, 0x09, 0xd9, 0x33, 0xc2, 0x1d, 0x8c, 0x42, 0x73, 0x59, 0xdb, 0xc0, 0x5c, 0x77, 0xa0, 0x54, - 0x1d, 0x14, 0xc2, 0xb7, 0xc0, 0x4a, 0x26, 0x75, 0x04, 0x91, 0xda, 0x7c, 0x45, 0x9b, 0x2f, 0x65, - 0x8a, 0x43, 0x22, 0x95, 0xed, 0x26, 0xa8, 0x22, 0xcf, 0x63, 0xcf, 0x3c, 0x2a, 0xa4, 0x09, 0x1b, - 0xa5, 0x66, 0xd5, 0xce, 0x05, 0x70, 0x03, 0x54, 0x5c, 0x12, 0x0c, 0xb5, 0x72, 0x55, 0x2b, 0xb3, - 0x67, 0xf8, 0x06, 0xa8, 0xfa, 0xaa, 0xc7, 0x4a, 0x74, 0x4a, 0xcc, 0xb5, 0x86, 0xd1, 0x2c, 0xdb, - 0x15, 0x9f, 0x06, 0x87, 0xea, 0x19, 0xb6, 0xc0, 0xaa, 0x46, 0x71, 0x68, 0xa0, 0xee, 0x29, 0x22, - 0x4e, 0x84, 0x3c, 0x61, 0xbe, 0xd6, 0x30, 0x9a, 0x15, 0x7b, 0x45, 0xab, 0xf6, 0x13, 0xcd, 0x31, - 0xf2, 0xc4, 0x9d, 0xeb, 0xbf, 0xfc, 0x6c, 0x6b, 0xea, 0xd3, 0xcf, 0xb6, 0xa6, 0xfe, 0xfe, 0x97, - 0x9b, 0x1b, 0x49, 0xfb, 0xe9, 0xb1, 0xa8, 0x95, 0xb4, 0xaa, 0x56, 0x87, 0x05, 0x92, 0x04, 0xd2, - 0xfa, 0x87, 0x01, 0xae, 0x74, 0xb2, 0x84, 0xf0, 0x59, 0x84, 0xbc, 0x6f, 0xb3, 0xf1, 0xec, 0x80, - 0xaa, 0x50, 0x37, 0xa2, 0x4b, 0xbd, 0xfc, 0x0a, 0xa5, 0x5e, 0x51, 0x6e, 0x4a, 0x71, 0xa7, 0xfe, - 0x35, 0x3b, 0xfa, 0xcf, 0x34, 0xd8, 0x4c, 0x77, 0xf4, 0x90, 0xb9, 0xf4, 0x84, 0x62, 0xf4, 0x6d, - 0xf7, 0xd3, 0x2c, 0xcf, 0xca, 0x13, 0xe4, 0xd9, 0xcc, 0xab, 0xe5, 0xd9, 0xec, 0x04, 0x79, 0x36, - 0x77, 0x59, 0x9e, 0x55, 0x2e, 0xcb, 0xb3, 0xea, 0x64, 0x79, 0x06, 0x2e, 0xc8, 0x33, 0xeb, 0x77, - 0x06, 0x58, 0xbb, 0xfb, 0x74, 0x40, 0x23, 0xf6, 0x7f, 0x3a, 0xe5, 0x07, 0x60, 0x81, 0x14, 0xf0, - 0x84, 0x59, 0x6a, 0x94, 0x9a, 0xb5, 0x5b, 0xd7, 0x5a, 0xc9, 0x95, 0x67, 0x73, 0x38, 0xbd, 0xf7, - 0xe2, 0xea, 0xf6, 0xa8, 0xef, 0x9d, 0x69, 0xd3, 0xb0, 0xfe, 0x66, 0x80, 0x0d, 0xd5, 0x0f, 0x7a, - 0xc4, 0x26, 0xcf, 0x10, 0x77, 0xf7, 0x48, 0xc0, 0x7c, 0xf1, 0x8d, 0xe3, 0xb4, 0xc0, 0x82, 0xab, - 0x91, 0x1c, 0xc9, 0x1c, 0xe4, 0xba, 0x3a, 0x4e, 0x6d, 0xa3, 0x84, 0x47, 0x6c, 0xc7, 0x75, 0x61, - 0x13, 0x2c, 0xe7, 0x36, 0x5c, 0x55, 0x97, 0x4a, 0x7a, 0x65, 0xb6, 0x98, 0x9a, 0xe9, 0x9a, 0x9b, - 0x20, 0xa9, 0x0d, 0xb0, 0xfc, 0xa1, 0xc7, 0xba, 0xc8, 0x3b, 0xf4, 0x90, 0xe8, 0xab, 0x5e, 0x39, - 0x54, 0xc5, 0xc4, 0x49, 0x32, 0xa4, 0x74, 0xf8, 0x13, 0x17, 0x93, 0x72, 0xd3, 0x63, 0xf3, 0x7d, - 0xb0, 0x92, 0x8d, 0x8d, 0x2c, 0xb9, 0xf5, 0x6e, 0x77, 0x57, 0x5f, 0x7c, 0xb9, 0xb5, 0x94, 0x16, - 0x52, 0x47, 0x27, 0xfa, 0x9e, 0xbd, 0x84, 0x47, 0x04, 0x2e, 0xac, 0x83, 0x1a, 0xed, 0x62, 0x47, - 0x90, 0xa7, 0x4e, 0x30, 0xf0, 0x75, 0x5d, 0x94, 0xed, 0x2a, 0xed, 0xe2, 0x43, 0xf2, 0xf4, 0xd1, - 0xc0, 0x87, 0xef, 0x80, 0xd7, 0x53, 0x32, 0xa9, 0x32, 0xc9, 0x51, 0xfe, 0xea, 0xb8, 0xb8, 0x2e, - 0x95, 0x79, 0x7b, 0x35, 0xd5, 0x1e, 0x23, 0x4f, 0x2d, 0xb6, 0xe3, 0xba, 0xdc, 0xfa, 0xd5, 0x1c, - 0x98, 0x3d, 0x40, 0x1c, 0xf9, 0x02, 0x1e, 0x81, 0x25, 0x49, 0xfc, 0xd0, 0x43, 0x92, 0x38, 0x31, - 0x25, 0x49, 0x76, 0x7a, 0x43, 0x53, 0x95, 0x22, 0xf1, 0x6b, 0x15, 0xa8, 0x5e, 0xb4, 0xdd, 0xea, - 0x68, 0xe9, 0xa1, 0x44, 0x92, 0xd8, 0x8b, 0x29, 0x46, 0x2c, 0x84, 0xb7, 0x81, 0x29, 0xf9, 0x40, - 0xc8, 0x9c, 0x2c, 0xe4, 0x53, 0x32, 0xbe, 0xeb, 0xd7, 0x53, 0x7d, 0x3c, 0x5f, 0xb3, 0xe9, 0x78, - 0x3e, 0x2f, 0x28, 0x7d, 0x13, 0x5e, 0x70, 0x08, 0x56, 0x15, 0xa9, 0x1a, 0xc7, 0x2c, 0x4f, 0x8e, - 0xb9, 0xa2, 0xfc, 0x47, 0x41, 0x3f, 0x02, 0x30, 0x12, 0x78, 0x1c, 0x73, 0xe6, 0x15, 0xe2, 0x8c, - 0x04, 0x1e, 0x85, 0x74, 0xc1, 0xa6, 0x50, 0xc9, 0xe7, 0xf8, 0x44, 0x6a, 0x96, 0x11, 0x7a, 0x24, - 0xa0, 0xa2, 0x9f, 0x82, 0xcf, 0x4e, 0x0e, 0xbe, 0xae, 0x81, 0x1e, 0x2a, 0x1c, 0x3b, 0x85, 0x49, - 0x56, 0xe9, 0x80, 0xfa, 0xf9, 0xab, 0x64, 0x17, 0x34, 0xa7, 0x2f, 0xe8, 0x8d, 0x73, 0x20, 0xb2, - 0x5b, 0x12, 0xe0, 0x7a, 0x81, 0x0d, 0xa9, 0xaa, 0x77, 0x74, 0xc1, 0x39, 0x9c, 0xf4, 0x14, 0x65, - 0x40, 0x31, 0x31, 0x22, 0x24, 0x63, 0x74, 0x49, 0xed, 0x29, 0x3a, 0x5f, 0x28, 0x3e, 0x1a, 0x24, - 0xb4, 0xd7, 0xca, 0x49, 0x53, 0xd6, 0x43, 0xec, 0x02, 0xd6, 0x07, 0x84, 0xa8, 0x6a, 0x2f, 0x10, - 0x27, 0x12, 0x32, 0xdc, 0xd7, 0x7d, 0xb3, 0x64, 0x2f, 0x66, 0x24, 0xe9, 0xae, 0x92, 0xc2, 0x8f, - 0xc1, 0x8d, 0x60, 0xe0, 0x77, 0x09, 0x77, 0xd8, 0x49, 0x6c, 0xa8, 0x3b, 0x84, 0x90, 0x88, 0x4b, - 0x87, 0x13, 0x4c, 0x68, 0xa4, 0x32, 0x33, 0x8e, 0x5c, 0x68, 0xde, 0x56, 0xb2, 0xaf, 0xc5, 0x2e, - 0x8f, 0x4f, 0x34, 0x86, 0x38, 0x62, 0x87, 0xca, 0xdc, 0x4e, 0xad, 0xe3, 0xc0, 0x04, 0xdc, 0x07, - 0x57, 0x7d, 0xf4, 0xdc, 0xc9, 0x8a, 0x4e, 0x05, 0x4e, 0x02, 0x31, 0x10, 0x4e, 0x3e, 0x70, 0x12, - 0xee, 0x56, 0xf7, 0xd1, 0xf3, 0x83, 0xc4, 0xae, 0x93, 0x9a, 0x1d, 0x67, 0x56, 0xf7, 0xcb, 0x95, - 0xca, 0x72, 0xd5, 0xfa, 0x3e, 0xa8, 0xea, 0x9e, 0xb3, 0x83, 0x4f, 0x85, 0x9e, 0x3a, 0xae, 0xcb, - 0x89, 0x10, 0x44, 0x98, 0x46, 0x32, 0x75, 0x52, 0x81, 0x25, 0xc1, 0xfa, 0x45, 0x6f, 0x31, 0x02, - 0x3e, 0x01, 0x73, 0x21, 0xd1, 0x14, 0x5b, 0x3b, 0xd6, 0x6e, 0xbd, 0xd7, 0x9a, 0xe0, 0xf5, 0xb3, - 0x75, 0x11, 0xa0, 0x9d, 0xa2, 0x59, 0x3c, 0x7f, 0x77, 0x1a, 0x63, 0x30, 0x02, 0x1e, 0x8f, 0x2f, - 0xfa, 0xa3, 0x57, 0x5a, 0x74, 0x0c, 0x2f, 0x5f, 0xf3, 0x06, 0xa8, 0xed, 0xc4, 0xdb, 0xfe, 0xb1, - 0x1a, 0xa9, 0x67, 0x8e, 0x65, 0xbe, 0x78, 0x2c, 0xf7, 0xc1, 0x62, 0x42, 0x48, 0x8f, 0x98, 0xee, - 0x9b, 0xf0, 0x3b, 0x00, 0x24, 0x4c, 0x56, 0xf5, 0xdb, 0x78, 0xf2, 0x54, 0x13, 0xc9, 0xbe, 0x3b, - 0xc2, 0x34, 0xa6, 0x47, 0x98, 0x86, 0x65, 0x83, 0xa5, 0x63, 0x81, 0x7f, 0x92, 0xbe, 0xad, 0x3c, - 0x0e, 0x05, 0x7c, 0x0d, 0xcc, 0xaa, 0x52, 0x4f, 0x80, 0xca, 0xf6, 0x4c, 0x24, 0xf0, 0xbe, 0x1e, - 0x3e, 0xf9, 0x1b, 0x11, 0x0b, 0x1d, 0xea, 0x0a, 0x73, 0xba, 0x51, 0x6a, 0x96, 0xed, 0xc5, 0x41, - 0xee, 0xbe, 0xef, 0x0a, 0xeb, 0xa7, 0xa0, 0x56, 0x00, 0x84, 0x8b, 0x60, 0x3a, 0xc3, 0x9a, 0xa6, - 0x2e, 0xbc, 0x03, 0xd6, 0x73, 0xa0, 0xd1, 0x69, 0x11, 0x23, 0x56, 0xed, 0x2b, 0x99, 0xc1, 0xc8, - 0xc0, 0x10, 0xd6, 0x63, 0xb0, 0xb6, 0x9f, 0xf7, 0xa6, 0x6c, 0x16, 0x8d, 0xec, 0xd0, 0x18, 0xe5, - 0x52, 0x9b, 0xa0, 0x9a, 0x7d, 0x24, 0xd0, 0xbb, 0x2f, 0xdb, 0xb9, 0xc0, 0xf2, 0xc1, 0xf2, 0xb1, - 0xc0, 0x87, 0x24, 0x70, 0x73, 0xb0, 0x0b, 0x0e, 0x60, 0x77, 0x1c, 0x68, 0xe2, 0xd7, 0xca, 0x7c, - 0x39, 0x06, 0xd6, 0x8f, 0x8b, 0xc4, 0x4b, 0xf3, 0x88, 0x03, 0x84, 0x4f, 0x89, 0x14, 0xd0, 0x06, - 0x65, 0x4d, 0xb0, 0xe2, 0xcc, 0xba, 0x7d, 0x61, 0x66, 0x45, 0xdb, 0xad, 0x8b, 0x40, 0xf6, 0x90, - 0x44, 0x49, 0x8b, 0xd1, 0x58, 0xd6, 0xf7, 0xc0, 0xea, 0x43, 0x24, 0x07, 0x9c, 0xb8, 0x23, 0x77, - 0xbc, 0x0c, 0x4a, 0xea, 0xfe, 0x0c, 0x7d, 0x7f, 0xea, 0xa7, 0xf5, 0x07, 0x03, 0x98, 0x77, 0x9f, - 0x87, 0x8c, 0x4b, 0xe2, 0x9e, 0x39, 0x91, 0x4b, 0x8e, 0xf7, 0x14, 0xac, 0xaa, 0xc3, 0x12, 0x24, - 0x70, 0x9d, 0x6c, 0x9f, 0xf1, 0x3d, 0xd6, 0x6e, 0xbd, 0x3b, 0x51, 0x75, 0x8c, 0x2f, 0x97, 0x6c, - 0x60, 0x25, 0x1a, 0x93, 0x0b, 0xeb, 0x37, 0x06, 0x30, 0x1f, 0x90, 0xe1, 0x8e, 0x10, 0xb4, 0x17, - 0xf8, 0x24, 0x90, 0xaa, 0x55, 0x23, 0x4c, 0xd4, 0x4f, 0xf8, 0x26, 0x58, 0xc8, 0xba, 0x94, 0x66, - 0x04, 0x86, 0x66, 0x04, 0xf3, 0xa9, 0x50, 0x15, 0x18, 0xbc, 0x03, 0x40, 0xc8, 0x49, 0xe4, 0x60, - 0xe7, 0x94, 0x0c, 0x93, 0x5b, 0xdc, 0x2c, 0x4e, 0xfa, 0xf8, 0x13, 0x4e, 0xeb, 0x60, 0xd0, 0xf5, - 0x28, 0x7e, 0x40, 0x86, 0x76, 0x45, 0xd9, 0x77, 0x1e, 0x90, 0xa1, 0xa2, 0x76, 0x9a, 0x75, 0xeb, - 0xf1, 0x5c, 0xb2, 0xe3, 0x07, 0xeb, 0xb7, 0x06, 0xb8, 0x92, 0x5d, 0x47, 0x9a, 0xae, 0x07, 0x83, - 0xae, 0xf2, 0xb8, 0xe4, 0xdc, 0xce, 0x44, 0x3b, 0x7d, 0x4e, 0xb4, 0xef, 0x83, 0xf9, 0xac, 0x40, - 0x54, 0xbc, 0xa5, 0x09, 0xe2, 0xad, 0xa5, 0x1e, 0x0f, 0xc8, 0xd0, 0xfa, 0x45, 0x21, 0xb6, 0xdd, - 0x61, 0xa1, 0xf7, 0xf1, 0xaf, 0x89, 0x2d, 0x5b, 0xb6, 0x18, 0x1b, 0x2e, 0xfa, 0x9f, 0xd9, 0x40, - 0xe9, 0xec, 0x06, 0xac, 0xdf, 0x1b, 0x60, 0xad, 0xb8, 0xaa, 0x38, 0x62, 0x07, 0x7c, 0x10, 0x90, - 0xcb, 0x56, 0xcf, 0xcb, 0x6f, 0xba, 0x58, 0x7e, 0x4f, 0xc0, 0xe2, 0x48, 0x50, 0x22, 0x39, 0x8d, - 0xb7, 0x27, 0xca, 0xb1, 0x42, 0x77, 0xb5, 0x17, 0x8a, 0xfb, 0x10, 0xd6, 0x5f, 0x0d, 0x00, 0xcf, - 0x8e, 0x2b, 0xf8, 0x03, 0x00, 0x47, 0x86, 0x5e, 0x31, 0xa7, 0x96, 0xc3, 0xc2, 0x98, 0xd3, 0xa7, - 0x91, 0xe5, 0xc6, 0x74, 0x21, 0x37, 0xe0, 0x0f, 0x01, 0x08, 0xf5, 0xc5, 0x4c, 0x7c, 0x7b, 0xd5, - 0x30, 0xfd, 0x09, 0xb7, 0x40, 0xed, 0xe7, 0x8c, 0x06, 0xc5, 0x2f, 0x6a, 0x25, 0x1b, 0x28, 0x51, - 0xfc, 0xb1, 0xcc, 0xfa, 0xb5, 0x91, 0xcf, 0xc7, 0x64, 0x5c, 0xef, 0x78, 0x5e, 0xf2, 0xb2, 0x02, - 0x43, 0x30, 0x97, 0x0e, 0xfc, 0xb8, 0xa1, 0x6c, 0x9e, 0x4b, 0x4a, 0xf6, 0x08, 0xd6, 0xbc, 0xe4, - 0xb6, 0xaa, 0xb9, 0x3f, 0x7d, 0xb5, 0x75, 0xa3, 0x47, 0x65, 0x7f, 0xd0, 0x6d, 0x61, 0xe6, 0x27, - 0x9f, 0x19, 0x93, 0x7f, 0x37, 0x85, 0x7b, 0xda, 0x96, 0xc3, 0x90, 0x88, 0xd4, 0x47, 0xfc, 0xf1, - 0xdf, 0x7f, 0x7e, 0xcb, 0xb0, 0xd3, 0x65, 0x76, 0x9f, 0x7c, 0xfe, 0xa2, 0x6e, 0x7c, 0xf1, 0xa2, - 0x6e, 0xfc, 0xeb, 0x45, 0xdd, 0xf8, 0xe4, 0x65, 0x7d, 0xea, 0x8b, 0x97, 0xf5, 0xa9, 0x7f, 0xbe, - 0xac, 0x4f, 0x7d, 0xfc, 0xde, 0x59, 0xd0, 0xfc, 0xd2, 0x6e, 0x66, 0x5f, 0x81, 0xa3, 0x77, 0xdb, - 0xcf, 0x47, 0xbf, 0x31, 0xeb, 0xf5, 0xba, 0xb3, 0xba, 0xbd, 0xbe, 0xf3, 0xbf, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xdd, 0xa1, 0xb4, 0x71, 0x94, 0x16, 0x00, 0x00, + // 1946 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0xcd, 0x6f, 0x1b, 0xc7, + 0x15, 0xd7, 0x8a, 0x94, 0x44, 0x0e, 0xf5, 0x39, 0x52, 0xec, 0x95, 0xa2, 0x92, 0x34, 0x53, 0x1b, + 0x6c, 0x5c, 0x2f, 0x23, 0x05, 0x05, 0x0c, 0xb7, 0x81, 0x21, 0x51, 0x4e, 0x6c, 0xa9, 0x71, 0xd8, + 0x15, 0xa1, 0x00, 0xe9, 0x61, 0x31, 0x9c, 0x1d, 0x91, 0x53, 0xed, 0xee, 0xac, 0x67, 0x86, 0x2b, + 0xf3, 0xd2, 0x73, 0x2f, 0x05, 0xd2, 0x5b, 0xd0, 0x4b, 0x73, 0x2c, 0x7a, 0xea, 0xa1, 0xe8, 0x1f, + 0xd0, 0x53, 0x50, 0xa0, 0x68, 0x8e, 0x3d, 0x25, 0x85, 0x7d, 0xe8, 0xa1, 0x40, 0xaf, 0xbd, 0x16, + 0x33, 0xfb, 0xc1, 0xa5, 0x3e, 0x1c, 0x1a, 0x69, 0x2e, 0xd2, 0xee, 0x7b, 0xbf, 0xf7, 0x9b, 0x37, + 0x33, 0xef, 0x8b, 0x0b, 0x76, 0x69, 0x20, 0x09, 0xc7, 0x03, 0x44, 0x03, 0x47, 0x10, 0x3c, 0xe4, + 0x54, 0x8e, 0x5a, 0x18, 0x47, 0xad, 0x90, 0xb3, 0x88, 0xba, 0x84, 0xb7, 0xa2, 0x9d, 0xec, 0xd9, + 0x0a, 0x39, 0x93, 0x0c, 0xbe, 0x75, 0x85, 0x8d, 0x85, 0x71, 0x64, 0x65, 0xb8, 0x68, 0x67, 0xeb, + 0xf6, 0x75, 0xc4, 0xd1, 0x4e, 0xeb, 0x9c, 0x72, 0x12, 0x73, 0x6d, 0x6d, 0xf4, 0x59, 0x9f, 0xe9, + 0xc7, 0x96, 0x7a, 0x4a, 0xa4, 0xb5, 0x3e, 0x63, 0x7d, 0x8f, 0xb4, 0xf4, 0x5b, 0x6f, 0x78, 0xda, + 0x92, 0xd4, 0x27, 0x42, 0x22, 0x3f, 0x4c, 0x00, 0xd5, 0x8b, 0x00, 0x77, 0xc8, 0x91, 0xa4, 0x2c, + 0x48, 0x09, 0x68, 0x0f, 0xb7, 0x30, 0xe3, 0xa4, 0x85, 0x3d, 0x4a, 0x02, 0xa9, 0x56, 0x8d, 0x9f, + 0x12, 0x40, 0x4b, 0x01, 0x3c, 0xda, 0x1f, 0xc8, 0x58, 0x2c, 0x5a, 0x92, 0x04, 0x2e, 0xe1, 0x3e, + 0x8d, 0xc1, 0xe3, 0xb7, 0xc4, 0x60, 0x3b, 0xa7, 0xc7, 0x7c, 0x14, 0x4a, 0xd6, 0x3a, 0x23, 0x23, + 0x91, 0x68, 0xef, 0x60, 0x26, 0x7c, 0x26, 0x5a, 0x44, 0xed, 0x3f, 0xc0, 0xa4, 0x15, 0xed, 0xf4, + 0x88, 0x44, 0x3b, 0x99, 0x20, 0xf5, 0x3b, 0xc1, 0xf5, 0x90, 0x18, 0x63, 0x30, 0xa3, 0xa9, 0xdf, + 0x9b, 0xb1, 0xde, 0x89, 0x4f, 0x24, 0x7e, 0x49, 0x54, 0x6b, 0xc8, 0xa7, 0x01, 0x6b, 0xe9, 0xbf, + 0xb1, 0xa8, 0xf1, 0xdf, 0x12, 0x30, 0xdb, 0x2c, 0x10, 0x43, 0x9f, 0xf0, 0x3d, 0xd7, 0xa5, 0xea, + 0x00, 0x3a, 0x9c, 0x85, 0x4c, 0x20, 0x0f, 0x6e, 0x80, 0x39, 0x49, 0xa5, 0x47, 0x4c, 0xa3, 0x6e, + 0x34, 0xcb, 0x76, 0xfc, 0x02, 0xeb, 0xa0, 0xe2, 0x12, 0x81, 0x39, 0x0d, 0x15, 0xd8, 0x9c, 0xd5, + 0xba, 0xbc, 0x08, 0x6e, 0x82, 0x52, 0x7c, 0x6b, 0xd4, 0x35, 0x0b, 0x5a, 0xbd, 0xa0, 0xdf, 0x9f, + 0xb8, 0xf0, 0x03, 0xb0, 0x4c, 0x03, 0x2a, 0x29, 0xf2, 0x9c, 0x01, 0x51, 0x67, 0x67, 0x16, 0xeb, + 0x46, 0xb3, 0xb2, 0xbb, 0x65, 0xd1, 0x1e, 0xb6, 0xd4, 0x71, 0x5b, 0xc9, 0x21, 0x47, 0x3b, 0xd6, + 0x63, 0x8d, 0xd8, 0x2f, 0x7e, 0xf1, 0x55, 0x6d, 0xc6, 0x5e, 0x4a, 0xec, 0x62, 0x21, 0xbc, 0x05, + 0x16, 0xfb, 0x24, 0x20, 0x82, 0x0a, 0x67, 0x80, 0xc4, 0xc0, 0x9c, 0xab, 0x1b, 0xcd, 0x45, 0xbb, + 0x92, 0xc8, 0x1e, 0x23, 0x31, 0x80, 0x35, 0x50, 0xe9, 0xd1, 0x00, 0xf1, 0x51, 0x8c, 0x98, 0xd7, + 0x08, 0x10, 0x8b, 0x34, 0xa0, 0x0d, 0x80, 0x08, 0xd1, 0x79, 0xe0, 0xa8, 0xd8, 0x30, 0x17, 0x12, + 0x47, 0xe2, 0xb8, 0xb0, 0xd2, 0xb8, 0xb0, 0xba, 0x69, 0xe0, 0xec, 0x97, 0x94, 0x23, 0x9f, 0x7e, + 0x5d, 0x33, 0xec, 0xb2, 0xb6, 0x53, 0x1a, 0xf8, 0x14, 0xac, 0x0e, 0x83, 0x1e, 0x0b, 0x5c, 0x1a, + 0xf4, 0x9d, 0x90, 0x70, 0xca, 0x5c, 0xb3, 0xa4, 0xa9, 0x36, 0x2f, 0x51, 0x1d, 0x24, 0x21, 0x16, + 0x33, 0x7d, 0xa6, 0x98, 0x56, 0x32, 0xe3, 0x8e, 0xb6, 0x85, 0x3f, 0x03, 0x10, 0xe3, 0x48, 0xbb, + 0xc4, 0x86, 0x32, 0x65, 0x2c, 0x4f, 0xcf, 0xb8, 0x8a, 0x71, 0xd4, 0x8d, 0xad, 0x13, 0xca, 0x9f, + 0x83, 0x9b, 0x92, 0xa3, 0x40, 0x9c, 0x12, 0x7e, 0x91, 0x17, 0x4c, 0xcf, 0xfb, 0x46, 0xca, 0x31, + 0x49, 0xfe, 0x18, 0xd4, 0x71, 0x12, 0x40, 0x0e, 0x27, 0x2e, 0x15, 0x92, 0xd3, 0xde, 0x50, 0xd9, + 0x3a, 0xa7, 0x1c, 0x61, 0x1d, 0x23, 0x15, 0x1d, 0x04, 0xd5, 0x14, 0x67, 0x4f, 0xc0, 0xde, 0x4f, + 0x50, 0xf0, 0x23, 0xf0, 0xfd, 0x9e, 0xc7, 0xf0, 0x99, 0x50, 0xce, 0x39, 0x13, 0x4c, 0x7a, 0x69, + 0x9f, 0x0a, 0xa1, 0xd8, 0x16, 0xeb, 0x46, 0xb3, 0x60, 0xdf, 0x8a, 0xb1, 0x1d, 0xc2, 0x0f, 0x72, + 0xc8, 0x6e, 0x0e, 0x08, 0xef, 0x01, 0x38, 0xa0, 0x42, 0x32, 0x4e, 0x31, 0xf2, 0x1c, 0x12, 0x48, + 0x4e, 0x89, 0x30, 0x97, 0xb4, 0xf9, 0xda, 0x58, 0xf3, 0x28, 0x56, 0xc0, 0x43, 0x70, 0xeb, 0xda, + 0x45, 0x1d, 0x3c, 0x40, 0x41, 0x40, 0x3c, 0x73, 0x59, 0x6f, 0xa5, 0xe6, 0x5e, 0xb3, 0x66, 0x3b, + 0x86, 0xc1, 0x75, 0x30, 0x27, 0x59, 0xe8, 0x3c, 0x35, 0x57, 0xea, 0x46, 0x73, 0xc9, 0x2e, 0x4a, + 0x16, 0x3e, 0x85, 0xef, 0x80, 0x8d, 0x08, 0x79, 0xd4, 0x45, 0x92, 0x71, 0xe1, 0x84, 0xec, 0x9c, + 0x70, 0x07, 0xa3, 0xd0, 0x5c, 0xd5, 0x18, 0x38, 0xd6, 0x75, 0x94, 0xaa, 0x8d, 0x42, 0xf8, 0x36, + 0x58, 0xcb, 0xa4, 0x8e, 0x20, 0x52, 0xc3, 0xd7, 0x34, 0x7c, 0x25, 0x53, 0x1c, 0x13, 0xa9, 0xb0, + 0xdb, 0xa0, 0x8c, 0x3c, 0x8f, 0x9d, 0x7b, 0x54, 0x48, 0x13, 0xd6, 0x0b, 0xcd, 0xb2, 0x3d, 0x16, + 0xc0, 0x2d, 0x50, 0x72, 0x49, 0x30, 0xd2, 0xca, 0x75, 0xad, 0xcc, 0xde, 0xe1, 0x9b, 0xa0, 0xec, + 0xab, 0x1a, 0x2b, 0xd1, 0x19, 0x31, 0x37, 0xea, 0x46, 0xb3, 0x68, 0x97, 0x7c, 0x1a, 0x1c, 0xab, + 0x77, 0x68, 0x81, 0x75, 0xcd, 0xe2, 0xd0, 0x40, 0xdd, 0x53, 0x44, 0x9c, 0x08, 0x79, 0xc2, 0x7c, + 0xa3, 0x6e, 0x34, 0x4b, 0xf6, 0x9a, 0x56, 0x3d, 0x49, 0x34, 0x27, 0xc8, 0x13, 0x0f, 0xee, 0xfc, + 0xea, 0xf3, 0xda, 0xcc, 0x67, 0x9f, 0xd7, 0x66, 0xfe, 0xfa, 0xa7, 0x7b, 0x5b, 0x49, 0xf9, 0xe9, + 0xb3, 0xc8, 0x4a, 0x4a, 0x95, 0xd5, 0x66, 0x81, 0x24, 0x81, 0x6c, 0xfc, 0xdd, 0x00, 0x37, 0xdb, + 0x59, 0x40, 0xf8, 0x2c, 0x42, 0xde, 0x77, 0x59, 0x78, 0xf6, 0x40, 0x59, 0xa8, 0x1b, 0xd1, 0xa9, + 0x5e, 0x7c, 0x8d, 0x54, 0x2f, 0x29, 0x33, 0xa5, 0x78, 0x50, 0xfd, 0x86, 0x1d, 0xfd, 0x7b, 0x16, + 0x6c, 0xa7, 0x3b, 0xfa, 0x90, 0xb9, 0xf4, 0x94, 0x62, 0xf4, 0x5d, 0xd7, 0xd3, 0x2c, 0xce, 0x8a, + 0x53, 0xc4, 0xd9, 0xdc, 0xeb, 0xc5, 0xd9, 0xfc, 0x14, 0x71, 0xb6, 0xf0, 0xaa, 0x38, 0x2b, 0xbd, + 0x2a, 0xce, 0xca, 0xd3, 0xc5, 0x19, 0xb8, 0x26, 0xce, 0x1a, 0xbf, 0x33, 0xc0, 0xc6, 0xa3, 0x67, + 0x43, 0x1a, 0xb1, 0xff, 0xd3, 0x29, 0x1f, 0x81, 0x25, 0x92, 0xe3, 0x13, 0x66, 0xa1, 0x5e, 0x68, + 0x56, 0x76, 0x6f, 0x5b, 0xc9, 0x95, 0x67, 0x7d, 0x38, 0xbd, 0xf7, 0xfc, 0xea, 0xf6, 0xa4, 0xed, + 0x83, 0x59, 0xd3, 0x68, 0xfc, 0xc5, 0x00, 0x5b, 0xaa, 0x1e, 0xf4, 0x89, 0x4d, 0xce, 0x11, 0x77, + 0x0f, 0x48, 0xc0, 0x7c, 0xf1, 0xad, 0xfd, 0x6c, 0x80, 0x25, 0x57, 0x33, 0x39, 0x92, 0x39, 0xc8, + 0x75, 0xb5, 0x9f, 0x1a, 0xa3, 0x84, 0x5d, 0xb6, 0xe7, 0xba, 0xb0, 0x09, 0x56, 0xc7, 0x18, 0xae, + 0xb2, 0x4b, 0x05, 0xbd, 0x82, 0x2d, 0xa7, 0x30, 0x9d, 0x73, 0x53, 0x04, 0xb5, 0x01, 0x56, 0x3f, + 0xf0, 0x58, 0x0f, 0x79, 0xc7, 0x1e, 0x12, 0x03, 0x55, 0x2b, 0x47, 0x2a, 0x99, 0x38, 0x49, 0x9a, + 0x94, 0x76, 0x7f, 0xea, 0x64, 0x52, 0x66, 0xba, 0x6d, 0x3e, 0x04, 0x6b, 0x59, 0xdb, 0xc8, 0x82, + 0x5b, 0xef, 0x76, 0x7f, 0xfd, 0xc5, 0x57, 0xb5, 0x95, 0x34, 0x91, 0xda, 0x3a, 0xd0, 0x0f, 0xec, + 0x15, 0x3c, 0x21, 0x70, 0x61, 0x15, 0x54, 0x68, 0x0f, 0x3b, 0x82, 0x3c, 0x73, 0x82, 0xa1, 0xaf, + 0xf3, 0xa2, 0x68, 0x97, 0x69, 0x0f, 0x1f, 0x93, 0x67, 0x4f, 0x87, 0x3e, 0x7c, 0x17, 0xdc, 0x48, + 0x87, 0x49, 0x15, 0x49, 0x8e, 0xb2, 0x57, 0xc7, 0xc5, 0x75, 0xaa, 0x2c, 0xda, 0xeb, 0xa9, 0xf6, + 0x04, 0x79, 0x6a, 0xb1, 0x3d, 0xd7, 0xe5, 0x8d, 0xff, 0xcc, 0x81, 0xf9, 0x0e, 0xe2, 0xc8, 0x17, + 0xb0, 0x0b, 0x56, 0x24, 0xf1, 0x43, 0x0f, 0x49, 0xe2, 0xc4, 0x23, 0x49, 0xb2, 0xd3, 0xbb, 0x7a, + 0x54, 0xc9, 0x0f, 0x7e, 0x56, 0x6e, 0xd4, 0x8b, 0x76, 0xac, 0xb6, 0x96, 0x1e, 0x4b, 0x24, 0x89, + 0xbd, 0x9c, 0x72, 0xc4, 0x42, 0x78, 0x1f, 0x98, 0x92, 0x0f, 0x85, 0x1c, 0x0f, 0x0b, 0xe3, 0x2e, + 0x19, 0xdf, 0xf5, 0x8d, 0x54, 0x1f, 0xf7, 0xd7, 0xac, 0x3b, 0x5e, 0x3d, 0x17, 0x14, 0xbe, 0xcd, + 0x5c, 0xe0, 0x82, 0x6d, 0xa1, 0x2e, 0xd5, 0xf1, 0x89, 0xd4, 0xdd, 0x3b, 0xf4, 0x48, 0x40, 0xc5, + 0x20, 0x25, 0x9f, 0x9f, 0x9e, 0x7c, 0x53, 0x13, 0x7d, 0xa8, 0x78, 0xec, 0x94, 0x26, 0x59, 0xa5, + 0x0d, 0xaa, 0x57, 0xaf, 0x92, 0x6d, 0x7c, 0x41, 0x6f, 0xfc, 0xcd, 0x2b, 0x28, 0xb2, 0xdd, 0x0b, + 0x70, 0x27, 0x37, 0x65, 0xa8, 0x6c, 0x72, 0x74, 0x20, 0x3b, 0x9c, 0xf4, 0x55, 0x2b, 0x46, 0xf1, + 0xc0, 0x41, 0x48, 0x36, 0x29, 0x25, 0x31, 0xad, 0xc6, 0xe4, 0x5c, 0x50, 0xd3, 0x20, 0x19, 0x27, + 0x1b, 0xe3, 0x61, 0x24, 0xcb, 0x4d, 0x3b, 0xc7, 0xf5, 0x3e, 0x21, 0x2a, 0x8b, 0x72, 0x03, 0x09, + 0x09, 0x19, 0x1e, 0xe8, 0x7a, 0x54, 0xb0, 0x97, 0xb3, 0xe1, 0xe3, 0x91, 0x92, 0xc2, 0x4f, 0xc0, + 0xdd, 0x60, 0xe8, 0xf7, 0x08, 0x77, 0xd8, 0x69, 0x0c, 0xd4, 0x99, 0x27, 0x24, 0xe2, 0xd2, 0xe1, + 0x04, 0x13, 0x1a, 0xa9, 0x1b, 0x8f, 0x3d, 0x17, 0x7a, 0x1e, 0x2a, 0xd8, 0xb7, 0x63, 0x93, 0x8f, + 0x4e, 0x35, 0x87, 0xe8, 0xb2, 0x63, 0x05, 0xb7, 0x53, 0x74, 0xec, 0x98, 0x80, 0x4f, 0xc0, 0x2d, + 0x1f, 0x3d, 0x77, 0xb2, 0x60, 0x56, 0x8e, 0x93, 0x40, 0x0c, 0x85, 0x33, 0x2e, 0xe4, 0xc9, 0x4c, + 0x54, 0xf5, 0xd1, 0xf3, 0x4e, 0x82, 0x6b, 0xa7, 0xb0, 0x93, 0x0c, 0x75, 0x58, 0x2c, 0x15, 0x57, + 0xe7, 0x0e, 0x8b, 0xa5, 0xb9, 0xd5, 0xf9, 0xc3, 0x62, 0xa9, 0xb4, 0x5a, 0x6e, 0xfc, 0x00, 0x94, + 0x75, 0x5e, 0xef, 0xe1, 0x33, 0xa1, 0x2b, 0xbb, 0xeb, 0x72, 0x22, 0x04, 0x11, 0xa6, 0x91, 0x54, + 0xf6, 0x54, 0xd0, 0x90, 0x60, 0xf3, 0xba, 0x5f, 0x0a, 0x02, 0x7e, 0x0c, 0x16, 0x42, 0xa2, 0xc7, + 0x58, 0x6d, 0x58, 0xd9, 0x7d, 0xcf, 0x9a, 0xe2, 0x27, 0x9e, 0x75, 0x1d, 0xa1, 0x9d, 0xb2, 0x35, + 0xf8, 0xf8, 0xf7, 0xc9, 0x85, 0x29, 0x41, 0xc0, 0x93, 0x8b, 0x8b, 0xfe, 0xe4, 0xb5, 0x16, 0xbd, + 0xc0, 0x37, 0x5e, 0xf3, 0x2e, 0xa8, 0xec, 0xc5, 0xdb, 0xfe, 0xa9, 0x6a, 0x5b, 0x97, 0x8e, 0x65, + 0x31, 0x7f, 0x2c, 0x87, 0x60, 0x39, 0x19, 0xfa, 0xba, 0x4c, 0xd7, 0x26, 0xf8, 0x3d, 0x00, 0x92, + 0x69, 0x51, 0xd5, 0xb4, 0xb8, 0xba, 0x97, 0x13, 0xc9, 0x13, 0x77, 0xa2, 0x9b, 0xcf, 0x4e, 0x74, + 0xf3, 0x06, 0x03, 0x9b, 0x27, 0xf9, 0x6e, 0xab, 0x9b, 0x47, 0x07, 0xe1, 0x33, 0x22, 0x05, 0xb4, + 0x41, 0x51, 0x77, 0xd5, 0x78, 0xab, 0xf7, 0xaf, 0xdd, 0x6a, 0xb4, 0x63, 0x5d, 0x47, 0x72, 0x80, + 0x24, 0x4a, 0xe2, 0x5f, 0x73, 0x35, 0x7e, 0x63, 0x00, 0xf3, 0x88, 0x8c, 0xf6, 0x84, 0xa0, 0xfd, + 0xc0, 0x27, 0x81, 0x54, 0x99, 0x87, 0x30, 0x51, 0x8f, 0xf0, 0x2d, 0xb0, 0x94, 0x05, 0x9d, 0x2e, + 0x9c, 0x86, 0x2e, 0x9c, 0x8b, 0xa9, 0x50, 0x9d, 0x11, 0x7c, 0x00, 0x40, 0xc8, 0x49, 0xe4, 0x60, + 0xe7, 0x8c, 0x8c, 0xf4, 0x7e, 0x2a, 0xbb, 0xdb, 0xf9, 0x82, 0x18, 0xff, 0xd2, 0xb5, 0x3a, 0xc3, + 0x9e, 0x47, 0xf1, 0x11, 0x19, 0xd9, 0x25, 0x85, 0x6f, 0x1f, 0x91, 0x91, 0xea, 0x80, 0x7a, 0x38, + 0xd1, 0x55, 0xac, 0x60, 0xc7, 0x2f, 0x8d, 0xdf, 0x1a, 0xe0, 0x66, 0xb6, 0x81, 0xf4, 0xae, 0x3a, + 0xc3, 0x9e, 0xb2, 0xc8, 0x9f, 0x9d, 0x31, 0x39, 0x09, 0x5d, 0xf2, 0x76, 0xf6, 0x0a, 0x6f, 0x1f, + 0x82, 0xc5, 0xac, 0x8c, 0x28, 0x7f, 0x0b, 0x53, 0xf8, 0x5b, 0x49, 0x2d, 0x8e, 0xc8, 0xa8, 0xf1, + 0xcb, 0x9c, 0x6f, 0xfb, 0xa3, 0x5c, 0xf8, 0xf2, 0x6f, 0xf0, 0x2d, 0x5b, 0x36, 0xef, 0x1b, 0xce, + 0xdb, 0x5f, 0xda, 0x40, 0xe1, 0xf2, 0x06, 0x1a, 0x7f, 0x33, 0xc0, 0x8d, 0xfc, 0xaa, 0xa2, 0xcb, + 0x3a, 0x7c, 0x18, 0x90, 0x93, 0xdd, 0x57, 0xad, 0xff, 0x10, 0x94, 0x42, 0x85, 0x72, 0xa4, 0x48, + 0xae, 0x68, 0xba, 0x76, 0xbd, 0xa0, 0xad, 0xba, 0x2a, 0xbd, 0x97, 0x27, 0x36, 0x20, 0x92, 0x93, + 0x7b, 0x67, 0xaa, 0x84, 0xcb, 0x25, 0x93, 0xbd, 0x94, 0xdf, 0xb3, 0x68, 0xfc, 0xd9, 0x00, 0xf0, + 0x72, 0xa5, 0x82, 0x3f, 0x04, 0x70, 0xa2, 0xde, 0xe5, 0xe3, 0x6f, 0x35, 0xcc, 0x55, 0x38, 0x7d, + 0x72, 0x59, 0x1c, 0xcd, 0xe6, 0xe2, 0x08, 0xfe, 0x18, 0x80, 0x50, 0x5f, 0xe2, 0xd4, 0x37, 0x5d, + 0x0e, 0xd3, 0x47, 0x58, 0x03, 0x95, 0x5f, 0x30, 0x1a, 0xe4, 0x3f, 0x52, 0x14, 0x6c, 0xa0, 0x44, + 0xf1, 0xf7, 0x87, 0xc6, 0xaf, 0x8d, 0x71, 0x39, 0x4c, 0x2a, 0xf5, 0x9e, 0xe7, 0x25, 0xf3, 0x1f, + 0x0c, 0xc1, 0x42, 0x5a, 0xeb, 0xe3, 0x74, 0xdd, 0xbe, 0xb2, 0x1f, 0x1d, 0x10, 0xac, 0x5b, 0xd2, + 0x7d, 0x75, 0xe2, 0x7f, 0xf8, 0xba, 0x76, 0xb7, 0x4f, 0xe5, 0x60, 0xd8, 0xb3, 0x30, 0xf3, 0x93, + 0x2f, 0x37, 0xc9, 0xbf, 0x7b, 0xc2, 0x3d, 0x6b, 0xc9, 0x51, 0x48, 0x44, 0x6a, 0x23, 0x7e, 0xff, + 0xaf, 0x3f, 0xbe, 0x6d, 0xd8, 0xe9, 0x32, 0xfb, 0x1f, 0x7f, 0xf1, 0xa2, 0x6a, 0x7c, 0xf9, 0xa2, + 0x6a, 0xfc, 0xf3, 0x45, 0xd5, 0xf8, 0xf4, 0x65, 0x75, 0xe6, 0xcb, 0x97, 0xd5, 0x99, 0x7f, 0xbc, + 0xac, 0xce, 0x7c, 0xf2, 0xde, 0x65, 0xd2, 0xf1, 0xa5, 0xdd, 0xcb, 0x3e, 0xac, 0x45, 0x3f, 0x6a, + 0x3d, 0x9f, 0xfc, 0x6c, 0xa7, 0xd7, 0xeb, 0xcd, 0xeb, 0x08, 0x79, 0xf7, 0x7f, 0x01, 0x00, 0x00, + 0xff, 0xff, 0x8d, 0xfa, 0x87, 0x04, 0xe7, 0x13, 0x00, 0x00, } func (m *ConsumerAdditionProposal) Marshal() (dAtA []byte, err error) { @@ -2420,29 +2068,13 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintProvider(dAtA, i, uint64(n9)) i-- dAtA[i] = 0x32 - n10, err10 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.VscTimeoutPeriod, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.VscTimeoutPeriod):]) + n10, err10 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.CcvTimeoutPeriod, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.CcvTimeoutPeriod):]) if err10 != nil { return 0, err10 } i -= n10 i = encodeVarintProvider(dAtA, i, uint64(n10)) i-- - dAtA[i] = 0x2a - n11, err11 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.InitTimeoutPeriod, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.InitTimeoutPeriod):]) - if err11 != nil { - return 0, err11 - } - i -= n11 - i = encodeVarintProvider(dAtA, i, uint64(n11)) - i-- - dAtA[i] = 0x22 - n12, err12 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.CcvTimeoutPeriod, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.CcvTimeoutPeriod):]) - if err12 != nil { - return 0, err12 - } - i -= n12 - i = encodeVarintProvider(dAtA, i, uint64(n12)) - i-- dAtA[i] = 0x1a if len(m.TrustingPeriodFraction) > 0 { i -= len(m.TrustingPeriodFraction) @@ -2641,7 +2273,7 @@ func (m *ChannelToChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *VscUnbondingOps) Marshal() (dAtA []byte, err error) { +func (m *ValidatorSetChangePackets) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -2651,43 +2283,34 @@ func (m *VscUnbondingOps) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *VscUnbondingOps) MarshalTo(dAtA []byte) (int, error) { +func (m *ValidatorSetChangePackets) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *VscUnbondingOps) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ValidatorSetChangePackets) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.UnbondingOpIds) > 0 { - dAtA15 := make([]byte, len(m.UnbondingOpIds)*10) - var j14 int - for _, num := range m.UnbondingOpIds { - for num >= 1<<7 { - dAtA15[j14] = uint8(uint64(num)&0x7f | 0x80) - num >>= 7 - j14++ - } - dAtA15[j14] = uint8(num) - j14++ - } - i -= j14 - copy(dAtA[i:], dAtA15[:j14]) - i = encodeVarintProvider(dAtA, i, uint64(j14)) - i-- - dAtA[i] = 0x12 - } - if m.VscId != 0 { - i = encodeVarintProvider(dAtA, i, uint64(m.VscId)) - i-- - dAtA[i] = 0x8 + if len(m.List) > 0 { + for iNdEx := len(m.List) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.List[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintProvider(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } } return len(dAtA) - i, nil } -func (m *UnbondingOp) Marshal() (dAtA []byte, err error) { +func (m *KeyAssignmentReplacement) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -2697,262 +2320,32 @@ func (m *UnbondingOp) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *UnbondingOp) MarshalTo(dAtA []byte) (int, error) { +func (m *KeyAssignmentReplacement) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *UnbondingOp) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *KeyAssignmentReplacement) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.UnbondingConsumerChains) > 0 { - for iNdEx := len(m.UnbondingConsumerChains) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.UnbondingConsumerChains[iNdEx]) - copy(dAtA[i:], m.UnbondingConsumerChains[iNdEx]) - i = encodeVarintProvider(dAtA, i, uint64(len(m.UnbondingConsumerChains[iNdEx]))) - i-- - dAtA[i] = 0x12 - } + if m.Power != 0 { + i = encodeVarintProvider(dAtA, i, uint64(m.Power)) + i-- + dAtA[i] = 0x18 } - if m.Id != 0 { - i = encodeVarintProvider(dAtA, i, uint64(m.Id)) + if m.PrevCKey != nil { + { + size, err := m.PrevCKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintProvider(dAtA, i, uint64(size)) + } i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *InitTimeoutTimestamp) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *InitTimeoutTimestamp) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *InitTimeoutTimestamp) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Timestamp != 0 { - i = encodeVarintProvider(dAtA, i, uint64(m.Timestamp)) - i-- - dAtA[i] = 0x10 - } - if len(m.ChainId) > 0 { - i -= len(m.ChainId) - copy(dAtA[i:], m.ChainId) - i = encodeVarintProvider(dAtA, i, uint64(len(m.ChainId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *VscSendTimestamp) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *VscSendTimestamp) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *VscSendTimestamp) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - n16, err16 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) - if err16 != nil { - return 0, err16 - } - i -= n16 - i = encodeVarintProvider(dAtA, i, uint64(n16)) - i-- - dAtA[i] = 0x12 - if m.VscId != 0 { - i = encodeVarintProvider(dAtA, i, uint64(m.VscId)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *ValidatorSetChangePackets) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ValidatorSetChangePackets) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ValidatorSetChangePackets) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.List) > 0 { - for iNdEx := len(m.List) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.List[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintProvider(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func (m *MaturedUnbondingOps) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MaturedUnbondingOps) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MaturedUnbondingOps) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Ids) > 0 { - dAtA18 := make([]byte, len(m.Ids)*10) - var j17 int - for _, num := range m.Ids { - for num >= 1<<7 { - dAtA18[j17] = uint8(uint64(num)&0x7f | 0x80) - num >>= 7 - j17++ - } - dAtA18[j17] = uint8(num) - j17++ - } - i -= j17 - copy(dAtA[i:], dAtA18[:j17]) - i = encodeVarintProvider(dAtA, i, uint64(j17)) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ExportedVscSendTimestamp) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ExportedVscSendTimestamp) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ExportedVscSendTimestamp) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.VscSendTimestamps) > 0 { - for iNdEx := len(m.VscSendTimestamps) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.VscSendTimestamps[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintProvider(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if len(m.ChainId) > 0 { - i -= len(m.ChainId) - copy(dAtA[i:], m.ChainId) - i = encodeVarintProvider(dAtA, i, uint64(len(m.ChainId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *KeyAssignmentReplacement) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *KeyAssignmentReplacement) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *KeyAssignmentReplacement) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Power != 0 { - i = encodeVarintProvider(dAtA, i, uint64(m.Power)) - i-- - dAtA[i] = 0x18 - } - if m.PrevCKey != nil { - { - size, err := m.PrevCKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintProvider(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 + dAtA[i] = 0x12 } if len(m.ProviderAddr) > 0 { i -= len(m.ProviderAddr) @@ -3057,7 +2450,7 @@ func (m *ValidatorByConsumerAddr) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } -func (m *ConsumerAddrsToPrune) Marshal() (dAtA []byte, err error) { +func (m *ConsumerAddrsToPruneV2) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -3067,12 +2460,12 @@ func (m *ConsumerAddrsToPrune) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ConsumerAddrsToPrune) MarshalTo(dAtA []byte) (int, error) { +func (m *ConsumerAddrsToPruneV2) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ConsumerAddrsToPrune) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ConsumerAddrsToPruneV2) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -3089,11 +2482,14 @@ func (m *ConsumerAddrsToPrune) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x1a } - if m.VscId != 0 { - i = encodeVarintProvider(dAtA, i, uint64(m.VscId)) - i-- - dAtA[i] = 0x10 + n15, err15 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.PruneTs, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.PruneTs):]) + if err15 != nil { + return 0, err15 } + i -= n15 + i = encodeVarintProvider(dAtA, i, uint64(n15)) + i-- + dAtA[i] = 0x12 if len(m.ChainId) > 0 { i -= len(m.ChainId) copy(dAtA[i:], m.ChainId) @@ -3445,10 +2841,6 @@ func (m *Params) Size() (n int) { } l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.CcvTimeoutPeriod) n += 1 + l + sovProvider(uint64(l)) - l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.InitTimeoutPeriod) - n += 1 + l + sovProvider(uint64(l)) - l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.VscTimeoutPeriod) - n += 1 + l + sovProvider(uint64(l)) l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.SlashMeterReplenishPeriod) n += 1 + l + sovProvider(uint64(l)) l = len(m.SlashMeterReplenishFraction) @@ -3546,44 +2938,42 @@ func (m *ChannelToChain) Size() (n int) { return n } -func (m *VscUnbondingOps) Size() (n int) { +func (m *ValidatorSetChangePackets) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.VscId != 0 { - n += 1 + sovProvider(uint64(m.VscId)) - } - if len(m.UnbondingOpIds) > 0 { - l = 0 - for _, e := range m.UnbondingOpIds { - l += sovProvider(uint64(e)) + if len(m.List) > 0 { + for _, e := range m.List { + l = e.Size() + n += 1 + l + sovProvider(uint64(l)) } - n += 1 + sovProvider(uint64(l)) + l } return n } -func (m *UnbondingOp) Size() (n int) { +func (m *KeyAssignmentReplacement) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.Id != 0 { - n += 1 + sovProvider(uint64(m.Id)) + l = len(m.ProviderAddr) + if l > 0 { + n += 1 + l + sovProvider(uint64(l)) } - if len(m.UnbondingConsumerChains) > 0 { - for _, s := range m.UnbondingConsumerChains { - l = len(s) - n += 1 + l + sovProvider(uint64(l)) - } + if m.PrevCKey != nil { + l = m.PrevCKey.Size() + n += 1 + l + sovProvider(uint64(l)) + } + if m.Power != 0 { + n += 1 + sovProvider(uint64(m.Power)) } return n } -func (m *InitTimeoutTimestamp) Size() (n int) { +func (m *ValidatorConsumerPubKey) Size() (n int) { if m == nil { return 0 } @@ -3593,159 +2983,58 @@ func (m *InitTimeoutTimestamp) Size() (n int) { if l > 0 { n += 1 + l + sovProvider(uint64(l)) } - if m.Timestamp != 0 { - n += 1 + sovProvider(uint64(m.Timestamp)) + l = len(m.ProviderAddr) + if l > 0 { + n += 1 + l + sovProvider(uint64(l)) + } + if m.ConsumerKey != nil { + l = m.ConsumerKey.Size() + n += 1 + l + sovProvider(uint64(l)) } return n } -func (m *VscSendTimestamp) Size() (n int) { +func (m *ValidatorByConsumerAddr) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.VscId != 0 { - n += 1 + sovProvider(uint64(m.VscId)) + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovProvider(uint64(l)) } - l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) - n += 1 + l + sovProvider(uint64(l)) - return n -} - -func (m *ValidatorSetChangePackets) Size() (n int) { - if m == nil { - return 0 + l = len(m.ConsumerAddr) + if l > 0 { + n += 1 + l + sovProvider(uint64(l)) } - var l int - _ = l - if len(m.List) > 0 { - for _, e := range m.List { - l = e.Size() - n += 1 + l + sovProvider(uint64(l)) - } + l = len(m.ProviderAddr) + if l > 0 { + n += 1 + l + sovProvider(uint64(l)) } return n } -func (m *MaturedUnbondingOps) Size() (n int) { +func (m *ConsumerAddrsToPruneV2) Size() (n int) { if m == nil { return 0 } var l int _ = l - if len(m.Ids) > 0 { - l = 0 - for _, e := range m.Ids { - l += sovProvider(uint64(e)) - } - n += 1 + sovProvider(uint64(l)) + l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovProvider(uint64(l)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.PruneTs) + n += 1 + l + sovProvider(uint64(l)) + if m.ConsumerAddrs != nil { + l = m.ConsumerAddrs.Size() + n += 1 + l + sovProvider(uint64(l)) } return n } -func (m *ExportedVscSendTimestamp) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovProvider(uint64(l)) - } - if len(m.VscSendTimestamps) > 0 { - for _, e := range m.VscSendTimestamps { - l = e.Size() - n += 1 + l + sovProvider(uint64(l)) - } - } - return n -} - -func (m *KeyAssignmentReplacement) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ProviderAddr) - if l > 0 { - n += 1 + l + sovProvider(uint64(l)) - } - if m.PrevCKey != nil { - l = m.PrevCKey.Size() - n += 1 + l + sovProvider(uint64(l)) - } - if m.Power != 0 { - n += 1 + sovProvider(uint64(m.Power)) - } - return n -} - -func (m *ValidatorConsumerPubKey) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovProvider(uint64(l)) - } - l = len(m.ProviderAddr) - if l > 0 { - n += 1 + l + sovProvider(uint64(l)) - } - if m.ConsumerKey != nil { - l = m.ConsumerKey.Size() - n += 1 + l + sovProvider(uint64(l)) - } - return n -} - -func (m *ValidatorByConsumerAddr) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovProvider(uint64(l)) - } - l = len(m.ConsumerAddr) - if l > 0 { - n += 1 + l + sovProvider(uint64(l)) - } - l = len(m.ProviderAddr) - if l > 0 { - n += 1 + l + sovProvider(uint64(l)) - } - return n -} - -func (m *ConsumerAddrsToPrune) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovProvider(uint64(l)) - } - if m.VscId != 0 { - n += 1 + sovProvider(uint64(m.VscId)) - } - if m.ConsumerAddrs != nil { - l = m.ConsumerAddrs.Size() - n += 1 + l + sovProvider(uint64(l)) - } - return n -} - -func (m *ConsensusValidator) Size() (n int) { +func (m *ConsensusValidator) Size() (n int) { if m == nil { return 0 } @@ -5539,72 +4828,6 @@ func (m *Params) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field InitTimeoutPeriod", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.InitTimeoutPeriod, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field VscTimeoutPeriod", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.VscTimeoutPeriod, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field SlashMeterReplenishPeriod", wireType) @@ -5713,554 +4936,20 @@ func (m *Params) Unmarshal(dAtA []byte) error { return ErrIntOverflowProvider } if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.BlocksPerEpoch |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 11: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NumberOfEpochsToStartReceivingRewards", wireType) - } - m.NumberOfEpochsToStartReceivingRewards = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NumberOfEpochsToStartReceivingRewards |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 12: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxProviderConsensusValidators", wireType) - } - m.MaxProviderConsensusValidators = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.MaxProviderConsensusValidators |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipProvider(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthProvider - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *SlashAcks) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: SlashAcks: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: SlashAcks: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipProvider(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthProvider - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ConsumerAdditionProposals) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ConsumerAdditionProposals: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConsumerAdditionProposals: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pending", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Pending = append(m.Pending, &ConsumerAdditionProposal{}) - if err := m.Pending[len(m.Pending)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipProvider(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthProvider - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ConsumerRemovalProposals) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ConsumerRemovalProposals: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConsumerRemovalProposals: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pending", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Pending = append(m.Pending, &ConsumerRemovalProposal{}) - if err := m.Pending[len(m.Pending)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipProvider(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthProvider - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *AddressList) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: AddressList: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: AddressList: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Addresses = append(m.Addresses, make([]byte, postIndex-iNdEx)) - copy(m.Addresses[len(m.Addresses)-1], dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipProvider(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthProvider - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ChannelToChain) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ChannelToChain: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ChannelToChain: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChainId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipProvider(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthProvider - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *VscUnbondingOps) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlocksPerEpoch |= int64(b&0x7F) << shift + if b < 0x80 { + break + } } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: VscUnbondingOps: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: VscUnbondingOps: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: + case 11: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field VscId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field NumberOfEpochsToStartReceivingRewards", wireType) } - m.VscId = 0 + m.NumberOfEpochsToStartReceivingRewards = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowProvider @@ -6270,86 +4959,29 @@ func (m *VscUnbondingOps) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.VscId |= uint64(b&0x7F) << shift + m.NumberOfEpochsToStartReceivingRewards |= int64(b&0x7F) << shift if b < 0x80 { break } } - case 2: - if wireType == 0 { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.UnbondingOpIds = append(m.UnbondingOpIds, v) - } else if wireType == 2 { - var packedLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - packedLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if packedLen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + packedLen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxProviderConsensusValidators", wireType) + } + m.MaxProviderConsensusValidators = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { return io.ErrUnexpectedEOF } - var elementCount int - var count int - for _, integer := range dAtA[iNdEx:postIndex] { - if integer < 128 { - count++ - } - } - elementCount = count - if elementCount != 0 && len(m.UnbondingOpIds) == 0 { - m.UnbondingOpIds = make([]uint64, 0, elementCount) - } - for iNdEx < postIndex { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.UnbondingOpIds = append(m.UnbondingOpIds, v) - } - } else { - return fmt.Errorf("proto: wrong wireType = %d for field UnbondingOpIds", wireType) + b := dAtA[iNdEx] + iNdEx++ + m.MaxProviderConsensusValidators |= int64(b&0x7F) << shift + if b < 0x80 { + break + } } default: iNdEx = preIndex @@ -6372,7 +5004,7 @@ func (m *VscUnbondingOps) Unmarshal(dAtA []byte) error { } return nil } -func (m *UnbondingOp) Unmarshal(dAtA []byte) error { +func (m *SlashAcks) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6395,34 +5027,15 @@ func (m *UnbondingOp) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: UnbondingOp: wiretype end group for non-group") + return fmt.Errorf("proto: SlashAcks: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: UnbondingOp: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: SlashAcks: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) - } - m.Id = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Id |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UnbondingConsumerChains", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -6450,7 +5063,7 @@ func (m *UnbondingOp) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.UnbondingConsumerChains = append(m.UnbondingConsumerChains, string(dAtA[iNdEx:postIndex])) + m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex default: iNdEx = preIndex @@ -6473,7 +5086,7 @@ func (m *UnbondingOp) Unmarshal(dAtA []byte) error { } return nil } -func (m *InitTimeoutTimestamp) Unmarshal(dAtA []byte) error { +func (m *ConsumerAdditionProposals) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6496,17 +5109,17 @@ func (m *InitTimeoutTimestamp) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: InitTimeoutTimestamp: wiretype end group for non-group") + return fmt.Errorf("proto: ConsumerAdditionProposals: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: InitTimeoutTimestamp: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ConsumerAdditionProposals: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Pending", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowProvider @@ -6516,43 +5129,26 @@ func (m *InitTimeoutTimestamp) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthProvider } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthProvider } if postIndex > l { return io.ErrUnexpectedEOF } - m.ChainId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) - } - m.Timestamp = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Timestamp |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } + m.Pending = append(m.Pending, &ConsumerAdditionProposal{}) + if err := m.Pending[len(m.Pending)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipProvider(dAtA[iNdEx:]) @@ -6574,7 +5170,7 @@ func (m *InitTimeoutTimestamp) Unmarshal(dAtA []byte) error { } return nil } -func (m *VscSendTimestamp) Unmarshal(dAtA []byte) error { +func (m *ConsumerRemovalProposals) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6597,34 +5193,15 @@ func (m *VscSendTimestamp) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: VscSendTimestamp: wiretype end group for non-group") + return fmt.Errorf("proto: ConsumerRemovalProposals: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: VscSendTimestamp: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ConsumerRemovalProposals: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field VscId", wireType) - } - m.VscId = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.VscId |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Pending", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -6651,7 +5228,8 @@ func (m *VscSendTimestamp) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + m.Pending = append(m.Pending, &ConsumerRemovalProposal{}) + if err := m.Pending[len(m.Pending)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -6676,7 +5254,7 @@ func (m *VscSendTimestamp) Unmarshal(dAtA []byte) error { } return nil } -func (m *ValidatorSetChangePackets) Unmarshal(dAtA []byte) error { +func (m *AddressList) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6699,17 +5277,17 @@ func (m *ValidatorSetChangePackets) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ValidatorSetChangePackets: wiretype end group for non-group") + return fmt.Errorf("proto: AddressList: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ValidatorSetChangePackets: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: AddressList: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field List", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType) } - var msglen int + var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowProvider @@ -6719,25 +5297,23 @@ func (m *ValidatorSetChangePackets) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + byteLen |= int(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + if byteLen < 0 { return ErrInvalidLengthProvider } - postIndex := iNdEx + msglen + postIndex := iNdEx + byteLen if postIndex < 0 { return ErrInvalidLengthProvider } if postIndex > l { return io.ErrUnexpectedEOF } - m.List = append(m.List, types3.ValidatorSetChangePacketData{}) - if err := m.List[len(m.List)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Addresses = append(m.Addresses, make([]byte, postIndex-iNdEx)) + copy(m.Addresses[len(m.Addresses)-1], dAtA[iNdEx:postIndex]) iNdEx = postIndex default: iNdEx = preIndex @@ -6760,7 +5336,7 @@ func (m *ValidatorSetChangePackets) Unmarshal(dAtA []byte) error { } return nil } -func (m *MaturedUnbondingOps) Unmarshal(dAtA []byte) error { +func (m *ChannelToChain) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6783,88 +5359,76 @@ func (m *MaturedUnbondingOps) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: MaturedUnbondingOps: wiretype end group for non-group") + return fmt.Errorf("proto: ChannelToChain: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: MaturedUnbondingOps: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ChannelToChain: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType == 0 { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Ids = append(m.Ids, v) - } else if wireType == 2 { - var packedLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - packedLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if packedLen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + packedLen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthProvider + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthProvider + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChannelId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { return io.ErrUnexpectedEOF } - var elementCount int - var count int - for _, integer := range dAtA[iNdEx:postIndex] { - if integer < 128 { - count++ - } - } - elementCount = count - if elementCount != 0 && len(m.Ids) == 0 { - m.Ids = make([]uint64, 0, elementCount) - } - for iNdEx < postIndex { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Ids = append(m.Ids, v) - } - } else { - return fmt.Errorf("proto: wrong wireType = %d for field Ids", wireType) + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthProvider } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthProvider + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipProvider(dAtA[iNdEx:]) @@ -6886,7 +5450,7 @@ func (m *MaturedUnbondingOps) Unmarshal(dAtA []byte) error { } return nil } -func (m *ExportedVscSendTimestamp) Unmarshal(dAtA []byte) error { +func (m *ValidatorSetChangePackets) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -6909,47 +5473,15 @@ func (m *ExportedVscSendTimestamp) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ExportedVscSendTimestamp: wiretype end group for non-group") + return fmt.Errorf("proto: ValidatorSetChangePackets: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ExportedVscSendTimestamp: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ValidatorSetChangePackets: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProvider - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthProvider - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthProvider - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChainId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field VscSendTimestamps", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field List", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -6976,8 +5508,8 @@ func (m *ExportedVscSendTimestamp) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.VscSendTimestamps = append(m.VscSendTimestamps, VscSendTimestamp{}) - if err := m.VscSendTimestamps[len(m.VscSendTimestamps)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.List = append(m.List, types3.ValidatorSetChangePacketData{}) + if err := m.List[len(m.List)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -7443,7 +5975,7 @@ func (m *ValidatorByConsumerAddr) Unmarshal(dAtA []byte) error { } return nil } -func (m *ConsumerAddrsToPrune) Unmarshal(dAtA []byte) error { +func (m *ConsumerAddrsToPruneV2) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -7466,10 +5998,10 @@ func (m *ConsumerAddrsToPrune) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ConsumerAddrsToPrune: wiretype end group for non-group") + return fmt.Errorf("proto: ConsumerAddrsToPruneV2: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ConsumerAddrsToPrune: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ConsumerAddrsToPruneV2: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -7505,10 +6037,10 @@ func (m *ConsumerAddrsToPrune) Unmarshal(dAtA []byte) error { m.ChainId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field VscId", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PruneTs", wireType) } - m.VscId = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowProvider @@ -7518,11 +6050,25 @@ func (m *ConsumerAddrsToPrune) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.VscId |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return ErrInvalidLengthProvider + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthProvider + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.PruneTs, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ConsumerAddrs", wireType) diff --git a/x/ccv/provider/types/query.pb.go b/x/ccv/provider/types/query.pb.go index 84e610776e..34f334704a 100644 --- a/x/ccv/provider/types/query.pb.go +++ b/x/ccv/provider/types/query.pb.go @@ -1656,22 +1656,21 @@ func (m *QueryValidatorConsumerCommissionRateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QueryValidatorConsumerCommissionRateResponse proto.InternalMessageInfo -type QueryOldestUnconfirmedVscRequest struct { - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +type QueryBlocksUntilNextEpochRequest struct { } -func (m *QueryOldestUnconfirmedVscRequest) Reset() { *m = QueryOldestUnconfirmedVscRequest{} } -func (m *QueryOldestUnconfirmedVscRequest) String() string { return proto.CompactTextString(m) } -func (*QueryOldestUnconfirmedVscRequest) ProtoMessage() {} -func (*QueryOldestUnconfirmedVscRequest) Descriptor() ([]byte, []int) { +func (m *QueryBlocksUntilNextEpochRequest) Reset() { *m = QueryBlocksUntilNextEpochRequest{} } +func (m *QueryBlocksUntilNextEpochRequest) String() string { return proto.CompactTextString(m) } +func (*QueryBlocksUntilNextEpochRequest) ProtoMessage() {} +func (*QueryBlocksUntilNextEpochRequest) Descriptor() ([]byte, []int) { return fileDescriptor_422512d7b7586cd7, []int{34} } -func (m *QueryOldestUnconfirmedVscRequest) XXX_Unmarshal(b []byte) error { +func (m *QueryBlocksUntilNextEpochRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *QueryOldestUnconfirmedVscRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *QueryBlocksUntilNextEpochRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_QueryOldestUnconfirmedVscRequest.Marshal(b, m, deterministic) + return xxx_messageInfo_QueryBlocksUntilNextEpochRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1681,41 +1680,35 @@ func (m *QueryOldestUnconfirmedVscRequest) XXX_Marshal(b []byte, deterministic b return b[:n], nil } } -func (m *QueryOldestUnconfirmedVscRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryOldestUnconfirmedVscRequest.Merge(m, src) +func (m *QueryBlocksUntilNextEpochRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBlocksUntilNextEpochRequest.Merge(m, src) } -func (m *QueryOldestUnconfirmedVscRequest) XXX_Size() int { +func (m *QueryBlocksUntilNextEpochRequest) XXX_Size() int { return m.Size() } -func (m *QueryOldestUnconfirmedVscRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryOldestUnconfirmedVscRequest.DiscardUnknown(m) +func (m *QueryBlocksUntilNextEpochRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBlocksUntilNextEpochRequest.DiscardUnknown(m) } -var xxx_messageInfo_QueryOldestUnconfirmedVscRequest proto.InternalMessageInfo - -func (m *QueryOldestUnconfirmedVscRequest) GetChainId() string { - if m != nil { - return m.ChainId - } - return "" -} +var xxx_messageInfo_QueryBlocksUntilNextEpochRequest proto.InternalMessageInfo -type QueryOldestUnconfirmedVscResponse struct { - VscSendTimestamp VscSendTimestamp `protobuf:"bytes,1,opt,name=vsc_send_timestamp,json=vscSendTimestamp,proto3" json:"vsc_send_timestamp"` +type QueryBlocksUntilNextEpochResponse struct { + // The number of blocks until the next epoch starts + BlocksUntilNextEpoch uint64 `protobuf:"varint,1,opt,name=blocks_until_next_epoch,json=blocksUntilNextEpoch,proto3" json:"blocks_until_next_epoch,omitempty"` } -func (m *QueryOldestUnconfirmedVscResponse) Reset() { *m = QueryOldestUnconfirmedVscResponse{} } -func (m *QueryOldestUnconfirmedVscResponse) String() string { return proto.CompactTextString(m) } -func (*QueryOldestUnconfirmedVscResponse) ProtoMessage() {} -func (*QueryOldestUnconfirmedVscResponse) Descriptor() ([]byte, []int) { +func (m *QueryBlocksUntilNextEpochResponse) Reset() { *m = QueryBlocksUntilNextEpochResponse{} } +func (m *QueryBlocksUntilNextEpochResponse) String() string { return proto.CompactTextString(m) } +func (*QueryBlocksUntilNextEpochResponse) ProtoMessage() {} +func (*QueryBlocksUntilNextEpochResponse) Descriptor() ([]byte, []int) { return fileDescriptor_422512d7b7586cd7, []int{35} } -func (m *QueryOldestUnconfirmedVscResponse) XXX_Unmarshal(b []byte) error { +func (m *QueryBlocksUntilNextEpochResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *QueryOldestUnconfirmedVscResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *QueryBlocksUntilNextEpochResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_QueryOldestUnconfirmedVscResponse.Marshal(b, m, deterministic) + return xxx_messageInfo_QueryBlocksUntilNextEpochResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1725,23 +1718,23 @@ func (m *QueryOldestUnconfirmedVscResponse) XXX_Marshal(b []byte, deterministic return b[:n], nil } } -func (m *QueryOldestUnconfirmedVscResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryOldestUnconfirmedVscResponse.Merge(m, src) +func (m *QueryBlocksUntilNextEpochResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBlocksUntilNextEpochResponse.Merge(m, src) } -func (m *QueryOldestUnconfirmedVscResponse) XXX_Size() int { +func (m *QueryBlocksUntilNextEpochResponse) XXX_Size() int { return m.Size() } -func (m *QueryOldestUnconfirmedVscResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryOldestUnconfirmedVscResponse.DiscardUnknown(m) +func (m *QueryBlocksUntilNextEpochResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBlocksUntilNextEpochResponse.DiscardUnknown(m) } -var xxx_messageInfo_QueryOldestUnconfirmedVscResponse proto.InternalMessageInfo +var xxx_messageInfo_QueryBlocksUntilNextEpochResponse proto.InternalMessageInfo -func (m *QueryOldestUnconfirmedVscResponse) GetVscSendTimestamp() VscSendTimestamp { +func (m *QueryBlocksUntilNextEpochResponse) GetBlocksUntilNextEpoch() uint64 { if m != nil { - return m.VscSendTimestamp + return m.BlocksUntilNextEpoch } - return VscSendTimestamp{} + return 0 } func init() { @@ -1779,8 +1772,8 @@ func init() { proto.RegisterType((*QueryConsumerChainsValidatorHasToValidateResponse)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainsValidatorHasToValidateResponse") proto.RegisterType((*QueryValidatorConsumerCommissionRateRequest)(nil), "interchain_security.ccv.provider.v1.QueryValidatorConsumerCommissionRateRequest") proto.RegisterType((*QueryValidatorConsumerCommissionRateResponse)(nil), "interchain_security.ccv.provider.v1.QueryValidatorConsumerCommissionRateResponse") - proto.RegisterType((*QueryOldestUnconfirmedVscRequest)(nil), "interchain_security.ccv.provider.v1.QueryOldestUnconfirmedVscRequest") - proto.RegisterType((*QueryOldestUnconfirmedVscResponse)(nil), "interchain_security.ccv.provider.v1.QueryOldestUnconfirmedVscResponse") + proto.RegisterType((*QueryBlocksUntilNextEpochRequest)(nil), "interchain_security.ccv.provider.v1.QueryBlocksUntilNextEpochRequest") + proto.RegisterType((*QueryBlocksUntilNextEpochResponse)(nil), "interchain_security.ccv.provider.v1.QueryBlocksUntilNextEpochResponse") } func init() { @@ -1788,133 +1781,132 @@ func init() { } var fileDescriptor_422512d7b7586cd7 = []byte{ - // 2015 bytes of a gzipped FileDescriptorProto + // 1994 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x59, 0xcd, 0x6f, 0xdc, 0xc6, - 0x15, 0x17, 0x57, 0x1f, 0x91, 0x46, 0xf1, 0x47, 0xc6, 0x6a, 0x22, 0x53, 0xca, 0xae, 0x42, 0xf7, - 0x43, 0x96, 0x5d, 0x52, 0x92, 0x61, 0xc4, 0xb1, 0xab, 0xc8, 0x5a, 0xc9, 0x76, 0x16, 0x76, 0x62, - 0x85, 0x96, 0xd5, 0xc2, 0x2d, 0x4a, 0x8f, 0xc9, 0xc9, 0x8a, 0x30, 0x97, 0x43, 0x71, 0xb8, 0xeb, - 0x2c, 0x8c, 0x1c, 0xd2, 0x43, 0x9b, 0x53, 0x11, 0xf4, 0x03, 0xe8, 0x31, 0x97, 0x1e, 0x7b, 0xe9, - 0xa1, 0xc8, 0x9f, 0x90, 0x5b, 0x53, 0xe4, 0x52, 0xf4, 0xe0, 0x16, 0x72, 0x0f, 0x45, 0x0f, 0x45, - 0x61, 0x14, 0xe8, 0xa9, 0x40, 0xc1, 0xe1, 0xf0, 0x6b, 0x97, 0xbb, 0x4b, 0xee, 0x2a, 0xb7, 0xe5, - 0xcc, 0xbc, 0xdf, 0xbc, 0xf7, 0xe6, 0xbd, 0x37, 0xef, 0x37, 0x0b, 0x14, 0xd3, 0xf6, 0xb0, 0xab, - 0x1f, 0x20, 0xd3, 0xd6, 0x28, 0xd6, 0x9b, 0xae, 0xe9, 0xb5, 0x15, 0x5d, 0x6f, 0x29, 0x8e, 0x4b, - 0x5a, 0xa6, 0x81, 0x5d, 0xa5, 0xb5, 0xa6, 0x1c, 0x36, 0xb1, 0xdb, 0x96, 0x1d, 0x97, 0x78, 0x04, - 0x9e, 0xcb, 0x10, 0x90, 0x75, 0xbd, 0x25, 0x87, 0x02, 0x72, 0x6b, 0x4d, 0x5c, 0xac, 0x13, 0x52, - 0xb7, 0xb0, 0x82, 0x1c, 0x53, 0x41, 0xb6, 0x4d, 0x3c, 0xe4, 0x99, 0xc4, 0xa6, 0x01, 0x84, 0x38, - 0x57, 0x27, 0x75, 0xc2, 0x7e, 0x2a, 0xfe, 0x2f, 0x3e, 0x5a, 0xe1, 0x32, 0xec, 0xeb, 0x51, 0xf3, - 0x03, 0xc5, 0x33, 0x1b, 0x98, 0x7a, 0xa8, 0xe1, 0xf0, 0x05, 0xeb, 0x79, 0x54, 0x8d, 0xb4, 0x08, - 0x64, 0x56, 0x7b, 0xc9, 0xb4, 0xd6, 0x14, 0x7a, 0x80, 0x5c, 0x6c, 0x68, 0x3a, 0xb1, 0x69, 0xb3, - 0x11, 0x49, 0x7c, 0xab, 0x8f, 0xc4, 0x13, 0xd3, 0xc5, 0x7c, 0xd9, 0xa2, 0x87, 0x6d, 0x03, 0xbb, - 0x0d, 0xd3, 0xf6, 0x14, 0xdd, 0x6d, 0x3b, 0x1e, 0x51, 0x1e, 0xe3, 0x76, 0x68, 0xe1, 0x59, 0x9d, - 0xd0, 0x06, 0xa1, 0x5a, 0x60, 0x64, 0xf0, 0x11, 0x4c, 0x49, 0x57, 0xc0, 0xc2, 0xfb, 0xbe, 0x3b, - 0xb7, 0xf9, 0xb6, 0xb7, 0xb0, 0x8d, 0xa9, 0x49, 0x55, 0x7c, 0xd8, 0xc4, 0xd4, 0x83, 0x67, 0xc1, - 0x74, 0xb0, 0xb7, 0x69, 0xcc, 0x0b, 0x4b, 0xc2, 0xf2, 0x8c, 0xfa, 0x12, 0xfb, 0xae, 0x19, 0xd2, - 0x53, 0xb0, 0x98, 0x2d, 0x49, 0x1d, 0x62, 0x53, 0x0c, 0x7f, 0x08, 0x4e, 0xd4, 0x83, 0x21, 0x8d, - 0x7a, 0xc8, 0xc3, 0x4c, 0x7e, 0x76, 0x7d, 0x55, 0xee, 0x75, 0x62, 0xad, 0x35, 0xb9, 0x03, 0xeb, - 0x9e, 0x2f, 0x57, 0x9d, 0xf8, 0xe2, 0x59, 0x65, 0x4c, 0x7d, 0xb9, 0x9e, 0x18, 0x93, 0x16, 0x81, - 0x98, 0xda, 0x7c, 0xdb, 0x87, 0x0b, 0xb5, 0x96, 0x50, 0x87, 0x51, 0xe1, 0x2c, 0xd7, 0xac, 0x0a, - 0xa6, 0xd8, 0xf6, 0x74, 0x5e, 0x58, 0x1a, 0x5f, 0x9e, 0x5d, 0x5f, 0x91, 0x73, 0x04, 0x91, 0xcc, - 0x40, 0x54, 0x2e, 0x29, 0x9d, 0x07, 0xdf, 0xe9, 0xde, 0xe2, 0x9e, 0x87, 0x5c, 0x6f, 0xd7, 0x25, - 0x0e, 0xa1, 0xc8, 0x8a, 0xb4, 0xf9, 0x44, 0x00, 0xcb, 0x83, 0xd7, 0x72, 0xdd, 0x7e, 0x04, 0x66, - 0x9c, 0x70, 0x90, 0x7b, 0xec, 0xed, 0x7c, 0xea, 0x71, 0xf0, 0x2d, 0xc3, 0x30, 0xfd, 0xe8, 0x8e, - 0xa1, 0x63, 0x40, 0x69, 0x19, 0x7c, 0x3b, 0x4b, 0x13, 0xe2, 0x74, 0x29, 0xfd, 0x53, 0x21, 0xdb, - 0xc0, 0xd4, 0xd2, 0xe8, 0xa4, 0xbb, 0x74, 0xde, 0x28, 0xa4, 0xb3, 0x8a, 0x1b, 0xa4, 0x85, 0xac, - 0x4c, 0x95, 0x7f, 0x53, 0x02, 0x93, 0x6c, 0xef, 0x3e, 0xb1, 0x08, 0x17, 0xc0, 0x8c, 0x6e, 0x99, - 0xd8, 0xf6, 0xfc, 0xb9, 0x12, 0x9b, 0x9b, 0x0e, 0x06, 0x6a, 0x06, 0x3c, 0x03, 0x26, 0x3d, 0xe2, - 0x68, 0xef, 0xcd, 0x8f, 0x2f, 0x09, 0xcb, 0x27, 0xd4, 0x09, 0x8f, 0x38, 0xef, 0xc1, 0x15, 0x00, - 0x1b, 0xa6, 0xad, 0x39, 0xe4, 0x09, 0x76, 0x35, 0xd3, 0xd6, 0x82, 0x15, 0x13, 0x4b, 0xc2, 0xf2, - 0xb8, 0x7a, 0xb2, 0x61, 0xda, 0xbb, 0xfe, 0x44, 0xcd, 0xde, 0xf3, 0xd7, 0xae, 0x82, 0xb9, 0x16, - 0xb2, 0x4c, 0x03, 0x79, 0xc4, 0xa5, 0x5c, 0x44, 0x47, 0xce, 0xfc, 0x24, 0xc3, 0x83, 0xf1, 0x1c, - 0x13, 0xda, 0x46, 0x0e, 0x5c, 0x01, 0xaf, 0x44, 0xa3, 0x1a, 0xc5, 0x1e, 0x5b, 0x3e, 0xc5, 0x96, - 0x9f, 0x8a, 0x26, 0xee, 0x61, 0xcf, 0x5f, 0xbb, 0x08, 0x66, 0x90, 0x65, 0x91, 0x27, 0x96, 0x49, - 0xbd, 0xf9, 0x97, 0x96, 0xc6, 0x97, 0x67, 0xd4, 0x78, 0x00, 0x8a, 0x60, 0xda, 0xc0, 0x76, 0x9b, - 0x4d, 0x4e, 0xb3, 0xc9, 0xe8, 0x5b, 0xfa, 0x99, 0x00, 0xde, 0x60, 0x67, 0xb4, 0x1f, 0x42, 0x26, - 0x82, 0xc0, 0x1d, 0x9c, 0xc2, 0x70, 0x03, 0x9c, 0x0e, 0x8f, 0x43, 0x43, 0x86, 0xe1, 0x62, 0x4a, - 0x03, 0xef, 0x55, 0xe1, 0x8b, 0x67, 0x95, 0x93, 0x6d, 0xd4, 0xb0, 0xae, 0x4a, 0x7c, 0x42, 0x52, - 0x4f, 0x85, 0x6b, 0xb7, 0x82, 0x91, 0xab, 0xd3, 0x9f, 0x7c, 0x56, 0x19, 0xfb, 0xc7, 0x67, 0x95, - 0x31, 0xe9, 0x2e, 0x90, 0xfa, 0x29, 0xc2, 0xe3, 0xe4, 0x3c, 0x38, 0x1d, 0x56, 0xb7, 0x68, 0xbb, - 0x40, 0xa3, 0x53, 0x7a, 0x62, 0xbd, 0xbf, 0x59, 0xb7, 0x69, 0xbb, 0x89, 0xcd, 0xf3, 0x99, 0xd6, - 0xb5, 0x57, 0x1f, 0xd3, 0x3a, 0xf6, 0xef, 0x67, 0x5a, 0x5a, 0x91, 0xd8, 0xb4, 0x2e, 0x4f, 0x72, - 0xd3, 0x3a, 0xbc, 0x26, 0x2d, 0x80, 0xb3, 0x0c, 0x70, 0xef, 0xc0, 0x25, 0x9e, 0x67, 0x61, 0x56, - 0xd0, 0xc2, 0xb4, 0xfb, 0x93, 0xc0, 0x0b, 0x5b, 0xc7, 0x2c, 0xdf, 0xa6, 0x02, 0x66, 0xa9, 0x85, - 0xe8, 0x81, 0xd6, 0xc0, 0x1e, 0x76, 0xd9, 0x0e, 0xe3, 0x2a, 0x60, 0x43, 0xef, 0xfa, 0x23, 0x70, - 0x1d, 0x7c, 0x23, 0xb1, 0x40, 0x63, 0x71, 0x84, 0x6c, 0x1d, 0x33, 0xdb, 0xc7, 0xd5, 0x33, 0xf1, - 0xd2, 0xad, 0x70, 0x0a, 0xfe, 0x18, 0xcc, 0xdb, 0xf8, 0x43, 0x4f, 0x73, 0xb1, 0x63, 0x61, 0xdb, - 0xa4, 0x07, 0x9a, 0x8e, 0x6c, 0xc3, 0x37, 0x16, 0xb3, 0x94, 0x99, 0x5d, 0x17, 0xe5, 0xe0, 0x32, - 0x94, 0xc3, 0xcb, 0x50, 0xde, 0x0b, 0x2f, 0xc3, 0xea, 0xb4, 0x5f, 0x9d, 0x3f, 0xfd, 0x6b, 0x45, - 0x50, 0x5f, 0xf5, 0x51, 0xd4, 0x10, 0x64, 0x3b, 0xc4, 0x90, 0x2e, 0x82, 0x15, 0x66, 0x92, 0x8a, - 0xeb, 0x26, 0xf5, 0xb0, 0x8b, 0x8d, 0x38, 0xef, 0x9f, 0x20, 0xd7, 0xd8, 0xc1, 0x36, 0x69, 0x44, - 0x85, 0xe7, 0x06, 0xb8, 0x90, 0x6b, 0x35, 0xf7, 0xc8, 0xab, 0x60, 0xca, 0x60, 0x23, 0xac, 0x96, - 0xcf, 0xa8, 0xfc, 0x4b, 0x2a, 0xf3, 0xdb, 0x29, 0xa8, 0x29, 0xd8, 0x60, 0x25, 0xa4, 0xb6, 0x13, - 0x6d, 0xf3, 0xb1, 0x00, 0x5e, 0xef, 0xb1, 0x80, 0x23, 0x3f, 0x04, 0x27, 0x9d, 0xe4, 0x5c, 0x78, - 0x5b, 0xac, 0xe7, 0x2a, 0x6d, 0x29, 0x58, 0x7e, 0x85, 0x75, 0xe0, 0x49, 0x35, 0x70, 0x22, 0xb5, - 0x0c, 0xce, 0x03, 0x1e, 0xbf, 0x3b, 0xe9, 0x70, 0xde, 0x81, 0x65, 0x00, 0xc2, 0x92, 0x58, 0xdb, - 0x61, 0x87, 0x39, 0xa1, 0x26, 0x46, 0xa4, 0x3b, 0x40, 0x61, 0xd6, 0x6c, 0x59, 0xd6, 0x2e, 0x32, - 0x5d, 0xba, 0x8f, 0xac, 0x6d, 0x62, 0xfb, 0x21, 0x57, 0x4d, 0x57, 0xf0, 0xda, 0x4e, 0x8e, 0xab, - 0xfd, 0xb7, 0x02, 0x58, 0xcd, 0x0f, 0xc7, 0xfd, 0x75, 0x08, 0x5e, 0x71, 0x90, 0xe9, 0x6a, 0x2d, - 0x64, 0xf9, 0x4d, 0x0c, 0x4b, 0x03, 0xee, 0xb2, 0x9b, 0xf9, 0x5c, 0x86, 0x4c, 0x37, 0xde, 0x28, - 0x4a, 0x33, 0x3b, 0x0e, 0x80, 0x93, 0x4e, 0x6a, 0x89, 0xf4, 0x1f, 0x01, 0xbc, 0x31, 0x50, 0x0a, - 0xde, 0xec, 0x95, 0x9b, 0xd5, 0x85, 0x17, 0xcf, 0x2a, 0xaf, 0x05, 0xa5, 0xa0, 0x73, 0x45, 0x77, - 0xb9, 0xf3, 0x71, 0x7a, 0x94, 0x94, 0x04, 0x4e, 0xe7, 0x8a, 0xee, 0xda, 0x02, 0x37, 0xc1, 0xcb, - 0xd1, 0xaa, 0xc7, 0xb8, 0xcd, 0x73, 0x6c, 0x51, 0x8e, 0x5b, 0x38, 0x39, 0x68, 0xe1, 0xe4, 0xdd, - 0xe6, 0x23, 0xcb, 0xd4, 0x6f, 0xe3, 0xb6, 0x3a, 0x1b, 0x4a, 0xdc, 0xc6, 0x6d, 0x69, 0x0e, 0xc0, - 0x20, 0x74, 0x91, 0x8b, 0xe2, 0xc4, 0x79, 0x08, 0xce, 0xa4, 0x46, 0xf9, 0xb1, 0xd4, 0xc0, 0x94, - 0xc3, 0x46, 0xf8, 0xcd, 0x7c, 0x21, 0xe7, 0x59, 0xf8, 0x22, 0x3c, 0x6e, 0x39, 0x80, 0x74, 0x8b, - 0x27, 0x72, 0x2a, 0x02, 0xee, 0x3a, 0x1e, 0x36, 0x6a, 0x76, 0x54, 0x1e, 0xf3, 0xb4, 0x8e, 0x87, - 0x3c, 0xc7, 0x07, 0x01, 0x45, 0xfd, 0xda, 0xeb, 0xc9, 0xfb, 0xb7, 0xe3, 0xa4, 0x70, 0x98, 0xfa, - 0x0b, 0x89, 0x8b, 0x38, 0x7d, 0x74, 0x98, 0x4a, 0xd7, 0x40, 0x39, 0xb5, 0x65, 0x21, 0x7d, 0x3f, - 0x17, 0xc0, 0x52, 0x0f, 0xe9, 0xe8, 0x57, 0xe6, 0x65, 0x2a, 0xe4, 0xbe, 0x4c, 0xbb, 0xa2, 0xa2, - 0x54, 0x30, 0x2a, 0xe0, 0x1c, 0x98, 0x64, 0xad, 0x09, 0x8b, 0xa7, 0x71, 0x35, 0xf8, 0xf0, 0x9b, - 0xcf, 0x4a, 0x4f, 0xc3, 0xb9, 0x7f, 0x31, 0x00, 0xb1, 0xeb, 0x78, 0xca, 0xde, 0xc8, 0x15, 0x26, - 0x83, 0x9c, 0xa2, 0x26, 0x80, 0xa5, 0x43, 0x5e, 0x54, 0xd2, 0x5d, 0x79, 0xb4, 0xf6, 0x1d, 0x44, - 0xf7, 0x08, 0xff, 0x0a, 0xef, 0xc3, 0x11, 0x9d, 0x2a, 0x21, 0xb0, 0x56, 0x60, 0x4b, 0xee, 0x8e, - 0x8b, 0x00, 0x46, 0x27, 0x11, 0x46, 0x44, 0x18, 0x63, 0x51, 0x05, 0x08, 0xaa, 0x9f, 0xc1, 0x3a, - 0x95, 0x0b, 0xd9, 0xbd, 0xcf, 0x36, 0x69, 0x34, 0x4c, 0x4a, 0x4d, 0x62, 0xab, 0x09, 0x8b, 0xbe, - 0xb6, 0x76, 0x4c, 0xaa, 0x83, 0x8b, 0xf9, 0x14, 0xe1, 0x76, 0xbe, 0x09, 0x26, 0xdc, 0x90, 0x97, - 0xcd, 0x54, 0xcf, 0xf9, 0xa9, 0xfe, 0x97, 0x67, 0x95, 0x85, 0x80, 0x1e, 0x52, 0xe3, 0xb1, 0x6c, - 0x12, 0xa5, 0x81, 0xbc, 0x03, 0xf9, 0x0e, 0xae, 0x23, 0xbd, 0xbd, 0x83, 0x75, 0x95, 0x09, 0x48, - 0x1b, 0x3c, 0x1b, 0xee, 0x5a, 0x06, 0xa6, 0xde, 0x7d, 0x5b, 0x27, 0xf6, 0x07, 0xa6, 0xdb, 0xc0, - 0xc6, 0x3e, 0xd5, 0x73, 0x64, 0xd3, 0xcf, 0xc3, 0xde, 0x2e, 0x5b, 0x9e, 0x6b, 0x67, 0x02, 0xd8, - 0xa2, 0xba, 0x46, 0xb1, 0x6d, 0x68, 0x11, 0xf5, 0xe6, 0x35, 0xec, 0x72, 0xae, 0xe0, 0xdc, 0xa7, - 0xfa, 0x3d, 0x6c, 0x1b, 0x71, 0xab, 0x12, 0x54, 0xb3, 0xd3, 0xad, 0x8e, 0xf1, 0xf5, 0xcf, 0x2b, - 0x60, 0x92, 0x29, 0x04, 0x8f, 0x04, 0x30, 0x97, 0x45, 0x6a, 0xe1, 0xf5, 0xe2, 0xe9, 0x90, 0x66, - 0xd2, 0xe2, 0xd6, 0x08, 0x08, 0x81, 0x4b, 0xa4, 0x1b, 0x3f, 0xf9, 0xea, 0xef, 0xbf, 0x2c, 0x6d, - 0xc2, 0x8d, 0xc1, 0xaf, 0x24, 0x51, 0x00, 0x73, 0xd6, 0xac, 0x3c, 0x0d, 0x4f, 0xe3, 0x23, 0xf8, - 0x95, 0xc0, 0x6f, 0x8a, 0x74, 0x56, 0xc0, 0xcd, 0xe2, 0x1a, 0xa6, 0x68, 0xb7, 0x78, 0x7d, 0x78, - 0x00, 0x6e, 0xe1, 0x5b, 0xcc, 0xc2, 0x4b, 0x70, 0xad, 0x80, 0x85, 0x01, 0x21, 0x87, 0x1f, 0x97, - 0xc0, 0x7c, 0x0f, 0x96, 0x4d, 0xe1, 0x9d, 0x21, 0x35, 0xcb, 0x24, 0xf4, 0xe2, 0xbb, 0xc7, 0x84, - 0xc6, 0x8d, 0x7e, 0x87, 0x19, 0x5d, 0x85, 0xd7, 0x8b, 0x1a, 0xad, 0x51, 0x1f, 0x50, 0x8b, 0xb8, - 0x32, 0xfc, 0x9f, 0x00, 0x5e, 0xcb, 0x26, 0xed, 0x14, 0xde, 0x1e, 0x5a, 0xe9, 0xee, 0xd7, 0x01, - 0xf1, 0xce, 0xf1, 0x80, 0x71, 0x07, 0xdc, 0x62, 0x0e, 0xd8, 0x82, 0x9b, 0x43, 0x38, 0x80, 0x38, - 0x09, 0xfb, 0xff, 0x1d, 0xb2, 0xa7, 0x4c, 0x1e, 0x0a, 0x6f, 0xe6, 0xd7, 0xba, 0x1f, 0xa3, 0x16, - 0x6f, 0x8d, 0x8c, 0xc3, 0x0d, 0xdf, 0x62, 0x86, 0x5f, 0x83, 0x6f, 0xe5, 0x78, 0xf6, 0x8c, 0x9e, - 0x13, 0x52, 0x1d, 0x66, 0x86, 0xc9, 0xc9, 0xde, 0x67, 0x28, 0x93, 0x33, 0x98, 0xf6, 0x50, 0x26, - 0x67, 0x11, 0xe5, 0xe1, 0x4c, 0x4e, 0xdd, 0x8a, 0xf0, 0x8f, 0x02, 0xef, 0x7f, 0x53, 0x1c, 0x19, - 0xbe, 0x9d, 0x5f, 0xc5, 0x2c, 0xea, 0x2d, 0x6e, 0x0e, 0x2d, 0xcf, 0x4d, 0xbb, 0xc2, 0x4c, 0x5b, - 0x87, 0xab, 0x83, 0x4d, 0xf3, 0x38, 0x40, 0xf0, 0x32, 0x0a, 0x7f, 0x5d, 0x02, 0xe7, 0x72, 0x90, - 0x5e, 0x78, 0x37, 0xbf, 0x8a, 0xb9, 0xc8, 0xb6, 0xb8, 0x7b, 0x7c, 0x80, 0xdc, 0x09, 0xb7, 0x99, - 0x13, 0x6e, 0xc0, 0xed, 0xc1, 0x4e, 0x70, 0x23, 0xc4, 0x38, 0xa6, 0x5d, 0x86, 0xa9, 0x05, 0x24, - 0x1e, 0xfe, 0xb3, 0x8b, 0xa4, 0xa7, 0xb9, 0x27, 0x85, 0x05, 0x6e, 0xd5, 0x1e, 0x2f, 0x01, 0x62, - 0x75, 0x14, 0x08, 0x6e, 0x75, 0x95, 0x59, 0xfd, 0x3d, 0x78, 0x75, 0xb0, 0xd5, 0xe1, 0x1b, 0x80, - 0xd6, 0x79, 0x81, 0xfd, 0xaa, 0xc4, 0x9f, 0x89, 0x73, 0x90, 0x6e, 0xb8, 0x97, 0x5f, 0xe9, 0xfc, - 0x4f, 0x02, 0xe2, 0xfd, 0x63, 0x46, 0xe5, 0xde, 0xb9, 0xc6, 0xbc, 0x73, 0x19, 0x5e, 0x2a, 0x5c, - 0xdf, 0x4d, 0x03, 0xfe, 0x5e, 0x00, 0xb3, 0x09, 0x5e, 0x0b, 0xdf, 0x2c, 0x70, 0x5c, 0x49, 0x7e, - 0x2c, 0x5e, 0x29, 0x2e, 0xc8, 0xf5, 0x5f, 0x65, 0xfa, 0xaf, 0xc0, 0xe5, 0x1c, 0xa7, 0x1b, 0x28, - 0xf9, 0x8b, 0x30, 0xa1, 0xfb, 0x33, 0xdc, 0x22, 0x09, 0x9d, 0x8b, 0x74, 0x17, 0x49, 0xe8, 0x7c, - 0xe4, 0xbb, 0x48, 0x77, 0x42, 0x7c, 0x10, 0xcd, 0xb4, 0xb5, 0x98, 0xf4, 0x25, 0xfb, 0xce, 0x3f, - 0x94, 0xc0, 0xf9, 0xdc, 0x6c, 0x0c, 0xde, 0x1f, 0xb6, 0x99, 0xec, 0x4b, 0x28, 0xc5, 0xfd, 0xe3, - 0x86, 0xe5, 0x6e, 0x7a, 0xc0, 0xdc, 0xb4, 0x07, 0xd5, 0xc2, 0x9d, 0xab, 0xe6, 0x60, 0x37, 0xf6, - 0x98, 0xf2, 0xb4, 0x93, 0x02, 0x7e, 0x04, 0x7f, 0x57, 0x02, 0xdf, 0xcc, 0xc3, 0xec, 0xe0, 0xee, - 0x08, 0x8d, 0x49, 0x26, 0x5b, 0x15, 0xdf, 0x3f, 0x46, 0x44, 0xee, 0xa9, 0x87, 0xcc, 0x53, 0x0f, - 0xe0, 0x0f, 0x8a, 0x78, 0x2a, 0x82, 0xd2, 0x7c, 0x06, 0x9a, 0x88, 0xaa, 0x2c, 0x7f, 0xfd, 0x57, - 0xe0, 0x4f, 0xec, 0x59, 0x04, 0x13, 0x16, 0x78, 0xd9, 0xe8, 0x43, 0x70, 0xc5, 0x9b, 0xa3, 0xc2, - 0x14, 0xbf, 0x30, 0x09, 0xc3, 0xd1, 0x9a, 0x31, 0x90, 0xd6, 0xa2, 0x7a, 0x32, 0xc5, 0xfe, 0xd5, - 0x49, 0x00, 0x12, 0xb5, 0x66, 0x7b, 0x94, 0x17, 0x9d, 0xd0, 0xea, 0x9d, 0xd1, 0x40, 0x46, 0x60, - 0x3c, 0x99, 0x35, 0xa5, 0xfa, 0xfd, 0x2f, 0x8e, 0xca, 0xc2, 0x97, 0x47, 0x65, 0xe1, 0x6f, 0x47, - 0x65, 0xe1, 0xd3, 0xe7, 0xe5, 0xb1, 0x2f, 0x9f, 0x97, 0xc7, 0xfe, 0xfc, 0xbc, 0x3c, 0xf6, 0x60, - 0xa3, 0x6e, 0x7a, 0x07, 0xcd, 0x47, 0xb2, 0x4e, 0x1a, 0xfc, 0x1f, 0xef, 0xc4, 0x66, 0xdf, 0x8d, - 0x36, 0x6b, 0x5d, 0x56, 0x3e, 0xec, 0xe8, 0xcd, 0xda, 0x0e, 0xa6, 0x8f, 0xa6, 0xd8, 0x5f, 0x1d, - 0x97, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x4e, 0xa1, 0x75, 0x91, 0x20, 0x00, 0x00, + 0x15, 0x17, 0x57, 0xb2, 0x22, 0x8d, 0x62, 0x3b, 0x19, 0xab, 0xb1, 0x4c, 0x29, 0xbb, 0x0a, 0xdd, + 0x0f, 0x59, 0x76, 0x49, 0x49, 0x86, 0x11, 0xc7, 0xae, 0x23, 0x6b, 0x25, 0xd9, 0x59, 0xd8, 0xb1, + 0x15, 0x5a, 0x76, 0x0b, 0xb7, 0x28, 0x3d, 0x22, 0xa7, 0x2b, 0xc2, 0x5c, 0x0e, 0xc5, 0x19, 0xad, + 0xbd, 0x30, 0x72, 0x48, 0x0f, 0x6d, 0x8e, 0x41, 0x3f, 0x80, 0x1e, 0x73, 0xe9, 0xb1, 0x3d, 0xf4, + 0x50, 0xf4, 0x4f, 0xc8, 0xad, 0x29, 0x72, 0x29, 0x7a, 0x70, 0x0b, 0xbb, 0x87, 0xa2, 0x40, 0x8b, + 0x22, 0xe8, 0xb5, 0x40, 0xc1, 0xe1, 0x90, 0x4b, 0xee, 0x72, 0x77, 0xc9, 0x5d, 0xe5, 0x26, 0xce, + 0xbc, 0xf7, 0x9b, 0xf7, 0xde, 0xbc, 0xf7, 0xe6, 0xfd, 0x56, 0x40, 0xb3, 0x5d, 0x86, 0x7d, 0x73, + 0x1f, 0xd9, 0xae, 0x41, 0xb1, 0x79, 0xe8, 0xdb, 0xac, 0xa5, 0x99, 0x66, 0x53, 0xf3, 0x7c, 0xd2, + 0xb4, 0x2d, 0xec, 0x6b, 0xcd, 0x55, 0xed, 0xe0, 0x10, 0xfb, 0x2d, 0xd5, 0xf3, 0x09, 0x23, 0xf0, + 0x6c, 0x86, 0x82, 0x6a, 0x9a, 0x4d, 0x35, 0x52, 0x50, 0x9b, 0xab, 0xf2, 0x42, 0x9d, 0x90, 0xba, + 0x83, 0x35, 0xe4, 0xd9, 0x1a, 0x72, 0x5d, 0xc2, 0x10, 0xb3, 0x89, 0x4b, 0x43, 0x08, 0x79, 0xb6, + 0x4e, 0xea, 0x84, 0xff, 0xa9, 0x05, 0x7f, 0x89, 0xd5, 0x8a, 0xd0, 0xe1, 0x5f, 0x7b, 0x87, 0x3f, + 0xd2, 0x98, 0xdd, 0xc0, 0x94, 0xa1, 0x86, 0x27, 0x04, 0xd6, 0xf2, 0x98, 0x1a, 0x5b, 0x11, 0xea, + 0xac, 0xf4, 0xd2, 0x69, 0xae, 0x6a, 0x74, 0x1f, 0xf9, 0xd8, 0x32, 0x4c, 0xe2, 0xd2, 0xc3, 0x46, + 0xac, 0xf1, 0x8d, 0x3e, 0x1a, 0x4f, 0x6c, 0x1f, 0x0b, 0xb1, 0x05, 0x86, 0x5d, 0x0b, 0xfb, 0x0d, + 0xdb, 0x65, 0x9a, 0xe9, 0xb7, 0x3c, 0x46, 0xb4, 0xc7, 0xb8, 0x15, 0x79, 0x78, 0xc6, 0x24, 0xb4, + 0x41, 0xa8, 0x11, 0x3a, 0x19, 0x7e, 0x84, 0x5b, 0xca, 0x65, 0x30, 0xff, 0x41, 0x10, 0xce, 0x4d, + 0x71, 0xec, 0x4d, 0xec, 0x62, 0x6a, 0x53, 0x1d, 0x1f, 0x1c, 0x62, 0xca, 0xe0, 0x19, 0x30, 0x15, + 0x9e, 0x6d, 0x5b, 0x73, 0xd2, 0xa2, 0xb4, 0x34, 0xad, 0xbf, 0xc2, 0xbf, 0x6b, 0x96, 0xf2, 0x0c, + 0x2c, 0x64, 0x6b, 0x52, 0x8f, 0xb8, 0x14, 0xc3, 0xef, 0x83, 0xe3, 0xf5, 0x70, 0xc9, 0xa0, 0x0c, + 0x31, 0xcc, 0xf5, 0x67, 0xd6, 0x56, 0xd4, 0x5e, 0x37, 0xd6, 0x5c, 0x55, 0x3b, 0xb0, 0xee, 0x05, + 0x7a, 0xd5, 0x89, 0xcf, 0x9e, 0x57, 0xc6, 0xf4, 0x57, 0xeb, 0x89, 0x35, 0x65, 0x01, 0xc8, 0xa9, + 0xc3, 0x37, 0x03, 0xb8, 0xc8, 0x6a, 0x05, 0x75, 0x38, 0x15, 0xed, 0x0a, 0xcb, 0xaa, 0x60, 0x92, + 0x1f, 0x4f, 0xe7, 0xa4, 0xc5, 0xf1, 0xa5, 0x99, 0xb5, 0x65, 0x35, 0x47, 0x12, 0xa9, 0x1c, 0x44, + 0x17, 0x9a, 0xca, 0x39, 0xf0, 0xad, 0xee, 0x23, 0xee, 0x31, 0xe4, 0xb3, 0x1d, 0x9f, 0x78, 0x84, + 0x22, 0x27, 0xb6, 0xe6, 0x63, 0x09, 0x2c, 0x0d, 0x96, 0x15, 0xb6, 0xfd, 0x00, 0x4c, 0x7b, 0xd1, + 0xa2, 0x88, 0xd8, 0xbb, 0xf9, 0xcc, 0x13, 0xe0, 0x1b, 0x96, 0x65, 0x07, 0xd9, 0xdd, 0x86, 0x6e, + 0x03, 0x2a, 0x4b, 0xe0, 0x9b, 0x59, 0x96, 0x10, 0xaf, 0xcb, 0xe8, 0x9f, 0x48, 0xd9, 0x0e, 0xa6, + 0x44, 0xe3, 0x9b, 0xee, 0xb2, 0xf9, 0x5a, 0x21, 0x9b, 0x75, 0xdc, 0x20, 0x4d, 0xe4, 0x64, 0x9a, + 0xfc, 0xab, 0x12, 0x38, 0xc6, 0xcf, 0xee, 0x93, 0x8b, 0x70, 0x1e, 0x4c, 0x9b, 0x8e, 0x8d, 0x5d, + 0x16, 0xec, 0x95, 0xf8, 0xde, 0x54, 0xb8, 0x50, 0xb3, 0xe0, 0x29, 0x70, 0x8c, 0x11, 0xcf, 0xb8, + 0x33, 0x37, 0xbe, 0x28, 0x2d, 0x1d, 0xd7, 0x27, 0x18, 0xf1, 0xee, 0xc0, 0x65, 0x00, 0x1b, 0xb6, + 0x6b, 0x78, 0xe4, 0x09, 0xf6, 0x0d, 0xdb, 0x35, 0x42, 0x89, 0x89, 0x45, 0x69, 0x69, 0x5c, 0x3f, + 0xd1, 0xb0, 0xdd, 0x9d, 0x60, 0xa3, 0xe6, 0xee, 0x06, 0xb2, 0x2b, 0x60, 0xb6, 0x89, 0x1c, 0xdb, + 0x42, 0x8c, 0xf8, 0x54, 0xa8, 0x98, 0xc8, 0x9b, 0x3b, 0xc6, 0xf1, 0x60, 0x7b, 0x8f, 0x2b, 0x6d, + 0x22, 0x0f, 0x2e, 0x83, 0xd7, 0xe3, 0x55, 0x83, 0x62, 0xc6, 0xc5, 0x27, 0xb9, 0xf8, 0xc9, 0x78, + 0xe3, 0x1e, 0x66, 0x81, 0xec, 0x02, 0x98, 0x46, 0x8e, 0x43, 0x9e, 0x38, 0x36, 0x65, 0x73, 0xaf, + 0x2c, 0x8e, 0x2f, 0x4d, 0xeb, 0xed, 0x05, 0x28, 0x83, 0x29, 0x0b, 0xbb, 0x2d, 0xbe, 0x39, 0xc5, + 0x37, 0xe3, 0x6f, 0xe5, 0xa7, 0x12, 0x78, 0x8b, 0xdf, 0xd1, 0x83, 0x08, 0x32, 0x91, 0x04, 0xfe, + 0xe0, 0x12, 0x86, 0xd7, 0xc0, 0x6b, 0xd1, 0x75, 0x18, 0xc8, 0xb2, 0x7c, 0x4c, 0x69, 0x18, 0xbd, + 0x2a, 0xfc, 0xf2, 0x79, 0xe5, 0x44, 0x0b, 0x35, 0x9c, 0x2b, 0x8a, 0xd8, 0x50, 0xf4, 0x93, 0x91, + 0xec, 0x46, 0xb8, 0x72, 0x65, 0xea, 0xe3, 0x4f, 0x2b, 0x63, 0xff, 0xf8, 0xb4, 0x32, 0xa6, 0xdc, + 0x05, 0x4a, 0x3f, 0x43, 0x44, 0x9e, 0x9c, 0x03, 0xaf, 0x45, 0xdd, 0x2d, 0x3e, 0x2e, 0xb4, 0xe8, + 0xa4, 0x99, 0x90, 0x0f, 0x0e, 0xeb, 0x76, 0x6d, 0x27, 0x71, 0x78, 0x3e, 0xd7, 0xba, 0xce, 0xea, + 0xe3, 0x5a, 0xc7, 0xf9, 0xfd, 0x5c, 0x4b, 0x1b, 0xd2, 0x76, 0xad, 0x2b, 0x92, 0xc2, 0xb5, 0x8e, + 0xa8, 0x29, 0xf3, 0xe0, 0x0c, 0x07, 0xdc, 0xdd, 0xf7, 0x09, 0x63, 0x0e, 0xe6, 0x0d, 0x2d, 0x2a, + 0xbb, 0x3f, 0x49, 0xa2, 0xb1, 0x75, 0xec, 0x8a, 0x63, 0x2a, 0x60, 0x86, 0x3a, 0x88, 0xee, 0x1b, + 0x0d, 0xcc, 0xb0, 0xcf, 0x4f, 0x18, 0xd7, 0x01, 0x5f, 0x7a, 0x3f, 0x58, 0x81, 0x6b, 0xe0, 0x6b, + 0x09, 0x01, 0x83, 0xe7, 0x11, 0x72, 0x4d, 0xcc, 0x7d, 0x1f, 0xd7, 0x4f, 0xb5, 0x45, 0x37, 0xa2, + 0x2d, 0xf8, 0x43, 0x30, 0xe7, 0xe2, 0xa7, 0xcc, 0xf0, 0xb1, 0xe7, 0x60, 0xd7, 0xa6, 0xfb, 0x86, + 0x89, 0x5c, 0x2b, 0x70, 0x16, 0xf3, 0x92, 0x99, 0x59, 0x93, 0xd5, 0xf0, 0x31, 0x54, 0xa3, 0xc7, + 0x50, 0xdd, 0x8d, 0x1e, 0xc3, 0xea, 0x54, 0xd0, 0x9d, 0x3f, 0xf9, 0x6b, 0x45, 0xd2, 0xdf, 0x08, + 0x50, 0xf4, 0x08, 0x64, 0x33, 0xc2, 0x50, 0x2e, 0x80, 0x65, 0xee, 0x92, 0x8e, 0xeb, 0x36, 0x65, + 0xd8, 0xc7, 0x56, 0xbb, 0xee, 0x9f, 0x20, 0xdf, 0xda, 0xc2, 0x2e, 0x69, 0xc4, 0x8d, 0x67, 0x1b, + 0x9c, 0xcf, 0x25, 0x2d, 0x22, 0xf2, 0x06, 0x98, 0xb4, 0xf8, 0x0a, 0xef, 0xe5, 0xd3, 0xba, 0xf8, + 0x52, 0xca, 0xe2, 0x75, 0x0a, 0x7b, 0x0a, 0xb6, 0x78, 0x0b, 0xa9, 0x6d, 0xc5, 0xc7, 0x7c, 0x24, + 0x81, 0x37, 0x7b, 0x08, 0x08, 0xe4, 0x47, 0xe0, 0x84, 0x97, 0xdc, 0x8b, 0x5e, 0x8b, 0xb5, 0x5c, + 0xad, 0x2d, 0x05, 0x2b, 0x9e, 0xb0, 0x0e, 0x3c, 0xa5, 0x06, 0x8e, 0xa7, 0xc4, 0xe0, 0x1c, 0x10, + 0xf9, 0xbb, 0x95, 0x4e, 0xe7, 0x2d, 0x58, 0x06, 0x20, 0x6a, 0x89, 0xb5, 0x2d, 0x7e, 0x99, 0x13, + 0x7a, 0x62, 0x45, 0xb9, 0x0d, 0x34, 0xee, 0xcd, 0x86, 0xe3, 0xec, 0x20, 0xdb, 0xa7, 0x0f, 0x90, + 0xb3, 0x49, 0xdc, 0x20, 0xe5, 0xaa, 0xe9, 0x0e, 0x5e, 0xdb, 0xca, 0xf1, 0xb4, 0xff, 0x5a, 0x02, + 0x2b, 0xf9, 0xe1, 0x44, 0xbc, 0x0e, 0xc0, 0xeb, 0x1e, 0xb2, 0x7d, 0xa3, 0x89, 0x9c, 0x60, 0x88, + 0xe1, 0x65, 0x20, 0x42, 0x76, 0x23, 0x5f, 0xc8, 0x90, 0xed, 0xb7, 0x0f, 0x8a, 0xcb, 0xcc, 0x6d, + 0x27, 0xc0, 0x09, 0x2f, 0x25, 0xa2, 0xfc, 0x57, 0x02, 0x6f, 0x0d, 0xd4, 0x82, 0x37, 0x7a, 0xd5, + 0x66, 0x75, 0xfe, 0xcb, 0xe7, 0x95, 0xd3, 0x61, 0x2b, 0xe8, 0x94, 0xe8, 0x6e, 0x77, 0x01, 0x4e, + 0x8f, 0x96, 0x92, 0xc0, 0xe9, 0x94, 0xe8, 0xee, 0x2d, 0x70, 0x1d, 0xbc, 0x1a, 0x4b, 0x3d, 0xc6, + 0x2d, 0x51, 0x63, 0x0b, 0x6a, 0x7b, 0x84, 0x53, 0xc3, 0x11, 0x4e, 0xdd, 0x39, 0xdc, 0x73, 0x6c, + 0xf3, 0x16, 0x6e, 0xe9, 0x33, 0x91, 0xc6, 0x2d, 0xdc, 0x52, 0x66, 0x01, 0x0c, 0x53, 0x17, 0xf9, + 0xa8, 0x5d, 0x38, 0x8f, 0xc0, 0xa9, 0xd4, 0xaa, 0xb8, 0x96, 0x1a, 0x98, 0xf4, 0xf8, 0x8a, 0x78, + 0x99, 0xcf, 0xe7, 0xbc, 0x8b, 0x40, 0x45, 0xe4, 0xad, 0x00, 0x50, 0x6e, 0x8a, 0x42, 0x4e, 0x65, + 0xc0, 0x5d, 0x8f, 0x61, 0xab, 0xe6, 0xc6, 0xed, 0x31, 0xcf, 0xe8, 0x78, 0x20, 0x6a, 0x7c, 0x10, + 0x50, 0x3c, 0xaf, 0xbd, 0x99, 0x7c, 0x7f, 0x3b, 0x6e, 0x0a, 0x47, 0xa5, 0x3f, 0x9f, 0x78, 0x88, + 0xd3, 0x57, 0x87, 0xa9, 0x72, 0x15, 0x94, 0x53, 0x47, 0x16, 0xb2, 0xf7, 0x0f, 0x12, 0x58, 0xec, + 0xa1, 0x1d, 0xff, 0x95, 0xf9, 0x98, 0x4a, 0xb9, 0x1f, 0xd3, 0xae, 0xac, 0x28, 0x15, 0xcc, 0x0a, + 0x38, 0x0b, 0x8e, 0xf1, 0xd1, 0x84, 0xe7, 0xd3, 0xb8, 0x1e, 0x7e, 0x04, 0xc3, 0x67, 0xa5, 0xa7, + 0xe3, 0x22, 0xbe, 0x18, 0x80, 0x76, 0xe8, 0x44, 0xc9, 0x6e, 0xe7, 0x4a, 0x93, 0x41, 0x41, 0xd1, + 0x13, 0xc0, 0xca, 0x81, 0x68, 0x2a, 0xe9, 0xa9, 0x3c, 0x96, 0x7d, 0x0f, 0xd1, 0x5d, 0x22, 0xbe, + 0xa2, 0xf7, 0x70, 0xc4, 0xa0, 0x2a, 0x08, 0xac, 0x16, 0x38, 0x52, 0x84, 0xe3, 0x02, 0x80, 0xf1, + 0x4d, 0x44, 0x19, 0x11, 0xe5, 0x58, 0xdc, 0x01, 0xc2, 0xee, 0x67, 0xf1, 0x49, 0xe5, 0x7c, 0xf6, + 0xec, 0xb3, 0x49, 0x1a, 0x0d, 0x9b, 0x52, 0x9b, 0xb8, 0x7a, 0xc2, 0xa3, 0xaf, 0x6c, 0x1c, 0x53, + 0xea, 0xe0, 0x42, 0x3e, 0x43, 0x84, 0x9f, 0x6f, 0x83, 0x09, 0x3f, 0xe2, 0x65, 0xd3, 0xd5, 0xb3, + 0x41, 0xa9, 0xff, 0xe5, 0x79, 0x65, 0x3e, 0xa4, 0x87, 0xd4, 0x7a, 0xac, 0xda, 0x44, 0x6b, 0x20, + 0xb6, 0xaf, 0xde, 0xc6, 0x75, 0x64, 0xb6, 0xb6, 0xb0, 0xa9, 0x73, 0x05, 0x45, 0x11, 0xd5, 0x50, + 0x75, 0x88, 0xf9, 0x98, 0xde, 0x77, 0x99, 0xed, 0xdc, 0xc1, 0x4f, 0xd9, 0xb6, 0x47, 0xcc, 0xfd, + 0xa8, 0x1b, 0x3d, 0x14, 0xf3, 0x5b, 0xb6, 0x8c, 0xb0, 0xe0, 0x12, 0x38, 0xbd, 0xc7, 0xf7, 0x8d, + 0xc3, 0x40, 0xc0, 0xe0, 0x63, 0x08, 0x0e, 0x44, 0xb8, 0x51, 0x13, 0xfa, 0xec, 0x5e, 0x86, 0xfa, + 0xda, 0x6f, 0x2b, 0xe0, 0x18, 0x07, 0x87, 0x2f, 0x24, 0x30, 0x9b, 0x45, 0x42, 0xe1, 0xf5, 0xe2, + 0xe9, 0x9b, 0x66, 0xbe, 0xf2, 0xc6, 0x08, 0x08, 0xa1, 0x7b, 0xca, 0xf6, 0x8f, 0xbf, 0xf8, 0xfb, + 0xcf, 0x4b, 0xeb, 0xf0, 0xda, 0xe0, 0x5f, 0x35, 0xe2, 0x84, 0x13, 0x2c, 0x57, 0x7b, 0x16, 0x25, + 0xc9, 0x87, 0xf0, 0x0b, 0x49, 0x74, 0xf6, 0x74, 0x16, 0xc3, 0xf5, 0xe2, 0x16, 0xa6, 0x68, 0xb2, + 0x7c, 0x7d, 0x78, 0x00, 0xe1, 0xe1, 0x3b, 0xdc, 0xc3, 0x8b, 0x70, 0xb5, 0x80, 0x87, 0x21, 0x81, + 0x86, 0x1f, 0x95, 0xc0, 0x5c, 0x0f, 0x56, 0x4c, 0xe1, 0xed, 0x21, 0x2d, 0xcb, 0x24, 0xe0, 0xf2, + 0xfb, 0x47, 0x84, 0x26, 0x9c, 0x7e, 0x8f, 0x3b, 0x5d, 0x85, 0xd7, 0x8b, 0x3a, 0x6d, 0xd0, 0x00, + 0xd0, 0x88, 0xb9, 0x2d, 0xfc, 0x9f, 0x04, 0x4e, 0x67, 0x93, 0x6c, 0x0a, 0x6f, 0x0d, 0x6d, 0x74, + 0x37, 0x9b, 0x97, 0x6f, 0x1f, 0x0d, 0x98, 0x08, 0xc0, 0x4d, 0x1e, 0x80, 0x0d, 0xb8, 0x3e, 0x44, + 0x00, 0x88, 0x97, 0xf0, 0xff, 0x3f, 0x11, 0xdb, 0xc9, 0xe4, 0x8d, 0xf0, 0x46, 0x7e, 0xab, 0xfb, + 0x31, 0x60, 0xf9, 0xe6, 0xc8, 0x38, 0xc2, 0xf1, 0x0d, 0xee, 0xf8, 0x55, 0xf8, 0x4e, 0x8e, 0x9f, + 0x29, 0x63, 0xfa, 0x9f, 0x9a, 0x08, 0x33, 0x5c, 0x4e, 0xce, 0x2a, 0x43, 0xb9, 0x9c, 0xc1, 0x8c, + 0x87, 0x72, 0x39, 0x8b, 0xd8, 0x0e, 0xe7, 0x72, 0xea, 0x15, 0x83, 0x7f, 0x94, 0xc4, 0xbc, 0x9a, + 0xe2, 0xb4, 0xf0, 0xdd, 0xfc, 0x26, 0x66, 0x51, 0x65, 0x79, 0x7d, 0x68, 0x7d, 0xe1, 0xda, 0x65, + 0xee, 0xda, 0x1a, 0x5c, 0x19, 0xec, 0x1a, 0x13, 0x00, 0xe1, 0x2f, 0x99, 0xf0, 0x97, 0x25, 0x70, + 0x36, 0x07, 0x49, 0x85, 0x77, 0xf3, 0x9b, 0x98, 0x8b, 0x1c, 0xcb, 0x3b, 0x47, 0x07, 0x28, 0x82, + 0x70, 0x8b, 0x07, 0x61, 0x1b, 0x6e, 0x0e, 0x0e, 0x82, 0x1f, 0x23, 0xb6, 0x73, 0xda, 0xe7, 0x98, + 0x46, 0x48, 0xba, 0xe1, 0x3f, 0xbb, 0x48, 0x75, 0x9a, 0x2b, 0x52, 0x58, 0xe0, 0x55, 0xed, 0xc1, + 0xdc, 0xe5, 0xea, 0x28, 0x10, 0xc2, 0xeb, 0x2a, 0xf7, 0xfa, 0x3b, 0xf0, 0xca, 0x60, 0xaf, 0x23, + 0xce, 0x6e, 0x74, 0x3e, 0x60, 0xbf, 0x28, 0x89, 0x9f, 0x75, 0x73, 0x90, 0x64, 0xb8, 0x9b, 0xdf, + 0xe8, 0xfc, 0x14, 0x5e, 0xbe, 0x7f, 0xc4, 0xa8, 0x22, 0x3a, 0x57, 0x79, 0x74, 0x2e, 0xc1, 0x8b, + 0x85, 0xfb, 0xbb, 0x6d, 0xc1, 0xdf, 0x49, 0x60, 0x26, 0xc1, 0x43, 0xe1, 0xdb, 0x05, 0xae, 0x2b, + 0xc9, 0x67, 0xe5, 0xcb, 0xc5, 0x15, 0x85, 0xfd, 0x2b, 0xdc, 0xfe, 0x65, 0xb8, 0x94, 0xe3, 0x76, + 0x43, 0x23, 0x7f, 0x16, 0x15, 0x74, 0x7f, 0x46, 0x5a, 0xa4, 0xa0, 0x73, 0x91, 0xe4, 0x22, 0x05, + 0x9d, 0x8f, 0x2c, 0x17, 0x99, 0x4e, 0x48, 0x00, 0x62, 0xd8, 0xae, 0xd1, 0x26, 0x69, 0xc9, 0xb9, + 0xf3, 0xf7, 0x25, 0x70, 0x2e, 0x37, 0x7b, 0x82, 0xf7, 0x87, 0x1d, 0x26, 0xfb, 0x12, 0x40, 0xf9, + 0xc1, 0x51, 0xc3, 0x8a, 0x30, 0x3d, 0xe4, 0x61, 0xda, 0x85, 0x7a, 0xe1, 0xc9, 0xd5, 0xf0, 0xb0, + 0xdf, 0x8e, 0x98, 0xf6, 0xac, 0x93, 0xb2, 0x7d, 0x08, 0x7f, 0x53, 0x02, 0x5f, 0xcf, 0xc3, 0xc4, + 0xe0, 0xce, 0x08, 0x83, 0x49, 0x26, 0xbb, 0x94, 0x3f, 0x38, 0x42, 0x44, 0x11, 0xa9, 0x47, 0x3c, + 0x52, 0x0f, 0xe1, 0xf7, 0x8a, 0x44, 0x2a, 0x86, 0x32, 0x02, 0xc6, 0x98, 0xc8, 0xaa, 0xac, 0x78, + 0xfd, 0xbb, 0x73, 0x0c, 0x4e, 0x54, 0xdc, 0xe6, 0x28, 0xbf, 0x43, 0x44, 0x51, 0xd9, 0x1a, 0x0d, + 0x64, 0x84, 0xb9, 0x3f, 0xbb, 0xb2, 0xfe, 0x25, 0x89, 0xff, 0x01, 0x64, 0xb1, 0x63, 0x58, 0xe0, + 0xa7, 0x97, 0x3e, 0x0c, 0x5c, 0xbe, 0x31, 0x2a, 0x4c, 0xf1, 0x09, 0xb0, 0x07, 0x99, 0xaf, 0x7e, + 0xf7, 0xb3, 0x17, 0x65, 0xe9, 0xf3, 0x17, 0x65, 0xe9, 0x6f, 0x2f, 0xca, 0xd2, 0x27, 0x2f, 0xcb, + 0x63, 0x9f, 0xbf, 0x2c, 0x8f, 0xfd, 0xf9, 0x65, 0x79, 0xec, 0xe1, 0xb5, 0xba, 0xcd, 0xf6, 0x0f, + 0xf7, 0x54, 0x93, 0x34, 0xc4, 0xff, 0xa5, 0x13, 0xa7, 0x7c, 0x3b, 0x3e, 0xa5, 0x79, 0x49, 0x7b, + 0xda, 0x31, 0x91, 0xb5, 0x3c, 0x4c, 0xf7, 0x26, 0xf9, 0x3f, 0x24, 0x2e, 0xfe, 0x3f, 0x00, 0x00, + 0xff, 0xff, 0xb5, 0x03, 0x23, 0x90, 0x37, 0x20, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1968,12 +1960,13 @@ type QueryClient interface { // QueryValidatorConsumerCommissionRate returns the commission rate a given // validator charges on a given consumer chain QueryValidatorConsumerCommissionRate(ctx context.Context, in *QueryValidatorConsumerCommissionRateRequest, opts ...grpc.CallOption) (*QueryValidatorConsumerCommissionRateResponse, error) - // QueryOldestUnconfirmedVsc returns the send timestamp of the oldest unconfirmed VSCPacket for a given chainID - QueryOldestUnconfirmedVsc(ctx context.Context, in *QueryOldestUnconfirmedVscRequest, opts ...grpc.CallOption) (*QueryOldestUnconfirmedVscResponse, error) // QueryConsumerValidators returns the latest set consumer-validator set for a given chainID // Note that this does not necessarily mean that the consumer chain is using this validator set at this exact moment // because a VSCPacket could be delayed to be delivered on the consumer chain. QueryConsumerValidators(ctx context.Context, in *QueryConsumerValidatorsRequest, opts ...grpc.CallOption) (*QueryConsumerValidatorsResponse, error) + // QueryBlocksUntilNextEpoch returns the number of blocks until the next epoch + // starts and validator updates are sent to the consumer chains + QueryBlocksUntilNextEpoch(ctx context.Context, in *QueryBlocksUntilNextEpochRequest, opts ...grpc.CallOption) (*QueryBlocksUntilNextEpochResponse, error) } type queryClient struct { @@ -2110,18 +2103,18 @@ func (c *queryClient) QueryValidatorConsumerCommissionRate(ctx context.Context, return out, nil } -func (c *queryClient) QueryOldestUnconfirmedVsc(ctx context.Context, in *QueryOldestUnconfirmedVscRequest, opts ...grpc.CallOption) (*QueryOldestUnconfirmedVscResponse, error) { - out := new(QueryOldestUnconfirmedVscResponse) - err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryOldestUnconfirmedVsc", in, out, opts...) +func (c *queryClient) QueryConsumerValidators(ctx context.Context, in *QueryConsumerValidatorsRequest, opts ...grpc.CallOption) (*QueryConsumerValidatorsResponse, error) { + out := new(QueryConsumerValidatorsResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryConsumerValidators", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *queryClient) QueryConsumerValidators(ctx context.Context, in *QueryConsumerValidatorsRequest, opts ...grpc.CallOption) (*QueryConsumerValidatorsResponse, error) { - out := new(QueryConsumerValidatorsResponse) - err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryConsumerValidators", in, out, opts...) +func (c *queryClient) QueryBlocksUntilNextEpoch(ctx context.Context, in *QueryBlocksUntilNextEpochRequest, opts ...grpc.CallOption) (*QueryBlocksUntilNextEpochResponse, error) { + out := new(QueryBlocksUntilNextEpochResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryBlocksUntilNextEpoch", in, out, opts...) if err != nil { return nil, err } @@ -2169,12 +2162,13 @@ type QueryServer interface { // QueryValidatorConsumerCommissionRate returns the commission rate a given // validator charges on a given consumer chain QueryValidatorConsumerCommissionRate(context.Context, *QueryValidatorConsumerCommissionRateRequest) (*QueryValidatorConsumerCommissionRateResponse, error) - // QueryOldestUnconfirmedVsc returns the send timestamp of the oldest unconfirmed VSCPacket for a given chainID - QueryOldestUnconfirmedVsc(context.Context, *QueryOldestUnconfirmedVscRequest) (*QueryOldestUnconfirmedVscResponse, error) // QueryConsumerValidators returns the latest set consumer-validator set for a given chainID // Note that this does not necessarily mean that the consumer chain is using this validator set at this exact moment // because a VSCPacket could be delayed to be delivered on the consumer chain. QueryConsumerValidators(context.Context, *QueryConsumerValidatorsRequest) (*QueryConsumerValidatorsResponse, error) + // QueryBlocksUntilNextEpoch returns the number of blocks until the next epoch + // starts and validator updates are sent to the consumer chains + QueryBlocksUntilNextEpoch(context.Context, *QueryBlocksUntilNextEpochRequest) (*QueryBlocksUntilNextEpochResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -2223,12 +2217,12 @@ func (*UnimplementedQueryServer) QueryConsumerChainsValidatorHasToValidate(ctx c func (*UnimplementedQueryServer) QueryValidatorConsumerCommissionRate(ctx context.Context, req *QueryValidatorConsumerCommissionRateRequest) (*QueryValidatorConsumerCommissionRateResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method QueryValidatorConsumerCommissionRate not implemented") } -func (*UnimplementedQueryServer) QueryOldestUnconfirmedVsc(ctx context.Context, req *QueryOldestUnconfirmedVscRequest) (*QueryOldestUnconfirmedVscResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method QueryOldestUnconfirmedVsc not implemented") -} func (*UnimplementedQueryServer) QueryConsumerValidators(ctx context.Context, req *QueryConsumerValidatorsRequest) (*QueryConsumerValidatorsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method QueryConsumerValidators not implemented") } +func (*UnimplementedQueryServer) QueryBlocksUntilNextEpoch(ctx context.Context, req *QueryBlocksUntilNextEpochRequest) (*QueryBlocksUntilNextEpochResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryBlocksUntilNextEpoch not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -2486,38 +2480,38 @@ func _Query_QueryValidatorConsumerCommissionRate_Handler(srv interface{}, ctx co return interceptor(ctx, in, info, handler) } -func _Query_QueryOldestUnconfirmedVsc_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryOldestUnconfirmedVscRequest) +func _Query_QueryConsumerValidators_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryConsumerValidatorsRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(QueryServer).QueryOldestUnconfirmedVsc(ctx, in) + return srv.(QueryServer).QueryConsumerValidators(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryOldestUnconfirmedVsc", + FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryConsumerValidators", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).QueryOldestUnconfirmedVsc(ctx, req.(*QueryOldestUnconfirmedVscRequest)) + return srv.(QueryServer).QueryConsumerValidators(ctx, req.(*QueryConsumerValidatorsRequest)) } return interceptor(ctx, in, info, handler) } -func _Query_QueryConsumerValidators_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryConsumerValidatorsRequest) +func _Query_QueryBlocksUntilNextEpoch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryBlocksUntilNextEpochRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(QueryServer).QueryConsumerValidators(ctx, in) + return srv.(QueryServer).QueryBlocksUntilNextEpoch(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryConsumerValidators", + FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryBlocksUntilNextEpoch", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).QueryConsumerValidators(ctx, req.(*QueryConsumerValidatorsRequest)) + return srv.(QueryServer).QueryBlocksUntilNextEpoch(ctx, req.(*QueryBlocksUntilNextEpochRequest)) } return interceptor(ctx, in, info, handler) } @@ -2582,14 +2576,14 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "QueryValidatorConsumerCommissionRate", Handler: _Query_QueryValidatorConsumerCommissionRate_Handler, }, - { - MethodName: "QueryOldestUnconfirmedVsc", - Handler: _Query_QueryOldestUnconfirmedVsc_Handler, - }, { MethodName: "QueryConsumerValidators", Handler: _Query_QueryConsumerValidators_Handler, }, + { + MethodName: "QueryBlocksUntilNextEpoch", + Handler: _Query_QueryBlocksUntilNextEpoch_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "interchain_security/ccv/provider/v1/query.proto", @@ -3737,7 +3731,7 @@ func (m *QueryValidatorConsumerCommissionRateResponse) MarshalToSizedBuffer(dAtA return len(dAtA) - i, nil } -func (m *QueryOldestUnconfirmedVscRequest) Marshal() (dAtA []byte, err error) { +func (m *QueryBlocksUntilNextEpochRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -3747,27 +3741,20 @@ func (m *QueryOldestUnconfirmedVscRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryOldestUnconfirmedVscRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryBlocksUntilNextEpochRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryOldestUnconfirmedVscRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryBlocksUntilNextEpochRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.ChainId) > 0 { - i -= len(m.ChainId) - copy(dAtA[i:], m.ChainId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChainId))) - i-- - dAtA[i] = 0xa - } return len(dAtA) - i, nil } -func (m *QueryOldestUnconfirmedVscResponse) Marshal() (dAtA []byte, err error) { +func (m *QueryBlocksUntilNextEpochResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -3777,26 +3764,21 @@ func (m *QueryOldestUnconfirmedVscResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *QueryOldestUnconfirmedVscResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryBlocksUntilNextEpochResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryOldestUnconfirmedVscResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryBlocksUntilNextEpochResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - { - size, err := m.VscSendTimestamp.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) + if m.BlocksUntilNextEpoch != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.BlocksUntilNextEpoch)) + i-- + dAtA[i] = 0x8 } - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -4295,27 +4277,24 @@ func (m *QueryValidatorConsumerCommissionRateResponse) Size() (n int) { return n } -func (m *QueryOldestUnconfirmedVscRequest) Size() (n int) { +func (m *QueryBlocksUntilNextEpochRequest) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } return n } -func (m *QueryOldestUnconfirmedVscResponse) Size() (n int) { +func (m *QueryBlocksUntilNextEpochResponse) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = m.VscSendTimestamp.Size() - n += 1 + l + sovQuery(uint64(l)) + if m.BlocksUntilNextEpoch != 0 { + n += 1 + sovQuery(uint64(m.BlocksUntilNextEpoch)) + } return n } @@ -7358,7 +7337,7 @@ func (m *QueryValidatorConsumerCommissionRateResponse) Unmarshal(dAtA []byte) er } return nil } -func (m *QueryOldestUnconfirmedVscRequest) Unmarshal(dAtA []byte) error { +func (m *QueryBlocksUntilNextEpochRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -7381,44 +7360,12 @@ func (m *QueryOldestUnconfirmedVscRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryOldestUnconfirmedVscRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryBlocksUntilNextEpochRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryOldestUnconfirmedVscRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryBlocksUntilNextEpochRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChainId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -7440,7 +7387,7 @@ func (m *QueryOldestUnconfirmedVscRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryOldestUnconfirmedVscResponse) Unmarshal(dAtA []byte) error { +func (m *QueryBlocksUntilNextEpochResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -7463,17 +7410,17 @@ func (m *QueryOldestUnconfirmedVscResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryOldestUnconfirmedVscResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryBlocksUntilNextEpochResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryOldestUnconfirmedVscResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryBlocksUntilNextEpochResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field VscSendTimestamp", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlocksUntilNextEpoch", wireType) } - var msglen int + m.BlocksUntilNextEpoch = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -7483,25 +7430,11 @@ func (m *QueryOldestUnconfirmedVscResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + m.BlocksUntilNextEpoch |= uint64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.VscSendTimestamp.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/ccv/provider/types/query.pb.gw.go b/x/ccv/provider/types/query.pb.gw.go index 16bb010d71..a115ace156 100644 --- a/x/ccv/provider/types/query.pb.gw.go +++ b/x/ccv/provider/types/query.pb.gw.go @@ -505,8 +505,8 @@ func local_request_Query_QueryValidatorConsumerCommissionRate_0(ctx context.Cont } -func request_Query_QueryOldestUnconfirmedVsc_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryOldestUnconfirmedVscRequest +func request_Query_QueryConsumerValidators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsumerValidatorsRequest var metadata runtime.ServerMetadata var ( @@ -527,13 +527,13 @@ func request_Query_QueryOldestUnconfirmedVsc_0(ctx context.Context, marshaler ru return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err) } - msg, err := client.QueryOldestUnconfirmedVsc(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.QueryConsumerValidators(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_QueryOldestUnconfirmedVsc_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryOldestUnconfirmedVscRequest +func local_request_Query_QueryConsumerValidators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsumerValidatorsRequest var metadata runtime.ServerMetadata var ( @@ -554,61 +554,25 @@ func local_request_Query_QueryOldestUnconfirmedVsc_0(ctx context.Context, marsha return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err) } - msg, err := server.QueryOldestUnconfirmedVsc(ctx, &protoReq) + msg, err := server.QueryConsumerValidators(ctx, &protoReq) return msg, metadata, err } -func request_Query_QueryConsumerValidators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryConsumerValidatorsRequest +func request_Query_QueryBlocksUntilNextEpoch_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryBlocksUntilNextEpochRequest var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["chain_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "chain_id") - } - - protoReq.ChainId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err) - } - - msg, err := client.QueryConsumerValidators(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.QueryBlocksUntilNextEpoch(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_QueryConsumerValidators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryConsumerValidatorsRequest +func local_request_Query_QueryBlocksUntilNextEpoch_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryBlocksUntilNextEpochRequest var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["chain_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "chain_id") - } - - protoReq.ChainId, err = runtime.String(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err) - } - - msg, err := server.QueryConsumerValidators(ctx, &protoReq) + msg, err := server.QueryBlocksUntilNextEpoch(ctx, &protoReq) return msg, metadata, err } @@ -941,7 +905,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) - mux.Handle("GET", pattern_Query_QueryOldestUnconfirmedVsc_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle("GET", pattern_Query_QueryConsumerValidators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream @@ -952,7 +916,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Query_QueryOldestUnconfirmedVsc_0(rctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_Query_QueryConsumerValidators_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -960,11 +924,11 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv return } - forward_Query_QueryOldestUnconfirmedVsc_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_Query_QueryConsumerValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle("GET", pattern_Query_QueryConsumerValidators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle("GET", pattern_Query_QueryBlocksUntilNextEpoch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream @@ -975,7 +939,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Query_QueryConsumerValidators_0(rctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_Query_QueryBlocksUntilNextEpoch_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -983,7 +947,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv return } - forward_Query_QueryConsumerValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_Query_QueryBlocksUntilNextEpoch_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1308,7 +1272,7 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) - mux.Handle("GET", pattern_Query_QueryOldestUnconfirmedVsc_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle("GET", pattern_Query_QueryConsumerValidators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) @@ -1317,18 +1281,18 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Query_QueryOldestUnconfirmedVsc_0(rctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_Query_QueryConsumerValidators_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_Query_QueryOldestUnconfirmedVsc_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_Query_QueryConsumerValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle("GET", pattern_Query_QueryConsumerValidators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle("GET", pattern_Query_QueryBlocksUntilNextEpoch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) @@ -1337,14 +1301,14 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Query_QueryConsumerValidators_0(rctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_Query_QueryBlocksUntilNextEpoch_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_Query_QueryConsumerValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_Query_QueryBlocksUntilNextEpoch_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1380,9 +1344,9 @@ var ( pattern_Query_QueryValidatorConsumerCommissionRate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"interchain_security", "ccv", "provider", "consumer_commission_rate", "chain_id", "provider_address"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_QueryOldestUnconfirmedVsc_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"interchain_security", "ccv", "provider", "oldest_unconfirmed_vsc", "chain_id"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_QueryConsumerValidators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"interchain_security", "ccv", "provider", "consumer_validators", "chain_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_QueryBlocksUntilNextEpoch_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"interchain_security", "ccv", "provider", "blocks_until_next_epoch"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -1414,7 +1378,7 @@ var ( forward_Query_QueryValidatorConsumerCommissionRate_0 = runtime.ForwardResponseMessage - forward_Query_QueryOldestUnconfirmedVsc_0 = runtime.ForwardResponseMessage - forward_Query_QueryConsumerValidators_0 = runtime.ForwardResponseMessage + + forward_Query_QueryBlocksUntilNextEpoch_0 = runtime.ForwardResponseMessage ) diff --git a/x/ccv/types/events.go b/x/ccv/types/events.go index 4c597ded56..3c63fd7954 100644 --- a/x/ccv/types/events.go +++ b/x/ccv/types/events.go @@ -15,7 +15,6 @@ const ( EventTypeExecuteConsumerChainSlash = "execute_consumer_chain_slash" EventTypeFeeDistribution = "fee_distribution" EventTypeConsumerSlashRequest = "consumer_slash_request" - EventTypeVSCMatured = "vsc_matured" AttributeKeyAckSuccess = "success" AttributeKeyAck = "acknowledgement"