From e475452f13a782cc9d57dca02a3a341bd6bdb035 Mon Sep 17 00:00:00 2001 From: insumity Date: Tue, 3 Sep 2024 14:24:26 +0200 Subject: [PATCH] init commit --- .../ccv/provider/v1/genesis.proto | 2 + .../ccv/provider/v1/provider.proto | 2 + .../ccv/provider/v1/query.proto | 2 +- .../ccv/provider/v1/tx.proto | 7 +- tests/e2e/action_rapid_test.go | 9 +- tests/e2e/actions.go | 20 +- tests/e2e/state.go | 9 +- tests/e2e/state_rapid_test.go | 7 +- tests/e2e/steps_stop_chain.go | 50 ++- tests/e2e/testlib/types.go | 7 +- tests/e2e/trace_handlers_test.go | 14 +- tests/e2e/v4/state.go | 9 +- tests/integration/stop_consumer.go | 7 +- testutil/keeper/expectations.go | 5 +- testutil/keeper/unit_test_helpers.go | 32 +- x/ccv/provider/client/cli/query.go | 2 +- x/ccv/provider/client/cli/tx.go | 17 +- x/ccv/provider/keeper/consumer_lifecycle.go | 103 +++--- .../keeper/consumer_lifecycle_test.go | 28 +- x/ccv/provider/keeper/distribution.go | 8 +- x/ccv/provider/keeper/genesis.go | 6 +- x/ccv/provider/keeper/genesis_test.go | 2 + x/ccv/provider/keeper/grpc_query.go | 10 +- x/ccv/provider/keeper/grpc_query_test.go | 3 +- x/ccv/provider/keeper/keeper.go | 19 +- x/ccv/provider/keeper/keeper_test.go | 28 +- x/ccv/provider/keeper/msg_server.go | 19 +- x/ccv/provider/keeper/relay.go | 31 +- x/ccv/provider/keeper/relay_test.go | 104 ++++-- .../provider/migrations/v5/migration_test.go | 9 +- x/ccv/provider/migrations/v5/migrations.go | 2 +- x/ccv/provider/migrations/v6/migrations.go | 2 +- x/ccv/provider/types/consumer.go | 2 + x/ccv/provider/types/genesis.pb.go | 131 ++++--- x/ccv/provider/types/legacy_proposal.go | 1 - x/ccv/provider/types/msg.go | 7 +- x/ccv/provider/types/provider.pb.go | 33 +- x/ccv/provider/types/query.pb.go | 2 +- x/ccv/provider/types/tx.pb.go | 320 ++++++++---------- 39 files changed, 560 insertions(+), 511 deletions(-) diff --git a/proto/interchain_security/ccv/provider/v1/genesis.proto b/proto/interchain_security/ccv/provider/v1/genesis.proto index 8a8a3e4cb8..0f212b0271 100644 --- a/proto/interchain_security/ccv/provider/v1/genesis.proto +++ b/proto/interchain_security/ccv/provider/v1/genesis.proto @@ -78,6 +78,8 @@ message ConsumerState { repeated interchain_security.ccv.v1.ValidatorSetChangePacketData pending_valset_changes = 6 [ (gogoproto.nullable) = false ]; repeated string slash_downtime_ack = 7; + // the phase of the consumer chain + ConsumerPhase phase = 9; } // 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 3a4a1108aa..0a96af8cae 100644 --- a/proto/interchain_security/ccv/provider/v1/provider.proto +++ b/proto/interchain_security/ccv/provider/v1/provider.proto @@ -480,4 +480,6 @@ enum ConsumerPhase { CONSUMER_PHASE_LAUNCHED = 3; // STOPPED defines the phase in which a previously-launched chain has stopped. CONSUMER_PHASE_STOPPED = 4; + // DELETED defines the phase in which the state of a stopped chain has been deleted. + CONSUMER_PHASE_DELETED = 5; } diff --git a/proto/interchain_security/ccv/provider/v1/query.proto b/proto/interchain_security/ccv/provider/v1/query.proto index f6d2f406aa..60102699de 100644 --- a/proto/interchain_security/ccv/provider/v1/query.proto +++ b/proto/interchain_security/ccv/provider/v1/query.proto @@ -156,7 +156,7 @@ message QueryConsumerGenesisResponse { message QueryConsumerChainsRequest { // The phase of the consumer chains returned (optional) - // Registered=1|Initialized=2|Launched=3|Stopped=4 + // Registered=1|Initialized=2|Launched=3|Stopped=4|Deleted=5 ConsumerPhase phase = 1; // The limit of consumer chains returned (optional) // default is 100 diff --git a/proto/interchain_security/ccv/provider/v1/tx.proto b/proto/interchain_security/ccv/provider/v1/tx.proto index 19541025e5..8f2d7b5c1c 100644 --- a/proto/interchain_security/ccv/provider/v1/tx.proto +++ b/proto/interchain_security/ccv/provider/v1/tx.proto @@ -228,12 +228,7 @@ message MsgRemoveConsumer { // the consumer id of the consumer chain to be stopped string consumer_id = 1; - // the time on the provider chain at which all validators are responsible to - // stop their consumer chain validator node - google.protobuf.Timestamp stop_time = 2 - [ (gogoproto.stdtime) = true, (gogoproto.nullable) = false ]; - // signer address - string signer = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string signer = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; } // MsgRemoveConsumerResponse defines response type for MsgRemoveConsumer messages diff --git a/tests/e2e/action_rapid_test.go b/tests/e2e/action_rapid_test.go index 004eb30d95..d51cb64129 100644 --- a/tests/e2e/action_rapid_test.go +++ b/tests/e2e/action_rapid_test.go @@ -261,11 +261,10 @@ func GetSubmitConsumerAdditionProposalActionGen() *rapid.Generator[SubmitConsume func GetSubmitConsumerRemovalProposalActionGen() *rapid.Generator[SubmitConsumerRemovalProposalAction] { return rapid.Custom(func(t *rapid.T) SubmitConsumerRemovalProposalAction { return SubmitConsumerRemovalProposalAction{ - Chain: GetChainIDGen().Draw(t, "Chain"), - From: GetValidatorIDGen().Draw(t, "From"), - Deposit: rapid.Uint().Draw(t, "Deposit"), - ConsumerChain: GetChainIDGen().Draw(t, "ConsumerChain"), - StopTimeOffset: time.Duration(rapid.Int64().Draw(t, "StopTimeOffset")), + Chain: GetChainIDGen().Draw(t, "Chain"), + From: GetValidatorIDGen().Draw(t, "From"), + Deposit: rapid.Uint().Draw(t, "Deposit"), + ConsumerChain: GetChainIDGen().Draw(t, "ConsumerChain"), } }) } diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index 22e1842050..b1356814eb 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -740,11 +740,10 @@ func (tr Chain) submitConsumerAdditionLegacyProposal( } type SubmitConsumerRemovalProposalAction struct { - Chain ChainID - From ValidatorID - Deposit uint - ConsumerChain ChainID - StopTimeOffset time.Duration // offset from time.Now() + Chain ChainID + From ValidatorID + Deposit uint + ConsumerChain ChainID } func (tr Chain) submitConsumerRemovalProposal( @@ -762,7 +761,6 @@ func (tr Chain) submitConsumerRemovalProposal( msg := types.MsgRemoveConsumer{ ConsumerId: consumerId, - StopTime: tr.testConfig.containerConfig.Now.Add(action.StopTimeOffset), Signer: authority, } @@ -811,13 +809,11 @@ func (tr Chain) submitConsumerRemovalLegacyProposal( action SubmitConsumerRemovalProposalAction, verbose bool, ) { - stopTime := tr.testConfig.containerConfig.Now.Add(action.StopTimeOffset) prop := client.ConsumerRemovalProposalJSON{ - Title: fmt.Sprintf("Stop the %v chain", action.ConsumerChain), - Summary: "It was a great chain", - ChainId: string(tr.testConfig.chainConfigs[action.ConsumerChain].ChainId), - StopTime: stopTime, - Deposit: fmt.Sprint(action.Deposit) + `stake`, + Title: fmt.Sprintf("Stop the %v chain", action.ConsumerChain), + Summary: "It was a great chain", + ChainId: string(tr.testConfig.chainConfigs[action.ConsumerChain].ChainId), + Deposit: fmt.Sprint(action.Deposit) + `stake`, } bz, err := json.Marshal(prop) diff --git a/tests/e2e/state.go b/tests/e2e/state.go index 676d8dcfc5..cdb25a0907 100644 --- a/tests/e2e/state.go +++ b/tests/e2e/state.go @@ -525,7 +525,6 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { } case "/interchain_security.ccv.provider.v1.MsgRemoveConsumer": consumerId := rawContent.Get("consumer_id").String() - stopTime := rawContent.Get("stop_time").Time().Sub(tr.containerConfig.Now) var chain ChainID for i, conf := range tr.chainConfigs { @@ -536,10 +535,9 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { } return ConsumerRemovalProposal{ - Deposit: uint(deposit), - Status: status, - Chain: chain, - StopTime: int(stopTime.Milliseconds()), + Deposit: uint(deposit), + Status: status, + Chain: chain, } case "/ibc.applications.transfer.v1.MsgUpdateParams": var params IBCTransferParams @@ -757,7 +755,6 @@ func (tr Commands) GetIBCTransferParams(chain ChainID) IBCTransferParams { func (tr Commands) GetConsumerChains(chain ChainID) map[ChainID]bool { binaryName := tr.chainConfigs[chain].BinaryName cmd := tr.target.ExecCommand(binaryName, - "query", "provider", "list-consumer-chains", `--node`, tr.GetQueryNode(chain), `-o`, `json`, diff --git a/tests/e2e/state_rapid_test.go b/tests/e2e/state_rapid_test.go index 1ca36d5578..fc591d5db1 100644 --- a/tests/e2e/state_rapid_test.go +++ b/tests/e2e/state_rapid_test.go @@ -203,10 +203,9 @@ func GetConsumerAdditionProposalGen() *rapid.Generator[ConsumerAdditionProposal] func GetConsumerRemovalProposalGen() *rapid.Generator[ConsumerRemovalProposal] { return rapid.Custom(func(t *rapid.T) ConsumerRemovalProposal { return ConsumerRemovalProposal{ - Deposit: rapid.Uint().Draw(t, "Deposit"), - Chain: GetChainIDGen().Draw(t, "Chain"), - StopTime: rapid.Int().Draw(t, "StopTime"), - Status: rapid.String().Draw(t, "Status"), + Deposit: rapid.Uint().Draw(t, "Deposit"), + Chain: GetChainIDGen().Draw(t, "Chain"), + Status: rapid.String().Draw(t, "Status"), } }) } diff --git a/tests/e2e/steps_stop_chain.go b/tests/e2e/steps_stop_chain.go index fbf86e4733..9efc240ee6 100644 --- a/tests/e2e/steps_stop_chain.go +++ b/tests/e2e/steps_stop_chain.go @@ -1,10 +1,8 @@ package main import ( - "strconv" - "time" - gov "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + "strconv" ) // start relayer so that all messages are relayed @@ -22,11 +20,10 @@ func stepsStopChain(consumerName string, propNumber uint) []Step { s := []Step{ { Action: SubmitConsumerRemovalProposalAction{ - Chain: ChainID("provi"), - From: ValidatorID("bob"), - Deposit: 10000001, - ConsumerChain: ChainID(consumerName), - StopTimeOffset: 0 * time.Millisecond, + Chain: ChainID("provi"), + From: ValidatorID("bob"), + Deposit: 10000001, + ConsumerChain: ChainID(consumerName), }, State: State{ ChainID("provi"): ChainState{ @@ -35,10 +32,9 @@ func stepsStopChain(consumerName string, propNumber uint) []Step { }, Proposals: &map[uint]Proposal{ propNumber: ConsumerRemovalProposal{ - Deposit: 10000001, - Chain: ChainID(consumerName), - StopTime: 0, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), + Deposit: 10000001, + Chain: ChainID(consumerName), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), }, }, ConsumerChains: &map[ChainID]bool{"consu": true}, // consumer chain not yet removed @@ -56,10 +52,9 @@ func stepsStopChain(consumerName string, propNumber uint) []Step { ChainID("provi"): ChainState{ Proposals: &map[uint]Proposal{ propNumber: ConsumerRemovalProposal{ - Deposit: 10000001, - Chain: ChainID(consumerName), - StopTime: 0, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), + Deposit: 10000001, + Chain: ChainID(consumerName), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), }, }, ValBalances: &map[ValidatorID]uint{ @@ -80,11 +75,10 @@ func stepsConsumerRemovalPropNotPassing(consumerName string, propNumber uint) [] s := []Step{ { Action: SubmitConsumerRemovalProposalAction{ - Chain: ChainID("provi"), - From: ValidatorID("bob"), - Deposit: 10000001, - ConsumerChain: ChainID(consumerName), - StopTimeOffset: 0 * time.Millisecond, + Chain: ChainID("provi"), + From: ValidatorID("bob"), + Deposit: 10000001, + ConsumerChain: ChainID(consumerName), }, State: State{ ChainID("provi"): ChainState{ @@ -93,10 +87,9 @@ func stepsConsumerRemovalPropNotPassing(consumerName string, propNumber uint) [] }, Proposals: &map[uint]Proposal{ propNumber: ConsumerRemovalProposal{ - Deposit: 10000001, - Chain: ChainID(consumerName), - StopTime: 0, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), + Deposit: 10000001, + Chain: ChainID(consumerName), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), }, }, ConsumerChains: &map[ChainID]bool{"consu": true}, // consumer chain not removed @@ -114,10 +107,9 @@ func stepsConsumerRemovalPropNotPassing(consumerName string, propNumber uint) [] ChainID("provi"): ChainState{ Proposals: &map[uint]Proposal{ propNumber: ConsumerRemovalProposal{ - Deposit: 10000001, - Chain: ChainID(consumerName), - StopTime: 0, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_REJECTED)), + Deposit: 10000001, + Chain: ChainID(consumerName), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_REJECTED)), }, }, ValBalances: &map[ValidatorID]uint{ diff --git a/tests/e2e/testlib/types.go b/tests/e2e/testlib/types.go index 8694e7185d..0c10d8578d 100644 --- a/tests/e2e/testlib/types.go +++ b/tests/e2e/testlib/types.go @@ -306,10 +306,9 @@ func (p UpgradeProposal) isProposal() {} func (p ConsumerAdditionProposal) isProposal() {} type ConsumerRemovalProposal struct { - Deposit uint - Chain ChainID - StopTime int - Status string + Deposit uint + Chain ChainID + Status string } func (p ConsumerRemovalProposal) isProposal() {} diff --git a/tests/e2e/trace_handlers_test.go b/tests/e2e/trace_handlers_test.go index e4f9e46f12..a773d00fe5 100644 --- a/tests/e2e/trace_handlers_test.go +++ b/tests/e2e/trace_handlers_test.go @@ -27,10 +27,9 @@ var proposalInStateSteps = []Step{ ChainID("provi"): ChainState{ Proposals: &map[uint]Proposal{ 1: ConsumerRemovalProposal{ - Deposit: 10000001, - Chain: ChainID("foo"), - StopTime: 0, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), + Deposit: 10000001, + Chain: ChainID("foo"), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), }, }, }, @@ -136,10 +135,9 @@ func TestMarshalAndUnmarshalChainState(t *testing.T) { "consumer removal proposal": {ChainState{ Proposals: &map[uint]Proposal{ 5: ConsumerRemovalProposal{ - Deposit: 10000001, - Chain: ChainID("test123"), - StopTime: 5000000000, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), + Deposit: 10000001, + Chain: ChainID("test123"), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), }, }, ValBalances: &map[ValidatorID]uint{ diff --git a/tests/e2e/v4/state.go b/tests/e2e/v4/state.go index 594004bc24..b4b7b70190 100644 --- a/tests/e2e/v4/state.go +++ b/tests/e2e/v4/state.go @@ -317,7 +317,6 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { } case "/interchain_security.ccv.provider.v1.ConsumerRemovalProposal": chainId := gjson.Get(string(bz), `messages.0.content.chain_id`).String() - stopTime := gjson.Get(string(bz), `messages.0.content.stop_time`).Time().Sub(containerConfig.Now) var chain ChainID for i, conf := range chainConfigs { @@ -328,10 +327,9 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { } return ConsumerRemovalProposal{ - Deposit: uint(deposit), - Status: status, - Chain: chain, - StopTime: int(stopTime.Milliseconds()), + Deposit: uint(deposit), + Status: status, + Chain: chain, } case "/cosmos.params.v1beta1.ParameterChangeProposal": return ParamsProposal{ @@ -391,7 +389,6 @@ func (tr Commands) GetParam(chain ChainID, param Param) string { func (tr Commands) GetConsumerChains(chain ChainID) map[ChainID]bool { binaryName := tr.ChainConfigs[chain].BinaryName cmd := tr.Target.ExecCommand(binaryName, - "query", "provider", "list-consumer-chains", `--node`, tr.GetQueryNode(chain), `-o`, `json`, diff --git a/tests/integration/stop_consumer.go b/tests/integration/stop_consumer.go index c296026e0a..6da22d6b66 100644 --- a/tests/integration/stop_consumer.go +++ b/tests/integration/stop_consumer.go @@ -3,6 +3,7 @@ package integration import ( "cosmossdk.io/math" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" + "github.com/cosmos/interchain-security/v5/x/ccv/provider/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -88,7 +89,8 @@ func (s *CCVTestSuite) TestStopConsumerChain() { } // stop the consumer chain - err = providerKeeper.StopConsumerChain(s.providerCtx(), firstBundle.ConsumerId, true) + providerKeeper.SetConsumerPhase(s.providerCtx(), firstBundle.ConsumerId, types.ConsumerPhase_CONSUMER_PHASE_STOPPED) + err = providerKeeper.DeleteConsumerChain(s.providerCtx(), firstBundle.ConsumerId) s.Require().NoError(err) // check all states are removed and the unbonding operation released @@ -105,7 +107,8 @@ func (s *CCVTestSuite) TestStopConsumerOnChannelClosed() { providerKeeper := s.providerApp.GetProviderKeeper() // stop the consumer chain - err := providerKeeper.StopConsumerChain(s.providerCtx(), s.getFirstBundle().ConsumerId, true) + providerKeeper.SetConsumerPhase(s.providerCtx(), s.getFirstBundle().ConsumerId, types.ConsumerPhase_CONSUMER_PHASE_STOPPED) + err := providerKeeper.DeleteConsumerChain(s.providerCtx(), s.getFirstBundle().ConsumerId) s.Require().NoError(err) err = s.path.EndpointA.UpdateClient() diff --git a/testutil/keeper/expectations.go b/testutil/keeper/expectations.go index 3ceaf4fd2b..53d16a6581 100644 --- a/testutil/keeper/expectations.go +++ b/testutil/keeper/expectations.go @@ -80,9 +80,8 @@ func GetMocksForSetConsumerChain(ctx sdk.Context, mocks *MockedKeepers, } } -// GetMocksForStopConsumerChainWithCloseChannel returns mock expectations needed to call StopConsumerChain() when -// `closeChan` is true. -func GetMocksForStopConsumerChainWithCloseChannel(ctx sdk.Context, mocks *MockedKeepers) []*gomock.Call { +// GetMocksForDeleteConsumerChain returns mock expectations needed to call `DeleteConsumerChain` +func GetMocksForDeleteConsumerChain(ctx sdk.Context, mocks *MockedKeepers) []*gomock.Call { dummyCap := &capabilitytypes.Capability{} return []*gomock.Call{ mocks.MockChannelKeeper.EXPECT().GetChannel(gomock.Any(), types.ProviderPortID, "channelID").Return( diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index 1572937607..3797dc8c1e 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -212,12 +212,12 @@ func GetNewSlashPacketData() types.SlashPacketData { } } -// 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 -// calling `StopConsumerChain` -- this does NOT necessarily mean that the consumer chain is stopped. -// Also see `TestProviderStateIsCleanedAfterConsumerChainIsStopped`. -func SetupForStoppingConsumerChain(t *testing.T, ctx sdk.Context, +// SetupForDeleteConsumerChain registers expected mock calls and corresponding state setup +// which assert that a consumer chain was properly setup to be later deleted from `DeleteConsumerChain`. +// Note: This function only setups and tests that we correctly setup a consumer chain that we could later delete when +// calling `DeleteConsumerChain` -- this does NOT necessarily mean that the consumer chain is deleted. +// Also see `TestProviderStateIsCleanedAfterConsumerChainIsDeleted`. +func SetupForDeleteConsumerChain(t *testing.T, ctx sdk.Context, providerKeeper *providerkeeper.Keeper, mocks MockedKeepers, consumerId string, ) { @@ -238,6 +238,8 @@ func SetupForStoppingConsumerChain(t *testing.T, ctx sdk.Context, require.NoError(t, err) err = providerKeeper.SetConsumerPowerShapingParameters(ctx, consumerId, GetTestPowerShapingParameters()) require.NoError(t, err) + + // set the chain to initialized so that we can create a consumer client providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_INITIALIZED) err = providerKeeper.CreateConsumerClient(ctx, consumerId) @@ -247,11 +249,14 @@ func SetupForStoppingConsumerChain(t *testing.T, ctx sdk.Context, // set the channel ID for the consumer chain err = providerKeeper.SetConsumerChain(ctx, "channelID") require.NoError(t, err) + + // set the chain to stopped sto the chain can be deleted + providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED) } -// TestProviderStateIsCleanedAfterConsumerChainIsStopped executes test assertions for the provider's state being cleaned -// after a stopped consumer chain. -func TestProviderStateIsCleanedAfterConsumerChainIsStopped(t *testing.T, ctx sdk.Context, providerKeeper providerkeeper.Keeper, +// TestProviderStateIsCleanedAfterConsumerChainIsDeleted executes test assertions for the provider's state being cleaned +// after a deleted consumer chain. +func TestProviderStateIsCleanedAfterConsumerChainIsDeleted(t *testing.T, ctx sdk.Context, providerKeeper providerkeeper.Keeper, consumerId, expectedChannelID string, expErr bool, ) { t.Helper() @@ -266,15 +271,6 @@ func TestProviderStateIsCleanedAfterConsumerChainIsStopped(t *testing.T, ctx sdk acks := providerKeeper.GetSlashAcks(ctx, consumerId) require.Empty(t, acks) - // in case the chain was successfully stopped, it should not contain a Top N associated to it - ps, err := providerKeeper.GetConsumerPowerShapingParameters(ctx, consumerId) - if expErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - require.Empty(t, ps) - // test key assignment state is cleaned require.Empty(t, providerKeeper.GetAllValidatorConsumerPubKeys(ctx, &consumerId)) require.Empty(t, providerKeeper.GetAllValidatorsByConsumerAddr(ctx, &consumerId)) diff --git a/x/ccv/provider/client/cli/query.go b/x/ccv/provider/client/cli/query.go index be516d584f..d9a5611bbf 100644 --- a/x/ccv/provider/client/cli/query.go +++ b/x/ccv/provider/client/cli/query.go @@ -78,7 +78,7 @@ func CmdConsumerChains() *cobra.Command { Short: "Query consumer chains for provider chain.", Long: `Query consumer chains for provider chain. An optional integer parameter can be passed for phase filtering of consumer chains, - (Registered=1|Initialized=2|Launched=3|Stopped=4).`, + (Registered=1|Initialized=2|Launched=3|Stopped=4|Deleted=5).`, Args: cobra.MaximumNArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { clientCtx, err := client.GetClientQueryContext(cmd) diff --git a/x/ccv/provider/client/cli/tx.go b/x/ccv/provider/client/cli/tx.go index 00826278b0..9a8a7e5046 100644 --- a/x/ccv/provider/client/cli/tx.go +++ b/x/ccv/provider/client/cli/tx.go @@ -1,13 +1,11 @@ package cli import ( + "cosmossdk.io/math" "encoding/json" "fmt" "os" "strings" - "time" - - "cosmossdk.io/math" ibctmtypes "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" "github.com/spf13/cobra" @@ -402,16 +400,14 @@ Example: func NewRemoveConsumerCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "remove-consumer [consumer-id] [stop-time-layout] [stop-time-value]", + Use: "remove-consumer [consumer-id]", Short: "remove a consumer chain", Long: strings.TrimSpace( fmt.Sprintf(`Removes (and stops) a consumer chain. Note that only the owner of the chain can remove it. -Stop time is parsed by using the layout and the value (see https://pkg.go.dev/time#Parse). - Example: -%s tx provider remove-consumer [consumer-id] [stop-time-layout] [stop-time-value] --from node0 --home ../node0 --chain-id $CID +%s tx provider remove-consumer [consumer-id] --from node0 --home ../node0 --chain-id $CID `, version.AppName)), - Args: cobra.ExactArgs(3), + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { @@ -426,15 +422,12 @@ Example: signer := clientCtx.GetFromAddress().String() consumerId := args[0] - stopTimeLayout := args[1] - stopTimeValue := args[2] - stopTime, err := time.Parse(stopTimeLayout, stopTimeValue) if err != nil { return err } - msg, err := types.NewMsgRemoveConsumer(signer, consumerId, stopTime) + msg, err := types.NewMsgRemoveConsumer(signer, consumerId) if err != nil { return err } diff --git a/x/ccv/provider/keeper/consumer_lifecycle.go b/x/ccv/provider/keeper/consumer_lifecycle.go index 58c83be9cf..9352d49178 100644 --- a/x/ccv/provider/keeper/consumer_lifecycle.go +++ b/x/ccv/provider/keeper/consumer_lifecycle.go @@ -68,7 +68,7 @@ func (k Keeper) CanLaunch(ctx sdk.Context, consumerId string) (time.Time, bool) func (k Keeper) BeginBlockLaunchConsumers(ctx sdk.Context) { // TODO (PERMISSIONLESS): we can parameterize the limit for _, consumerId := range k.GetConsumersReadyToLaunch(ctx, 200) { - record, err := k.GetConsumerInitializationParameters(ctx, consumerId) + initializationParameters, err := k.GetConsumerInitializationParameters(ctx, consumerId) if err != nil { ctx.Logger().Error("could not retrieve initialization record", "consumerId", consumerId, @@ -77,7 +77,7 @@ func (k Keeper) BeginBlockLaunchConsumers(ctx sdk.Context) { } // Remove consumer to prevent re-trying launching this chain. // We would only try to re-launch this chain if a new `MsgUpdateConsumer` message is sent. - err = k.RemoveConsumerToBeLaunched(ctx, consumerId, record.SpawnTime) + err = k.RemoveConsumerToBeLaunched(ctx, consumerId, initializationParameters.SpawnTime) if err != nil { ctx.Logger().Error("could not remove consumer from to-be-launched queue", "consumerId", consumerId, @@ -93,7 +93,6 @@ func (k Keeper) BeginBlockLaunchConsumers(ctx sdk.Context) { "error", err) continue } - k.SetConsumerPhase(cachedCtx, consumerId, types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) // the cached context is created with a new EventManager, so we merge the events into the original context ctx.EventManager().EmitEvents(cachedCtx.EventManager().Events()) @@ -161,6 +160,8 @@ func (k Keeper) LaunchConsumer(ctx sdk.Context, consumerId string) error { return errorsmod.Wrapf(types.ErrInvalidConsumerGenesis, "consumer genesis initial validator set is empty - no validators opted in consumer id: %s", consumerId) } + k.SetConsumerPhase(ctx, consumerId, types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) + return nil } @@ -353,45 +354,66 @@ func (k Keeper) MakeConsumerGenesis( return gen, hash, nil } +func (k Keeper) StopAndPrepareForConsumerDeletion(ctx sdk.Context, consumerId string) error { + // The phase of the chain is immediately set to stopped, albeit its state is removed later (see below). + // Setting the phase here helps in not considering this chain when we look at launched chains (e.g., in `QueueVSCPackets) + k.SetConsumerPhase(ctx, consumerId, types.ConsumerPhase_CONSUMER_PHASE_STOPPED) + + // state of this chain is removed once UnbondingPeriod elapses + unbondingPeriod, err := k.stakingKeeper.UnbondingTime(ctx) + if err != nil { + return err + } + stopTime := ctx.BlockTime().Add(unbondingPeriod) + + if err := k.SetConsumerStopTime(ctx, consumerId, stopTime); err != nil { + return errorsmod.Wrapf(types.ErrInvalidStopTime, "cannot set stop time: %s", err.Error()) + } + if err := k.AppendConsumerToBeStopped(ctx, consumerId, stopTime); err != nil { + return errorsmod.Wrapf(ccv.ErrInvalidConsumerState, "cannot set consumer to be stopped: %s", err.Error()) + } + + return nil +} + // BeginBlockStopConsumers iterates over the pending consumer proposals and stop/removes the chain if the stop time has passed func (k Keeper) BeginBlockStopConsumers(ctx sdk.Context) { // TODO (PERMISSIONLESS): parameterize the limit for _, consumerId := range k.GetConsumersReadyToStop(ctx, 200) { - // stop consumer chain in a cached context to handle errors - cachedCtx, writeFn := ctx.CacheContext() - stopTime, err := k.GetConsumerStopTime(ctx, consumerId) if err != nil { k.Logger(ctx).Error("chain could not be stopped", "consumerId", consumerId, - "err", err.Error()) + "error", err.Error()) continue } - err = k.StopConsumerChain(cachedCtx, consumerId, true) + // Remove consumer to prevent re-trying stopping this chain. + // We would only try to re-stop this chain if a new `MsgRemoveConsumer` message is sent. + err = k.RemoveConsumerToBeStopped(ctx, consumerId, stopTime) if err != nil { - k.Logger(ctx).Error("consumer chain could not be stopped", + ctx.Logger().Error("could not remove consumer from to-be-stopped queue", "consumerId", consumerId, - "err", err.Error()) + "error", err) continue } - k.SetConsumerPhase(cachedCtx, consumerId, types.ConsumerPhase_CONSUMER_PHASE_STOPPED) - - err = k.RemoveConsumerToBeStopped(ctx, consumerId, stopTime) + // delete consumer chain in a cached context to abort deletion in case of errors + cachedCtx, writeFn := ctx.CacheContext() + err = k.DeleteConsumerChain(cachedCtx, consumerId) if err != nil { - ctx.Logger().Error("could not remove consumer from to-be-stopped queue", + k.Logger(ctx).Error("consumer chain could not be stopped", "consumerId", consumerId, - "error", err) + "error", err.Error()) continue } - // The cached context is created with a new EventManager so we merge the event into the original context + // The cached context is created with a new EventManager, so we merge the event into the original context ctx.EventManager().EmitEvents(cachedCtx.EventManager().Events()) writeFn() - k.Logger(ctx).Info("executed consumer removal", + k.Logger(ctx).Info("executed consumer deletion", "consumer id", consumerId, "stop time", stopTime, ) @@ -440,13 +462,11 @@ func (k Keeper) GetConsumersReadyToStop(ctx sdk.Context, limit uint32) []string return result } -// StopConsumerChain cleans up the states for the given consumer id -func (k Keeper) StopConsumerChain(ctx sdk.Context, consumerId string, closeChan bool) (err error) { - // check that a client for consumerId exists - // TODO (PERMISSIONLESS): change to use phases instead - if _, found := k.GetConsumerClientId(ctx, consumerId); !found { - return errorsmod.Wrap(types.ErrConsumerChainNotFound, - fmt.Sprintf("cannot stop non-existent consumer chain: %s", consumerId)) +// DeleteConsumerChain cleans up the states for the given consumer id +func (k Keeper) DeleteConsumerChain(ctx sdk.Context, consumerId string) (err error) { + phase := k.GetConsumerPhase(ctx, consumerId) + if phase != types.ConsumerPhase_CONSUMER_PHASE_STOPPED { + return fmt.Errorf("cannot delete non-stopped chain: %s", consumerId) } // clean up states @@ -459,19 +479,17 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, consumerId string, closeChan // close channel and delete the mappings between chain ID and channel ID if channelID, found := k.GetConsumerIdToChannelId(ctx, consumerId); found { - if closeChan { - // Close the channel for the given channel ID on the condition - // that the channel exists and isn't already in the CLOSED state - channel, found := k.channelKeeper.GetChannel(ctx, ccv.ProviderPortID, channelID) - if found && channel.State != channeltypes.CLOSED { - err := k.chanCloseInit(ctx, channelID) - if err != nil { - k.Logger(ctx).Error("channel to consumer chain could not be closed", - "consumerId", consumerId, - "channelID", channelID, - "error", err.Error(), - ) - } + // Close the channel for the given channel ID on the condition + // that the channel exists and isn't already in the CLOSED state + channel, found := k.channelKeeper.GetChannel(ctx, ccv.ProviderPortID, channelID) + if found && channel.State != channeltypes.CLOSED { + err := k.chanCloseInit(ctx, channelID) + if err != nil { + k.Logger(ctx).Error("channel to consumer chain could not be closed", + "consumerId", consumerId, + "channelID", channelID, + "error", err.Error(), + ) } } k.DeleteConsumerIdToChannelId(ctx, consumerId) @@ -493,9 +511,16 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, consumerId string, closeChan k.DeleteAllOptedIn(ctx, consumerId) k.DeleteConsumerValSet(ctx, consumerId) + // We do not delete ConsumerIdToChainIdKeyName, ConsumerIdToPhaseKeyName + k.DeleteConsumerRewardsAllocation(ctx, consumerId) + k.DeleteConsumerOwnerAddress(ctx, consumerId) + + k.DeleteConsumerStopTime(ctx, consumerId) + // TODO (PERMISSIONLESS) add newly-added state to be deleted - k.Logger(ctx).Info("consumer chain removed from provider", "consumerId", consumerId) + k.SetConsumerPhase(ctx, consumerId, types.ConsumerPhase_CONSUMER_PHASE_DELETED) + k.Logger(ctx).Info("consumer chain deleted from provider", "consumerId", consumerId) return nil } @@ -642,7 +667,7 @@ func (k Keeper) AppendConsumerToBeStopped(ctx sdk.Context, consumerId string, st return k.appendConsumerIdOnTime(ctx, consumerId, types.StopTimeToConsumerIdsKey, stopTime) } -// RemoveConsumerToBeStopped removes consumer id from if stored for this specific stop time +// RemoveConsumerToBeStopped removes consumer id from the given stop time func (k Keeper) RemoveConsumerToBeStopped(ctx sdk.Context, consumerId string, stopTime time.Time) error { return k.removeConsumerIdFromTime(ctx, consumerId, types.StopTimeToConsumerIdsKey, stopTime) } diff --git a/x/ccv/provider/keeper/consumer_lifecycle_test.go b/x/ccv/provider/keeper/consumer_lifecycle_test.go index 7fc238570c..c00c2525c0 100644 --- a/x/ccv/provider/keeper/consumer_lifecycle_test.go +++ b/x/ccv/provider/keeper/consumer_lifecycle_test.go @@ -674,8 +674,8 @@ func TestBeginBlockStopConsumers(t *testing.T) { expectations = append(expectations, testkeeper.GetMocksForSetConsumerChain(ctx, &mocks, chainId)...) } // Only first two consumer chains should be stopped - expectations = append(expectations, testkeeper.GetMocksForStopConsumerChainWithCloseChannel(ctx, &mocks)...) - expectations = append(expectations, testkeeper.GetMocksForStopConsumerChainWithCloseChannel(ctx, &mocks)...) + expectations = append(expectations, testkeeper.GetMocksForDeleteConsumerChain(ctx, &mocks)...) + expectations = append(expectations, testkeeper.GetMocksForDeleteConsumerChain(ctx, &mocks)...) gomock.InOrder(expectations...) @@ -703,8 +703,8 @@ func TestBeginBlockStopConsumers(t *testing.T) { err = providerKeeper.SetConsumerChain(ctx, "channelID") require.NoError(t, err) - // after we have created the consumer client, the chain is considered launched and hence we could later stop the chain - providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) + // the chain is considered to be stopped and ready for deletion (i.e., `StopAndPrepareForConsumerDeletion` is called) + providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED) } // @@ -715,12 +715,12 @@ func TestBeginBlockStopConsumers(t *testing.T) { // Only the 3rd (final) proposal is still stored as pending phase := providerKeeper.GetConsumerPhase(ctx, consumerIds[0]) - require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED, phase) + require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_DELETED, phase) phase = providerKeeper.GetConsumerPhase(ctx, consumerIds[1]) - require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED, phase) - // third chain had a stopTime in the future and hence did not stop + require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_DELETED, phase) + // third chain had a stopTime in the future and hence did not get deleted phase = providerKeeper.GetConsumerPhase(ctx, consumerIds[2]) - require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED, phase) + require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED, phase) } func TestGetConsumersReadyToStop(t *testing.T) { @@ -754,7 +754,7 @@ func TestGetConsumersReadyToStop(t *testing.T) { require.Equal(t, []string{"consumerId1", "consumerId2", "consumerId3"}, providerKeeper.GetConsumersReadyToStop(ctx, 3)) } -// Tests the StopConsumerChain method against the spec, +// Tests the DeleteConsumerChain method against the spec, // with more granularity than what's covered in TestHandleLegacyConsumerRemovalProposal, or integration tests. // See: https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/methods.md#ccv-pcf-stcc1 // Spec tag: [CCV-PCF-STCC.1] @@ -780,13 +780,13 @@ func TestStopConsumerChain(t *testing.T) { { description: "valid stop of consumer chain, all mock calls hit", setup: func(ctx sdk.Context, providerKeeper *providerkeeper.Keeper, mocks testkeeper.MockedKeepers) { - testkeeper.SetupForStoppingConsumerChain(t, ctx, providerKeeper, mocks, consumerId) + testkeeper.SetupForDeleteConsumerChain(t, ctx, providerKeeper, mocks, consumerId) // set consumer minimum equivocation height providerKeeper.SetEquivocationEvidenceMinHeight(ctx, consumerId, 1) - // assert mocks for expected calls to `StopConsumerChain` when closing the underlying channel - gomock.InOrder(testkeeper.GetMocksForStopConsumerChainWithCloseChannel(ctx, &mocks)...) + // assert mocks for expected calls to `DeleteConsumerChain` when closing the underlying channel + gomock.InOrder(testkeeper.GetMocksForDeleteConsumerChain(ctx, &mocks)...) }, expErr: false, }, @@ -802,7 +802,7 @@ func TestStopConsumerChain(t *testing.T) { // Setup specific to test case tc.setup(ctx, &providerKeeper, mocks) - err := providerKeeper.StopConsumerChain(ctx, consumerId, true) + err := providerKeeper.DeleteConsumerChain(ctx, consumerId) if tc.expErr { require.Error(t, err, t) @@ -810,7 +810,7 @@ func TestStopConsumerChain(t *testing.T) { require.NoError(t, err) } - testkeeper.TestProviderStateIsCleanedAfterConsumerChainIsStopped(t, ctx, providerKeeper, consumerId, "channelID", tc.expErr) + testkeeper.TestProviderStateIsCleanedAfterConsumerChainIsDeleted(t, ctx, providerKeeper, consumerId, "channelID", tc.expErr) ctrl.Finish() } diff --git a/x/ccv/provider/keeper/distribution.go b/x/ccv/provider/keeper/distribution.go index 87a2e5e9e4..8d687da363 100644 --- a/x/ccv/provider/keeper/distribution.go +++ b/x/ccv/provider/keeper/distribution.go @@ -75,7 +75,7 @@ func (k Keeper) AllocateTokens(ctx sdk.Context) { } // Iterate over all launched consumer chains - for _, consumerId := range k.GetAllRegisteredConsumerIds(ctx) { + for _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { // note that it's possible that no rewards are collected even though the // reward pool isn't empty. This can happen if the reward pool holds some tokens @@ -269,6 +269,12 @@ func (k Keeper) SetConsumerRewardsAllocation(ctx sdk.Context, consumerId string, store.Set(types.ConsumerRewardsAllocationKey(consumerId), b) } +// DeleteConsumerRewardsAllocation deletes the consumer rewards allocation for the given consumer id +func (k Keeper) DeleteConsumerRewardsAllocation(ctx sdk.Context, consumerId string) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.ConsumerRewardsAllocationKey(consumerId)) +} + // GetConsumerRewardsPool returns the balance // of the consumer rewards pool module account func (k Keeper) GetConsumerRewardsPool(ctx sdk.Context) sdk.Coins { diff --git a/x/ccv/provider/keeper/genesis.go b/x/ccv/provider/keeper/genesis.go index 127b15c65a..ca9ed83f6d 100644 --- a/x/ccv/provider/keeper/genesis.go +++ b/x/ccv/provider/keeper/genesis.go @@ -36,6 +36,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) []abc for _, cs := range genState.ConsumerStates { chainID := cs.ChainId k.SetConsumerClientId(ctx, chainID, cs.ClientId) + k.SetConsumerPhase(ctx, chainID, cs.Phase) if err := k.SetConsumerGenesis(ctx, chainID, cs.ConsumerGenesis); err != nil { // An error here would indicate something is very wrong, // the ConsumerGenesis validated in ConsumerState.Validate(). @@ -119,13 +120,13 @@ func (k Keeper) InitGenesisValUpdates(ctx sdk.Context) []abci.ValidatorUpdate { // ExportGenesis returns the CCV provider module's exported genesis func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { // get a list of all registered consumer chains - registeredConsumerIds := k.GetAllRegisteredConsumerIds(ctx) + registeredConsumerIds := k.GetAllLaunchedConsumerIds(ctx) // export states for each consumer chains var consumerStates []types.ConsumerState for _, consumerId := range registeredConsumerIds { // no need for the second return value of GetConsumerClientId - // as GetAllRegisteredConsumerIds already iterated through + // as GetAllLaunchedConsumerIds already iterated through // the entire prefix range clientId, _ := k.GetConsumerClientId(ctx, consumerId) gen, found := k.GetConsumerGenesis(ctx, consumerId) @@ -138,6 +139,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { ChainId: consumerId, ClientId: clientId, ConsumerGenesis: gen, + Phase: k.GetConsumerPhase(ctx, consumerId), } // try to find channel id for the current consumer chain diff --git a/x/ccv/provider/keeper/genesis_test.go b/x/ccv/provider/keeper/genesis_test.go index 3f3ec2d240..a9126f9afe 100644 --- a/x/ccv/provider/keeper/genesis_test.go +++ b/x/ccv/provider/keeper/genesis_test.go @@ -51,6 +51,7 @@ func TestInitAndExportGenesis(t *testing.T) { *ccv.DefaultConsumerGenesisState(), []ccv.ValidatorSetChangePacketData{}, []string{"slashedValidatorConsAddress"}, + providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED, ), providertypes.NewConsumerStates( cChainIDs[1], @@ -60,6 +61,7 @@ func TestInitAndExportGenesis(t *testing.T) { *ccv.DefaultConsumerGenesisState(), []ccv.ValidatorSetChangePacketData{{ValsetUpdateId: vscID}}, nil, + providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED, ), }, params, diff --git a/x/ccv/provider/keeper/grpc_query.go b/x/ccv/provider/keeper/grpc_query.go index 57dd6ce317..ae77d4357e 100644 --- a/x/ccv/provider/keeper/grpc_query.go +++ b/x/ccv/provider/keeper/grpc_query.go @@ -55,8 +55,8 @@ func (k Keeper) QueryConsumerChains(goCtx context.Context, req *types.QueryConsu // if the phase filter is set Launched get consumer from the state directly if phaseFilter == types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED { - consumerIds = append(consumerIds, k.GetAllRegisteredConsumerIds(ctx)...) - // otherwise iterate over all the consumer using the last unused consumer Id + consumerIds = append(consumerIds, k.GetAllLaunchedConsumerIds(ctx)...) + // otherwise iterate over all the consumer using the last unused consumer id } else { firstUnusedConsumerId, ok := k.GetConsumerId(ctx) if !ok { @@ -65,7 +65,7 @@ func (k Keeper) QueryConsumerChains(goCtx context.Context, req *types.QueryConsu for i := uint64(0); i < firstUnusedConsumerId; i++ { // if the phase filter is set, verify that the consumer has the same phase if phaseFilter != types.ConsumerPhase_CONSUMER_PHASE_UNSPECIFIED { - p := k.GetConsumerPhase(ctx, strconv.FormatInt(int64(i), 10)) + p := k.GetConsumerPhase(ctx, strconv.FormatUint(i, 10)) if p == types.ConsumerPhase_CONSUMER_PHASE_UNSPECIFIED { return nil, status.Error(codes.Internal, fmt.Sprintf("cannot retrieve phase for consumer id: %d", i)) } @@ -74,7 +74,7 @@ func (k Keeper) QueryConsumerChains(goCtx context.Context, req *types.QueryConsu } } - consumerIds = append(consumerIds, strconv.FormatInt(int64(i), 10)) + consumerIds = append(consumerIds, strconv.FormatUint(i, 10)) } } @@ -445,7 +445,7 @@ func (k Keeper) QueryConsumerChainsValidatorHasToValidate(goCtx context.Context, // get all the consumer chains for which the validator is either already // opted-in, currently a consumer validator or if its voting power is within the TopN validators consumersToValidate := []string{} - for _, consumerChainID := range k.GetAllRegisteredConsumerIds(ctx) { + for _, consumerChainID := range k.GetAllLaunchedConsumerIds(ctx) { if hasToValidate, err := k.hasToValidate(ctx, provAddr, consumerChainID); err == nil && hasToValidate { consumersToValidate = append(consumersToValidate, consumerChainID) } diff --git a/x/ccv/provider/keeper/grpc_query_test.go b/x/ccv/provider/keeper/grpc_query_test.go index 9d91bd25f7..12f85c71dc 100644 --- a/x/ccv/provider/keeper/grpc_query_test.go +++ b/x/ccv/provider/keeper/grpc_query_test.go @@ -304,10 +304,11 @@ func TestQueryConsumerChainsValidatorHasToValidate(t *testing.T) { ProviderAddress: providerAddr.String(), } - // set up some consumer chains + // set up some launched consumer chains consumerIDs := []string{"1", "23", "456", "6789"} for _, cID := range consumerIDs { pk.SetConsumerClientId(ctx, cID, "clientID") + pk.SetConsumerPhase(ctx, cID, types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) err := pk.SetConsumerPowerShapingParameters(ctx, cID, types.PowerShapingParameters{}) require.NoError(t, err) } diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index b4c037c0c3..82a3e1fe4b 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -211,15 +211,12 @@ func (k Keeper) DeleteConsumerIdToChannelId(ctx sdk.Context, consumerId string) store.Delete(types.ConsumerIdToChannelIdKey(consumerId)) } -// GetAllRegisteredConsumerIds gets all of the consumer chain IDs, for which the provider module -// created IBC clients. Consumer chains with created clients are also referred to as registered. -// -// Note that the registered consumer chains are stored under keys with the following format: -// ConsumerIdToClientIdKeyPrefix | consumerId -// Thus, the returned array is in ascending order of chainIDs. -func (k Keeper) GetAllRegisteredConsumerIds(ctx sdk.Context) []string { +// GetAllLaunchedConsumerIds returns all consumer ids of chains that are currently launched. +func (k Keeper) GetAllLaunchedConsumerIds(ctx sdk.Context) []string { consumerIds := []string{} + // All launched chains have created an IBC client when they launched (see `LaunchConsumer`), so we traverse over + // `ConsumerIdToClientIdKeyPrefix` to retrieve the launched chains. store := ctx.KVStore(k.storeKey) iterator := storetypes.KVStorePrefixIterator(store, types.ConsumerIdToClientIdKeyPrefix()) defer iterator.Close() @@ -227,6 +224,14 @@ func (k Keeper) GetAllRegisteredConsumerIds(ctx sdk.Context) []string { for ; iterator.Valid(); iterator.Next() { // remove 1 byte prefix from key to retrieve consumerId consumerId := string(iterator.Key()[1:]) + + // A chain might have stopped, but we might not yet have its consumer id to client id association deleted. + // To avoid returning stopped chains, we check the phase of the consumer chain and only return launched chains. + phase := k.GetConsumerPhase(ctx, consumerId) + if phase != types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED { + continue + } + consumerIds = append(consumerIds, consumerId) } diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 0a5fe59c97..271cc1da0c 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -223,22 +223,28 @@ func TestInitHeight(t *testing.T) { } } -func TestGetAllRegisteredConsumerChainIDs(t *testing.T) { +func TestGetAllLaunchedConsumerIds(t *testing.T) { pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - chainIDs := []string{"chain-2", "chain-1", "chain-4", "chain-3"} - // GetAllRegisteredConsumerIds iterates over consumerId in lexicographical order - expectedChainIDs := []string{"chain-1", "chain-2", "chain-3", "chain-4"} - - for i, chainID := range chainIDs { - clientID := fmt.Sprintf("client-%d", len(chainIDs)-i) - pk.SetConsumerClientId(ctx, chainID, clientID) + consumerIds := []string{"2", "1", "4", "3"} + for i, consumerId := range consumerIds { + clientId := fmt.Sprintf("client-%d", len(consumerIds)-i) + pk.SetConsumerClientId(ctx, consumerId, clientId) + pk.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) } - result := pk.GetAllRegisteredConsumerIds(ctx) - require.Len(t, result, len(chainIDs)) - require.Equal(t, expectedChainIDs, result) + actualConsumerIds := pk.GetAllLaunchedConsumerIds(ctx) + require.Len(t, actualConsumerIds, len(consumerIds)) + + // sort the consumer ids before comparing they are equal + sort.Slice(consumerIds, func(i, j int) bool { + return consumerIds[i] < consumerIds[j] + }) + sort.Slice(actualConsumerIds, func(i, j int) bool { + return actualConsumerIds[i] < actualConsumerIds[j] + }) + require.Equal(t, consumerIds, actualConsumerIds) } // TestGetAllChannelToChains tests GetAllChannelToConsumers behaviour correctness diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index 83664e369e..ed74b8f9d8 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -469,25 +469,12 @@ func (k msgServer) RemoveConsumer(goCtx context.Context, msg *types.MsgRemoveCon phase := k.Keeper.GetConsumerPhase(ctx, consumerId) if phase != types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED { - return nil, errorsmod.Wrapf(types.ErrInvalidPhase, + return &resp, errorsmod.Wrapf(types.ErrInvalidPhase, "chain with consumer id: %s has to be in its launched phase", consumerId) } - previousStopTime, err := k.Keeper.GetConsumerStopTime(ctx, consumerId) - if err == nil { - if err := k.Keeper.RemoveConsumerToBeStopped(ctx, consumerId, previousStopTime); err != nil { - return &resp, errorsmod.Wrapf(ccvtypes.ErrInvalidConsumerState, "cannot remove previous stop time: %s", err.Error()) - } - } - - if err := k.Keeper.SetConsumerStopTime(ctx, consumerId, msg.StopTime); err != nil { - return &resp, errorsmod.Wrapf(types.ErrInvalidStopTime, "cannot set stop time: %s", err.Error()) - } - if err := k.Keeper.AppendConsumerToBeStopped(ctx, consumerId, msg.StopTime); err != nil { - return &resp, errorsmod.Wrapf(ccvtypes.ErrInvalidConsumerState, "cannot set consumer to be stopped: %s", err.Error()) - } - - return &resp, nil + err = k.Keeper.StopAndPrepareForConsumerDeletion(ctx, consumerId) + return &resp, err } func (k msgServer) ConsumerAddition(_ context.Context, _ *types.MsgConsumerAddition) (*types.MsgConsumerAdditionResponse, error) { diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index 88369568ff..b5683f800d 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -30,8 +30,11 @@ func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Pac "error", err, ) if consumerId, ok := k.GetChannelIdToConsumerId(ctx, packet.SourceChannel); ok { - // stop consumer chain and release unbonding - return k.StopConsumerChain(ctx, consumerId, false) + return k.StopAndPrepareForConsumerDeletion(ctx, consumerId) + + //// set consumer chain as stopped and delete its state + //k.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED) + //return k.DeleteConsumerChain(ctx, consumerId, false) } return errorsmod.Wrapf(providertypes.ErrUnknownConsumerChannelId, "recv ErrorAcknowledgement on unknown channel %s", packet.SourceChannel) } @@ -51,8 +54,11 @@ func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet) err ) } k.Logger(ctx).Info("packet timeout, removing the consumer:", "consumerId", consumerId) - // stop consumer chain and release unbondings - return k.StopConsumerChain(ctx, consumerId, false) + // set consumer chain as stopped and delete its state + return k.StopAndPrepareForConsumerDeletion(ctx, consumerId) + // + //k.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED) + //return k.DeleteConsumerChain(ctx, consumerId, false) } // EndBlockVSU contains the EndBlock logic needed for @@ -135,7 +141,7 @@ func (k Keeper) BlocksUntilNextEpoch(ctx sdk.Context) int64 { // If the CCV channel is not established for a consumer chain, // the updates will remain queued until the channel is established func (k Keeper) SendVSCPackets(ctx sdk.Context) { - for _, consumerId := range k.GetAllRegisteredConsumerIds(ctx) { + for _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { // check if CCV channel is established and send if channelID, found := k.GetConsumerIdToChannelId(ctx, consumerId); found { k.SendVSCPacketsToChain(ctx, consumerId, channelID) @@ -167,10 +173,15 @@ func (k Keeper) SendVSCPacketsToChain(ctx sdk.Context, consumerId, channelId str } // Not able to send packet over IBC! k.Logger(ctx).Error("cannot send VSC, removing consumer:", "consumerId", consumerId, "vscid", data.ValsetUpdateId, "err", err.Error()) - // If this happens, most likely the consumer is malicious; remove it - err := k.StopConsumerChain(ctx, consumerId, true) + + err := k.StopAndPrepareForConsumerDeletion(ctx, consumerId) + //// If this happens, most likely the consumer is malicious; remove it + //// set consumer chain as stopped and delete its state + //k.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED) + //err := k.DeleteConsumerChain(ctx, consumerId, true) if err != nil { - panic(fmt.Errorf("consumer chain failed to stop: %w", err)) + k.Logger(ctx).Info("consumer chain failed to stop:", "consumerId", consumerId, "error", err.Error()) + //panic(fmt.Errorf("consumer chain failed to stop: %w", err)) } return } @@ -191,7 +202,7 @@ func (k Keeper) QueueVSCPackets(ctx sdk.Context) { panic(fmt.Errorf("failed to get last validators: %w", err)) } - for _, consumerId := range k.GetAllRegisteredConsumerIds(ctx) { + for _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { currentValidators, err := k.GetConsumerValSet(ctx, consumerId) if err != nil { panic(fmt.Errorf("failed to get consumer validators, consumerId(%s): %w", consumerId, err)) @@ -269,7 +280,7 @@ func (k Keeper) EndBlockCIS(ctx sdk.Context) { 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 _, consumerId := range k.GetAllRegisteredConsumerIds(ctx) { + for _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { k.PruneKeyAssignments(ctx, consumerId) } } diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index e45fedf35a..4bd95b7d0f 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -1,16 +1,17 @@ package keeper_test import ( - "sort" - "strings" - "testing" - "cosmossdk.io/math" + capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types" ibctesting "github.com/cosmos/ibc-go/v8/testing" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + "sort" + "strings" + "testing" + "time" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -103,8 +104,9 @@ func TestQueueVSCPacketsDoesNotResetConsumerValidatorsHeights(t *testing.T) { mocks.MockStakingKeeper.EXPECT().GetValidatorByConsAddr(ctx, valBConsAddr).Return(valB, nil).AnyTimes() testkeeper.SetupMocksForLastBondedValidatorsExpectation(mocks.MockStakingKeeper, 2, []stakingtypes.Validator{valA, valB}, -1) - // set a consumer client, so we have a consumer chain (i.e., `k.GetAllConsumerChains(ctx)` is non empty) + // set a consumer client id and its phase, so we have a consumer chain (i.e., `GetAllLaunchedConsumerIds` is non-empty) providerKeeper.SetConsumerClientId(ctx, "consumerId", "clientID") + providerKeeper.SetConsumerPhase(ctx, "consumerId", providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) // opt in validator A and set as a consumer validator providerKeeper.SetOptedIn(ctx, "consumerId", providertypes.NewProviderConsAddress(valAConsAddr)) @@ -483,10 +485,10 @@ func TestSendVSCPacketsToChainFailure(t *testing.T) { providerKeeper.SetParams(ctx, providertypes.DefaultParams()) // Append mocks for full consumer setup - mockCalls := testkeeper.GetMocksForSetConsumerChain(ctx, &mocks, "consumerChainID") + mockCalls := testkeeper.GetMocksForSetConsumerChain(ctx, &mocks, "consumerId") // Set 3 pending vsc packets - providerKeeper.AppendPendingVSCPackets(ctx, "consumerChainID", []ccv.ValidatorSetChangePacketData{{}, {}, {}}...) + providerKeeper.AppendPendingVSCPackets(ctx, "consumerId", []ccv.ValidatorSetChangePacketData{{}, {}, {}}...) // append mocks for the channel keeper to return an error mockCalls = append(mockCalls, @@ -494,22 +496,35 @@ func TestSendVSCPacketsToChainFailure(t *testing.T) { "CCVChannelID").Return(channeltypes.Channel{}, false).Times(1), ) - // Append mocks for expected call to StopConsumerChain - mockCalls = append(mockCalls, testkeeper.GetMocksForStopConsumerChainWithCloseChannel(ctx, &mocks)...) + // Append mocks for expected call to DeleteConsumerChain + mockCalls = append(mockCalls, testkeeper.GetMocksForDeleteConsumerChain(ctx, &mocks)...) // Assert mock calls hit gomock.InOrder(mockCalls...) // Execute setup - providerKeeper.SetConsumerClientId(ctx, "consumerChainID", "clientID") + providerKeeper.SetConsumerClientId(ctx, "consumerId", "clientID") err := providerKeeper.SetConsumerChain(ctx, "channelID") require.NoError(t, err) - // No panic should occur, StopConsumerChain should be called - providerKeeper.SendVSCPacketsToChain(ctx, "consumerChainID", "CCVChannelID") + unbondingTime := 123 * time.Second + mocks.MockStakingKeeper.EXPECT().UnbondingTime(gomock.Any()).Return(unbondingTime, nil).AnyTimes() + + // No panic should occur, DeleteConsumerChain should be called + providerKeeper.SendVSCPacketsToChain(ctx, "consumerId", "CCVChannelID") + + // Verify the chain is about to be deleted + stopTime, err := providerKeeper.GetConsumerStopTime(ctx, "consumerId") + require.NoError(t, err) + require.Equal(t, ctx.BlockTime().Add(unbondingTime), stopTime) - // Pending VSC packets should be deleted in StopConsumerChain - require.Empty(t, providerKeeper.GetPendingVSCPackets(ctx, "consumerChainID")) + // Increase the block time by `unbondingTime` so the chain actually gets deleted + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(unbondingTime)) + providerKeeper.BeginBlockStopConsumers(ctx) + + // Pending VSC packets should be deleted in DeleteConsumerChain + require.Empty(t, providerKeeper.GetPendingVSCPackets(ctx, "consumerId")) + require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_DELETED, providerKeeper.GetConsumerPhase(ctx, "consumerId")) } // TestOnTimeoutPacketWithNoChainFound tests the `OnTimeoutPacket` method fails when no chain is found @@ -534,15 +549,30 @@ func TestOnTimeoutPacketStopsChain(t *testing.T) { defer ctrl.Finish() providerKeeper.SetParams(ctx, providertypes.DefaultParams()) - testkeeper.SetupForStoppingConsumerChain(t, ctx, &providerKeeper, mocks, "consumerId") + testkeeper.SetupForDeleteConsumerChain(t, ctx, &providerKeeper, mocks, "consumerId") + mocks.MockChannelKeeper.EXPECT().GetChannel(gomock.Any(), ccv.ProviderPortID, "channelID").Return( + channeltypes.Channel{State: channeltypes.OPEN, + ConnectionHops: []string{"connectionID"}, + }, true, + ).Times(1) + dummyCap := &capabilitytypes.Capability{} + mocks.MockScopedKeeper.EXPECT().GetCapability(gomock.Any(), gomock.Any()).Return(dummyCap, true).Times(1) + mocks.MockChannelKeeper.EXPECT().ChanCloseInit(gomock.Any(), ccv.ProviderPortID, "channelID", dummyCap).Times(1) + + unbondingTime := 123 * time.Second + mocks.MockStakingKeeper.EXPECT().UnbondingTime(gomock.Any()).Return(unbondingTime, nil).AnyTimes() packet := channeltypes.Packet{ SourceChannel: "channelID", } err := providerKeeper.OnTimeoutPacket(ctx, packet) - - testkeeper.TestProviderStateIsCleanedAfterConsumerChainIsStopped(t, ctx, providerKeeper, "consumerId", "channelID", false) require.NoError(t, err) + + // increase the block time by `unbondingTime` so the chain actually gets deleted + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(unbondingTime)) + providerKeeper.BeginBlockStopConsumers(ctx) + + testkeeper.TestProviderStateIsCleanedAfterConsumerChainIsDeleted(t, ctx, providerKeeper, "consumerId", "channelID", false) } // TestOnAcknowledgementPacketWithNoAckError tests `OnAcknowledgementPacket` when the underlying ack contains no error @@ -570,15 +600,30 @@ func TestOnAcknowledgementPacketWithAckError(t *testing.T) { require.True(t, strings.Contains(err.Error(), providertypes.ErrUnknownConsumerChannelId.Error())) // test that we stop the consumer chain when `OnAcknowledgementPacket` returns an error and the chain is found - testkeeper.SetupForStoppingConsumerChain(t, ctx, &providerKeeper, mocks, "consumerId") + testkeeper.SetupForDeleteConsumerChain(t, ctx, &providerKeeper, mocks, "consumerId") packet := channeltypes.Packet{ SourceChannel: "channelID", } - err = providerKeeper.OnAcknowledgementPacket(ctx, packet, ackError) + unbondingTime := 123 * time.Second + mocks.MockStakingKeeper.EXPECT().UnbondingTime(gomock.Any()).Return(unbondingTime, nil).AnyTimes() + mocks.MockChannelKeeper.EXPECT().GetChannel(gomock.Any(), ccv.ProviderPortID, "channelID").Return( + channeltypes.Channel{State: channeltypes.OPEN, + ConnectionHops: []string{"connectionID"}, + }, true, + ).Times(1) + dummyCap := &capabilitytypes.Capability{} + mocks.MockScopedKeeper.EXPECT().GetCapability(gomock.Any(), gomock.Any()).Return(dummyCap, true).Times(1) + mocks.MockChannelKeeper.EXPECT().ChanCloseInit(gomock.Any(), ccv.ProviderPortID, "channelID", dummyCap).Times(1) - testkeeper.TestProviderStateIsCleanedAfterConsumerChainIsStopped(t, ctx, providerKeeper, "consumerId", "channelID", false) + err = providerKeeper.OnAcknowledgementPacket(ctx, packet, ackError) require.NoError(t, err) + + // increase the block time by `unbondingTime` so the chain actually gets deleted + ctx = ctx.WithBlockTime(ctx.BlockTime().Add(unbondingTime)) + providerKeeper.BeginBlockStopConsumers(ctx) + + testkeeper.TestProviderStateIsCleanedAfterConsumerChainIsDeleted(t, ctx, providerKeeper, "consumerId", "channelID", false) } // TestEndBlockVSU tests that during `EndBlockVSU`, we only queue VSC packets at the boundaries of an epoch @@ -586,7 +631,7 @@ func TestEndBlockVSU(t *testing.T) { providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - chainID := "consumerId" + consumerId := "0" err := providerKeeper.SetConsumerPowerShapingParameters(ctx, "consumerId", providertypes.PowerShapingParameters{ Top_N: 100, @@ -616,30 +661,32 @@ func TestEndBlockVSU(t *testing.T) { }) mocks.MockStakingKeeper.EXPECT().GetBondedValidatorsByPower(gomock.Any()).Return(lastValidators, nil).AnyTimes() - // set a sample client for a consumer chain so that `GetAllConsumerChains` in `QueueVSCPackets` iterates at least once - providerKeeper.SetConsumerClientId(ctx, chainID, "clientID") + // set a sample client for a launched consumer chain so that `GetAllLaunchedConsumerIds` in `QueueVSCPackets` iterates at least once + providerKeeper.SetConsumerClientId(ctx, consumerId, "clientId") + providerKeeper.SetConsumerPowerShapingParameters(ctx, consumerId, providertypes.PowerShapingParameters{Top_N: 100}) + providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) // with block height of 1 we do not expect any queueing of VSC packets ctx = ctx.WithBlockHeight(1) providerKeeper.EndBlockVSU(ctx) - require.Equal(t, 0, len(providerKeeper.GetPendingVSCPackets(ctx, chainID))) + require.Equal(t, 0, len(providerKeeper.GetPendingVSCPackets(ctx, consumerId))) // with block height of 5 we do not expect any queueing of VSC packets ctx = ctx.WithBlockHeight(5) providerKeeper.EndBlockVSU(ctx) - require.Equal(t, 0, len(providerKeeper.GetPendingVSCPackets(ctx, chainID))) + require.Equal(t, 0, len(providerKeeper.GetPendingVSCPackets(ctx, consumerId))) // with block height of 10 we expect the queueing of one VSC packet ctx = ctx.WithBlockHeight(10) providerKeeper.EndBlockVSU(ctx) - require.Equal(t, 1, len(providerKeeper.GetPendingVSCPackets(ctx, chainID))) + require.Equal(t, 1, len(providerKeeper.GetPendingVSCPackets(ctx, consumerId))) // With block height of 15 we expect no additional queueing of a VSC packet. // Note that the pending VSC packet is still there because `SendVSCPackets` does not send the packet. We // need to mock channels, etc. for this to work, and it's out of scope for this test. ctx = ctx.WithBlockHeight(15) providerKeeper.EndBlockVSU(ctx) - require.Equal(t, 1, len(providerKeeper.GetPendingVSCPackets(ctx, chainID))) + require.Equal(t, 1, len(providerKeeper.GetPendingVSCPackets(ctx, consumerId))) } // TestProviderValidatorUpdates tests that the provider validator updates are correctly calculated, @@ -740,7 +787,8 @@ func TestQueueVSCPacketsWithPowerCapping(t *testing.T) { testkeeper.SetupMocksForLastBondedValidatorsExpectation(mocks.MockStakingKeeper, 5, []stakingtypes.Validator{valA, valB, valC, valD, valE}, -1) // add a consumer chain - providerKeeper.SetConsumerClientId(ctx, "consumerId", "clientID") + providerKeeper.SetConsumerClientId(ctx, "consumerId", "clientId") + providerKeeper.SetConsumerPhase(ctx, "consumerId", providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) err := providerKeeper.SetConsumerPowerShapingParameters(ctx, "consumerId", providertypes.PowerShapingParameters{ Top_N: 50, // would opt in E diff --git a/x/ccv/provider/migrations/v5/migration_test.go b/x/ccv/provider/migrations/v5/migration_test.go index 1ae0e98a20..498c8b5b98 100644 --- a/x/ccv/provider/migrations/v5/migration_test.go +++ b/x/ccv/provider/migrations/v5/migration_test.go @@ -1,6 +1,7 @@ package v5 import ( + "github.com/cosmos/interchain-security/v5/x/ccv/provider/types" "testing" "github.com/stretchr/testify/require" @@ -13,17 +14,19 @@ func TestMigrateParams(t *testing.T) { provKeeper, ctx, ctrl, _ := testutil.GetProviderKeeperAndCtx(t, inMemParams) defer ctrl.Finish() - provKeeper.SetConsumerClientId(ctx, "chainID", "clientID") + // set up a launched consumer chain + provKeeper.SetConsumerClientId(ctx, "consumerId", "clientId") + provKeeper.SetConsumerPhase(ctx, "consumerId", types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) // initially top N should not exist - _, err := provKeeper.GetConsumerPowerShapingParameters(ctx, "chainID") + _, err := provKeeper.GetConsumerPowerShapingParameters(ctx, "consumerId") require.Error(t, err) // migrate MigrateTopNForRegisteredChains(ctx, provKeeper) // after migration, top N should be 95 - powerShapingParameters, err := provKeeper.GetConsumerPowerShapingParameters(ctx, "chainID") + powerShapingParameters, err := provKeeper.GetConsumerPowerShapingParameters(ctx, "consumerId") require.NoError(t, err) require.Equal(t, uint32(95), powerShapingParameters.Top_N) } diff --git a/x/ccv/provider/migrations/v5/migrations.go b/x/ccv/provider/migrations/v5/migrations.go index 1dca37bbae..32da11db85 100644 --- a/x/ccv/provider/migrations/v5/migrations.go +++ b/x/ccv/provider/migrations/v5/migrations.go @@ -12,7 +12,7 @@ import ( // and a migration to rewrite the proposal is needed. func MigrateTopNForRegisteredChains(ctx sdk.Context, providerKeeper providerkeeper.Keeper) { // Set the topN of each chain to 95 - for _, consumerId := range providerKeeper.GetAllRegisteredConsumerIds(ctx) { + for _, consumerId := range providerKeeper.GetAllLaunchedConsumerIds(ctx) { // TODO (PERMISSIONLESS): this migration already took place and does not make much sense in the Permissionless world // living here for now and we should totally remove providerKeeper.SetConsumerPowerShapingParameters(ctx, consumerId, types.PowerShapingParameters{ diff --git a/x/ccv/provider/migrations/v6/migrations.go b/x/ccv/provider/migrations/v6/migrations.go index efbded3d02..730cbdca30 100644 --- a/x/ccv/provider/migrations/v6/migrations.go +++ b/x/ccv/provider/migrations/v6/migrations.go @@ -19,7 +19,7 @@ func MigrateParams(ctx sdk.Context, paramsSubspace paramtypes.Subspace) { func MigrateMinPowerInTopN(ctx sdk.Context, providerKeeper providerkeeper.Keeper) { // we only get the registered consumer chains and not also the proposed consumer chains because // the minimal power is first set when the consumer chain addition proposal passes - registeredConsumerChains := providerKeeper.GetAllRegisteredConsumerIds(ctx) + registeredConsumerChains := providerKeeper.GetAllLaunchedConsumerIds(ctx) for _, chain := range registeredConsumerChains { // get the top N diff --git a/x/ccv/provider/types/consumer.go b/x/ccv/provider/types/consumer.go index 37c286422f..ebc1bcbf30 100644 --- a/x/ccv/provider/types/consumer.go +++ b/x/ccv/provider/types/consumer.go @@ -12,6 +12,7 @@ func NewConsumerStates( genesis ccv.ConsumerGenesisState, pendingValsetChanges []ccv.ValidatorSetChangePacketData, slashDowntimeAck []string, + phase ConsumerPhase, ) ConsumerState { return ConsumerState{ ChainId: chainID, @@ -21,5 +22,6 @@ func NewConsumerStates( PendingValsetChanges: pendingValsetChanges, ConsumerGenesis: genesis, SlashDowntimeAck: slashDowntimeAck, + Phase: phase, } } diff --git a/x/ccv/provider/types/genesis.pb.go b/x/ccv/provider/types/genesis.pb.go index 5dc5b300c4..92a7aa345e 100644 --- a/x/ccv/provider/types/genesis.pb.go +++ b/x/ccv/provider/types/genesis.pb.go @@ -141,6 +141,8 @@ 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"` + // the phase of the consumer chain + Phase ConsumerPhase `protobuf:"varint,9,opt,name=phase,proto3,enum=interchain_security.ccv.provider.v1.ConsumerPhase" json:"phase,omitempty"` } func (m *ConsumerState) Reset() { *m = ConsumerState{} } @@ -225,6 +227,13 @@ func (m *ConsumerState) GetSlashDowntimeAck() []string { return nil } +func (m *ConsumerState) GetPhase() ConsumerPhase { + if m != nil { + return m.Phase + } + return ConsumerPhase_CONSUMER_PHASE_UNSPECIFIED +} + // ValsetUpdateIdToHeight defines the genesis information for the mapping // of each valset update id to a block height type ValsetUpdateIdToHeight struct { @@ -290,53 +299,54 @@ func init() { } var fileDescriptor_48411d9c7900d48e = []byte{ - // 730 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xcd, 0x6e, 0xda, 0x4c, - 0x14, 0xc5, 0xc1, 0x01, 0x33, 0x09, 0x7c, 0x96, 0x15, 0x21, 0x7f, 0x89, 0x4a, 0x10, 0x55, 0x24, - 0xa4, 0xb6, 0x38, 0x50, 0x55, 0xaa, 0xfa, 0xb3, 0x08, 0x89, 0xd4, 0xe2, 0x6e, 0x10, 0x49, 0x53, - 0x29, 0x1b, 0x6b, 0x98, 0x19, 0xc1, 0x08, 0xb0, 0x2d, 0xcf, 0xe0, 0x14, 0x55, 0x95, 0xda, 0x37, - 0xe8, 0xba, 0x2f, 0xd1, 0xd7, 0xc8, 0x32, 0xcb, 0xae, 0xa2, 0x2a, 0x79, 0x83, 0x3e, 0x41, 0xe5, - 0xf1, 0xe0, 0x40, 0x4a, 0x22, 0xd2, 0x9d, 0x7d, 0xcf, 0x9c, 0x7b, 0xcf, 0xfd, 0x05, 0x75, 0xea, - 0x72, 0x12, 0xa0, 0x3e, 0xa4, 0xae, 0xc3, 0x08, 0x1a, 0x07, 0x94, 0x4f, 0x2c, 0x84, 0x42, 0xcb, - 0x0f, 0xbc, 0x90, 0x62, 0x12, 0x58, 0x61, 0xdd, 0xea, 0x11, 0x97, 0x30, 0xca, 0x6a, 0x7e, 0xe0, - 0x71, 0xcf, 0x78, 0xb8, 0x80, 0x52, 0x43, 0x28, 0xac, 0x4d, 0x29, 0xb5, 0xb0, 0xbe, 0xb9, 0xd1, - 0xf3, 0x7a, 0x9e, 0x78, 0x6f, 0x45, 0x5f, 0x31, 0x75, 0x73, 0xf7, 0xb6, 0x68, 0x61, 0xdd, 0x62, - 0x7d, 0x18, 0x10, 0xec, 0x20, 0xcf, 0x65, 0xe3, 0x11, 0x09, 0x24, 0x63, 0xe7, 0x0e, 0xc6, 0x29, - 0x0d, 0x88, 0x7c, 0xd6, 0x58, 0x26, 0x8d, 0x44, 0x9f, 0xe0, 0x54, 0x7e, 0x64, 0xc0, 0xfa, 0x9b, - 0x38, 0xb3, 0x43, 0x0e, 0x39, 0x31, 0xaa, 0x40, 0x0f, 0xe1, 0x90, 0x11, 0xee, 0x8c, 0x7d, 0x0c, - 0x39, 0x71, 0x28, 0x36, 0x95, 0xb2, 0x52, 0x55, 0x3b, 0x85, 0xd8, 0xfe, 0x5e, 0x98, 0x5b, 0xd8, - 0xf8, 0x04, 0xfe, 0x9b, 0xea, 0x74, 0x58, 0xc4, 0x65, 0xe6, 0x4a, 0x39, 0x5d, 0x5d, 0x6b, 0x34, - 0x6a, 0x4b, 0x14, 0xa7, 0xb6, 0x2f, 0xb9, 0x22, 0x6c, 0xb3, 0x74, 0x76, 0xb1, 0x9d, 0xfa, 0x7d, - 0xb1, 0x5d, 0x9c, 0xc0, 0xd1, 0xf0, 0x45, 0xe5, 0x86, 0xe3, 0x4a, 0xa7, 0x80, 0x66, 0x9f, 0x33, - 0xe3, 0x33, 0xd8, 0xbc, 0x29, 0xd3, 0xe1, 0x9e, 0xd3, 0x27, 0xb4, 0xd7, 0xe7, 0xe6, 0xaa, 0xd0, - 0xf1, 0x72, 0x29, 0x1d, 0xc7, 0x73, 0x59, 0x1d, 0x79, 0x6f, 0x85, 0x8b, 0xa6, 0x1a, 0x09, 0xea, - 0x14, 0xc3, 0x85, 0xa8, 0xd1, 0x02, 0x19, 0x1f, 0x06, 0x70, 0xc4, 0x4c, 0xad, 0xac, 0x54, 0xd7, - 0x1a, 0x8f, 0x96, 0x0a, 0xd5, 0x16, 0x14, 0xe9, 0x5a, 0x3a, 0x30, 0xbe, 0x28, 0x22, 0x15, 0x8a, - 0x21, 0xf7, 0x82, 0xa4, 0xf3, 0x8e, 0x3f, 0xee, 0x0e, 0xc8, 0x84, 0x99, 0x39, 0x91, 0xca, 0xab, - 0x65, 0x53, 0x89, 0xdd, 0x4c, 0x6b, 0xdb, 0x1e, 0x77, 0xdf, 0x91, 0x89, 0x0c, 0x68, 0x86, 0x0b, - 0xe0, 0x28, 0x86, 0xf1, 0x55, 0x01, 0x5b, 0x09, 0xc8, 0x9c, 0xee, 0xe4, 0x5a, 0x06, 0xc4, 0x38, - 0x30, 0xc1, 0xbf, 0x68, 0x68, 0x4e, 0xa6, 0x61, 0xf6, 0x30, 0x0e, 0xfe, 0xd2, 0xc0, 0xe6, 0xf1, - 0xa8, 0xa1, 0x73, 0x41, 0x59, 0xd4, 0x4e, 0x3f, 0x18, 0xbb, 0xc4, 0x09, 0x1b, 0x66, 0xe1, 0x1e, - 0x0d, 0x9d, 0x75, 0xcb, 0x8e, 0xbc, 0x76, 0xe4, 0xe3, 0xb8, 0x31, 0x6d, 0x28, 0x5a, 0x88, 0xda, - 0xaa, 0x96, 0xd6, 0x55, 0x5b, 0xd5, 0x54, 0x7d, 0xd5, 0x56, 0xb5, 0x8c, 0x9e, 0xb5, 0x55, 0x2d, - 0xab, 0x6b, 0xb6, 0xaa, 0xad, 0xe9, 0xeb, 0xb6, 0xaa, 0xad, 0xeb, 0x79, 0x5b, 0xd5, 0xf2, 0x7a, - 0xa1, 0xf2, 0x3d, 0x0d, 0xf2, 0x73, 0xb3, 0x6b, 0xfc, 0x0f, 0xb4, 0x58, 0x92, 0x5c, 0x95, 0x5c, - 0x27, 0x2b, 0xfe, 0x5b, 0xd8, 0x78, 0x00, 0x00, 0xea, 0x43, 0xd7, 0x25, 0xc3, 0x08, 0x5c, 0x11, - 0x60, 0x4e, 0x5a, 0x5a, 0xd8, 0xd8, 0x02, 0x39, 0x34, 0xa4, 0xc4, 0xe5, 0x11, 0x9a, 0x16, 0xa8, - 0x16, 0x1b, 0x5a, 0xd8, 0xd8, 0x01, 0x05, 0xea, 0x52, 0x4e, 0xe1, 0x70, 0x3a, 0xd6, 0xaa, 0xd8, - 0xc3, 0xbc, 0xb4, 0xca, 0x51, 0x84, 0x40, 0x4f, 0x0a, 0x27, 0x6f, 0x94, 0xb9, 0x2a, 0x86, 0x72, - 0xf7, 0xd6, 0x72, 0xcd, 0x54, 0x69, 0x76, 0xf9, 0x65, 0x8d, 0x92, 0xb5, 0x96, 0x98, 0xc1, 0x41, - 0xd1, 0x27, 0x2e, 0xa6, 0x6e, 0xcf, 0x91, 0x4b, 0x17, 0xa5, 0xd0, 0x23, 0xcc, 0xcc, 0x88, 0xbe, - 0x3c, 0xbf, 0x2b, 0x50, 0x32, 0x10, 0x87, 0x84, 0xef, 0x0b, 0x5a, 0x1b, 0xa2, 0x01, 0xe1, 0x07, - 0x90, 0x43, 0x19, 0x70, 0x43, 0x7a, 0x8f, 0x57, 0x31, 0x7e, 0xc4, 0x8c, 0xc7, 0xc0, 0x60, 0x43, - 0xc8, 0xfa, 0x0e, 0xf6, 0x4e, 0x5d, 0x4e, 0x47, 0xc4, 0x81, 0x68, 0x60, 0x66, 0xcb, 0xe9, 0x6a, - 0xae, 0xa3, 0x0b, 0xe4, 0x40, 0x02, 0x7b, 0x68, 0x60, 0xab, 0x9a, 0xa6, 0xe7, 0x2a, 0x27, 0xa0, - 0xb8, 0x78, 0x9f, 0xef, 0x71, 0xd7, 0x8a, 0x20, 0x23, 0xeb, 0xbd, 0x22, 0x70, 0xf9, 0xd7, 0xfc, - 0x70, 0x76, 0x59, 0x52, 0xce, 0x2f, 0x4b, 0xca, 0xaf, 0xcb, 0x92, 0xf2, 0xed, 0xaa, 0x94, 0x3a, - 0xbf, 0x2a, 0xa5, 0x7e, 0x5e, 0x95, 0x52, 0x27, 0xaf, 0x7b, 0x94, 0xf7, 0xc7, 0xdd, 0x1a, 0xf2, - 0x46, 0x16, 0xf2, 0xd8, 0xc8, 0x63, 0xd6, 0x75, 0x41, 0x9e, 0x24, 0xa7, 0x38, 0x7c, 0x66, 0x7d, - 0x9c, 0xbf, 0xc7, 0x7c, 0xe2, 0x13, 0xd6, 0xcd, 0x88, 0x53, 0xfc, 0xf4, 0x4f, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x42, 0x5f, 0xb9, 0x07, 0x87, 0x06, 0x00, 0x00, + // 750 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xdd, 0x6e, 0xda, 0x48, + 0x14, 0xc6, 0xc1, 0x80, 0x99, 0x04, 0xd6, 0xb2, 0x22, 0xe4, 0x4d, 0xb4, 0x04, 0xb1, 0x8a, 0x84, + 0xb4, 0xbb, 0x38, 0xb0, 0xaa, 0x54, 0xf5, 0xe7, 0x22, 0x24, 0x52, 0x83, 0x7b, 0x83, 0x48, 0x9a, + 0x4a, 0xb9, 0xb1, 0x86, 0x99, 0x11, 0x1e, 0x01, 0xb6, 0xe5, 0x19, 0x9c, 0xa2, 0xaa, 0x52, 0xfb, + 0x06, 0x7d, 0x93, 0xbe, 0x46, 0x2e, 0x73, 0xd9, 0xab, 0xa8, 0x4a, 0xfa, 0x04, 0x7d, 0x82, 0xca, + 0xe3, 0x81, 0x40, 0x4a, 0x22, 0xd2, 0x3b, 0xfb, 0x7c, 0xf3, 0x9d, 0xf3, 0x9d, 0x5f, 0xd0, 0xa0, + 0x1e, 0x27, 0x21, 0x72, 0x21, 0xf5, 0x1c, 0x46, 0xd0, 0x38, 0xa4, 0x7c, 0x62, 0x21, 0x14, 0x59, + 0x41, 0xe8, 0x47, 0x14, 0x93, 0xd0, 0x8a, 0x1a, 0x56, 0x9f, 0x78, 0x84, 0x51, 0x56, 0x0f, 0x42, + 0x9f, 0xfb, 0xc6, 0xdf, 0x4b, 0x28, 0x75, 0x84, 0xa2, 0xfa, 0x94, 0x52, 0x8f, 0x1a, 0x5b, 0x9b, + 0x7d, 0xbf, 0xef, 0x8b, 0xf7, 0x56, 0xfc, 0x95, 0x50, 0xb7, 0xf6, 0xee, 0x8b, 0x16, 0x35, 0x2c, + 0xe6, 0xc2, 0x90, 0x60, 0x07, 0xf9, 0x1e, 0x1b, 0x8f, 0x48, 0x28, 0x19, 0xbb, 0x0f, 0x30, 0xce, + 0x69, 0x48, 0xe4, 0xb3, 0xe6, 0x2a, 0x69, 0xcc, 0xf4, 0x09, 0x4e, 0xf5, 0x4b, 0x16, 0x6c, 0xbc, + 0x4a, 0x32, 0x3b, 0xe6, 0x90, 0x13, 0xa3, 0x06, 0xf4, 0x08, 0x0e, 0x19, 0xe1, 0xce, 0x38, 0xc0, + 0x90, 0x13, 0x87, 0x62, 0x53, 0xa9, 0x28, 0x35, 0xb5, 0x5b, 0x4c, 0xec, 0x6f, 0x84, 0xb9, 0x8d, + 0x8d, 0xf7, 0xe0, 0x8f, 0xa9, 0x4e, 0x87, 0xc5, 0x5c, 0x66, 0xae, 0x55, 0xd2, 0xb5, 0xf5, 0x66, + 0xb3, 0xbe, 0x42, 0x71, 0xea, 0x07, 0x92, 0x2b, 0xc2, 0xb6, 0xca, 0x17, 0x57, 0x3b, 0xa9, 0x1f, + 0x57, 0x3b, 0xa5, 0x09, 0x1c, 0x0d, 0x9f, 0x55, 0xef, 0x38, 0xae, 0x76, 0x8b, 0x68, 0xfe, 0x39, + 0x33, 0x3e, 0x80, 0xad, 0xbb, 0x32, 0x1d, 0xee, 0x3b, 0x2e, 0xa1, 0x7d, 0x97, 0x9b, 0x19, 0xa1, + 0xe3, 0xf9, 0x4a, 0x3a, 0x4e, 0x17, 0xb2, 0x3a, 0xf1, 0x8f, 0x84, 0x8b, 0x96, 0x1a, 0x0b, 0xea, + 0x96, 0xa2, 0xa5, 0xa8, 0xd1, 0x06, 0xd9, 0x00, 0x86, 0x70, 0xc4, 0x4c, 0xad, 0xa2, 0xd4, 0xd6, + 0x9b, 0xff, 0xac, 0x14, 0xaa, 0x23, 0x28, 0xd2, 0xb5, 0x74, 0x60, 0x7c, 0x54, 0x44, 0x2a, 0x14, + 0x43, 0xee, 0x87, 0xb3, 0xce, 0x3b, 0xc1, 0xb8, 0x37, 0x20, 0x13, 0x66, 0xe6, 0x45, 0x2a, 0x2f, + 0x56, 0x4d, 0x25, 0x71, 0x33, 0xad, 0x6d, 0x67, 0xdc, 0x7b, 0x4d, 0x26, 0x32, 0xa0, 0x19, 0x2d, + 0x81, 0xe3, 0x18, 0xc6, 0x27, 0x05, 0x6c, 0xcf, 0x40, 0xe6, 0xf4, 0x26, 0xb7, 0x32, 0x20, 0xc6, + 0xa1, 0x09, 0x7e, 0x47, 0x43, 0x6b, 0x32, 0x0d, 0xb3, 0x8f, 0x71, 0xf8, 0x8b, 0x06, 0xb6, 0x88, + 0xc7, 0x0d, 0x5d, 0x08, 0xca, 0xe2, 0x76, 0x06, 0xe1, 0xd8, 0x23, 0x4e, 0xd4, 0x34, 0x8b, 0x8f, + 0x68, 0xe8, 0xbc, 0x5b, 0x76, 0xe2, 0x77, 0x62, 0x1f, 0xa7, 0xcd, 0x69, 0x43, 0xd1, 0x52, 0xd4, + 0x56, 0xb5, 0xb4, 0xae, 0xda, 0xaa, 0xa6, 0xea, 0x19, 0x5b, 0xd5, 0xb2, 0x7a, 0xce, 0x56, 0xb5, + 0x9c, 0xae, 0xd9, 0xaa, 0xb6, 0xae, 0x6f, 0xd8, 0xaa, 0xb6, 0xa1, 0x17, 0x6c, 0x55, 0x2b, 0xe8, + 0xc5, 0xea, 0xf7, 0x34, 0x28, 0x2c, 0xcc, 0xae, 0xf1, 0x27, 0xd0, 0x12, 0x49, 0x72, 0x55, 0xf2, + 0xdd, 0x9c, 0xf8, 0x6f, 0x63, 0xe3, 0x2f, 0x00, 0x90, 0x0b, 0x3d, 0x8f, 0x0c, 0x63, 0x70, 0x4d, + 0x80, 0x79, 0x69, 0x69, 0x63, 0x63, 0x1b, 0xe4, 0xd1, 0x90, 0x12, 0x8f, 0xc7, 0x68, 0x5a, 0xa0, + 0x5a, 0x62, 0x68, 0x63, 0x63, 0x17, 0x14, 0xa9, 0x47, 0x39, 0x85, 0xc3, 0xe9, 0x58, 0xab, 0x62, + 0x0f, 0x0b, 0xd2, 0x2a, 0x47, 0x11, 0x02, 0x7d, 0x56, 0x38, 0x79, 0xa3, 0xcc, 0x8c, 0x18, 0xca, + 0xbd, 0x7b, 0xcb, 0x35, 0x57, 0xa5, 0xf9, 0xe5, 0x97, 0x35, 0x9a, 0xad, 0xb5, 0xc4, 0x0c, 0x0e, + 0x4a, 0x01, 0xf1, 0x30, 0xf5, 0xfa, 0x8e, 0x5c, 0xba, 0x38, 0x85, 0x3e, 0x61, 0x66, 0x56, 0xf4, + 0xe5, 0xe9, 0x43, 0x81, 0x66, 0x03, 0x71, 0x4c, 0xf8, 0x81, 0xa0, 0x75, 0x20, 0x1a, 0x10, 0x7e, + 0x08, 0x39, 0x94, 0x01, 0x37, 0xa5, 0xf7, 0x64, 0x15, 0x93, 0x47, 0xcc, 0xf8, 0x17, 0x18, 0x6c, + 0x08, 0x99, 0xeb, 0x60, 0xff, 0xdc, 0xe3, 0x74, 0x44, 0x1c, 0x88, 0x06, 0x66, 0xae, 0x92, 0xae, + 0xe5, 0xbb, 0xba, 0x40, 0x0e, 0x25, 0xb0, 0x8f, 0x06, 0xc6, 0x11, 0xc8, 0x04, 0x2e, 0x64, 0xc4, + 0xcc, 0x57, 0x94, 0x5a, 0xf1, 0x91, 0x37, 0xa8, 0x13, 0x33, 0xbb, 0x89, 0x03, 0x5b, 0xd5, 0x34, + 0x3d, 0x5f, 0x3d, 0x03, 0xa5, 0xe5, 0x97, 0xe1, 0x11, 0x17, 0xb2, 0x04, 0xb2, 0xb2, 0x73, 0x6b, + 0x02, 0x97, 0x7f, 0xad, 0xb7, 0x17, 0xd7, 0x65, 0xe5, 0xf2, 0xba, 0xac, 0x7c, 0xbb, 0x2e, 0x2b, + 0x9f, 0x6f, 0xca, 0xa9, 0xcb, 0x9b, 0x72, 0xea, 0xeb, 0x4d, 0x39, 0x75, 0xf6, 0xb2, 0x4f, 0xb9, + 0x3b, 0xee, 0xd5, 0x91, 0x3f, 0xb2, 0x90, 0xcf, 0x46, 0x3e, 0xb3, 0x6e, 0xf3, 0xf8, 0x6f, 0x76, + 0xd4, 0xa3, 0x27, 0xd6, 0xbb, 0xc5, 0xcb, 0xce, 0x27, 0x01, 0x61, 0xbd, 0xac, 0x38, 0xea, 0xff, + 0xff, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x1e, 0x1f, 0x55, 0x38, 0xd1, 0x06, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -467,6 +477,11 @@ func (m *ConsumerState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Phase != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Phase)) + i-- + dAtA[i] = 0x48 + } if len(m.SlashDowntimeAck) > 0 { for iNdEx := len(m.SlashDowntimeAck) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.SlashDowntimeAck[iNdEx]) @@ -652,6 +667,9 @@ func (m *ConsumerState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } + if m.Phase != 0 { + n += 1 + sovGenesis(uint64(m.Phase)) + } return n } @@ -1191,6 +1209,25 @@ func (m *ConsumerState) Unmarshal(dAtA []byte) error { } m.SlashDowntimeAck = append(m.SlashDowntimeAck, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Phase", wireType) + } + m.Phase = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Phase |= ConsumerPhase(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/ccv/provider/types/legacy_proposal.go b/x/ccv/provider/types/legacy_proposal.go index 9cc6ef2a77..b86c409109 100644 --- a/x/ccv/provider/types/legacy_proposal.go +++ b/x/ccv/provider/types/legacy_proposal.go @@ -136,7 +136,6 @@ func NewConsumerRemovalProposal(title, description, chainID string, stopTime tim Title: title, Description: description, ChainId: chainID, - StopTime: stopTime, } } diff --git a/x/ccv/provider/types/msg.go b/x/ccv/provider/types/msg.go index 361ac79a2c..0ce64b688a 100644 --- a/x/ccv/provider/types/msg.go +++ b/x/ccv/provider/types/msg.go @@ -3,11 +3,9 @@ package types import ( "encoding/json" "fmt" + cmttypes "github.com/cometbft/cometbft/types" "strconv" "strings" - "time" - - cmttypes "github.com/cometbft/cometbft/types" ibctmtypes "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" @@ -360,11 +358,10 @@ func (msg MsgUpdateConsumer) ValidateBasic() error { } // NewMsgRemoveConsumer creates a new MsgRemoveConsumer instance -func NewMsgRemoveConsumer(signer string, consumerId string, stopTime time.Time) (*MsgRemoveConsumer, error) { +func NewMsgRemoveConsumer(signer string, consumerId string) (*MsgRemoveConsumer, error) { return &MsgRemoveConsumer{ Signer: signer, ConsumerId: consumerId, - StopTime: stopTime, }, nil } diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index 1c0755344d..bcdf7dd2ab 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -54,6 +54,8 @@ const ( ConsumerPhase_CONSUMER_PHASE_LAUNCHED ConsumerPhase = 3 // STOPPED defines the phase in which a previously-launched chain has stopped. ConsumerPhase_CONSUMER_PHASE_STOPPED ConsumerPhase = 4 + // DELETED defines the phase in which the state of a stopped chain has been deleted. + ConsumerPhase_CONSUMER_PHASE_DELETED ConsumerPhase = 5 ) var ConsumerPhase_name = map[int32]string{ @@ -62,6 +64,7 @@ var ConsumerPhase_name = map[int32]string{ 2: "CONSUMER_PHASE_INITIALIZED", 3: "CONSUMER_PHASE_LAUNCHED", 4: "CONSUMER_PHASE_STOPPED", + 5: "CONSUMER_PHASE_DELETED", } var ConsumerPhase_value = map[string]int32{ @@ -70,6 +73,7 @@ var ConsumerPhase_value = map[string]int32{ "CONSUMER_PHASE_INITIALIZED": 2, "CONSUMER_PHASE_LAUNCHED": 3, "CONSUMER_PHASE_STOPPED": 4, + "CONSUMER_PHASE_DELETED": 5, } func (x ConsumerPhase) String() string { @@ -1826,13 +1830,13 @@ func init() { } var fileDescriptor_f22ec409a72b7b72 = []byte{ - // 2220 bytes of a gzipped FileDescriptorProto + // 2231 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x59, 0xbd, 0x6f, 0x1b, 0xc9, 0x15, 0xd7, 0x8a, 0x94, 0x44, 0x3e, 0xea, 0x83, 0x1a, 0xfb, 0x6c, 0x4a, 0xd6, 0x51, 0x34, 0x2f, 0x36, 0x14, 0x3b, 0x26, 0x4f, 0x3a, 0x04, 0x30, 0x9c, 0x1c, 0x0c, 0x99, 0xa4, 0x6d, 0xfa, 0x43, 0x66, 0x96, 0xb4, 0x0e, 0x70, 0x8a, 0xc5, 0x70, 0x77, 0x44, 0x4e, 0xb4, 0xbb, 0xb3, 0xde, 0x19, - 0xd2, 0x66, 0x8a, 0xd4, 0x41, 0x80, 0x00, 0x97, 0x54, 0x87, 0x34, 0xb9, 0x2e, 0x41, 0xaa, 0x14, - 0x41, 0xfe, 0x80, 0x54, 0x87, 0x00, 0x41, 0xae, 0x4c, 0x75, 0x17, 0xd8, 0x45, 0x8a, 0x00, 0x69, + 0xd2, 0x66, 0x8a, 0xd4, 0x41, 0x80, 0x00, 0x97, 0x54, 0x87, 0x34, 0xb9, 0x32, 0x48, 0x95, 0x22, + 0xc8, 0x1f, 0x90, 0x34, 0x87, 0x00, 0x41, 0xae, 0x4c, 0x75, 0x17, 0xd8, 0x45, 0x8a, 0x00, 0x69, 0xd3, 0x06, 0x33, 0xfb, 0xc1, 0xa5, 0x3e, 0x6c, 0x1a, 0xb6, 0xd3, 0x48, 0x3b, 0xef, 0xfd, 0xde, 0x9b, 0x37, 0x33, 0xef, 0x6b, 0x86, 0xb0, 0x43, 0x5d, 0x41, 0x7c, 0xb3, 0x8f, 0xa9, 0x6b, 0x70, 0x62, 0x0e, 0x7c, 0x2a, 0x46, 0x55, 0xd3, 0x1c, 0x56, 0x3d, 0x9f, 0x0d, 0xa9, 0x45, 0xfc, 0xea, @@ -1879,7 +1883,7 @@ var fileDescriptor_f22ec409a72b7b72 = []byte{ 0x24, 0x85, 0xb3, 0x25, 0x6d, 0x2b, 0xad, 0x67, 0x1c, 0xea, 0xb6, 0xe5, 0x18, 0x55, 0xe0, 0x8c, 0xd2, 0x62, 0x50, 0x57, 0x9e, 0xd3, 0x90, 0x18, 0x43, 0x6c, 0xf3, 0xc2, 0x07, 0x25, 0x6d, 0x2b, 0xa3, 0xaf, 0x2a, 0x56, 0x33, 0xe4, 0xec, 0x63, 0x9b, 0xdf, 0xb8, 0xfc, 0xf3, 0x2f, 0x37, 0x67, - 0xbe, 0xf8, 0x72, 0x73, 0xe6, 0xaf, 0x7f, 0xba, 0xb6, 0x1e, 0xa6, 0x9f, 0x1e, 0x1b, 0x56, 0xc2, + 0xbe, 0xf8, 0x72, 0x73, 0xe6, 0xaf, 0x7f, 0xbc, 0xb6, 0x1e, 0xa6, 0x9f, 0x1e, 0x1b, 0x56, 0xc2, 0x54, 0x55, 0xa9, 0x31, 0x57, 0x10, 0x57, 0x94, 0xff, 0xae, 0xc1, 0xf9, 0x5a, 0xec, 0x10, 0x0e, 0x1b, 0x62, 0xfb, 0x7d, 0x26, 0x9e, 0x5d, 0xc8, 0x72, 0x79, 0x22, 0x2a, 0xd4, 0xd3, 0x6f, 0x10, 0xea, 0x19, 0x29, 0x26, 0x19, 0x37, 0x8a, 0xaf, 0x59, 0xd1, 0xbf, 0x67, 0x61, 0x23, 0x5a, 0xd1, @@ -1888,7 +1892,7 @@ var fileDescriptor_f22ec409a72b7b72 = []byte{ 0xe7, 0x67, 0x70, 0x8a, 0x9f, 0x95, 0x7f, 0xab, 0xc1, 0xd9, 0xc6, 0xd3, 0x01, 0x1d, 0xb2, 0x77, 0xb4, 0xcb, 0xf7, 0x61, 0x89, 0x24, 0xf4, 0xf1, 0x42, 0xaa, 0x94, 0xda, 0xca, 0xed, 0x5c, 0xaa, 0x84, 0x47, 0x1e, 0xd7, 0xe1, 0xe8, 0xdc, 0x93, 0xb3, 0xeb, 0x93, 0xb2, 0x37, 0x66, 0x0b, 0x5a, - 0xf9, 0x2f, 0x1a, 0xac, 0xcb, 0x7c, 0xd0, 0x23, 0x3a, 0x79, 0x86, 0x7d, 0xab, 0x4e, 0x5c, 0xe6, + 0xf9, 0xcf, 0x1a, 0xac, 0xcb, 0x7c, 0xd0, 0x23, 0x3a, 0x79, 0x86, 0x7d, 0xab, 0x4e, 0x5c, 0xe6, 0xf0, 0xb7, 0xb6, 0xb3, 0x0c, 0x4b, 0x96, 0xd2, 0x64, 0x08, 0x66, 0x60, 0xcb, 0x52, 0x76, 0x2a, 0x8c, 0x24, 0x76, 0xd8, 0xae, 0x65, 0xa1, 0x2d, 0xc8, 0x8f, 0x31, 0xbe, 0x8c, 0x2e, 0xe9, 0xf4, 0x12, 0xb6, 0x1c, 0xc1, 0x54, 0xcc, 0x4d, 0xe1, 0xd4, 0x1a, 0xe4, 0xef, 0xd8, 0xac, 0x8b, 0xed, @@ -1937,14 +1941,14 @@ var fileDescriptor_f22ec409a72b7b72 = []byte{ 0xa9, 0xe3, 0x0b, 0x28, 0xff, 0x4d, 0x83, 0x73, 0xc9, 0x59, 0x79, 0x87, 0xb5, 0xfc, 0x81, 0x4b, 0xf6, 0x77, 0x5e, 0x35, 0xff, 0x4d, 0xc8, 0x78, 0x12, 0x65, 0x08, 0x1e, 0x1e, 0xd1, 0x74, 0xe5, 0x7a, 0x41, 0x49, 0x75, 0x64, 0x78, 0x2f, 0x4f, 0x2c, 0x80, 0x87, 0x3b, 0xf7, 0xf1, 0x54, 0x01, - 0x97, 0x08, 0x26, 0x7d, 0x29, 0xb9, 0x66, 0x5e, 0xfe, 0xb3, 0x06, 0xe8, 0x78, 0xa6, 0x42, 0xdf, + 0x97, 0x08, 0x26, 0x7d, 0x29, 0xb9, 0x66, 0x5e, 0xfe, 0x93, 0x06, 0xe8, 0x78, 0xa6, 0x42, 0xdf, 0x03, 0x34, 0x91, 0xef, 0x92, 0xfe, 0x97, 0xf7, 0x12, 0x19, 0x4e, 0xed, 0x5c, 0xec, 0x47, 0xb3, 0x09, 0x3f, 0x42, 0x3f, 0x00, 0xf0, 0xd4, 0x21, 0x4e, 0x7d, 0xd2, 0x59, 0x2f, 0xfa, 0x44, 0x9b, 0x90, 0xfb, 0x09, 0xa3, 0x6e, 0xf2, 0x91, 0x22, 0xa5, 0x83, 0x24, 0x05, 0xef, 0x0f, 0xe5, 0x5f, 0x6a, 0xe3, 0x74, 0x18, 0x66, 0xea, 0x5d, 0xdb, 0x0e, 0xfb, 0x3f, 0xe4, 0xc1, 0x42, 0x94, 0xeb, - 0x83, 0x70, 0xdd, 0x38, 0xb1, 0x1e, 0xd5, 0x89, 0xa9, 0x4a, 0xd2, 0x75, 0xb9, 0xe3, 0x7f, 0xf8, + 0x83, 0x70, 0xdd, 0x38, 0xb1, 0x1e, 0xd5, 0x89, 0xa9, 0x4a, 0xd2, 0x75, 0xb9, 0xe3, 0xbf, 0xff, 0x76, 0xf3, 0x6a, 0x8f, 0x8a, 0xfe, 0xa0, 0x5b, 0x31, 0x99, 0x13, 0xbe, 0xdc, 0x84, 0xff, 0xae, - 0x71, 0xeb, 0xb0, 0x2a, 0x46, 0x1e, 0xe1, 0x91, 0x0c, 0xff, 0xfd, 0xbf, 0xfe, 0x78, 0x45, 0xd3, + 0x71, 0xeb, 0xb0, 0x2a, 0x46, 0x1e, 0xe1, 0x91, 0x0c, 0xff, 0xdd, 0xbf, 0xfe, 0x70, 0x45, 0xd3, 0xa3, 0x69, 0xca, 0x16, 0xe4, 0xe3, 0xbb, 0x07, 0x11, 0xd8, 0xc2, 0x02, 0x23, 0x04, 0x69, 0x17, 0x3b, 0x51, 0x83, 0xa9, 0xbe, 0xa7, 0xe8, 0x2f, 0xd7, 0x21, 0xe3, 0x84, 0x1a, 0xc2, 0xdb, 0x46, 0x3c, 0x2e, 0xff, 0x62, 0x1e, 0x4a, 0xd1, 0x34, 0xcd, 0xe0, 0x3d, 0x86, 0xfe, 0x34, 0x68, 0xbf, @@ -1955,17 +1959,18 @@ var fileDescriptor_f22ec409a72b7b72 = []byte{ 0xba, 0xdd, 0xc7, 0x9e, 0x3c, 0xdc, 0x71, 0x08, 0xc4, 0xd7, 0x72, 0x6d, 0x8a, 0x6b, 0xf9, 0xec, 0x9b, 0x5d, 0xcb, 0x53, 0x53, 0x5c, 0xcb, 0xd3, 0xaf, 0xba, 0x96, 0xcf, 0xbd, 0xea, 0x5a, 0x3e, 0x3f, 0xdd, 0xb5, 0x7c, 0xe1, 0xb4, 0x6b, 0xf9, 0x26, 0xe4, 0xe2, 0x04, 0x61, 0x71, 0x94, 0x87, - 0x14, 0xb5, 0xa2, 0x66, 0x52, 0x7e, 0x5e, 0xf9, 0x9d, 0x06, 0x4b, 0x71, 0x55, 0xef, 0x63, 0x4e, + 0x14, 0xb5, 0xa2, 0x66, 0x52, 0x7e, 0x5e, 0xf9, 0x8b, 0x06, 0x4b, 0x71, 0x55, 0xef, 0x63, 0x4e, 0x50, 0x11, 0xd6, 0x6b, 0x8f, 0xf6, 0xda, 0x8f, 0x1f, 0x36, 0x74, 0xa3, 0x75, 0x77, 0xb7, 0xdd, 0x30, 0x1e, 0xef, 0xb5, 0x5b, 0x8d, 0x5a, 0xf3, 0x76, 0xb3, 0x51, 0xcf, 0xcf, 0xa0, 0x0f, 0x61, 0xed, 0x08, 0x5f, 0x6f, 0xdc, 0x69, 0xb6, 0x3b, 0x0d, 0xbd, 0x51, 0xcf, 0x6b, 0x27, 0x88, 0x37, 0xf7, 0x9a, 0x9d, 0xe6, 0xee, 0x83, 0xe6, 0x93, 0x46, 0x3d, 0x3f, 0x8b, 0x2e, 0xc0, 0xf9, 0x23, 0xfc, 0x07, 0xbb, 0x8f, 0xf7, 0x6a, 0x77, 0x1b, 0xf5, 0x7c, 0x0a, 0xad, 0xc3, 0xb9, 0x23, 0xcc, - 0x76, 0xe7, 0x51, 0xab, 0xd5, 0xa8, 0xe7, 0xd3, 0xb7, 0x3e, 0xfb, 0xea, 0x45, 0x51, 0xfb, 0xfa, - 0x45, 0x51, 0xfb, 0xe7, 0x8b, 0xa2, 0xf6, 0xf9, 0xcb, 0xe2, 0xcc, 0xd7, 0x2f, 0x8b, 0x33, 0xff, - 0x78, 0x59, 0x9c, 0x79, 0xf2, 0xe9, 0xf1, 0x3c, 0x3d, 0xae, 0x83, 0xd7, 0xe2, 0xdf, 0x2a, 0x86, - 0xdf, 0xaf, 0x3e, 0x9f, 0xfc, 0x25, 0x44, 0xa5, 0xf0, 0xee, 0xbc, 0x0a, 0xc1, 0x4f, 0xfe, 0x17, - 0x00, 0x00, 0xff, 0xff, 0x1d, 0xf2, 0xb2, 0x97, 0x3a, 0x19, 0x00, 0x00, + 0x76, 0xe7, 0x51, 0xab, 0xd5, 0xa8, 0xe7, 0xd3, 0x27, 0xf0, 0xea, 0x8d, 0x07, 0x8d, 0x4e, 0xa3, + 0x9e, 0x9f, 0xbb, 0xf5, 0xd9, 0x57, 0x2f, 0x8a, 0xda, 0xd7, 0x2f, 0x8a, 0xda, 0x3f, 0x5f, 0x14, + 0xb5, 0xcf, 0x5f, 0x16, 0x67, 0xbe, 0x7e, 0x59, 0x9c, 0xf9, 0xc7, 0xcb, 0xe2, 0xcc, 0x93, 0x4f, + 0x8f, 0xe7, 0xf0, 0x71, 0x8d, 0xbc, 0x16, 0xff, 0x8e, 0x31, 0xfc, 0x7e, 0xf5, 0xf9, 0xe4, 0xaf, + 0x24, 0x2a, 0xbd, 0x77, 0xe7, 0x55, 0x78, 0x7e, 0xf2, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x63, + 0x65, 0x8b, 0xc3, 0x56, 0x19, 0x00, 0x00, } func (m *ConsumerAdditionProposal) Marshal() (dAtA []byte, err error) { diff --git a/x/ccv/provider/types/query.pb.go b/x/ccv/provider/types/query.pb.go index 161c4e70f9..271df4d582 100644 --- a/x/ccv/provider/types/query.pb.go +++ b/x/ccv/provider/types/query.pb.go @@ -128,7 +128,7 @@ func (m *QueryConsumerGenesisResponse) GetGenesisState() types.ConsumerGenesisSt type QueryConsumerChainsRequest struct { // The phase of the consumer chains returned (optional) - // Registered=1|Initialized=2|Launched=3|Stopped=4 + // Registered=1|Initialized=2|Launched=3|Stopped=4|Deleted=5 Phase ConsumerPhase `protobuf:"varint,1,opt,name=phase,proto3,enum=interchain_security.ccv.provider.v1.ConsumerPhase" json:"phase,omitempty"` // The limit of consumer chains returned (optional) // default is 100 diff --git a/x/ccv/provider/types/tx.pb.go b/x/ccv/provider/types/tx.pb.go index 447ce8d15c..a656dd8f7d 100644 --- a/x/ccv/provider/types/tx.pb.go +++ b/x/ccv/provider/types/tx.pb.go @@ -771,11 +771,7 @@ var xxx_messageInfo_MsgConsumerRemovalResponse proto.InternalMessageInfo type MsgRemoveConsumer struct { // the consumer id of the consumer chain to be stopped ConsumerId string `protobuf:"bytes,1,opt,name=consumer_id,json=consumerId,proto3" json:"consumer_id,omitempty"` - // the time on the provider chain at which all validators are responsible to - // stop their consumer chain validator node - StopTime time.Time `protobuf:"bytes,2,opt,name=stop_time,json=stopTime,proto3,stdtime" json:"stop_time"` - // signer address - Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"` + Signer string `protobuf:"bytes,2,opt,name=signer,proto3" json:"signer,omitempty"` } func (m *MsgRemoveConsumer) Reset() { *m = MsgRemoveConsumer{} } @@ -818,13 +814,6 @@ func (m *MsgRemoveConsumer) GetConsumerId() string { return "" } -func (m *MsgRemoveConsumer) GetStopTime() time.Time { - if m != nil { - return m.StopTime - } - return time.Time{} -} - func (m *MsgRemoveConsumer) GetSigner() string { if m != nil { return m.Signer @@ -1692,138 +1681,138 @@ func init() { } var fileDescriptor_43221a4391e9fbf4 = []byte{ - // 2086 bytes of a gzipped FileDescriptorProto + // 2081 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x59, 0x4d, 0x70, 0x1c, 0x47, - 0x15, 0xd6, 0xec, 0xae, 0x94, 0xdd, 0x5e, 0xfd, 0xb6, 0xe4, 0x68, 0xb5, 0xb6, 0xb5, 0xb2, 0x08, - 0x89, 0xca, 0x44, 0xb3, 0xb1, 0xc0, 0x0e, 0x08, 0xf3, 0xa3, 0x1f, 0x83, 0x15, 0x90, 0xa5, 0x8c, - 0x8c, 0x53, 0x05, 0x55, 0x4c, 0xf5, 0xce, 0xb4, 0x67, 0xbb, 0xbc, 0x33, 0x3d, 0x35, 0xdd, 0xbb, - 0x8a, 0x38, 0x51, 0x39, 0xf9, 0x68, 0x2a, 0x1c, 0xb8, 0x91, 0x03, 0x1c, 0xa8, 0x02, 0x2a, 0x87, - 0x14, 0x07, 0x8e, 0x9c, 0x52, 0xc5, 0x25, 0xe4, 0x44, 0xe5, 0x60, 0x28, 0xfb, 0x10, 0x2e, 0x5c, - 0xb8, 0x71, 0xa3, 0xba, 0xa7, 0x67, 0x76, 0x66, 0x77, 0x25, 0xcd, 0xae, 0x42, 0x38, 0x70, 0x51, - 0x69, 0xfa, 0xbd, 0xf7, 0xbd, 0x9f, 0x7e, 0xfd, 0x5e, 0xbf, 0x5e, 0xf0, 0x2a, 0xf1, 0x38, 0x0e, - 0xac, 0x26, 0x22, 0x9e, 0xc9, 0xb0, 0xd5, 0x0e, 0x08, 0x3f, 0xa9, 0x5b, 0x56, 0xa7, 0xee, 0x07, - 0xb4, 0x43, 0x6c, 0x1c, 0xd4, 0x3b, 0x37, 0xea, 0xfc, 0x6d, 0xdd, 0x0f, 0x28, 0xa7, 0xf0, 0x0b, - 0x03, 0xb8, 0x75, 0xcb, 0xea, 0xe8, 0x11, 0xb7, 0xde, 0xb9, 0x51, 0x9d, 0x43, 0x2e, 0xf1, 0x68, - 0x5d, 0xfe, 0x0d, 0xe5, 0xaa, 0x57, 0x1c, 0x4a, 0x9d, 0x16, 0xae, 0x23, 0x9f, 0xd4, 0x91, 0xe7, - 0x51, 0x8e, 0x38, 0xa1, 0x1e, 0x53, 0xd4, 0x9a, 0xa2, 0xca, 0xaf, 0x46, 0xfb, 0x61, 0x9d, 0x13, - 0x17, 0x33, 0x8e, 0x5c, 0x5f, 0x31, 0x2c, 0xf7, 0x32, 0xd8, 0xed, 0x40, 0x22, 0x28, 0xfa, 0x52, - 0x2f, 0x1d, 0x79, 0x27, 0x8a, 0xb4, 0xe0, 0x50, 0x87, 0xca, 0x7f, 0xeb, 0xe2, 0xbf, 0x48, 0xc0, - 0xa2, 0xcc, 0xa5, 0xcc, 0x0c, 0x09, 0xe1, 0x87, 0x22, 0x2d, 0x86, 0x5f, 0x75, 0x97, 0x39, 0xc2, - 0x75, 0x97, 0x39, 0x91, 0x95, 0xa4, 0x61, 0xd5, 0x2d, 0x1a, 0xe0, 0xba, 0xd5, 0x22, 0xd8, 0xe3, - 0x82, 0x1a, 0xfe, 0xa7, 0x18, 0x36, 0xb2, 0x84, 0x32, 0x0e, 0x54, 0x28, 0x53, 0x17, 0xa0, 0x2d, - 0xe2, 0x34, 0x79, 0x08, 0xc5, 0xea, 0x1c, 0x7b, 0x36, 0x0e, 0x5c, 0x12, 0x2a, 0xe8, 0x7e, 0x45, - 0x56, 0x24, 0xe8, 0xfc, 0xc4, 0xc7, 0xac, 0x8e, 0x05, 0x9e, 0x67, 0xe1, 0x90, 0x61, 0xf5, 0xdf, - 0x1a, 0x58, 0xd8, 0x67, 0xce, 0x16, 0x63, 0xc4, 0xf1, 0x76, 0xa8, 0xc7, 0xda, 0x2e, 0x0e, 0xbe, - 0x87, 0x4f, 0xe0, 0x55, 0x50, 0x0c, 0x6d, 0x23, 0x76, 0x45, 0x5b, 0xd1, 0xd6, 0x4a, 0xdb, 0xb9, - 0x8a, 0x66, 0xbc, 0x20, 0xd7, 0xf6, 0x6c, 0xf8, 0x3a, 0x98, 0x8a, 0x6c, 0x33, 0x91, 0x6d, 0x07, - 0x95, 0x9c, 0xe4, 0x81, 0xff, 0x7a, 0x5a, 0x9b, 0x3e, 0x41, 0x6e, 0x6b, 0x73, 0x55, 0xac, 0x62, - 0xc6, 0x56, 0x8d, 0xc9, 0x88, 0x71, 0xcb, 0xb6, 0x03, 0x78, 0x0d, 0x4c, 0x5a, 0x4a, 0x8d, 0xf9, - 0x08, 0x9f, 0x54, 0xf2, 0x42, 0xce, 0x28, 0x5b, 0x09, 0xd5, 0xaf, 0x81, 0x09, 0x61, 0x0d, 0x0e, - 0x2a, 0x05, 0x09, 0x5a, 0xf9, 0xf8, 0x83, 0xf5, 0x05, 0x15, 0xf5, 0xad, 0x10, 0xf5, 0x88, 0x07, - 0xc4, 0x73, 0x0c, 0xc5, 0x07, 0x6b, 0x20, 0x06, 0x10, 0xf6, 0x8e, 0x4b, 0x4c, 0x10, 0x2d, 0xed, - 0xd9, 0x9b, 0xf3, 0x8f, 0xdf, 0xab, 0x8d, 0xfd, 0xe3, 0xbd, 0xda, 0xd8, 0x3b, 0x9f, 0xbe, 0x7f, - 0x5d, 0x49, 0xad, 0x2e, 0x83, 0x2b, 0x83, 0x5c, 0x37, 0x30, 0xf3, 0xa9, 0xc7, 0xf0, 0xea, 0x33, - 0x0d, 0x5c, 0xdd, 0x67, 0xce, 0x51, 0xbb, 0xe1, 0x12, 0x1e, 0x31, 0xec, 0x13, 0xd6, 0xc0, 0x4d, - 0xd4, 0x21, 0xb4, 0x1d, 0xc0, 0x5b, 0xa0, 0xc4, 0x24, 0x95, 0xe3, 0x40, 0x45, 0xe9, 0x74, 0x63, - 0xbb, 0xac, 0xf0, 0x10, 0x4c, 0xba, 0x09, 0x1c, 0x19, 0xbc, 0xf2, 0xc6, 0xab, 0x3a, 0x69, 0x58, - 0x7a, 0x72, 0x7b, 0xf5, 0xc4, 0x86, 0x76, 0x6e, 0xe8, 0x49, 0xdd, 0x46, 0x0a, 0xa1, 0x37, 0x02, - 0xf9, 0xbe, 0x08, 0xbc, 0x98, 0x8c, 0x40, 0xd7, 0x94, 0xd5, 0x57, 0xc0, 0x17, 0xcf, 0xf4, 0x31, - 0x8e, 0xc6, 0x5f, 0x72, 0x03, 0xa2, 0xb1, 0x4b, 0xdb, 0x8d, 0x16, 0x7e, 0x40, 0x39, 0xf1, 0x9c, - 0x91, 0xa3, 0x61, 0x82, 0x45, 0xbb, 0xed, 0xb7, 0x88, 0x85, 0x38, 0x36, 0x3b, 0x94, 0x63, 0x33, - 0x4a, 0x52, 0x15, 0x98, 0x57, 0x92, 0x71, 0x90, 0x69, 0xac, 0xef, 0x46, 0x02, 0x0f, 0x28, 0xc7, - 0x77, 0x14, 0xbb, 0x71, 0xc9, 0x1e, 0xb4, 0x0c, 0x7f, 0x0c, 0x16, 0x89, 0xf7, 0x30, 0x40, 0x96, - 0x28, 0x02, 0x66, 0xa3, 0x45, 0xad, 0x47, 0x66, 0x13, 0x23, 0x1b, 0x07, 0x32, 0x50, 0xe5, 0x8d, - 0x97, 0xcf, 0x8b, 0xfc, 0x5d, 0xc9, 0x6d, 0x5c, 0xea, 0xc2, 0x6c, 0x0b, 0x94, 0x70, 0xb9, 0x37, - 0xf8, 0x85, 0x0b, 0x05, 0x3f, 0x19, 0xd2, 0x38, 0xf8, 0xbf, 0xd2, 0xc0, 0xcc, 0x3e, 0x73, 0x7e, - 0xe0, 0xdb, 0x88, 0xe3, 0x43, 0x14, 0x20, 0x97, 0x89, 0x70, 0xa3, 0x36, 0x6f, 0x52, 0x51, 0x38, - 0xce, 0x0f, 0x77, 0xcc, 0x0a, 0xf7, 0xc0, 0x84, 0x2f, 0x11, 0x54, 0x74, 0xbf, 0xa4, 0x67, 0x28, - 0xd3, 0x7a, 0xa8, 0x74, 0xbb, 0xf0, 0xe1, 0xd3, 0xda, 0x98, 0xa1, 0x00, 0x36, 0xa7, 0xa5, 0x3f, - 0x31, 0xf4, 0xea, 0x12, 0x58, 0xec, 0xb1, 0x32, 0xf6, 0xe0, 0x93, 0x22, 0x98, 0xdf, 0x67, 0x4e, - 0xe4, 0xe5, 0x96, 0x6d, 0x13, 0x11, 0x46, 0xb8, 0xd4, 0x5b, 0x67, 0xba, 0x35, 0xe6, 0xbb, 0x60, - 0x9a, 0x78, 0x84, 0x13, 0xd4, 0x32, 0x9b, 0x58, 0xec, 0x8d, 0x32, 0xb8, 0x2a, 0x77, 0x4b, 0xd4, - 0x56, 0x5d, 0x55, 0x54, 0xb9, 0x43, 0x82, 0x43, 0xd9, 0x37, 0xa5, 0xe4, 0xc2, 0x45, 0x51, 0x73, - 0x1c, 0xec, 0x61, 0x46, 0x98, 0xd9, 0x44, 0xac, 0x29, 0x37, 0x7d, 0xd2, 0x28, 0xab, 0xb5, 0xbb, - 0x88, 0x35, 0xc5, 0x16, 0x36, 0x88, 0x87, 0x82, 0x93, 0x90, 0xa3, 0x20, 0x39, 0x40, 0xb8, 0x24, - 0x19, 0x76, 0x00, 0x60, 0x3e, 0x3a, 0xf6, 0x4c, 0xd1, 0x6d, 0x64, 0x85, 0x11, 0x86, 0x84, 0x9d, - 0x44, 0x8f, 0x3a, 0x89, 0x7e, 0x3f, 0x6a, 0x45, 0xdb, 0x45, 0x61, 0xc8, 0x93, 0xbf, 0xd5, 0x34, - 0xa3, 0x24, 0xe5, 0x04, 0x05, 0xde, 0x03, 0xb3, 0x6d, 0xaf, 0x41, 0x3d, 0x9b, 0x78, 0x8e, 0xe9, - 0xe3, 0x80, 0x50, 0xbb, 0x32, 0x21, 0xa1, 0x96, 0xfa, 0xa0, 0x76, 0x55, 0xd3, 0x0a, 0x91, 0x7e, - 0x21, 0x90, 0x66, 0x62, 0xe1, 0x43, 0x29, 0x0b, 0xdf, 0x04, 0xd0, 0xb2, 0x3a, 0xd2, 0x24, 0xda, - 0xe6, 0x11, 0xe2, 0x0b, 0xd9, 0x11, 0x67, 0x2d, 0xab, 0x73, 0x3f, 0x94, 0x56, 0x90, 0x3f, 0x02, - 0x8b, 0x3c, 0x40, 0x1e, 0x7b, 0x88, 0x83, 0x5e, 0xdc, 0x62, 0x76, 0xdc, 0x4b, 0x11, 0x46, 0x1a, - 0xfc, 0x2e, 0x58, 0x89, 0x0f, 0x4a, 0x80, 0x6d, 0xc2, 0x78, 0x40, 0x1a, 0x6d, 0x79, 0x2a, 0xa3, - 0x73, 0x55, 0x29, 0xc9, 0x24, 0x58, 0x8e, 0xf8, 0x8c, 0x14, 0xdb, 0x77, 0x14, 0x17, 0x3c, 0x00, - 0x2f, 0xc9, 0x73, 0xcc, 0x84, 0x71, 0x66, 0x0a, 0x49, 0xaa, 0x76, 0x09, 0x63, 0x02, 0x0d, 0xac, - 0x68, 0x6b, 0x79, 0xe3, 0x5a, 0xc8, 0x7b, 0x88, 0x83, 0xdd, 0x04, 0xe7, 0xfd, 0x04, 0x23, 0x5c, - 0x07, 0xb0, 0x49, 0x18, 0xa7, 0x01, 0xb1, 0x50, 0xcb, 0xc4, 0x1e, 0x0f, 0x08, 0x66, 0x95, 0xb2, - 0x14, 0x9f, 0xeb, 0x52, 0xee, 0x84, 0x04, 0xf8, 0x06, 0xb8, 0x76, 0xaa, 0x52, 0xd3, 0x6a, 0x22, - 0xcf, 0xc3, 0xad, 0xca, 0xa4, 0x74, 0xa5, 0x66, 0x9f, 0xa2, 0x73, 0x27, 0x64, 0x83, 0xf3, 0x60, - 0x9c, 0x53, 0xdf, 0xbc, 0x57, 0x99, 0x5a, 0xd1, 0xd6, 0xa6, 0x8c, 0x02, 0xa7, 0xfe, 0x3d, 0xf8, - 0x1a, 0x58, 0xe8, 0xa0, 0x16, 0xb1, 0x11, 0xa7, 0x01, 0x33, 0x7d, 0x7a, 0x8c, 0x03, 0xd3, 0x42, - 0x7e, 0x65, 0x5a, 0xf2, 0xc0, 0x2e, 0xed, 0x50, 0x90, 0x76, 0x90, 0x0f, 0xaf, 0x83, 0xb9, 0x78, - 0xd5, 0x64, 0x98, 0x4b, 0xf6, 0x19, 0xc9, 0x3e, 0x13, 0x13, 0x8e, 0x30, 0x17, 0xbc, 0x57, 0x40, - 0x09, 0xb5, 0x5a, 0xf4, 0xb8, 0x45, 0x18, 0xaf, 0xcc, 0xae, 0xe4, 0xd7, 0x4a, 0x46, 0x77, 0x01, - 0x56, 0x41, 0xd1, 0xc6, 0xde, 0x89, 0x24, 0xce, 0x49, 0x62, 0xfc, 0x9d, 0xae, 0x3a, 0x30, 0x7b, - 0xd5, 0xb9, 0x0c, 0x4a, 0xae, 0xa8, 0x2f, 0x1c, 0x3d, 0xc2, 0x95, 0xf9, 0x15, 0x6d, 0xad, 0x60, - 0x14, 0x5d, 0xe2, 0x1d, 0x89, 0x6f, 0xa8, 0x83, 0x79, 0xa9, 0xdd, 0x24, 0x9e, 0xd8, 0xdf, 0x0e, - 0x36, 0x3b, 0xa8, 0xc5, 0x2a, 0x0b, 0x2b, 0xda, 0x5a, 0xd1, 0x98, 0x93, 0xa4, 0x3d, 0x45, 0x79, - 0x80, 0x5a, 0xfd, 0x75, 0xe7, 0x2a, 0xb8, 0x3c, 0xa0, 0xb6, 0xc4, 0xb5, 0xe7, 0x8f, 0x1a, 0x80, - 0x09, 0xba, 0x81, 0x5d, 0xda, 0x41, 0xad, 0xb3, 0x4a, 0xcf, 0x16, 0x28, 0x31, 0xb1, 0x27, 0xf2, - 0xb0, 0xe7, 0x86, 0x38, 0xec, 0x45, 0x21, 0x26, 0xcf, 0x7a, 0x2a, 0x50, 0xf9, 0xcc, 0x81, 0xea, - 0xf3, 0xed, 0x0a, 0xa8, 0xf6, 0xdb, 0x1e, 0xbb, 0xf6, 0x07, 0x0d, 0xcc, 0xed, 0x33, 0x47, 0x2e, - 0xe3, 0x88, 0xa9, 0xb7, 0x21, 0x69, 0xbd, 0x0d, 0xe9, 0xb3, 0xf0, 0xaf, 0x7b, 0x4b, 0xcb, 0x67, - 0xbb, 0xa5, 0x6d, 0x96, 0x93, 0x97, 0xaf, 0xcb, 0x60, 0xa9, 0xcf, 0xee, 0xd8, 0xab, 0xdf, 0x69, - 0xe0, 0x92, 0x70, 0xba, 0x89, 0x3c, 0x07, 0x1b, 0xf8, 0x18, 0x05, 0xf6, 0x2e, 0xf6, 0xa8, 0xcb, - 0xe0, 0x2a, 0x98, 0xb2, 0xe5, 0x7f, 0x26, 0xa7, 0xe2, 0xe2, 0x59, 0xd1, 0x64, 0x7e, 0x96, 0xc3, - 0xc5, 0xfb, 0x74, 0xcb, 0xb6, 0xe1, 0x1a, 0x98, 0xed, 0xf2, 0x04, 0x52, 0x43, 0x25, 0x27, 0xd9, - 0xa6, 0x23, 0xb6, 0x50, 0xef, 0x67, 0xb6, 0x47, 0x35, 0x79, 0x35, 0xea, 0x37, 0x37, 0x76, 0xe8, - 0x9f, 0x1a, 0x28, 0xee, 0x33, 0xe7, 0xc0, 0xe7, 0x7b, 0xde, 0xff, 0xc3, 0xd5, 0x1a, 0x82, 0xd9, - 0xc8, 0xdd, 0x38, 0x06, 0x7f, 0xd6, 0x40, 0x29, 0x5c, 0x3c, 0x68, 0xf3, 0xff, 0x5a, 0x10, 0x86, - 0x4e, 0xcb, 0xf3, 0x6f, 0x6f, 0x03, 0x3d, 0x9c, 0x97, 0xe7, 0x2e, 0x74, 0x26, 0x76, 0xf1, 0xd7, - 0x39, 0x39, 0x52, 0x88, 0x22, 0xab, 0xc4, 0x77, 0xa8, 0xab, 0xaa, 0xbd, 0x81, 0x38, 0xee, 0x77, - 0x4b, 0xcb, 0xe8, 0x56, 0x32, 0x5c, 0xb9, 0xfe, 0x70, 0xdd, 0x01, 0x85, 0x00, 0x71, 0xac, 0x7c, - 0xbe, 0x21, 0x8e, 0xeb, 0x27, 0x4f, 0x6b, 0x97, 0x43, 0xbf, 0x99, 0xfd, 0x48, 0x27, 0xb4, 0xee, - 0x22, 0xde, 0xd4, 0xbf, 0x8f, 0x1d, 0x64, 0x9d, 0xec, 0x62, 0xeb, 0xe3, 0x0f, 0xd6, 0x81, 0x0a, - 0xcb, 0x2e, 0xb6, 0x0c, 0x29, 0xfe, 0xb9, 0xa5, 0xc7, 0xcb, 0xe0, 0xa5, 0xb3, 0xc2, 0x14, 0xc7, - 0xf3, 0xf7, 0x79, 0x79, 0xa1, 0x8c, 0xe7, 0x12, 0x6a, 0x93, 0x87, 0xe2, 0x7a, 0x2f, 0x1a, 0xf6, - 0x02, 0x18, 0xe7, 0x84, 0xb7, 0xb0, 0xaa, 0x6e, 0xe1, 0x07, 0x5c, 0x01, 0x65, 0x1b, 0x33, 0x2b, - 0x20, 0xbe, 0xbc, 0x4c, 0xe4, 0xc2, 0x23, 0x90, 0x58, 0x4a, 0x55, 0xfd, 0x7c, 0xba, 0xea, 0xc7, - 0x8d, 0xb8, 0x90, 0xa1, 0x11, 0x8f, 0x0f, 0xd7, 0x88, 0x27, 0x32, 0x34, 0xe2, 0x17, 0xce, 0x6a, - 0xc4, 0xc5, 0xb3, 0x1a, 0x71, 0x69, 0xc4, 0x46, 0x0c, 0xb2, 0x35, 0xe2, 0x72, 0xd6, 0x46, 0x7c, - 0x0d, 0xd4, 0x4e, 0xd9, 0xaf, 0x78, 0x4f, 0xff, 0x94, 0x97, 0x27, 0x67, 0x27, 0xc0, 0x88, 0x77, - 0x3b, 0x56, 0x37, 0xf3, 0xb4, 0x8c, 0x99, 0xb7, 0xd4, 0x7b, 0x22, 0xba, 0xfb, 0xf8, 0x16, 0x28, - 0xba, 0x98, 0x23, 0x1b, 0x71, 0xa4, 0x06, 0xbc, 0x9b, 0x99, 0x66, 0x9c, 0xd8, 0x6e, 0x25, 0xac, - 0xa6, 0x89, 0x18, 0x0c, 0xbe, 0xa3, 0x81, 0x25, 0x35, 0x5a, 0x90, 0x9f, 0x48, 0xb7, 0x4c, 0x39, - 0x09, 0x61, 0x8e, 0x03, 0x26, 0xb3, 0xa6, 0xbc, 0x71, 0x67, 0x28, 0x55, 0x7b, 0x29, 0xb4, 0xc3, - 0x18, 0xcc, 0xa8, 0x90, 0x53, 0x28, 0xb0, 0x0d, 0x2a, 0x61, 0x16, 0xb2, 0x26, 0xf2, 0xe5, 0x20, - 0xd1, 0x35, 0x21, 0x9c, 0x4b, 0xbe, 0x9e, 0x6d, 0xa2, 0x13, 0x20, 0x47, 0x21, 0x46, 0x42, 0xf1, - 0x8b, 0xfe, 0xc0, 0xf5, 0x74, 0xf7, 0xbe, 0x2d, 0xbb, 0x77, 0x7a, 0x0f, 0xa3, 0x1d, 0x3e, 0xf7, - 0xf6, 0xb1, 0xfa, 0xb8, 0x20, 0x53, 0x20, 0x9c, 0x13, 0x2f, 0x90, 0x02, 0x3d, 0x8a, 0x72, 0x7d, - 0xd7, 0x9c, 0x5d, 0x30, 0xe7, 0xe1, 0x63, 0x93, 0x1e, 0x7b, 0xaa, 0xde, 0x62, 0xc6, 0xce, 0xed, - 0x0b, 0x33, 0x1e, 0x3e, 0x3e, 0x10, 0x12, 0x6a, 0x19, 0xbe, 0x99, 0x48, 0xa7, 0xc2, 0x05, 0xd2, - 0x29, 0x73, 0x22, 0x8d, 0xff, 0xef, 0x13, 0x69, 0xe2, 0x73, 0x4a, 0xa4, 0xf0, 0x1a, 0x98, 0xce, - 0x84, 0x28, 0x91, 0x36, 0xde, 0x9d, 0x05, 0xf9, 0x7d, 0xe6, 0xc0, 0x9f, 0x69, 0x60, 0xae, 0xff, - 0x85, 0xf2, 0x6b, 0x99, 0x8c, 0x1b, 0xf4, 0xc2, 0x57, 0xdd, 0x1a, 0x59, 0x34, 0x4e, 0xf2, 0xdf, - 0x6a, 0xa0, 0x7a, 0xc6, 0xcb, 0xe0, 0x76, 0x56, 0x0d, 0xa7, 0x63, 0x54, 0xdf, 0xb8, 0x38, 0xc6, - 0x19, 0xe6, 0xa6, 0x9e, 0xee, 0x46, 0x34, 0x37, 0x89, 0x31, 0xaa, 0xb9, 0x83, 0xde, 0xbb, 0xe0, - 0xbb, 0x1a, 0x98, 0xed, 0x7b, 0x2a, 0xfa, 0x6a, 0x56, 0x05, 0xbd, 0x92, 0xd5, 0x6f, 0x8f, 0x2a, - 0x19, 0x77, 0xad, 0xfc, 0xe3, 0x9c, 0x06, 0x9f, 0x68, 0x60, 0xa6, 0x77, 0x88, 0x7c, 0x7d, 0x58, - 0x68, 0x25, 0x58, 0xfd, 0xd6, 0x88, 0x82, 0x69, 0x93, 0x1e, 0x6b, 0x60, 0xba, 0xa7, 0x95, 0xde, - 0xca, 0x0c, 0x9c, 0x92, 0xab, 0x7e, 0x73, 0x34, 0xb9, 0x78, 0xcf, 0x84, 0x29, 0x3d, 0x25, 0x3d, - 0xb3, 0x29, 0x69, 0xb9, 0xec, 0xa6, 0x0c, 0x2e, 0x1c, 0xd2, 0x94, 0x9e, 0x91, 0x38, 0xb3, 0x29, - 0x69, 0xb9, 0xec, 0xa6, 0x0c, 0x1e, 0x65, 0x45, 0xa5, 0x9f, 0x4c, 0x3d, 0xdb, 0x7e, 0x65, 0x38, - 0xdf, 0x42, 0xa9, 0xea, 0xed, 0x51, 0xa4, 0x62, 0x23, 0x5c, 0x30, 0x1e, 0x8e, 0x9e, 0xeb, 0x59, - 0x61, 0x24, 0x7b, 0xf5, 0xe6, 0x50, 0xec, 0xb1, 0x3a, 0x1f, 0x4c, 0xa8, 0x29, 0x4f, 0x1f, 0x02, - 0xe0, 0xa0, 0xcd, 0xab, 0xb7, 0x86, 0xe3, 0x8f, 0x35, 0xfe, 0x46, 0x03, 0x4b, 0xa7, 0x4f, 0x5d, - 0x99, 0xcb, 0xfd, 0xa9, 0x10, 0xd5, 0xbd, 0x0b, 0x43, 0xc4, 0xb6, 0xfe, 0x52, 0x03, 0x0b, 0x03, - 0x27, 0x9a, 0xdb, 0xc3, 0x56, 0x84, 0xa4, 0x74, 0x75, 0xf7, 0x22, 0xd2, 0xe9, 0xa2, 0xf2, 0x73, - 0x0d, 0xc0, 0x01, 0x6f, 0x2f, 0x9b, 0x99, 0x35, 0xf4, 0xc9, 0x56, 0xb7, 0x47, 0x97, 0x8d, 0x6c, - 0xab, 0x8e, 0xff, 0xf4, 0xd3, 0xf7, 0xaf, 0x6b, 0xdb, 0x6f, 0x7d, 0xf8, 0x6c, 0x59, 0xfb, 0xe8, - 0xd9, 0xb2, 0xf6, 0xf7, 0x67, 0xcb, 0xda, 0x93, 0xe7, 0xcb, 0x63, 0x1f, 0x3d, 0x5f, 0x1e, 0xfb, - 0xeb, 0xf3, 0xe5, 0xb1, 0x1f, 0x7e, 0xc3, 0x21, 0xbc, 0xd9, 0x6e, 0xe8, 0x16, 0x75, 0xd5, 0xaf, - 0xb4, 0xf5, 0xae, 0xd6, 0xf5, 0xf8, 0x47, 0xd6, 0xce, 0xcd, 0xfa, 0xdb, 0xe9, 0x5f, 0x5a, 0xe5, - 0x6f, 0x4a, 0x8d, 0x09, 0xf9, 0xf2, 0xf5, 0xe5, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x96, 0xcd, - 0x06, 0xd7, 0xe5, 0x1e, 0x00, 0x00, + 0x15, 0xd6, 0xec, 0xae, 0xe4, 0xdd, 0x5e, 0x59, 0x3f, 0x2d, 0x39, 0x1a, 0xad, 0x6d, 0xad, 0x2c, + 0x42, 0xa2, 0x32, 0xd1, 0x6c, 0x2c, 0xb0, 0x03, 0xc2, 0xfc, 0xe8, 0xc7, 0x60, 0x05, 0x64, 0x29, + 0x23, 0xe3, 0x54, 0x41, 0x15, 0x53, 0xbd, 0x33, 0xed, 0xd9, 0x2e, 0xef, 0x4c, 0x4f, 0x4d, 0xf7, + 0xae, 0x22, 0x4e, 0x54, 0x4e, 0x3e, 0x9a, 0x0a, 0x07, 0x6e, 0xe4, 0x00, 0x07, 0xaa, 0x80, 0xca, + 0x21, 0x27, 0x8e, 0x9c, 0x52, 0xc5, 0x25, 0xe4, 0x44, 0xe5, 0x60, 0x28, 0xfb, 0x10, 0x2e, 0x5c, + 0xb8, 0x71, 0xa3, 0xba, 0xa7, 0x67, 0x76, 0x66, 0x77, 0x25, 0x8f, 0x56, 0x10, 0x0e, 0x5c, 0x54, + 0x9a, 0x7e, 0xef, 0x7d, 0xef, 0xa7, 0x5f, 0xbf, 0xd7, 0xaf, 0x17, 0xbc, 0x46, 0x7c, 0x8e, 0x43, + 0xbb, 0x85, 0x88, 0x6f, 0x31, 0x6c, 0x77, 0x42, 0xc2, 0x8f, 0x1b, 0xb6, 0xdd, 0x6d, 0x04, 0x21, + 0xed, 0x12, 0x07, 0x87, 0x8d, 0xee, 0x8d, 0x06, 0x7f, 0xc7, 0x08, 0x42, 0xca, 0x29, 0xfc, 0xc2, + 0x10, 0x6e, 0xc3, 0xb6, 0xbb, 0x46, 0xcc, 0x6d, 0x74, 0x6f, 0xd4, 0x66, 0x91, 0x47, 0x7c, 0xda, + 0x90, 0x7f, 0x23, 0xb9, 0xda, 0x15, 0x97, 0x52, 0xb7, 0x8d, 0x1b, 0x28, 0x20, 0x0d, 0xe4, 0xfb, + 0x94, 0x23, 0x4e, 0xa8, 0xcf, 0x14, 0xb5, 0xae, 0xa8, 0xf2, 0xab, 0xd9, 0x79, 0xd8, 0xe0, 0xc4, + 0xc3, 0x8c, 0x23, 0x2f, 0x50, 0x0c, 0x4b, 0xfd, 0x0c, 0x4e, 0x27, 0x94, 0x08, 0x8a, 0xbe, 0xd8, + 0x4f, 0x47, 0xfe, 0xb1, 0x22, 0xcd, 0xbb, 0xd4, 0xa5, 0xf2, 0xdf, 0x86, 0xf8, 0x2f, 0x16, 0xb0, + 0x29, 0xf3, 0x28, 0xb3, 0x22, 0x42, 0xf4, 0xa1, 0x48, 0x0b, 0xd1, 0x57, 0xc3, 0x63, 0xae, 0x70, + 0xdd, 0x63, 0x6e, 0x6c, 0x25, 0x69, 0xda, 0x0d, 0x9b, 0x86, 0xb8, 0x61, 0xb7, 0x09, 0xf6, 0xb9, + 0xa0, 0x46, 0xff, 0x29, 0x86, 0xf5, 0x3c, 0xa1, 0x4c, 0x02, 0x15, 0xc9, 0x34, 0x04, 0x68, 0x9b, + 0xb8, 0x2d, 0x1e, 0x41, 0xb1, 0x06, 0xc7, 0xbe, 0x83, 0x43, 0x8f, 0x44, 0x0a, 0x7a, 0x5f, 0xb1, + 0x15, 0x29, 0x3a, 0x3f, 0x0e, 0x30, 0x6b, 0x60, 0x81, 0xe7, 0xdb, 0x38, 0x62, 0x58, 0xf9, 0x97, + 0x06, 0xe6, 0xf7, 0x98, 0xbb, 0xc9, 0x18, 0x71, 0xfd, 0x6d, 0xea, 0xb3, 0x8e, 0x87, 0xc3, 0xef, + 0xe1, 0x63, 0x78, 0x15, 0x94, 0x23, 0xdb, 0x88, 0xa3, 0x6b, 0xcb, 0xda, 0x6a, 0x65, 0xab, 0xa0, + 0x6b, 0xe6, 0x05, 0xb9, 0xb6, 0xeb, 0xc0, 0x37, 0xc0, 0xc5, 0xd8, 0x36, 0x0b, 0x39, 0x4e, 0xa8, + 0x17, 0x24, 0x0f, 0xfc, 0xe7, 0xd3, 0xfa, 0xd4, 0x31, 0xf2, 0xda, 0x1b, 0x2b, 0x62, 0x15, 0x33, + 0xb6, 0x62, 0x4e, 0xc6, 0x8c, 0x9b, 0x8e, 0x13, 0xc2, 0x6b, 0x60, 0xd2, 0x56, 0x6a, 0xac, 0x47, + 0xf8, 0x58, 0x2f, 0x0a, 0x39, 0xb3, 0x6a, 0xa7, 0x54, 0xbf, 0x0e, 0x26, 0x84, 0x35, 0x38, 0xd4, + 0x4b, 0x12, 0x54, 0xff, 0xe4, 0xc3, 0xb5, 0x79, 0x15, 0xf5, 0xcd, 0x08, 0xf5, 0x90, 0x87, 0xc4, + 0x77, 0x4d, 0xc5, 0x07, 0xeb, 0x20, 0x01, 0x10, 0xf6, 0x8e, 0x4b, 0x4c, 0x10, 0x2f, 0xed, 0x3a, + 0x1b, 0x73, 0x8f, 0xdf, 0xaf, 0x8f, 0xfd, 0xfd, 0xfd, 0xfa, 0xd8, 0xbb, 0x9f, 0x7d, 0x70, 0x5d, + 0x49, 0xad, 0x2c, 0x81, 0x2b, 0xc3, 0x5c, 0x37, 0x31, 0x0b, 0xa8, 0xcf, 0xf0, 0xca, 0x33, 0x0d, + 0x5c, 0xdd, 0x63, 0xee, 0x61, 0xa7, 0xe9, 0x11, 0x1e, 0x33, 0xec, 0x11, 0xd6, 0xc4, 0x2d, 0xd4, + 0x25, 0xb4, 0x13, 0xc2, 0x5b, 0xa0, 0xc2, 0x24, 0x95, 0xe3, 0x50, 0x45, 0xe9, 0x64, 0x63, 0x7b, + 0xac, 0xf0, 0x00, 0x4c, 0x7a, 0x29, 0x1c, 0x19, 0xbc, 0xea, 0xfa, 0x6b, 0x06, 0x69, 0xda, 0x46, + 0x7a, 0x7b, 0x8d, 0xd4, 0x86, 0x76, 0x6f, 0x18, 0x69, 0xdd, 0x66, 0x06, 0xa1, 0x3f, 0x02, 0xc5, + 0x81, 0x08, 0xbc, 0x94, 0x8e, 0x40, 0xcf, 0x94, 0x95, 0x57, 0xc1, 0x17, 0x4f, 0xf5, 0x31, 0x89, + 0xc6, 0x9f, 0x0b, 0x43, 0xa2, 0xb1, 0x43, 0x3b, 0xcd, 0x36, 0x7e, 0x40, 0x39, 0xf1, 0xdd, 0x91, + 0xa3, 0x61, 0x81, 0x05, 0xa7, 0x13, 0xb4, 0x89, 0x8d, 0x38, 0xb6, 0xba, 0x94, 0x63, 0x2b, 0x4e, + 0x52, 0x15, 0x98, 0x57, 0xd3, 0x71, 0x90, 0x69, 0x6c, 0xec, 0xc4, 0x02, 0x0f, 0x28, 0xc7, 0x77, + 0x14, 0xbb, 0x79, 0xc9, 0x19, 0xb6, 0x0c, 0x7f, 0x0c, 0x16, 0x88, 0xff, 0x30, 0x44, 0xb6, 0x28, + 0x02, 0x56, 0xb3, 0x4d, 0xed, 0x47, 0x56, 0x0b, 0x23, 0x07, 0x87, 0x32, 0x50, 0xd5, 0xf5, 0x57, + 0x5e, 0x14, 0xf9, 0xbb, 0x92, 0xdb, 0xbc, 0xd4, 0x83, 0xd9, 0x12, 0x28, 0xd1, 0x72, 0x7f, 0xf0, + 0x4b, 0xe7, 0x0a, 0x7e, 0x3a, 0xa4, 0x49, 0xf0, 0x7f, 0xa5, 0x81, 0xe9, 0x3d, 0xe6, 0xfe, 0x20, + 0x70, 0x10, 0xc7, 0x07, 0x28, 0x44, 0x1e, 0x13, 0xe1, 0x46, 0x1d, 0xde, 0xa2, 0xa2, 0x70, 0xbc, + 0x38, 0xdc, 0x09, 0x2b, 0xdc, 0x05, 0x13, 0x81, 0x44, 0x50, 0xd1, 0xfd, 0x92, 0x91, 0xa3, 0x4c, + 0x1b, 0x91, 0xd2, 0xad, 0xd2, 0x47, 0x4f, 0xeb, 0x63, 0xa6, 0x02, 0xd8, 0x98, 0x92, 0xfe, 0x24, + 0xd0, 0x2b, 0x8b, 0x60, 0xa1, 0xcf, 0xca, 0xc4, 0x83, 0x4f, 0xcb, 0x60, 0x6e, 0x8f, 0xb9, 0xb1, + 0x97, 0x9b, 0x8e, 0x43, 0x44, 0x18, 0xe1, 0x62, 0x7f, 0x9d, 0xe9, 0xd5, 0x98, 0xef, 0x82, 0x29, + 0xe2, 0x13, 0x4e, 0x50, 0xdb, 0x6a, 0x61, 0xb1, 0x37, 0xca, 0xe0, 0x9a, 0xdc, 0x2d, 0x51, 0x5b, + 0x0d, 0x55, 0x51, 0xe5, 0x0e, 0x09, 0x0e, 0x65, 0xdf, 0x45, 0x25, 0x17, 0x2d, 0x8a, 0x9a, 0xe3, + 0x62, 0x1f, 0x33, 0xc2, 0xac, 0x16, 0x62, 0x2d, 0xb9, 0xe9, 0x93, 0x66, 0x55, 0xad, 0xdd, 0x45, + 0xac, 0x25, 0xb6, 0xb0, 0x49, 0x7c, 0x14, 0x1e, 0x47, 0x1c, 0x25, 0xc9, 0x01, 0xa2, 0x25, 0xc9, + 0xb0, 0x0d, 0x00, 0x0b, 0xd0, 0x91, 0x6f, 0x89, 0x6e, 0x23, 0x2b, 0x8c, 0x30, 0x24, 0xea, 0x24, + 0x46, 0xdc, 0x49, 0x8c, 0xfb, 0x71, 0x2b, 0xda, 0x2a, 0x0b, 0x43, 0x9e, 0xfc, 0xb5, 0xae, 0x99, + 0x15, 0x29, 0x27, 0x28, 0xf0, 0x1e, 0x98, 0xe9, 0xf8, 0x4d, 0xea, 0x3b, 0xc4, 0x77, 0xad, 0x00, + 0x87, 0x84, 0x3a, 0xfa, 0x84, 0x84, 0x5a, 0x1c, 0x80, 0xda, 0x51, 0x4d, 0x2b, 0x42, 0xfa, 0x85, + 0x40, 0x9a, 0x4e, 0x84, 0x0f, 0xa4, 0x2c, 0x7c, 0x0b, 0x40, 0xdb, 0xee, 0x4a, 0x93, 0x68, 0x87, + 0xc7, 0x88, 0x17, 0xf2, 0x23, 0xce, 0xd8, 0x76, 0xf7, 0x7e, 0x24, 0xad, 0x20, 0x7f, 0x04, 0x16, + 0x78, 0x88, 0x7c, 0xf6, 0x10, 0x87, 0xfd, 0xb8, 0xe5, 0xfc, 0xb8, 0x97, 0x62, 0x8c, 0x2c, 0xf8, + 0x5d, 0xb0, 0x9c, 0x1c, 0x94, 0x10, 0x3b, 0x84, 0xf1, 0x90, 0x34, 0x3b, 0xf2, 0x54, 0xc6, 0xe7, + 0x4a, 0xaf, 0xc8, 0x24, 0x58, 0x8a, 0xf9, 0xcc, 0x0c, 0xdb, 0x77, 0x14, 0x17, 0xdc, 0x07, 0x2f, + 0xcb, 0x73, 0xcc, 0x84, 0x71, 0x56, 0x06, 0x49, 0xaa, 0xf6, 0x08, 0x63, 0x02, 0x0d, 0x2c, 0x6b, + 0xab, 0x45, 0xf3, 0x5a, 0xc4, 0x7b, 0x80, 0xc3, 0x9d, 0x14, 0xe7, 0xfd, 0x14, 0x23, 0x5c, 0x03, + 0xb0, 0x45, 0x18, 0xa7, 0x21, 0xb1, 0x51, 0xdb, 0xc2, 0x3e, 0x0f, 0x09, 0x66, 0x7a, 0x55, 0x8a, + 0xcf, 0xf6, 0x28, 0x77, 0x22, 0x02, 0x7c, 0x13, 0x5c, 0x3b, 0x51, 0xa9, 0x65, 0xb7, 0x90, 0xef, + 0xe3, 0xb6, 0x3e, 0x29, 0x5d, 0xa9, 0x3b, 0x27, 0xe8, 0xdc, 0x8e, 0xd8, 0xe0, 0x1c, 0x18, 0xe7, + 0x34, 0xb0, 0xee, 0xe9, 0x17, 0x97, 0xb5, 0xd5, 0x8b, 0x66, 0x89, 0xd3, 0xe0, 0x1e, 0x7c, 0x1d, + 0xcc, 0x77, 0x51, 0x9b, 0x38, 0x88, 0xd3, 0x90, 0x59, 0x01, 0x3d, 0xc2, 0xa1, 0x65, 0xa3, 0x40, + 0x9f, 0x92, 0x3c, 0xb0, 0x47, 0x3b, 0x10, 0xa4, 0x6d, 0x14, 0xc0, 0xeb, 0x60, 0x36, 0x59, 0xb5, + 0x18, 0xe6, 0x92, 0x7d, 0x5a, 0xb2, 0x4f, 0x27, 0x84, 0x43, 0xcc, 0x05, 0xef, 0x15, 0x50, 0x41, + 0xed, 0x36, 0x3d, 0x6a, 0x13, 0xc6, 0xf5, 0x99, 0xe5, 0xe2, 0x6a, 0xc5, 0xec, 0x2d, 0xc0, 0x1a, + 0x28, 0x3b, 0xd8, 0x3f, 0x96, 0xc4, 0x59, 0x49, 0x4c, 0xbe, 0xb3, 0x55, 0x07, 0xe6, 0xaf, 0x3a, + 0x97, 0x41, 0xc5, 0x13, 0xf5, 0x85, 0xa3, 0x47, 0x58, 0x9f, 0x5b, 0xd6, 0x56, 0x4b, 0x66, 0xd9, + 0x23, 0xfe, 0xa1, 0xf8, 0x86, 0x06, 0x98, 0x93, 0xda, 0x2d, 0xe2, 0x8b, 0xfd, 0xed, 0x62, 0xab, + 0x8b, 0xda, 0x4c, 0x9f, 0x5f, 0xd6, 0x56, 0xcb, 0xe6, 0xac, 0x24, 0xed, 0x2a, 0xca, 0x03, 0xd4, + 0x1e, 0xac, 0x3b, 0x57, 0xc1, 0xe5, 0x21, 0xb5, 0x25, 0xa9, 0x3d, 0x7f, 0xd0, 0x00, 0x4c, 0xd1, + 0x4d, 0xec, 0xd1, 0x2e, 0x6a, 0x9f, 0x56, 0x7a, 0x36, 0x41, 0x85, 0x89, 0x3d, 0x91, 0x87, 0xbd, + 0x70, 0x86, 0xc3, 0x5e, 0x16, 0x62, 0xf2, 0xac, 0x67, 0x02, 0x55, 0xcc, 0x1d, 0xa8, 0x01, 0xdf, + 0xae, 0x80, 0xda, 0xa0, 0xed, 0x89, 0x6b, 0x0c, 0xcc, 0xee, 0x31, 0x57, 0xae, 0xe2, 0x98, 0xa7, + 0xbf, 0x1f, 0x69, 0xfd, 0xfd, 0x28, 0x75, 0xc3, 0x2a, 0xe4, 0xbb, 0x61, 0x6d, 0x54, 0xd3, 0x17, + 0xa7, 0xcb, 0x60, 0x71, 0x40, 0x69, 0x62, 0xd1, 0xef, 0x34, 0x70, 0x49, 0x18, 0xdc, 0x42, 0xbe, + 0x8b, 0x4d, 0x7c, 0x84, 0x42, 0x67, 0x07, 0xfb, 0xd4, 0x63, 0x70, 0x05, 0x5c, 0x74, 0xe4, 0x7f, + 0x16, 0xa7, 0xe2, 0xd2, 0xa8, 0x6b, 0x32, 0xb7, 0xaa, 0xd1, 0xe2, 0x7d, 0xba, 0xe9, 0x38, 0x70, + 0x15, 0xcc, 0xf4, 0x78, 0x42, 0xa9, 0x41, 0x2f, 0x48, 0xb6, 0xa9, 0x98, 0x2d, 0xd2, 0xfb, 0x1f, + 0x8b, 0x6f, 0x5d, 0x5e, 0x6b, 0x06, 0xcd, 0x4d, 0x1c, 0xfa, 0x87, 0x06, 0xca, 0x7b, 0xcc, 0xdd, + 0x0f, 0xf8, 0xae, 0xff, 0xff, 0x70, 0x2d, 0x86, 0x60, 0x26, 0x76, 0x37, 0x89, 0xc1, 0x9f, 0x34, + 0x50, 0x89, 0x16, 0xf7, 0x3b, 0xfc, 0xbf, 0x16, 0x84, 0x9e, 0x87, 0xc5, 0xd1, 0x3c, 0x2c, 0xe5, + 0xf3, 0x70, 0x4e, 0x1e, 0x9a, 0xc8, 0x99, 0xc4, 0xc5, 0x5f, 0x17, 0xe4, 0x38, 0x20, 0x0a, 0xa4, + 0x12, 0xdf, 0xa6, 0x9e, 0xaa, 0xd4, 0x26, 0xe2, 0x78, 0xd0, 0x2d, 0x2d, 0xa7, 0x5b, 0xe9, 0x70, + 0x15, 0x06, 0xc3, 0x75, 0x07, 0x94, 0x42, 0xc4, 0xb1, 0xf2, 0xf9, 0x86, 0x28, 0x25, 0x9f, 0x3e, + 0xad, 0x5f, 0x8e, 0xfc, 0x66, 0xce, 0x23, 0x83, 0xd0, 0x86, 0x87, 0x78, 0xcb, 0xf8, 0x3e, 0x76, + 0x91, 0x7d, 0xbc, 0x83, 0xed, 0x4f, 0x3e, 0x5c, 0x03, 0x2a, 0x2c, 0x3b, 0xd8, 0x36, 0xa5, 0xf8, + 0xe7, 0x96, 0x1e, 0xaf, 0x80, 0x97, 0x4f, 0x0b, 0x53, 0x12, 0xcf, 0xdf, 0x17, 0xe5, 0x65, 0x30, + 0x99, 0x29, 0xa8, 0x43, 0x1e, 0x8a, 0xab, 0xb9, 0x68, 0xb6, 0xf3, 0x60, 0x9c, 0x13, 0xde, 0xc6, + 0xaa, 0x34, 0x45, 0x1f, 0x70, 0x19, 0x54, 0x1d, 0xcc, 0xec, 0x90, 0x04, 0xf2, 0x22, 0x50, 0x88, + 0x8e, 0x40, 0x6a, 0x29, 0x53, 0xb1, 0x8b, 0xd9, 0x8a, 0x9d, 0x34, 0xd1, 0x52, 0x8e, 0x26, 0x3a, + 0x7e, 0xb6, 0x26, 0x3a, 0x91, 0xa3, 0x89, 0x5e, 0x38, 0xad, 0x89, 0x96, 0x4f, 0x6b, 0xa2, 0x95, + 0x11, 0x9b, 0x28, 0xc8, 0xd7, 0x44, 0xab, 0x79, 0x9b, 0xe8, 0x35, 0x50, 0x3f, 0x61, 0xbf, 0x92, + 0x3d, 0xfd, 0x63, 0x51, 0x9e, 0x9c, 0xed, 0x10, 0x23, 0xde, 0x6b, 0x37, 0xbd, 0xcc, 0xd3, 0x72, + 0x66, 0xde, 0x62, 0xff, 0x89, 0xe8, 0xed, 0xe3, 0xdb, 0xa0, 0xec, 0x61, 0x8e, 0x1c, 0xc4, 0x91, + 0x1a, 0xce, 0x6e, 0xe6, 0x9a, 0x4f, 0x12, 0xbb, 0x95, 0xb0, 0x9a, 0x04, 0x12, 0x30, 0xf8, 0xae, + 0x06, 0x16, 0xd5, 0x58, 0x40, 0x7e, 0x22, 0xdd, 0xb2, 0xe4, 0x14, 0x83, 0x39, 0x0e, 0x99, 0xcc, + 0x9a, 0xea, 0xfa, 0x9d, 0x33, 0xa9, 0xda, 0xcd, 0xa0, 0x1d, 0x24, 0x60, 0xa6, 0x4e, 0x4e, 0xa0, + 0xc0, 0x0e, 0xd0, 0xa3, 0x2c, 0x64, 0x2d, 0x14, 0xc8, 0x21, 0xa0, 0x67, 0x42, 0x34, 0x53, 0x7c, + 0x3d, 0xdf, 0x34, 0x26, 0x40, 0x0e, 0x23, 0x8c, 0x94, 0xe2, 0x97, 0x82, 0xa1, 0xeb, 0xd9, 0xee, + 0x7d, 0x5b, 0x76, 0xef, 0xec, 0x1e, 0xc6, 0x3b, 0xfc, 0xc2, 0xab, 0xc3, 0xca, 0xe3, 0x92, 0x4c, + 0x81, 0x68, 0xc6, 0x3b, 0x47, 0x0a, 0xf4, 0x29, 0x2a, 0x0c, 0xdc, 0x51, 0x76, 0xc0, 0xac, 0x8f, + 0x8f, 0x2c, 0x7a, 0xe4, 0xab, 0x7a, 0x8b, 0x19, 0x7b, 0x61, 0x5f, 0x98, 0xf6, 0xf1, 0xd1, 0xbe, + 0x90, 0x50, 0xcb, 0xf0, 0xad, 0x54, 0x3a, 0x95, 0xce, 0x91, 0x4e, 0xb9, 0x13, 0x69, 0xfc, 0x7f, + 0x9f, 0x48, 0x13, 0x9f, 0x53, 0x22, 0x45, 0xd7, 0xc0, 0x6c, 0x26, 0xc4, 0x89, 0xb4, 0xfe, 0xde, + 0x0c, 0x28, 0xee, 0x31, 0x17, 0xfe, 0x4c, 0x03, 0xb3, 0x83, 0xaf, 0x8b, 0x5f, 0xcb, 0x65, 0xdc, + 0xb0, 0xd7, 0xb9, 0xda, 0xe6, 0xc8, 0xa2, 0x49, 0x92, 0xff, 0x56, 0x03, 0xb5, 0x53, 0x5e, 0xf5, + 0xb6, 0xf2, 0x6a, 0x38, 0x19, 0xa3, 0xf6, 0xe6, 0xf9, 0x31, 0x4e, 0x31, 0x37, 0xf3, 0xec, 0x36, + 0xa2, 0xb9, 0x69, 0x8c, 0x51, 0xcd, 0x1d, 0xf6, 0x56, 0x05, 0xdf, 0xd3, 0xc0, 0xcc, 0xc0, 0x33, + 0xcf, 0x57, 0xf3, 0x2a, 0xe8, 0x97, 0xac, 0x7d, 0x7b, 0x54, 0xc9, 0xa4, 0x6b, 0x15, 0x1f, 0x17, + 0x34, 0xf8, 0x44, 0x03, 0xd3, 0xfd, 0x03, 0xe0, 0x1b, 0x67, 0x85, 0x56, 0x82, 0xb5, 0x6f, 0x8d, + 0x28, 0x98, 0x35, 0xe9, 0xb1, 0x06, 0xa6, 0xfa, 0x5a, 0xe9, 0xad, 0xdc, 0xc0, 0x19, 0xb9, 0xda, + 0x37, 0x47, 0x93, 0x4b, 0xf6, 0x4c, 0x98, 0xd2, 0x57, 0xd2, 0x73, 0x9b, 0x92, 0x95, 0xcb, 0x6f, + 0xca, 0xf0, 0xc2, 0x21, 0x4d, 0xe9, 0x9b, 0x67, 0x73, 0x9b, 0x92, 0x95, 0xcb, 0x6f, 0xca, 0xf0, + 0x51, 0x56, 0x54, 0xfa, 0xc9, 0xcc, 0x93, 0xeb, 0x57, 0xce, 0xe6, 0x5b, 0x24, 0x55, 0xbb, 0x3d, + 0x8a, 0x54, 0x62, 0x84, 0x07, 0xc6, 0xa3, 0xd1, 0x73, 0x2d, 0x2f, 0x8c, 0x64, 0xaf, 0xdd, 0x3c, + 0x13, 0x7b, 0xa2, 0x2e, 0x00, 0x13, 0x6a, 0xca, 0x33, 0xce, 0x00, 0xb0, 0xdf, 0xe1, 0xb5, 0x5b, + 0x67, 0xe3, 0x4f, 0x34, 0xfe, 0x46, 0x03, 0x8b, 0x27, 0x4f, 0x5d, 0xb9, 0xcb, 0xfd, 0x89, 0x10, + 0xb5, 0xdd, 0x73, 0x43, 0x24, 0xb6, 0xfe, 0x52, 0x03, 0xf3, 0x43, 0x27, 0x9a, 0xdb, 0x67, 0xad, + 0x08, 0x69, 0xe9, 0xda, 0xce, 0x79, 0xa4, 0xb3, 0x45, 0xe5, 0xe7, 0x1a, 0x80, 0x43, 0xde, 0x5e, + 0x36, 0x72, 0x6b, 0x18, 0x90, 0xad, 0x6d, 0x8d, 0x2e, 0x1b, 0xdb, 0x56, 0x1b, 0xff, 0xe9, 0x67, + 0x1f, 0x5c, 0xd7, 0xb6, 0xde, 0xfe, 0xe8, 0xd9, 0x92, 0xf6, 0xf1, 0xb3, 0x25, 0xed, 0x6f, 0xcf, + 0x96, 0xb4, 0x27, 0xcf, 0x97, 0xc6, 0x3e, 0x7e, 0xbe, 0x34, 0xf6, 0x97, 0xe7, 0x4b, 0x63, 0x3f, + 0xfc, 0x86, 0x4b, 0x78, 0xab, 0xd3, 0x34, 0x6c, 0xea, 0xa9, 0x5f, 0x58, 0x1b, 0x3d, 0xad, 0x6b, + 0xc9, 0x0f, 0xa4, 0xdd, 0x9b, 0x8d, 0x77, 0xb2, 0xbf, 0x92, 0xca, 0xdf, 0x83, 0x9a, 0x13, 0xf2, + 0x55, 0xee, 0xcb, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x02, 0xb5, 0x16, 0xbc, 0xa1, 0x1e, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2968,16 +2957,8 @@ func (m *MsgRemoveConsumer) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.Signer) i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) i-- - dAtA[i] = 0x1a - } - n11, err11 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.StopTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.StopTime):]) - if err11 != nil { - return 0, err11 + dAtA[i] = 0x12 } - i -= n11 - i = encodeVarintTx(dAtA, i, uint64(n11)) - i-- - dAtA[i] = 0x12 if len(m.ConsumerId) > 0 { i -= len(m.ConsumerId) copy(dAtA[i:], m.ConsumerId) @@ -3907,8 +3888,6 @@ func (m *MsgRemoveConsumer) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.StopTime) - n += 1 + l + sovTx(uint64(l)) l = len(m.Signer) if l > 0 { n += 1 + l + sovTx(uint64(l)) @@ -5995,39 +5974,6 @@ func (m *MsgRemoveConsumer) Unmarshal(dAtA []byte) error { m.ConsumerId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field StopTime", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.StopTime, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) }