From 0870cb08a3d10b815c4da2237fa39ea76f17c884 Mon Sep 17 00:00:00 2001 From: insumity Date: Tue, 3 Sep 2024 14:24:26 +0200 Subject: [PATCH 01/11] 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 | 102 +++--- .../keeper/consumer_lifecycle_test.go | 28 +- x/ccv/provider/keeper/distribution.go | 8 +- x/ccv/provider/keeper/genesis.go | 11 +- x/ccv/provider/keeper/genesis_test.go | 2 + x/ccv/provider/keeper/grpc_query.go | 14 +- x/ccv/provider/keeper/grpc_query_test.go | 3 +- x/ccv/provider/keeper/keeper.go | 18 +- x/ccv/provider/keeper/keeper_test.go | 28 +- x/ccv/provider/keeper/msg_server.go | 19 +- x/ccv/provider/keeper/relay.go | 20 +- 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, 550 insertions(+), 517 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..7de405b434 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 with `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..6f97662557 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,36 +354,58 @@ func (k Keeper) MakeConsumerGenesis( return gen, hash, nil } +// StopAndPrepareForConsumerDeletion sets the phase of the chain to stopped and prepares to get the state of the +// chain deleted after unbonding period elapses +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. + 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 } @@ -391,7 +414,7 @@ func (k Keeper) BeginBlockStopConsumers(ctx sdk.Context) { writeFn() - k.Logger(ctx).Info("executed consumer removal", + k.Logger(ctx).Info("executed consumer deletion", "consumer id", consumerId, "stop time", stopTime, ) @@ -440,13 +463,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 state of the given consumer chain +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 +480,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 +512,16 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, consumerId string, closeChan k.DeleteAllOptedIn(ctx, consumerId) k.DeleteConsumerValSet(ctx, consumerId) + k.DeleteConsumerRewardsAllocation(ctx, consumerId) + k.DeleteConsumerOwnerAddress(ctx, consumerId) + k.DeleteConsumerStopTime(ctx, consumerId) + // TODO (PERMISSIONLESS) add newly-added state to be deleted + // Note that we do not delete ConsumerIdToChainIdKey and ConsumerIdToPhase, as well + // as consumer metadata, initialization and power-shaping parameters. - 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 +668,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..939812658a 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(). @@ -118,14 +119,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) + launchedConsumerIds := k.GetAllLaunchedConsumerIds(ctx) // export states for each consumer chains var consumerStates []types.ConsumerState - for _, consumerId := range registeredConsumerIds { + for _, consumerId := range launchedConsumerIds { // 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 +138,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 @@ -157,7 +158,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { // ConsumerAddrsToPrune are added only for registered consumer chains consumerAddrsToPrune := []types.ConsumerAddrsToPruneV2{} - for _, chainID := range registeredConsumerIds { + for _, chainID := range launchedConsumerIds { consumerAddrsToPrune = append(consumerAddrsToPrune, k.GetAllConsumerAddrsToPrune(ctx, chainID)...) } 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..df85334c92 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,9 +445,9 @@ 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) { - if hasToValidate, err := k.hasToValidate(ctx, provAddr, consumerChainID); err == nil && hasToValidate { - consumersToValidate = append(consumersToValidate, consumerChainID) + for _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { + if hasToValidate, err := k.hasToValidate(ctx, provAddr, consumerId); err == nil && hasToValidate { + consumersToValidate = append(consumersToValidate, consumerId) } } 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..3eb7d1fab6 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,7 +224,12 @@ 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:]) - consumerIds = append(consumerIds, consumerId) + + // 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. + if k.GetConsumerPhase(ctx, consumerId) == types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED { + consumerIds = append(consumerIds, consumerId) + } } return consumerIds 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..ad26912013 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -30,8 +30,7 @@ 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) } return errorsmod.Wrapf(providertypes.ErrUnknownConsumerChannelId, "recv ErrorAcknowledgement on unknown channel %s", packet.SourceChannel) } @@ -50,9 +49,8 @@ func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet) err packet.SourceChannel, ) } - k.Logger(ctx).Info("packet timeout, removing the consumer:", "consumerId", consumerId) - // stop consumer chain and release unbondings - return k.StopConsumerChain(ctx, consumerId, false) + k.Logger(ctx).Info("packet timeout, deleting the consumer:", "consumerId", consumerId) + return k.StopAndPrepareForConsumerDeletion(ctx, consumerId) } // EndBlockVSU contains the EndBlock logic needed for @@ -135,7 +133,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 +165,10 @@ 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 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()) } return } @@ -191,7 +189,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 +267,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) } From 78a14591106bf2b24b22543c6f2d1aa9c9658c49 Mon Sep 17 00:00:00 2001 From: insumity Date: Tue, 3 Sep 2024 17:11:49 +0200 Subject: [PATCH 02/11] renamed stop time to removal time --- x/ccv/provider/keeper/consumer_lifecycle.go | 88 +++++++-------- .../keeper/consumer_lifecycle_test.go | 102 +++++++++--------- x/ccv/provider/keeper/msg_server.go | 4 +- x/ccv/provider/keeper/permissionless.go | 8 +- x/ccv/provider/keeper/relay.go | 6 +- x/ccv/provider/keeper/relay_test.go | 10 +- x/ccv/provider/module.go | 2 +- x/ccv/provider/types/errors.go | 2 +- x/ccv/provider/types/keys.go | 48 ++++----- x/ccv/provider/types/keys_test.go | 8 +- 10 files changed, 139 insertions(+), 139 deletions(-) diff --git a/x/ccv/provider/keeper/consumer_lifecycle.go b/x/ccv/provider/keeper/consumer_lifecycle.go index 6f97662557..5c927c7d05 100644 --- a/x/ccv/provider/keeper/consumer_lifecycle.go +++ b/x/ccv/provider/keeper/consumer_lifecycle.go @@ -354,9 +354,9 @@ func (k Keeper) MakeConsumerGenesis( return gen, hash, nil } -// StopAndPrepareForConsumerDeletion sets the phase of the chain to stopped and prepares to get the state of the -// chain deleted after unbonding period elapses -func (k Keeper) StopAndPrepareForConsumerDeletion(ctx sdk.Context, consumerId string) error { +// StopAndPrepareForConsumerRemoval sets the phase of the chain to stopped and prepares to get the state of the +// chain removed after unbonding period elapses +func (k Keeper) StopAndPrepareForConsumerRemoval(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) @@ -366,23 +366,23 @@ func (k Keeper) StopAndPrepareForConsumerDeletion(ctx sdk.Context, consumerId st if err != nil { return err } - stopTime := ctx.BlockTime().Add(unbondingPeriod) + removalTime := 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.SetConsumerRemovalTime(ctx, consumerId, removalTime); err != nil { + return errorsmod.Wrapf(types.ErrInvalidRemovalTime, "cannot set removal 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()) + if err := k.AppendConsumerToBeRemoved(ctx, consumerId, removalTime); err != nil { + return errorsmod.Wrapf(ccv.ErrInvalidConsumerState, "cannot set consumer to be removed: %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) { +// BeginBlockRemoveConsumers iterates over the pending consumer proposals and stop/removes the chain if the removal time has passed +func (k Keeper) BeginBlockRemoveConsumers(ctx sdk.Context) { // TODO (PERMISSIONLESS): parameterize the limit for _, consumerId := range k.GetConsumersReadyToStop(ctx, 200) { - stopTime, err := k.GetConsumerStopTime(ctx, consumerId) + removalTime, err := k.GetConsumerRemovalTime(ctx, consumerId) if err != nil { k.Logger(ctx).Error("chain could not be stopped", "consumerId", consumerId, @@ -390,8 +390,8 @@ func (k Keeper) BeginBlockStopConsumers(ctx sdk.Context) { continue } - // Remove consumer to prevent re-trying stopping this chain. - err = k.RemoveConsumerToBeStopped(ctx, consumerId, stopTime) + // Remove consumer to prevent re-trying removing this chain. + err = k.RemoveConsumerToBeRemoved(ctx, consumerId, removalTime) if err != nil { ctx.Logger().Error("could not remove consumer from to-be-stopped queue", "consumerId", consumerId, @@ -416,7 +416,7 @@ func (k Keeper) BeginBlockStopConsumers(ctx sdk.Context) { k.Logger(ctx).Info("executed consumer deletion", "consumer id", consumerId, - "stop time", stopTime, + "removal time", removalTime, ) } } @@ -426,26 +426,26 @@ func (k Keeper) BeginBlockStopConsumers(ctx sdk.Context) { func (k Keeper) GetConsumersReadyToStop(ctx sdk.Context, limit uint32) []string { store := ctx.KVStore(k.storeKey) - stopTimeToConsumerIdsKeyPrefix := types.StopTimeToConsumerIdsKeyPrefix() - iterator := storetypes.KVStorePrefixIterator(store, []byte{stopTimeToConsumerIdsKeyPrefix}) + removalTimeToConsumerIdsKeyPrefix := types.RemovalTimeToConsumerIdsKeyPrefix() + iterator := storetypes.KVStorePrefixIterator(store, []byte{removalTimeToConsumerIdsKeyPrefix}) defer iterator.Close() result := []string{} for ; iterator.Valid(); iterator.Next() { - stopTime, err := types.ParseTime(stopTimeToConsumerIdsKeyPrefix, iterator.Key()) + removalTime, err := types.ParseTime(removalTimeToConsumerIdsKeyPrefix, iterator.Key()) if err != nil { - k.Logger(ctx).Error("failed to parse stop time", + k.Logger(ctx).Error("failed to parse removal time", "error", err) continue } - if stopTime.After(ctx.BlockTime()) { + if removalTime.After(ctx.BlockTime()) { return result } - consumers, err := k.GetConsumersToBeStopped(ctx, stopTime) + consumers, err := k.GetConsumersToBeRemoved(ctx, removalTime) if err != nil { k.Logger(ctx).Error("failed to retrieve consumers to stop", - "stop time", stopTime, + "removal time", removalTime, "error", err) continue } @@ -514,7 +514,7 @@ func (k Keeper) DeleteConsumerChain(ctx sdk.Context, consumerId string) (err err k.DeleteConsumerRewardsAllocation(ctx, consumerId) k.DeleteConsumerOwnerAddress(ctx, consumerId) - k.DeleteConsumerStopTime(ctx, consumerId) + k.DeleteConsumerRemovalTime(ctx, consumerId) // TODO (PERMISSIONLESS) add newly-added state to be deleted // Note that we do not delete ConsumerIdToChainIdKey and ConsumerIdToPhase, as well @@ -530,35 +530,35 @@ func (k Keeper) DeleteConsumerChain(ctx sdk.Context, consumerId string) (err err // Setters and Getters // -// GetConsumerStopTime returns the stop time associated with the to-be-stopped chain with consumer id -func (k Keeper) GetConsumerStopTime(ctx sdk.Context, consumerId string) (time.Time, error) { +// GetConsumerRemovalTime returns the removal time associated with the to-be-removed chain with consumer id +func (k Keeper) GetConsumerRemovalTime(ctx sdk.Context, consumerId string) (time.Time, error) { store := ctx.KVStore(k.storeKey) - buf := store.Get(types.ConsumerIdToStopTimeKey(consumerId)) + buf := store.Get(types.ConsumerIdToRemovalTimeKey(consumerId)) if buf == nil { - return time.Time{}, fmt.Errorf("failed to retrieve stop time for consumer id (%s)", consumerId) + return time.Time{}, fmt.Errorf("failed to retrieve removal time for consumer id (%s)", consumerId) } var time time.Time if err := time.UnmarshalBinary(buf); err != nil { - return time, fmt.Errorf("failed to unmarshal stop time for consumer id (%s): %w", consumerId, err) + return time, fmt.Errorf("failed to unmarshal removal time for consumer id (%s): %w", consumerId, err) } return time, nil } -// SetConsumerStopTime sets the stop time associated with this consumer id -func (k Keeper) SetConsumerStopTime(ctx sdk.Context, consumerId string, stopTime time.Time) error { +// SetConsumerRemovalTime sets the removal time associated with this consumer id +func (k Keeper) SetConsumerRemovalTime(ctx sdk.Context, consumerId string, removalTime time.Time) error { store := ctx.KVStore(k.storeKey) - buf, err := stopTime.MarshalBinary() + buf, err := removalTime.MarshalBinary() if err != nil { - return fmt.Errorf("failed to marshal stop time (%+v) for consumer id (%s): %w", stopTime, consumerId, err) + return fmt.Errorf("failed to marshal removal time (%+v) for consumer id (%s): %w", removalTime, consumerId, err) } - store.Set(types.ConsumerIdToStopTimeKey(consumerId), buf) + store.Set(types.ConsumerIdToRemovalTimeKey(consumerId), buf) return nil } -// DeleteConsumerStopTime deletes the stop time associated with this consumer id -func (k Keeper) DeleteConsumerStopTime(ctx sdk.Context, consumerId string) { +// DeleteConsumerRemovalTime deletes the removal time associated with this consumer id +func (k Keeper) DeleteConsumerRemovalTime(ctx sdk.Context, consumerId string) { store := ctx.KVStore(k.storeKey) - store.Delete(types.ConsumerIdToStopTimeKey(consumerId)) + store.Delete(types.ConsumerIdToRemovalTimeKey(consumerId)) } // getConsumerIdsBasedOnTime returns all the consumer ids stored under this specific `key(time)` @@ -658,17 +658,17 @@ func (k Keeper) RemoveConsumerToBeLaunched(ctx sdk.Context, consumerId string, s return k.removeConsumerIdFromTime(ctx, consumerId, types.SpawnTimeToConsumerIdsKey, spawnTime) } -// GetConsumersToBeStopped returns all the consumer ids of chains stored under this stop time -func (k Keeper) GetConsumersToBeStopped(ctx sdk.Context, stopTime time.Time) (types.ConsumerIds, error) { - return k.getConsumerIdsBasedOnTime(ctx, types.StopTimeToConsumerIdsKey, stopTime) +// GetConsumersToBeRemoved returns all the consumer ids of chains stored under this removal time +func (k Keeper) GetConsumersToBeRemoved(ctx sdk.Context, removalTime time.Time) (types.ConsumerIds, error) { + return k.getConsumerIdsBasedOnTime(ctx, types.RemovalTimeToConsumerIdsKey, removalTime) } -// AppendConsumerToBeStopped appends the provider consumer id for the given stop time -func (k Keeper) AppendConsumerToBeStopped(ctx sdk.Context, consumerId string, stopTime time.Time) error { - return k.appendConsumerIdOnTime(ctx, consumerId, types.StopTimeToConsumerIdsKey, stopTime) +// AppendConsumerToBeRemoved appends the provider consumer id for the given removal time +func (k Keeper) AppendConsumerToBeRemoved(ctx sdk.Context, consumerId string, removalTime time.Time) error { + return k.appendConsumerIdOnTime(ctx, consumerId, types.RemovalTimeToConsumerIdsKey, removalTime) } -// 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) +// RemoveConsumerToBeRemoved removes consumer id from the given removal time +func (k Keeper) RemoveConsumerToBeRemoved(ctx sdk.Context, consumerId string, removalTime time.Time) error { + return k.removeConsumerIdFromTime(ctx, consumerId, types.RemovalTimeToConsumerIdsKey, removalTime) } diff --git a/x/ccv/provider/keeper/consumer_lifecycle_test.go b/x/ccv/provider/keeper/consumer_lifecycle_test.go index c00c2525c0..47e7b4420f 100644 --- a/x/ccv/provider/keeper/consumer_lifecycle_test.go +++ b/x/ccv/provider/keeper/consumer_lifecycle_test.go @@ -648,17 +648,17 @@ func TestBeginBlockStopConsumers(t *testing.T) { chainIds := []string{"chain1", "chain2", "chain3"} consumerIds := []string{"consumerId1", "consumerId2", "consumerId3"} - err := providerKeeper.SetConsumerStopTime(ctx, consumerIds[0], now.Add(-time.Hour)) + err := providerKeeper.SetConsumerRemovalTime(ctx, consumerIds[0], now.Add(-time.Hour)) require.NoError(t, err) - err = providerKeeper.AppendConsumerToBeStopped(ctx, consumerIds[0], now.Add(-time.Hour)) + err = providerKeeper.AppendConsumerToBeRemoved(ctx, consumerIds[0], now.Add(-time.Hour)) require.NoError(t, err) - err = providerKeeper.SetConsumerStopTime(ctx, consumerIds[1], now) + err = providerKeeper.SetConsumerRemovalTime(ctx, consumerIds[1], now) require.NoError(t, err) - err = providerKeeper.AppendConsumerToBeStopped(ctx, consumerIds[1], now) + err = providerKeeper.AppendConsumerToBeRemoved(ctx, consumerIds[1], now) require.NoError(t, err) - err = providerKeeper.SetConsumerStopTime(ctx, consumerIds[2], now.Add(time.Hour)) + err = providerKeeper.SetConsumerRemovalTime(ctx, consumerIds[2], now.Add(time.Hour)) require.NoError(t, err) - err = providerKeeper.AppendConsumerToBeStopped(ctx, consumerIds[2], now.Add(time.Hour)) + err = providerKeeper.AppendConsumerToBeRemoved(ctx, consumerIds[2], now.Add(time.Hour)) require.NoError(t, err) // @@ -703,7 +703,7 @@ func TestBeginBlockStopConsumers(t *testing.T) { err = providerKeeper.SetConsumerChain(ctx, "channelID") require.NoError(t, err) - // the chain is considered to be stopped and ready for deletion (i.e., `StopAndPrepareForConsumerDeletion` is called) + // the chain is considered to be stopped and ready for deletion (i.e., `StopAndPrepareForConsumerRemoval` is called) providerKeeper.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED) } @@ -711,14 +711,14 @@ func TestBeginBlockStopConsumers(t *testing.T) { // Test execution // - providerKeeper.BeginBlockStopConsumers(ctx) + providerKeeper.BeginBlockRemoveConsumers(ctx) // Only the 3rd (final) proposal is still stored as pending phase := providerKeeper.GetConsumerPhase(ctx, consumerIds[0]) require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_DELETED, phase) phase = providerKeeper.GetConsumerPhase(ctx, consumerIds[1]) require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_DELETED, phase) - // third chain had a stopTime in the future and hence did not get deleted + // third chain had a removal time in the future and hence did not get deleted phase = providerKeeper.GetConsumerPhase(ctx, consumerIds[2]) require.Equal(t, providertypes.ConsumerPhase_CONSUMER_PHASE_STOPPED, phase) } @@ -730,26 +730,26 @@ func TestGetConsumersReadyToStop(t *testing.T) { // no chains to-be-stopped exist require.Empty(t, providerKeeper.GetConsumersReadyToStop(ctx, 3)) - err := providerKeeper.AppendConsumerToBeStopped(ctx, "consumerId1", time.Unix(10, 0)) + err := providerKeeper.AppendConsumerToBeRemoved(ctx, "consumerId1", time.Unix(10, 0)) require.NoError(t, err) - err = providerKeeper.AppendConsumerToBeStopped(ctx, "consumerId2", time.Unix(20, 0)) + err = providerKeeper.AppendConsumerToBeRemoved(ctx, "consumerId2", time.Unix(20, 0)) require.NoError(t, err) - err = providerKeeper.AppendConsumerToBeStopped(ctx, "consumerId3", time.Unix(30, 0)) + err = providerKeeper.AppendConsumerToBeRemoved(ctx, "consumerId3", time.Unix(30, 0)) require.NoError(t, err) - // time has not yet reached the stop time of "consumerId1" + // time has not yet reached the removal time of "consumerId1" ctx = ctx.WithBlockTime(time.Unix(9, 999999999)) require.Empty(t, providerKeeper.GetConsumersReadyToStop(ctx, 3)) - // time has reached the stop time of "consumerId1" + // time has reached the removal time of "consumerId1" ctx = ctx.WithBlockTime(time.Unix(10, 0)) require.Equal(t, []string{"consumerId1"}, providerKeeper.GetConsumersReadyToStop(ctx, 3)) - // time has reached the stop time of "consumerId1" and "consumerId2" + // time has reached the removal time of "consumerId1" and "consumerId2" ctx = ctx.WithBlockTime(time.Unix(20, 0)) require.Equal(t, []string{"consumerId1", "consumerId2"}, providerKeeper.GetConsumersReadyToStop(ctx, 3)) - // time has reached the stop time of all chains + // time has reached the removal time of all chains ctx = ctx.WithBlockTime(time.Unix(30, 0)) require.Equal(t, []string{"consumerId1", "consumerId2", "consumerId3"}, providerKeeper.GetConsumersReadyToStop(ctx, 3)) } @@ -820,22 +820,22 @@ func TestStopConsumerChain(t *testing.T) { // Setters and Getters // -// TestConsumerStopTime tests the getter, setter, and deletion of the consumer id to stop times methods -func TestConsumerStopTime(t *testing.T) { +// TestConsumerRemovalTime tests the getter, setter, and deletion of the consumer id to removal times methods +func TestConsumerRemovalTime(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - _, err := providerKeeper.GetConsumerStopTime(ctx, "consumerId") + _, err := providerKeeper.GetConsumerRemovalTime(ctx, "consumerId") require.Error(t, err) - expectedStopTime := time.Unix(1234, 56789) - providerKeeper.SetConsumerStopTime(ctx, "consumerId", expectedStopTime) - actualStopTime, err := providerKeeper.GetConsumerStopTime(ctx, "consumerId") + expectedRemovalTime := time.Unix(1234, 56789) + providerKeeper.SetConsumerRemovalTime(ctx, "consumerId", expectedRemovalTime) + actualRemovalTime, err := providerKeeper.GetConsumerRemovalTime(ctx, "consumerId") require.NoError(t, err) - require.Equal(t, actualStopTime, expectedStopTime) + require.Equal(t, actualRemovalTime, expectedRemovalTime) - providerKeeper.DeleteConsumerStopTime(ctx, "consumerId") - _, err = providerKeeper.GetConsumerStopTime(ctx, "consumerId") + providerKeeper.DeleteConsumerRemovalTime(ctx, "consumerId") + _, err = providerKeeper.GetConsumerRemovalTime(ctx, "consumerId") require.Error(t, err) } @@ -905,68 +905,68 @@ func TestConsumersToBeLaunched(t *testing.T) { require.Equal(t, []string{"consumerId5"}, consumers.Ids) } -// TestConsumersToBeStopped tests `AppendConsumerToBeLaunched`, `GetConsumersToBeLaunched`, and `RemoveConsumerToBeLaunched` -func TestConsumersToBeStopped(t *testing.T) { +// TestConsumersToBeRemoved tests `AppendConsumerToBeRemoved`, `GetConsumersToBeRemoved`, and `RemoveConsumerToBeRemoved` +func TestConsumersToBeRemoved(t *testing.T) { providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - stopTime := time.Now() - err := providerKeeper.AppendConsumerToBeStopped(ctx, "consumerId1", stopTime) + removalTime := time.Now() + err := providerKeeper.AppendConsumerToBeRemoved(ctx, "consumerId1", removalTime) require.NoError(t, err) - consumers, err := providerKeeper.GetConsumersToBeStopped(ctx, stopTime) + consumers, err := providerKeeper.GetConsumersToBeRemoved(ctx, removalTime) require.NoError(t, err) require.Equal(t, []string{"consumerId1"}, consumers.Ids) - err = providerKeeper.AppendConsumerToBeStopped(ctx, "consumerId2", stopTime) + err = providerKeeper.AppendConsumerToBeRemoved(ctx, "consumerId2", removalTime) require.NoError(t, err) - consumers, err = providerKeeper.GetConsumersToBeStopped(ctx, stopTime) + consumers, err = providerKeeper.GetConsumersToBeRemoved(ctx, removalTime) require.NoError(t, err) require.Equal(t, []string{"consumerId1", "consumerId2"}, consumers.Ids) - err = providerKeeper.AppendConsumerToBeStopped(ctx, "consumerId3", stopTime) + err = providerKeeper.AppendConsumerToBeRemoved(ctx, "consumerId3", removalTime) require.NoError(t, err) - consumers, err = providerKeeper.GetConsumersToBeStopped(ctx, stopTime) + consumers, err = providerKeeper.GetConsumersToBeRemoved(ctx, removalTime) require.NoError(t, err) require.Equal(t, []string{"consumerId1", "consumerId2", "consumerId3"}, consumers.Ids) - err = providerKeeper.RemoveConsumerToBeStopped(ctx, "consumerId2", stopTime) + err = providerKeeper.RemoveConsumerToBeRemoved(ctx, "consumerId2", removalTime) require.NoError(t, err) - consumers, err = providerKeeper.GetConsumersToBeStopped(ctx, stopTime) + consumers, err = providerKeeper.GetConsumersToBeRemoved(ctx, removalTime) require.NoError(t, err) require.Equal(t, []string{"consumerId1", "consumerId3"}, consumers.Ids) - // also add consumer ids under a different stop time and verify everything under the original stop time is still there - stopTimePlusOneHour := stopTime.Add(time.Hour) - err = providerKeeper.AppendConsumerToBeStopped(ctx, "consumerId4", stopTimePlusOneHour) + // also add consumer ids under a different removal time and verify everything under the original removal time is still there + removalTimePlusOneHour := removalTime.Add(time.Hour) + err = providerKeeper.AppendConsumerToBeRemoved(ctx, "consumerId4", removalTimePlusOneHour) require.NoError(t, err) - consumers, err = providerKeeper.GetConsumersToBeStopped(ctx, stopTimePlusOneHour) + consumers, err = providerKeeper.GetConsumersToBeRemoved(ctx, removalTimePlusOneHour) require.NoError(t, err) require.Equal(t, []string{"consumerId4"}, consumers.Ids) - consumers, err = providerKeeper.GetConsumersToBeStopped(ctx, stopTime) + consumers, err = providerKeeper.GetConsumersToBeRemoved(ctx, removalTime) require.NoError(t, err) require.Equal(t, []string{"consumerId1", "consumerId3"}, consumers.Ids) - // start removing all consumers from `stopTime` - err = providerKeeper.RemoveConsumerToBeStopped(ctx, "consumerId3", stopTime) + // start removing all consumers from `removalTime` + err = providerKeeper.RemoveConsumerToBeRemoved(ctx, "consumerId3", removalTime) require.NoError(t, err) - err = providerKeeper.RemoveConsumerToBeStopped(ctx, "consumerId1", stopTime) + err = providerKeeper.RemoveConsumerToBeRemoved(ctx, "consumerId1", removalTime) require.NoError(t, err) - consumers, err = providerKeeper.GetConsumersToBeStopped(ctx, stopTime) + consumers, err = providerKeeper.GetConsumersToBeRemoved(ctx, removalTime) require.NoError(t, err) require.Empty(t, consumers.Ids) - // remove from `stopTimePlusOneHour` - err = providerKeeper.RemoveConsumerToBeStopped(ctx, "consumerId4", stopTimePlusOneHour) + // remove from `removalTimePlusOneHour` + err = providerKeeper.RemoveConsumerToBeRemoved(ctx, "consumerId4", removalTimePlusOneHour) require.NoError(t, err) - consumers, err = providerKeeper.GetConsumersToBeStopped(ctx, stopTimePlusOneHour) + consumers, err = providerKeeper.GetConsumersToBeRemoved(ctx, removalTimePlusOneHour) require.NoError(t, err) require.Empty(t, consumers.Ids) - // add another consumer for `stopTime` - err = providerKeeper.AppendConsumerToBeStopped(ctx, "consumerId5", stopTime) + // add another consumer for `removalTime` + err = providerKeeper.AppendConsumerToBeRemoved(ctx, "consumerId5", removalTime) require.NoError(t, err) - consumers, err = providerKeeper.GetConsumersToBeStopped(ctx, stopTime) + consumers, err = providerKeeper.GetConsumersToBeRemoved(ctx, removalTime) require.NoError(t, err) require.Equal(t, []string{"consumerId5"}, consumers.Ids) } diff --git a/x/ccv/provider/keeper/msg_server.go b/x/ccv/provider/keeper/msg_server.go index ed74b8f9d8..b24e09ae4d 100644 --- a/x/ccv/provider/keeper/msg_server.go +++ b/x/ccv/provider/keeper/msg_server.go @@ -343,7 +343,7 @@ func (k msgServer) CreateConsumer(goCtx context.Context, msg *types.MsgCreateCon return &resp, nil } -// UpdateConsumer updates the record of a consumer chain +// UpdateConsumer updates the metadata, power-shaping or initialization parameters of a consumer chain func (k msgServer) UpdateConsumer(goCtx context.Context, msg *types.MsgUpdateConsumer) (*types.MsgUpdateConsumerResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) resp := types.MsgUpdateConsumerResponse{} @@ -473,7 +473,7 @@ func (k msgServer) RemoveConsumer(goCtx context.Context, msg *types.MsgRemoveCon "chain with consumer id: %s has to be in its launched phase", consumerId) } - err = k.Keeper.StopAndPrepareForConsumerDeletion(ctx, consumerId) + err = k.Keeper.StopAndPrepareForConsumerRemoval(ctx, consumerId) return &resp, err } diff --git a/x/ccv/provider/keeper/permissionless.go b/x/ccv/provider/keeper/permissionless.go index ecedda108d..039b016ffd 100644 --- a/x/ccv/provider/keeper/permissionless.go +++ b/x/ccv/provider/keeper/permissionless.go @@ -119,11 +119,11 @@ func (k Keeper) GetConsumerInitializationParameters(ctx sdk.Context, consumerId if bz == nil { return types.ConsumerInitializationParameters{}, fmt.Errorf("failed to retrieve initialization parameters for consumer id (%s)", consumerId) } - var record types.ConsumerInitializationParameters - if err := record.Unmarshal(bz); err != nil { - return types.ConsumerInitializationParameters{}, fmt.Errorf("failed to unmarshal stop time for consumer id (%s): %w", consumerId, err) + var initializationParameters types.ConsumerInitializationParameters + if err := initializationParameters.Unmarshal(bz); err != nil { + return types.ConsumerInitializationParameters{}, fmt.Errorf("failed to unmarshal initialization parameters for consumer id (%s): %w", consumerId, err) } - return record, nil + return initializationParameters, nil } // SetConsumerInitializationParameters sets the initialization parameters associated with this consumer id diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index ad26912013..b0a9024528 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -30,7 +30,7 @@ func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Pac "error", err, ) if consumerId, ok := k.GetChannelIdToConsumerId(ctx, packet.SourceChannel); ok { - return k.StopAndPrepareForConsumerDeletion(ctx, consumerId) + return k.StopAndPrepareForConsumerRemoval(ctx, consumerId) } return errorsmod.Wrapf(providertypes.ErrUnknownConsumerChannelId, "recv ErrorAcknowledgement on unknown channel %s", packet.SourceChannel) } @@ -50,7 +50,7 @@ func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet) err ) } k.Logger(ctx).Info("packet timeout, deleting the consumer:", "consumerId", consumerId) - return k.StopAndPrepareForConsumerDeletion(ctx, consumerId) + return k.StopAndPrepareForConsumerRemoval(ctx, consumerId) } // EndBlockVSU contains the EndBlock logic needed for @@ -166,7 +166,7 @@ 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()) - err := k.StopAndPrepareForConsumerDeletion(ctx, consumerId) + err := k.StopAndPrepareForConsumerRemoval(ctx, consumerId) if err != nil { k.Logger(ctx).Info("consumer chain failed to stop:", "consumerId", consumerId, "error", err.Error()) } diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index 4bd95b7d0f..088590f206 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -514,13 +514,13 @@ func TestSendVSCPacketsToChainFailure(t *testing.T) { providerKeeper.SendVSCPacketsToChain(ctx, "consumerId", "CCVChannelID") // Verify the chain is about to be deleted - stopTime, err := providerKeeper.GetConsumerStopTime(ctx, "consumerId") + removalTime, err := providerKeeper.GetConsumerRemovalTime(ctx, "consumerId") require.NoError(t, err) - require.Equal(t, ctx.BlockTime().Add(unbondingTime), stopTime) + require.Equal(t, ctx.BlockTime().Add(unbondingTime), removalTime) // Increase the block time by `unbondingTime` so the chain actually gets deleted ctx = ctx.WithBlockTime(ctx.BlockTime().Add(unbondingTime)) - providerKeeper.BeginBlockStopConsumers(ctx) + providerKeeper.BeginBlockRemoveConsumers(ctx) // Pending VSC packets should be deleted in DeleteConsumerChain require.Empty(t, providerKeeper.GetPendingVSCPackets(ctx, "consumerId")) @@ -570,7 +570,7 @@ func TestOnTimeoutPacketStopsChain(t *testing.T) { // increase the block time by `unbondingTime` so the chain actually gets deleted ctx = ctx.WithBlockTime(ctx.BlockTime().Add(unbondingTime)) - providerKeeper.BeginBlockStopConsumers(ctx) + providerKeeper.BeginBlockRemoveConsumers(ctx) testkeeper.TestProviderStateIsCleanedAfterConsumerChainIsDeleted(t, ctx, providerKeeper, "consumerId", "channelID", false) } @@ -621,7 +621,7 @@ func TestOnAcknowledgementPacketWithAckError(t *testing.T) { // increase the block time by `unbondingTime` so the chain actually gets deleted ctx = ctx.WithBlockTime(ctx.BlockTime().Add(unbondingTime)) - providerKeeper.BeginBlockStopConsumers(ctx) + providerKeeper.BeginBlockRemoveConsumers(ctx) testkeeper.TestProviderStateIsCleanedAfterConsumerChainIsDeleted(t, ctx, providerKeeper, "consumerId", "channelID", false) } diff --git a/x/ccv/provider/module.go b/x/ccv/provider/module.go index 30ac49363a..2f089509ee 100644 --- a/x/ccv/provider/module.go +++ b/x/ccv/provider/module.go @@ -176,7 +176,7 @@ func (am AppModule) BeginBlock(ctx context.Context) error { // Create clients to consumer chains that are due to be spawned am.keeper.BeginBlockLaunchConsumers(sdkCtx) // Stop and remove state for any consumer chains that are due to be stopped - am.keeper.BeginBlockStopConsumers(sdkCtx) + am.keeper.BeginBlockRemoveConsumers(sdkCtx) // Check for replenishing slash meter before any slash packets are processed for this block am.keeper.BeginBlockCIS(sdkCtx) // BeginBlock logic needed for the Reward Distribution sub-protocol diff --git a/x/ccv/provider/types/errors.go b/x/ccv/provider/types/errors.go index b4fe49942f..933e363f73 100644 --- a/x/ccv/provider/types/errors.go +++ b/x/ccv/provider/types/errors.go @@ -36,7 +36,7 @@ var ( ErrInvalidTransformToOptIn = errorsmod.Register(ModuleName, 40, "invalid transform to Opt In chain") ErrCannotCreateTopNChain = errorsmod.Register(ModuleName, 41, "cannot create Top N chain outside permissionlessly") ErrCannotPrepareForLaunch = errorsmod.Register(ModuleName, 42, "cannot prepare chain for launch") - ErrInvalidStopTime = errorsmod.Register(ModuleName, 43, "invalid stop time") + ErrInvalidRemovalTime = errorsmod.Register(ModuleName, 43, "invalid removal time") ErrInvalidMsgCreateConsumer = errorsmod.Register(ModuleName, 44, "invalid create consumer message") ErrInvalidMsgUpdateConsumer = errorsmod.Register(ModuleName, 45, "invalid update consumer message") ErrInvalidMsgAssignConsumerKey = errorsmod.Register(ModuleName, 46, "invalid assign consumer key message") diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index 5f6010d260..ef7eae0172 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -139,11 +139,11 @@ const ( ConsumerIdToPhaseKeyName = "ConsumerIdToPhaseKey" - ConsumerIdToStopTimeKeyName = "ConsumerIdToStopTimeKey" + ConsumerIdToRemovalTimeKeyName = "ConsumerIdToRemovalTimeKey" SpawnTimeToConsumerIdsKeyName = "SpawnTimeToConsumerIdsKeyName" - StopTimeToConsumerIdsKeyName = "StopTimeToConsumerIdsKeyName" + RemovalTimeToConsumerIdsKeyName = "RemovalTimeToConsumerIdsKeyName" ProviderConsAddrToOptedInConsumerIdsKeyName = "ProviderConsAddrToOptedInConsumerIdsKeyName" @@ -364,16 +364,16 @@ func getKeyPrefixes() map[string]byte { // ConsumerIdToPhaseKeyName is the key for storing the phase of a consumer chain with the given consumer id ConsumerIdToPhaseKeyName: 49, - // ConsumerIdToStopTimeKeyName is the key for storing the stop time of a consumer chain that is to be removed - ConsumerIdToStopTimeKeyName: 50, + // ConsumerIdToRemovalTimeKeyName is the key for storing the removal time of a consumer chain that is to be removed + ConsumerIdToRemovalTimeKeyName: 50, // SpawnTimeToConsumerIdKeyName is the key for storing pending initialized consumers that are to be launched. // For a specific spawn time, it might store multiple consumer chain ids for chains that are to be launched. SpawnTimeToConsumerIdsKeyName: 51, - // StopTimeToConsumerIdKeyName is the key for storing pending launched consumers that are to be stopped. - // For a specific stop time, it might store multiple consumer chain ids for chains that are to be stopped. - StopTimeToConsumerIdsKeyName: 52, + // RemovalTimeToConsumerIdsKeyName is the key for storing pending launched consumers that are to be removed. + // For a specific removal time, it might store multiple consumer chain ids for chains that are to be removed. + RemovalTimeToConsumerIdsKeyName: 52, // ProviderConsAddrToOptedInConsumerIdsKeyName is the key for storing all the consumer ids that a validator // is currently opted in to. @@ -665,17 +665,17 @@ func ConsumerIdToMetadataKey(consumerId string) []byte { return StringIdWithLenKey(ConsumerIdToMetadataKeyPrefix(), consumerId) } -// ConsumerIdToInitializationParametersKeyPrefix returns the key prefix for storing consumer initialization records +// ConsumerIdToInitializationParametersKeyPrefix returns the key prefix for storing consumer initialization parameters func ConsumerIdToInitializationParametersKeyPrefix() byte { return mustGetKeyPrefix(ConsumerIdToInitializationParametersKeyName) } -// ConsumerIdToInitializationParametersKey returns the key used to store the initialization record that corresponds to this consumer id +// ConsumerIdToInitializationParametersKey returns the key used to store the initialization parameters that corresponds to this consumer id func ConsumerIdToInitializationParametersKey(consumerId string) []byte { return StringIdWithLenKey(ConsumerIdToInitializationParametersKeyPrefix(), consumerId) } -// ConsumerIdToPowerShapingParametersKey returns the key used to store the update record that corresponds to this consumer id +// ConsumerIdToPowerShapingParametersKey returns the key used to store the power-shaping parameters that corresponds to this consumer id func ConsumerIdToPowerShapingParametersKey(consumerId string) []byte { return StringIdWithLenKey(mustGetKeyPrefix(ConsumerIdToPowerShapingParameters), consumerId) } @@ -685,15 +685,15 @@ func ConsumerIdToPhaseKey(consumerId string) []byte { return StringIdWithLenKey(mustGetKeyPrefix(ConsumerIdToPhaseKeyName), consumerId) } -// ConsumerIdToStopTimeKeyPrefix returns the key prefix for storing the stop times of consumer chains -// that are about to be stopped -func ConsumerIdToStopTimeKeyPrefix() byte { - return mustGetKeyPrefix(ConsumerIdToStopTimeKeyName) +// ConsumerIdToRemovalTimeKeyPrefix returns the key prefix for storing the removal times of consumer chains +// that are about to be removed +func ConsumerIdToRemovalTimeKeyPrefix() byte { + return mustGetKeyPrefix(ConsumerIdToRemovalTimeKeyName) } -// ConsumerIdToStopTimeKey returns the key used to store the stop time that corresponds to a to-be-stopped chain with consumer id -func ConsumerIdToStopTimeKey(consumerId string) []byte { - return StringIdWithLenKey(ConsumerIdToStopTimeKeyPrefix(), consumerId) +// ConsumerIdToRemovalTimeKey returns the key used to store the removal time that corresponds to a to-be-removed chain with consumer id +func ConsumerIdToRemovalTimeKey(consumerId string) []byte { + return StringIdWithLenKey(ConsumerIdToRemovalTimeKeyPrefix(), consumerId) } // SpawnTimeToConsumerIdsKeyPrefix returns the key prefix for storing pending chains that are to be launched @@ -712,17 +712,17 @@ func SpawnTimeToConsumerIdsKey(spawnTime time.Time) []byte { ) } -// StopTimeToConsumerIdsKeyPrefix returns the key prefix for storing pending chains that are to be stopped -func StopTimeToConsumerIdsKeyPrefix() byte { - return mustGetKeyPrefix(StopTimeToConsumerIdsKeyName) +// RemovalTimeToConsumerIdsKeyPrefix returns the key prefix for storing pending chains that are to be removed +func RemovalTimeToConsumerIdsKeyPrefix() byte { + return mustGetKeyPrefix(RemovalTimeToConsumerIdsKeyName) } -// StopTimeToConsumerIdsKey returns the key prefix for storing the stop times of consumer chains -// that are about to be stopped -func StopTimeToConsumerIdsKey(spawnTime time.Time) []byte { +// RemovalTimeToConsumerIdsKey returns the key prefix for storing the removal times of consumer chains +// that are about to be removed +func RemovalTimeToConsumerIdsKey(spawnTime time.Time) []byte { return ccvtypes.AppendMany( // append the prefix - []byte{StopTimeToConsumerIdsKeyPrefix()}, + []byte{RemovalTimeToConsumerIdsKeyPrefix()}, // append the time sdk.FormatTimeBytes(spawnTime), ) diff --git a/x/ccv/provider/types/keys_test.go b/x/ccv/provider/types/keys_test.go index 741b036c78..92ec762845 100644 --- a/x/ccv/provider/types/keys_test.go +++ b/x/ccv/provider/types/keys_test.go @@ -134,11 +134,11 @@ func TestPreserveBytePrefix(t *testing.T) { i++ require.Equal(t, byte(49), providertypes.ConsumerIdToPhaseKey("13")[0]) i++ - require.Equal(t, byte(50), providertypes.ConsumerIdToStopTimeKeyPrefix()) + require.Equal(t, byte(50), providertypes.ConsumerIdToRemovalTimeKeyPrefix()) i++ require.Equal(t, byte(51), providertypes.SpawnTimeToConsumerIdsKeyPrefix()) i++ - require.Equal(t, byte(52), providertypes.StopTimeToConsumerIdsKeyPrefix()) + require.Equal(t, byte(52), providertypes.RemovalTimeToConsumerIdsKeyPrefix()) i++ require.Equal(t, byte(53), providertypes.ProviderConsAddrToOptedInConsumerIdsKey(providertypes.NewProviderConsAddress([]byte{0x05}))[0]) i++ @@ -208,9 +208,9 @@ func getAllFullyDefinedKeys() [][]byte { providertypes.ConsumerIdToInitializationParametersKey("13"), providertypes.ConsumerIdToPowerShapingParametersKey("13"), providertypes.ConsumerIdToPhaseKey("13"), - providertypes.ConsumerIdToStopTimeKey("13"), + providertypes.ConsumerIdToRemovalTimeKey("13"), providertypes.SpawnTimeToConsumerIdsKey(time.Time{}), - providertypes.StopTimeToConsumerIdsKey(time.Time{}), + providertypes.RemovalTimeToConsumerIdsKey(time.Time{}), providertypes.ProviderConsAddrToOptedInConsumerIdsKey(providertypes.NewProviderConsAddress([]byte{0x05})), providertypes.ClientIdToConsumerIdKey("clientId"), } From 48175e8c53d2c687173e271a9e5fbc9fea33600d Mon Sep 17 00:00:00 2001 From: mpoke Date: Tue, 3 Sep 2024 19:30:01 +0200 Subject: [PATCH 03/11] fix errors in tests --- x/ccv/provider/keeper/relay_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index dbc4551812..9e50efde63 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -130,7 +130,7 @@ func TestQueueVSCPacketsDoesNotResetConsumerValidatorsHeights(t *testing.T) { err := providerKeeper.SetConsumerPowerShapingParameters(ctx, "consumerId", providertypes.PowerShapingParameters{}) require.NoError(t, err) - err := providerKeeper.QueueVSCPackets(ctx) + err = providerKeeper.QueueVSCPackets(ctx) require.NoError(t, err) // the height of consumer validator A should not be modified because A was already a consumer validator @@ -674,7 +674,7 @@ func TestEndBlockVSU(t *testing.T) { // with block height of 1 we do not expect any queueing of VSC packets ctx = ctx.WithBlockHeight(1) - _, err := providerKeeper.EndBlockVSU(ctx) + _, err = providerKeeper.EndBlockVSU(ctx) require.NoError(t, err) require.Equal(t, 0, len(providerKeeper.GetPendingVSCPackets(ctx, consumerId))) @@ -821,7 +821,7 @@ func TestQueueVSCPacketsWithPowerCapping(t *testing.T) { params.MaxProviderConsensusValidators = 180 providerKeeper.SetParams(ctx, params) - err := providerKeeper.QueueVSCPackets(ctx) + err = providerKeeper.QueueVSCPackets(ctx) require.NoError(t, err) actualQueuedVSCPackets := providerKeeper.GetPendingVSCPackets(ctx, "consumerId") From 1186fa9a17be471b4b7222b557f9ed85d5290177 Mon Sep 17 00:00:00 2001 From: mpoke Date: Wed, 4 Sep 2024 09:43:44 +0200 Subject: [PATCH 04/11] add GetAllConsumerWithIBCClients --- x/ccv/provider/keeper/genesis.go | 4 ++-- x/ccv/provider/keeper/grpc_query_test.go | 1 - x/ccv/provider/keeper/keeper.go | 4 ++-- x/ccv/provider/keeper/keeper_test.go | 4 ++-- x/ccv/provider/keeper/relay.go | 4 ++++ x/ccv/provider/migrations/v6/migrations.go | 1 + 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/x/ccv/provider/keeper/genesis.go b/x/ccv/provider/keeper/genesis.go index 939812658a..662297d8f3 100644 --- a/x/ccv/provider/keeper/genesis.go +++ b/x/ccv/provider/keeper/genesis.go @@ -119,13 +119,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 { - launchedConsumerIds := k.GetAllLaunchedConsumerIds(ctx) + launchedConsumerIds := k.GetAllConsumerWithIBCClients(ctx) // export states for each consumer chains var consumerStates []types.ConsumerState for _, consumerId := range launchedConsumerIds { // no need for the second return value of GetConsumerClientId - // as GetAllLaunchedConsumerIds already iterated through + // as GetAllConsumerWithIBCClients already iterated through // the entire prefix range clientId, _ := k.GetConsumerClientId(ctx, consumerId) gen, found := k.GetConsumerGenesis(ctx, consumerId) diff --git a/x/ccv/provider/keeper/grpc_query_test.go b/x/ccv/provider/keeper/grpc_query_test.go index 541ba50f96..5c55979dfa 100644 --- a/x/ccv/provider/keeper/grpc_query_test.go +++ b/x/ccv/provider/keeper/grpc_query_test.go @@ -303,7 +303,6 @@ func TestQueryConsumerChainsValidatorHasToValidate(t *testing.T) { ProviderAddress: providerAddr.String(), } - consumerNum := 4 consumerIds := make([]string, consumerNum) diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index 34058f4ed1..e45a4a9c4a 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -211,8 +211,8 @@ func (k Keeper) DeleteConsumerIdToChannelId(ctx sdk.Context, consumerId string) store.Delete(types.ConsumerIdToChannelIdKey(consumerId)) } -// GetAllLaunchedConsumerIds returns all consumer ids of chains that are currently launched. -func (k Keeper) GetAllLaunchedConsumerIds(ctx sdk.Context) []string { +// GetAllConsumerWithIBCClients returns all ids of consumer chains that with IBC clients created. +func (k Keeper) GetAllConsumerWithIBCClients(ctx sdk.Context) []string { consumerIds := []string{} // All launched chains have created an IBC client when they launched (see `LaunchConsumer`), so we traverse over diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 271cc1da0c..271436e534 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -223,7 +223,7 @@ func TestInitHeight(t *testing.T) { } } -func TestGetAllLaunchedConsumerIds(t *testing.T) { +func TestGetAllConsumerWithIBCClients(t *testing.T) { pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() @@ -234,7 +234,7 @@ func TestGetAllLaunchedConsumerIds(t *testing.T) { pk.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) } - actualConsumerIds := pk.GetAllLaunchedConsumerIds(ctx) + actualConsumerIds := pk.GetAllConsumerWithIBCClients(ctx) require.Len(t, actualConsumerIds, len(consumerIds)) // sort the consumer ids before comparing they are equal diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index 3398c3cf87..425ef02a66 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -139,6 +139,8 @@ func (k Keeper) BlocksUntilNextEpoch(ctx sdk.Context) int64 { // VSC packets to the chains with established CCV channels. // If the CCV channel is not established for a consumer chain, // the updates will remain queued until the channel is established +// +// TODO (mpoke): iterate only over consumers with established channel func (k Keeper) SendVSCPackets(ctx sdk.Context) error { for _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { // check if CCV channel is established and send @@ -193,6 +195,8 @@ func (k Keeper) SendVSCPacketsToChain(ctx sdk.Context, consumerId, channelId str } // QueueVSCPackets queues latest validator updates for every registered consumer chain +// +// TODO (mpoke): iterate only over consumers with established channel func (k Keeper) QueueVSCPackets(ctx sdk.Context) error { valUpdateID := k.GetValidatorSetUpdateId(ctx) // current valset update ID diff --git a/x/ccv/provider/migrations/v6/migrations.go b/x/ccv/provider/migrations/v6/migrations.go index 730cbdca30..463001abec 100644 --- a/x/ccv/provider/migrations/v6/migrations.go +++ b/x/ccv/provider/migrations/v6/migrations.go @@ -16,6 +16,7 @@ func MigrateParams(ctx sdk.Context, paramsSubspace paramtypes.Subspace) { paramsSubspace.Set(ctx, providertypes.KeyNumberOfEpochsToStartReceivingRewards, providertypes.DefaultNumberOfEpochsToStartReceivingRewards) } +// TODO (PERMISSIONLESS): this migration needs to be fix or removed 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 From 060bf608ea848d71d653cb75a530866f76e2d122 Mon Sep 17 00:00:00 2001 From: mpoke Date: Wed, 4 Sep 2024 11:09:45 +0200 Subject: [PATCH 05/11] use GetAllConsumerWithIBCClients for efficiency --- x/ccv/provider/keeper/distribution.go | 6 ++++-- x/ccv/provider/keeper/grpc_query.go | 4 +++- x/ccv/provider/keeper/grpc_query_test.go | 5 +++++ x/ccv/provider/keeper/relay.go | 13 +++++++------ x/ccv/provider/keeper/relay_test.go | 4 ++-- x/ccv/provider/migrations/v5/migrations.go | 2 ++ 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/x/ccv/provider/keeper/distribution.go b/x/ccv/provider/keeper/distribution.go index 8d687da363..7cedcb22af 100644 --- a/x/ccv/provider/keeper/distribution.go +++ b/x/ccv/provider/keeper/distribution.go @@ -74,8 +74,10 @@ func (k Keeper) AllocateTokens(ctx sdk.Context) { return } - // Iterate over all launched consumer chains - for _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { + // Iterate over all launched consumer chains. + // To avoid large iterations over all the consumer IDs, iterate only over + // chains with an IBC client created. + for _, consumerId := range k.GetAllConsumerWithIBCClients(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 diff --git a/x/ccv/provider/keeper/grpc_query.go b/x/ccv/provider/keeper/grpc_query.go index 08c93fae08..5b2427b3ec 100644 --- a/x/ccv/provider/keeper/grpc_query.go +++ b/x/ccv/provider/keeper/grpc_query.go @@ -424,7 +424,9 @@ 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 _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { + // To avoid large iterations over all the consumer IDs, iterate only over + // chains with an IBC client created. + for _, consumerId := range k.GetAllConsumerWithIBCClients(ctx) { if hasToValidate, err := k.hasToValidate(ctx, provAddr, consumerId); err == nil && hasToValidate { consumersToValidate = append(consumersToValidate, consumerId) } diff --git a/x/ccv/provider/keeper/grpc_query_test.go b/x/ccv/provider/keeper/grpc_query_test.go index 5c55979dfa..0cdd7ebeec 100644 --- a/x/ccv/provider/keeper/grpc_query_test.go +++ b/x/ccv/provider/keeper/grpc_query_test.go @@ -319,6 +319,11 @@ func TestQueryConsumerChainsValidatorHasToValidate(t *testing.T) { resp, err := msgServer.CreateConsumer(ctx, &msg) require.NoError(t, err) consumerId := resp.ConsumerId + + // set a consumer client id, so that `GetAllConsumerWithIBCClients` is non-empty + clientID := "client-" + strconv.Itoa(i) + pk.SetConsumerClientId(ctx, consumerId, clientID) + pk.SetConsumerPhase(ctx, consumerId, types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) consumerIds[i] = consumerId } diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index 425ef02a66..ff13d8f222 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -135,14 +135,14 @@ func (k Keeper) BlocksUntilNextEpoch(ctx sdk.Context) int64 { } } -// SendVSCPackets iterates over all registered consumers and sends pending -// VSC packets to the chains with established CCV channels. +// SendVSCPackets iterates over all consumers chains with created IBC clients +// and sends pending VSC packets to the chains with established CCV channels. // If the CCV channel is not established for a consumer chain, // the updates will remain queued until the channel is established // // TODO (mpoke): iterate only over consumers with established channel func (k Keeper) SendVSCPackets(ctx sdk.Context) error { - for _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { + for _, consumerId := range k.GetAllConsumerWithIBCClients(ctx) { // check if CCV channel is established and send if channelID, found := k.GetConsumerIdToChannelId(ctx, consumerId); found { if err := k.SendVSCPacketsToChain(ctx, consumerId, channelID); err != nil { @@ -194,7 +194,8 @@ func (k Keeper) SendVSCPacketsToChain(ctx sdk.Context, consumerId, channelId str return nil } -// QueueVSCPackets queues latest validator updates for every registered consumer chain +// QueueVSCPackets queues latest validator updates for every consumer chain +// with the IBC client created. // // TODO (mpoke): iterate only over consumers with established channel func (k Keeper) QueueVSCPackets(ctx sdk.Context) error { @@ -212,7 +213,7 @@ func (k Keeper) QueueVSCPackets(ctx sdk.Context) error { return fmt.Errorf("getting provider active validators: %w", err) } - for _, consumerId := range k.GetAllLaunchedConsumerIds(ctx) { + for _, consumerId := range k.GetAllConsumerWithIBCClients(ctx) { currentValidators, err := k.GetConsumerValSet(ctx, consumerId) if err != nil { return fmt.Errorf("getting consumer validators, consumerId(%s): %w", consumerId, err) @@ -285,7 +286,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.GetAllLaunchedConsumerIds(ctx) { + for _, consumerId := range k.GetAllConsumerWithIBCClients(ctx) { k.PruneKeyAssignments(ctx, consumerId) } } diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index 9e50efde63..78aa291f59 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -108,7 +108,7 @@ 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 id and its phase, so we have a consumer chain (i.e., `GetAllLaunchedConsumerIds` is non-empty) + // set a consumer client id and its phase, so we have a consumer chain (i.e., `GetAllConsumerWithIBCClients` is non-empty) providerKeeper.SetConsumerClientId(ctx, "consumerId", "clientID") providerKeeper.SetConsumerPhase(ctx, "consumerId", providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) @@ -667,7 +667,7 @@ func TestEndBlockVSU(t *testing.T) { }) mocks.MockStakingKeeper.EXPECT().GetBondedValidatorsByPower(gomock.Any()).Return(lastValidators, nil).AnyTimes() - // set a sample client for a launched consumer chain so that `GetAllLaunchedConsumerIds` in `QueueVSCPackets` iterates at least once + // set a sample client for a launched consumer chain so that `GetAllConsumerWithIBCClients` 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) diff --git a/x/ccv/provider/migrations/v5/migrations.go b/x/ccv/provider/migrations/v5/migrations.go index 32da11db85..d9dd416e09 100644 --- a/x/ccv/provider/migrations/v5/migrations.go +++ b/x/ccv/provider/migrations/v5/migrations.go @@ -10,6 +10,8 @@ import ( // This migration only takes already registered chains into account. // If a chain is in voting while the upgrade happens, this is not sufficient, // and a migration to rewrite the proposal is needed. +// +// TODO (PERMISSIONLESS): this migration needs to be fix or removed func MigrateTopNForRegisteredChains(ctx sdk.Context, providerKeeper providerkeeper.Keeper) { // Set the topN of each chain to 95 for _, consumerId := range providerKeeper.GetAllLaunchedConsumerIds(ctx) { From 8457336d4a8e696fcdf71c2f3eabdcc35baa0ff2 Mon Sep 17 00:00:00 2001 From: mpoke Date: Wed, 4 Sep 2024 11:10:57 +0200 Subject: [PATCH 06/11] fix UTs --- x/ccv/provider/migrations/v5/migrations.go | 2 +- x/ccv/provider/migrations/v6/migrations.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x/ccv/provider/migrations/v5/migrations.go b/x/ccv/provider/migrations/v5/migrations.go index d9dd416e09..d5e23e23a0 100644 --- a/x/ccv/provider/migrations/v5/migrations.go +++ b/x/ccv/provider/migrations/v5/migrations.go @@ -14,7 +14,7 @@ import ( // TODO (PERMISSIONLESS): this migration needs to be fix or removed func MigrateTopNForRegisteredChains(ctx sdk.Context, providerKeeper providerkeeper.Keeper) { // Set the topN of each chain to 95 - for _, consumerId := range providerKeeper.GetAllLaunchedConsumerIds(ctx) { + for _, consumerId := range providerKeeper.GetAllConsumerWithIBCClients(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 463001abec..6752b93d18 100644 --- a/x/ccv/provider/migrations/v6/migrations.go +++ b/x/ccv/provider/migrations/v6/migrations.go @@ -20,7 +20,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.GetAllLaunchedConsumerIds(ctx) + registeredConsumerChains := providerKeeper.GetAllConsumerWithIBCClients(ctx) for _, chain := range registeredConsumerChains { // get the top N From 2f7e04c83cd03beabc3fdf2af5fa4ec2096d65d9 Mon Sep 17 00:00:00 2001 From: mpoke Date: Wed, 4 Sep 2024 11:15:46 +0200 Subject: [PATCH 07/11] remove GetAllLaunchedConsumerIds as not needed --- x/ccv/provider/keeper/keeper.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index e45a4a9c4a..187d62ab00 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -742,18 +742,6 @@ func (k Keeper) GetAllActiveConsumerIds(ctx sdk.Context) []string { return consumerIds } -// GetAllLaunchedConsumerIds returns all the consumer ids of chains that are launched -func (k Keeper) GetAllLaunchedConsumerIds(ctx sdk.Context) []string { - consumerIds := []string{} - for _, consumerId := range k.GetAllConsumerIds(ctx) { - if phase := k.GetConsumerPhase(ctx, consumerId); phase != types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED { - continue - } - consumerIds = append(consumerIds, consumerId) - } - return consumerIds -} - func (k Keeper) SetOptedIn( ctx sdk.Context, consumerId string, From e41f7fde1752a12c11c672343fb1f9284180b4fb Mon Sep 17 00:00:00 2001 From: mpoke Date: Wed, 4 Sep 2024 11:28:18 +0200 Subject: [PATCH 08/11] typo in GetAllConsumersWithIBCClients --- x/ccv/provider/keeper/distribution.go | 2 +- x/ccv/provider/keeper/genesis.go | 4 ++-- x/ccv/provider/keeper/grpc_query.go | 2 +- x/ccv/provider/keeper/grpc_query_test.go | 2 +- x/ccv/provider/keeper/keeper.go | 4 ++-- x/ccv/provider/keeper/keeper_test.go | 4 ++-- x/ccv/provider/keeper/relay.go | 6 +++--- x/ccv/provider/keeper/relay_test.go | 4 ++-- x/ccv/provider/migrations/v5/migrations.go | 2 +- x/ccv/provider/migrations/v6/migrations.go | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/x/ccv/provider/keeper/distribution.go b/x/ccv/provider/keeper/distribution.go index 7cedcb22af..db75ff9b6e 100644 --- a/x/ccv/provider/keeper/distribution.go +++ b/x/ccv/provider/keeper/distribution.go @@ -77,7 +77,7 @@ func (k Keeper) AllocateTokens(ctx sdk.Context) { // Iterate over all launched consumer chains. // To avoid large iterations over all the consumer IDs, iterate only over // chains with an IBC client created. - for _, consumerId := range k.GetAllConsumerWithIBCClients(ctx) { + for _, consumerId := range k.GetAllConsumersWithIBCClients(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 diff --git a/x/ccv/provider/keeper/genesis.go b/x/ccv/provider/keeper/genesis.go index 662297d8f3..7e8fd4bb76 100644 --- a/x/ccv/provider/keeper/genesis.go +++ b/x/ccv/provider/keeper/genesis.go @@ -119,13 +119,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 { - launchedConsumerIds := k.GetAllConsumerWithIBCClients(ctx) + launchedConsumerIds := k.GetAllConsumersWithIBCClients(ctx) // export states for each consumer chains var consumerStates []types.ConsumerState for _, consumerId := range launchedConsumerIds { // no need for the second return value of GetConsumerClientId - // as GetAllConsumerWithIBCClients already iterated through + // as GetAllConsumersWithIBCClients already iterated through // the entire prefix range clientId, _ := k.GetConsumerClientId(ctx, consumerId) gen, found := k.GetConsumerGenesis(ctx, consumerId) diff --git a/x/ccv/provider/keeper/grpc_query.go b/x/ccv/provider/keeper/grpc_query.go index 5b2427b3ec..3325ffd193 100644 --- a/x/ccv/provider/keeper/grpc_query.go +++ b/x/ccv/provider/keeper/grpc_query.go @@ -426,7 +426,7 @@ func (k Keeper) QueryConsumerChainsValidatorHasToValidate(goCtx context.Context, consumersToValidate := []string{} // To avoid large iterations over all the consumer IDs, iterate only over // chains with an IBC client created. - for _, consumerId := range k.GetAllConsumerWithIBCClients(ctx) { + for _, consumerId := range k.GetAllConsumersWithIBCClients(ctx) { if hasToValidate, err := k.hasToValidate(ctx, provAddr, consumerId); err == nil && hasToValidate { consumersToValidate = append(consumersToValidate, consumerId) } diff --git a/x/ccv/provider/keeper/grpc_query_test.go b/x/ccv/provider/keeper/grpc_query_test.go index 0cdd7ebeec..f87c62c375 100644 --- a/x/ccv/provider/keeper/grpc_query_test.go +++ b/x/ccv/provider/keeper/grpc_query_test.go @@ -320,7 +320,7 @@ func TestQueryConsumerChainsValidatorHasToValidate(t *testing.T) { require.NoError(t, err) consumerId := resp.ConsumerId - // set a consumer client id, so that `GetAllConsumerWithIBCClients` is non-empty + // set a consumer client id, so that `GetAllConsumersWithIBCClients` is non-empty clientID := "client-" + strconv.Itoa(i) pk.SetConsumerClientId(ctx, consumerId, clientID) diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index 187d62ab00..04f4ca9051 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -211,8 +211,8 @@ func (k Keeper) DeleteConsumerIdToChannelId(ctx sdk.Context, consumerId string) store.Delete(types.ConsumerIdToChannelIdKey(consumerId)) } -// GetAllConsumerWithIBCClients returns all ids of consumer chains that with IBC clients created. -func (k Keeper) GetAllConsumerWithIBCClients(ctx sdk.Context) []string { +// GetAllConsumersWithIBCClients returns all ids of consumer chains that with IBC clients created. +func (k Keeper) GetAllConsumersWithIBCClients(ctx sdk.Context) []string { consumerIds := []string{} // All launched chains have created an IBC client when they launched (see `LaunchConsumer`), so we traverse over diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 271436e534..79d0b7fe8c 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -223,7 +223,7 @@ func TestInitHeight(t *testing.T) { } } -func TestGetAllConsumerWithIBCClients(t *testing.T) { +func TestGetAllConsumersWithIBCClients(t *testing.T) { pk, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() @@ -234,7 +234,7 @@ func TestGetAllConsumerWithIBCClients(t *testing.T) { pk.SetConsumerPhase(ctx, consumerId, providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) } - actualConsumerIds := pk.GetAllConsumerWithIBCClients(ctx) + actualConsumerIds := pk.GetAllConsumersWithIBCClients(ctx) require.Len(t, actualConsumerIds, len(consumerIds)) // sort the consumer ids before comparing they are equal diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index ff13d8f222..18b292d73e 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -142,7 +142,7 @@ func (k Keeper) BlocksUntilNextEpoch(ctx sdk.Context) int64 { // // TODO (mpoke): iterate only over consumers with established channel func (k Keeper) SendVSCPackets(ctx sdk.Context) error { - for _, consumerId := range k.GetAllConsumerWithIBCClients(ctx) { + for _, consumerId := range k.GetAllConsumersWithIBCClients(ctx) { // check if CCV channel is established and send if channelID, found := k.GetConsumerIdToChannelId(ctx, consumerId); found { if err := k.SendVSCPacketsToChain(ctx, consumerId, channelID); err != nil { @@ -213,7 +213,7 @@ func (k Keeper) QueueVSCPackets(ctx sdk.Context) error { return fmt.Errorf("getting provider active validators: %w", err) } - for _, consumerId := range k.GetAllConsumerWithIBCClients(ctx) { + for _, consumerId := range k.GetAllConsumersWithIBCClients(ctx) { currentValidators, err := k.GetConsumerValSet(ctx, consumerId) if err != nil { return fmt.Errorf("getting consumer validators, consumerId(%s): %w", consumerId, err) @@ -286,7 +286,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.GetAllConsumerWithIBCClients(ctx) { + for _, consumerId := range k.GetAllConsumersWithIBCClients(ctx) { k.PruneKeyAssignments(ctx, consumerId) } } diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index 78aa291f59..88ec9159e3 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -108,7 +108,7 @@ 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 id and its phase, so we have a consumer chain (i.e., `GetAllConsumerWithIBCClients` is non-empty) + // set a consumer client id and its phase, so we have a consumer chain (i.e., `GetAllConsumersWithIBCClients` is non-empty) providerKeeper.SetConsumerClientId(ctx, "consumerId", "clientID") providerKeeper.SetConsumerPhase(ctx, "consumerId", providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED) @@ -667,7 +667,7 @@ func TestEndBlockVSU(t *testing.T) { }) mocks.MockStakingKeeper.EXPECT().GetBondedValidatorsByPower(gomock.Any()).Return(lastValidators, nil).AnyTimes() - // set a sample client for a launched consumer chain so that `GetAllConsumerWithIBCClients` in `QueueVSCPackets` iterates at least once + // set a sample client for a launched consumer chain so that `GetAllConsumersWithIBCClients` 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) diff --git a/x/ccv/provider/migrations/v5/migrations.go b/x/ccv/provider/migrations/v5/migrations.go index d5e23e23a0..4c4ba3a988 100644 --- a/x/ccv/provider/migrations/v5/migrations.go +++ b/x/ccv/provider/migrations/v5/migrations.go @@ -14,7 +14,7 @@ import ( // TODO (PERMISSIONLESS): this migration needs to be fix or removed func MigrateTopNForRegisteredChains(ctx sdk.Context, providerKeeper providerkeeper.Keeper) { // Set the topN of each chain to 95 - for _, consumerId := range providerKeeper.GetAllConsumerWithIBCClients(ctx) { + for _, consumerId := range providerKeeper.GetAllConsumersWithIBCClients(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 6752b93d18..58c48915b9 100644 --- a/x/ccv/provider/migrations/v6/migrations.go +++ b/x/ccv/provider/migrations/v6/migrations.go @@ -20,7 +20,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.GetAllConsumerWithIBCClients(ctx) + registeredConsumerChains := providerKeeper.GetAllConsumersWithIBCClients(ctx) for _, chain := range registeredConsumerChains { // get the top N From ef5ca2b0fe7cc4428f5268c76d9e5bc58a8f5b24 Mon Sep 17 00:00:00 2001 From: mpoke Date: Wed, 4 Sep 2024 11:46:04 +0200 Subject: [PATCH 09/11] improve comment --- x/ccv/provider/keeper/keeper.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index 04f4ca9051..ee25626169 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -211,12 +211,12 @@ func (k Keeper) DeleteConsumerIdToChannelId(ctx sdk.Context, consumerId string) store.Delete(types.ConsumerIdToChannelIdKey(consumerId)) } -// GetAllConsumersWithIBCClients returns all ids of consumer chains that with IBC clients created. +// GetAllConsumersWithIBCClients returns the ids of all consumer chains that with IBC clients created. +// This is equivalent to getting the ids of all launched consumer chains: +// All launched chains have created an IBC client when they launched (see `LaunchConsumer`). func (k Keeper) GetAllConsumersWithIBCClients(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() From eef6bb8eaf3cba2d13d2f035b39eb9ad24c63bb9 Mon Sep 17 00:00:00 2001 From: insumity Date: Wed, 4 Sep 2024 14:15:34 +0200 Subject: [PATCH 10/11] Apply suggestions from code review Co-authored-by: Marius Poke --- x/ccv/provider/keeper/consumer_lifecycle.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x/ccv/provider/keeper/consumer_lifecycle.go b/x/ccv/provider/keeper/consumer_lifecycle.go index 5c927c7d05..b292e49ba4 100644 --- a/x/ccv/provider/keeper/consumer_lifecycle.go +++ b/x/ccv/provider/keeper/consumer_lifecycle.go @@ -369,7 +369,7 @@ func (k Keeper) StopAndPrepareForConsumerRemoval(ctx sdk.Context, consumerId str removalTime := ctx.BlockTime().Add(unbondingPeriod) if err := k.SetConsumerRemovalTime(ctx, consumerId, removalTime); err != nil { - return errorsmod.Wrapf(types.ErrInvalidRemovalTime, "cannot set removal time: %s", err.Error()) + return fmt.Errorf("cannot set removal time (%s): %s", removalTime.String(), err.Error()) } if err := k.AppendConsumerToBeRemoved(ctx, consumerId, removalTime); err != nil { return errorsmod.Wrapf(ccv.ErrInvalidConsumerState, "cannot set consumer to be removed: %s", err.Error()) @@ -393,7 +393,7 @@ func (k Keeper) BeginBlockRemoveConsumers(ctx sdk.Context) { // Remove consumer to prevent re-trying removing this chain. err = k.RemoveConsumerToBeRemoved(ctx, consumerId, removalTime) if err != nil { - ctx.Logger().Error("could not remove consumer from to-be-stopped queue", + ctx.Logger().Error("could not remove consumer from to-be-removed queue", "consumerId", consumerId, "error", err) continue @@ -403,7 +403,7 @@ func (k Keeper) BeginBlockRemoveConsumers(ctx sdk.Context) { cachedCtx, writeFn := ctx.CacheContext() err = k.DeleteConsumerChain(cachedCtx, consumerId) if err != nil { - k.Logger(ctx).Error("consumer chain could not be stopped", + k.Logger(ctx).Error("consumer chain could not be removed", "consumerId", consumerId, "error", err.Error()) continue @@ -444,7 +444,7 @@ func (k Keeper) GetConsumersReadyToStop(ctx sdk.Context, limit uint32) []string consumers, err := k.GetConsumersToBeRemoved(ctx, removalTime) if err != nil { - k.Logger(ctx).Error("failed to retrieve consumers to stop", + k.Logger(ctx).Error("failed to retrieve consumers to remove", "removal time", removalTime, "error", err) continue From e1adcc526aa08265582a325d1f88c820267fe479 Mon Sep 17 00:00:00 2001 From: insumity Date: Wed, 4 Sep 2024 15:04:53 +0200 Subject: [PATCH 11/11] took into account comments --- x/ccv/provider/keeper/consumer_lifecycle.go | 1 - x/ccv/provider/keeper/keeper.go | 9 +-------- x/ccv/provider/keeper/relay.go | 10 ++++++++++ x/ccv/provider/types/legacy_proposal.go | 1 + 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/x/ccv/provider/keeper/consumer_lifecycle.go b/x/ccv/provider/keeper/consumer_lifecycle.go index b292e49ba4..1dc3ef3d95 100644 --- a/x/ccv/provider/keeper/consumer_lifecycle.go +++ b/x/ccv/provider/keeper/consumer_lifecycle.go @@ -513,7 +513,6 @@ func (k Keeper) DeleteConsumerChain(ctx sdk.Context, consumerId string) (err err k.DeleteConsumerValSet(ctx, consumerId) k.DeleteConsumerRewardsAllocation(ctx, consumerId) - k.DeleteConsumerOwnerAddress(ctx, consumerId) k.DeleteConsumerRemovalTime(ctx, consumerId) // TODO (PERMISSIONLESS) add newly-added state to be deleted diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index ee25626169..4d60cf8dc9 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -212,8 +212,6 @@ func (k Keeper) DeleteConsumerIdToChannelId(ctx sdk.Context, consumerId string) } // GetAllConsumersWithIBCClients returns the ids of all consumer chains that with IBC clients created. -// This is equivalent to getting the ids of all launched consumer chains: -// All launched chains have created an IBC client when they launched (see `LaunchConsumer`). func (k Keeper) GetAllConsumersWithIBCClients(ctx sdk.Context) []string { consumerIds := []string{} @@ -224,12 +222,7 @@ func (k Keeper) GetAllConsumersWithIBCClients(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. - if k.GetConsumerPhase(ctx, consumerId) == types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED { - consumerIds = append(consumerIds, consumerId) - } + consumerIds = append(consumerIds, consumerId) } return consumerIds diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index 18b292d73e..f5e5216bb6 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -143,6 +143,11 @@ func (k Keeper) BlocksUntilNextEpoch(ctx sdk.Context) int64 { // TODO (mpoke): iterate only over consumers with established channel func (k Keeper) SendVSCPackets(ctx sdk.Context) error { for _, consumerId := range k.GetAllConsumersWithIBCClients(ctx) { + if k.GetConsumerPhase(ctx, consumerId) != providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED { + // only send VSCPackets to launched chains + continue + } + // check if CCV channel is established and send if channelID, found := k.GetConsumerIdToChannelId(ctx, consumerId); found { if err := k.SendVSCPacketsToChain(ctx, consumerId, channelID); err != nil { @@ -214,6 +219,11 @@ func (k Keeper) QueueVSCPackets(ctx sdk.Context) error { } for _, consumerId := range k.GetAllConsumersWithIBCClients(ctx) { + if k.GetConsumerPhase(ctx, consumerId) != providertypes.ConsumerPhase_CONSUMER_PHASE_LAUNCHED { + // only queue VSCPackets to launched chains + continue + } + currentValidators, err := k.GetConsumerValSet(ctx, consumerId) if err != nil { return fmt.Errorf("getting consumer validators, consumerId(%s): %w", consumerId, err) diff --git a/x/ccv/provider/types/legacy_proposal.go b/x/ccv/provider/types/legacy_proposal.go index b86c409109..9cc6ef2a77 100644 --- a/x/ccv/provider/types/legacy_proposal.go +++ b/x/ccv/provider/types/legacy_proposal.go @@ -136,6 +136,7 @@ func NewConsumerRemovalProposal(title, description, chainID string, stopTime tim Title: title, Description: description, ChainId: chainID, + StopTime: stopTime, } }