diff --git a/app/consumer-democracy/app.go b/app/consumer-democracy/app.go index f3ac4b024b..25eee224bc 100644 --- a/app/consumer-democracy/app.go +++ b/app/consumer-democracy/app.go @@ -785,6 +785,11 @@ func (app *App) GetE2eEvidenceKeeper() e2e.E2eEvidenceKeeper { return app.EvidenceKeeper } +// GetUpgradeKeeper implements the ConsumerApp interface. +func (app *App) GetUpgradeKeeper() upgradekeeper.Keeper { + return app.UpgradeKeeper +} + // GetE2eStakingKeeper implements the ConsumerApp interface. func (app *App) GetE2eStakingKeeper() e2e.E2eStakingKeeper { return app.StakingKeeper diff --git a/app/consumer/app.go b/app/consumer/app.go index 4cd1dee606..990af88103 100644 --- a/app/consumer/app.go +++ b/app/consumer/app.go @@ -679,6 +679,11 @@ func (app *App) GetE2eEvidenceKeeper() e2e.E2eEvidenceKeeper { return app.EvidenceKeeper } +// GetUpgradeKeeper implements the ConsumerApp interface. +func (app *App) GetUpgradeKeeper() upgradekeeper.Keeper { + return app.UpgradeKeeper +} + // TestingApp functions // GetBaseApp implements the TestingApp interface. diff --git a/docs/quality_assurance.md b/docs/quality_assurance.md index 45691f7528..3143393c92 100644 --- a/docs/quality_assurance.md +++ b/docs/quality_assurance.md @@ -49,10 +49,10 @@ IBC packets: | -- | ------- | ----------- | ------------ | ----------- | ------------- | ------- | | 2.01 | Create IBC clients | `Scheduled` (ibc-go) | `Done` [TestCreateConsumerClient](../x/ccv/provider/keeper/proposal_test.go#117), [TestInitGenesis](../x/ccv/consumer/keeper/genesis_test.go#26) | `Done` [SetupTest](../tests/e2e/setup_test.go#39), [TestConsumerGenesis](../tests/e2e/channel_init_test.go#21) | `Future work` | `Scheduled` | | 2.02 | Create CCV channel (handshake) | `Scheduled` (ibc-go) | `Done` [provider/ibc_module_test.go](../x/ccv/provider/ibc_module_test.go), [consumer/ibc_module_test.go](../x/ccv/consumer/ibc_module_test.go) | `Done` [SetupCCVChannel](../tests/e2e/setup_test.go#125) | `Future work` | `Scheduled` | -| 2.03 | Sending IBC packets
[SendIBCPacket](../x/ccv/utils/utils.go#40) | `Scheduled` (ibc-go) | `NA` | `Done` [TestSendVSCMaturedPackets](../tests/e2e/valset_update_test.go#39), [TestSendSlashPacket](../tests/e2e/slashing_test.go#648) | `Done` | `Scheduled` | +| 2.03 | Sending IBC packets | `Scheduled` (ibc-go) | `NA` | `Done` [TestSendVSCMaturedPackets](../tests/e2e/valset_update_test.go#39), [TestSendSlashPacket](../tests/e2e/slashing_test.go#648) | `Done` | `Scheduled` | | 2.04 | Handling acknowledgments | `Scheduled` (ibc-go) | [Scheduled](https://github.com/cosmos/interchain-security/issues/362) | `Partial coverage` [TestOnAcknowledgementPacket](../x/ccv/consumer/keeper/relay_test.go#152), [TestSlashPacketAcknowldgement](../tests/e2e/slashing_test.go#258) | `Done` | `Scheduled` | | 2.05 | Handling timeouts | `Scheduled` (ibc-go) | [Scheduled](https://github.com/cosmos/interchain-security/issues/362) |`NA` | `Future work` | `Scheduled` | -| 2.06 | Handling IBC client expiration
- high priority| `Scheduled` (ibc-go) | `NA` | `NA` | `Future work` | `Scheduled` | +| 2.06 | Handling IBC client expiration | `Scheduled` (ibc-go) | `NA` | `Done` [expired_client.go](../tests/e2e/expired_client.go) | `Future work` | `Scheduled` | | 2.07 | ICS-20 channel creation | `Scheduled` (ibc-go) | `NA` | `Done` [SetupTransferChannel](../tests/e2e/setup_test.go#152) |`Future work` | `Scheduled` | | 2.08 | ICS-20 transfer | `Scheduled` (ibc-go) | `NA` | `Done` [TestRewardsDistribution](../tests/e2e/distribution_test.go#17) | `NA` | `Scheduled` | | 2.09 | Changes in IBC-GO testing suite | `Scheduled` (ibc-go) | `NA` | `NA` | `Partial coverage` | `NA` | @@ -63,7 +63,7 @@ IBC packets: | ID | Concern | Code Review | Unit Testing | E2E Testing | Diff. Testing | Testnet | | -- | ------- | ----------- | ------------ | ----------- | ------------- | ------- | -| 3.01 | Changes to staking module | `Done` | `Done` (Cosmos-SDK side) | `Partial coverage`
[unbonding_test.go](../tests/e2e/unbonding_test.go)
redelegation could be expanded, validator unbonding missing | `Partial coverage` | `Scheduled` | +| 3.01 | Changes to staking module | `Done` | `Done` [unbonding_test.go](https://github.com/cosmos/cosmos-sdk/blob/interchain-security-rebase.0.45.6/x/staking/keeper/unbonding_test.go) | `Partial coverage`
[unbonding_test.go](../tests/e2e/unbonding_test.go)
redelegation could be expanded, validator unbonding missing | `Partial coverage` | `Scheduled` | | 3.02 | Changes to slashing module | `Done` | `NA` | `Done`
[TestValidatorDowntime](../tests/e2e/slashing_test.go#L502)
| `Partial coverage` | `Scheduled` | | 3.03 | Changes to evidence module | `Done` | `NA` | `Done`
[TestValidatorDoubleSigning](../tests/e2e/slashing_test.go#L584)
| `NA` | `Scheduled` | diff --git a/proto/interchain_security/ccv/consumer/v1/consumer.proto b/proto/interchain_security/ccv/consumer/v1/consumer.proto index ae2a2b7bad..6747380c95 100644 --- a/proto/interchain_security/ccv/consumer/v1/consumer.proto +++ b/proto/interchain_security/ccv/consumer/v1/consumer.proto @@ -6,7 +6,6 @@ import "interchain_security/ccv/v1/ccv.proto"; option go_package = "github.com/cosmos/interchain-security/x/ccv/consumer/types"; import "google/protobuf/any.proto"; -import "cosmos/staking/v1beta1/staking.proto"; import "gogoproto/gogo.proto"; import "cosmos_proto/cosmos.proto"; import "google/protobuf/duration.proto"; @@ -69,14 +68,26 @@ message CrossChainValidator { ]; } -// SlashRequest defines a slashing request for CCV consumer module -message SlashRequest { - interchain_security.ccv.v1.SlashPacketData packet = 1; - cosmos.staking.v1beta1.InfractionType infraction = 2; +// ConsumerPacketType indicates interchain security specific packet types. +enum ConsumerPacketType { + option (gogoproto.goproto_enum_prefix) = false; + + // UNSPECIFIED packet type + CONSUMER_PACKET_TYPE_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UnspecifiedPacket"]; + // Slash packet + CONSUMER_PACKET_TYPE_SLASH = 1 [(gogoproto.enumvalue_customname) = "SlashPacket"]; + // VSCMatured packet + CONSUMER_PACKET_TYPE_VSCM = 2 [(gogoproto.enumvalue_customname) = "VscMaturedPacket"]; +} + +// ConsumerPacket contains raw packet bytes and packet type. +message ConsumerPacket { + ConsumerPacketType type = 1; + bytes data = 2; } -// SlashRequests is a list of slash requests for CCV consumer module -message SlashRequests { - repeated SlashRequest requests = 1 +// ConsumerPackets is a list of data packets. +message ConsumerPackets { + repeated ConsumerPacket list = 1 [ (gogoproto.nullable) = false ]; } diff --git a/proto/interchain_security/ccv/consumer/v1/genesis.proto b/proto/interchain_security/ccv/consumer/v1/genesis.proto index c71aecd64a..d0798b33dd 100644 --- a/proto/interchain_security/ccv/consumer/v1/genesis.proto +++ b/proto/interchain_security/ccv/consumer/v1/genesis.proto @@ -32,9 +32,6 @@ message GenesisState { // OutstandingDowntimes nil on new chain, filled on restart. repeated OutstandingDowntime outstanding_downtime_slashing = 10 [ (gogoproto.nullable) = false ]; - // PendingSlashRequests filled in on new chain, nil on restart. - interchain_security.ccv.consumer.v1.SlashRequests pending_slash_requests = 11 - [ (gogoproto.nullable) = false ]; } // MaturingVSCPacket defines the genesis information for the diff --git a/tests/difference/core/driver/core_test.go b/tests/difference/core/driver/core_test.go index 39542f846b..41288f3243 100644 --- a/tests/difference/core/driver/core_test.go +++ b/tests/difference/core/driver/core_test.go @@ -381,8 +381,8 @@ func (s *CoreSuite) TestAssumptions() { s.T().Fatal(FAIL_MSG) } - // Consumer has no slash requests - s.Require().Empty(s.consumerKeeper().GetPendingSlashRequests(s.ctx(C))) + // Consumer has no pending data packets + s.Require().Empty(s.consumerKeeper().GetPendingPackets(s.ctx(C))) // Consumer has no maturities s.consumerKeeper().IteratePacketMaturityTime(s.ctx(C), diff --git a/tests/difference/core/driver/setup.go b/tests/difference/core/driver/setup.go index cc303e9e27..2c1dedd62b 100644 --- a/tests/difference/core/driver/setup.go +++ b/tests/difference/core/driver/setup.go @@ -481,7 +481,7 @@ func (b *Builder) createConsumerGenesis(tmConfig *ibctesting.TendermintConfig) * consumertypes.DefaultHistoricalEntries, consumertypes.DefaultConsumerUnbondingPeriod, ) - return consumertypes.NewInitialGenesisState(providerClient, providerConsState, valUpdates, consumertypes.SlashRequests{}, params) + return consumertypes.NewInitialGenesisState(providerClient, providerConsState, valUpdates, params) } func (b *Builder) createLink() { diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 62f34b59ea..3657117adc 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -12,6 +12,7 @@ E2e tests are categorized into files as follows: - `distribution.go` - e2e tests for the _Reward Distribution_ sub-protocol - `stop_consumer.go` - e2e tests for the _Consumer Chain Removal_ sub-protocol - `normal_operations.go` - e2e tests for _normal operations_ of ICS enabled chains +- `expired_client.go` - e2e tests for testing expired clients - `instance_test.go` - ties the e2e test structure into golang's standard test mechanism, with appropriate definitions for concrete app types and setup callback To run the e2e tests defined in this repo on any arbitrary consumer and provider implementation, copy the pattern exemplified in `instance_test.go` and `specific_setup.go` diff --git a/tests/e2e/channel_init.go b/tests/e2e/channel_init.go index 044b6e5272..f202aaeba6 100644 --- a/tests/e2e/channel_init.go +++ b/tests/e2e/channel_init.go @@ -166,7 +166,7 @@ func (suite *CCVTestSuite) TestInitTimeout() { suite.providerChain.NextBlock() // increment time - incrementTimeBy(suite, initTimeout) + incrementTime(suite, initTimeout) // check whether the chain was removed _, found = providerKeeper.GetConsumerClientId(suite.providerCtx(), chainID) diff --git a/tests/e2e/common.go b/tests/e2e/common.go index 216d5d0f56..eb2a169da6 100644 --- a/tests/e2e/common.go +++ b/tests/e2e/common.go @@ -7,7 +7,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/interchain-security/testutil/e2e" - consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" @@ -17,6 +16,7 @@ import ( channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types" "github.com/cosmos/ibc-go/v3/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" ibctesting "github.com/cosmos/ibc-go/v3/testing" ) @@ -212,29 +212,16 @@ func relayAllCommittedPackets( // Note that it is expected for the provider unbonding period // to be one day larger than the consumer unbonding period. func incrementTimeByUnbondingPeriod(s *CCVTestSuite, chainType ChainType) { - // Get unboding period from staking keeper + // Get unboding periods providerUnbondingPeriod := s.providerApp.GetStakingKeeper().UnbondingTime(s.providerCtx()) consumerUnbondingPeriod := s.consumerApp.GetConsumerKeeper().GetUnbondingPeriod(s.consumerCtx()) - // Note: the assertions below are not strictly necessary, and rely on default values - s.Require().Equal(consumertypes.DefaultConsumerUnbondingPeriod+24*time.Hour, providerUnbondingPeriod, "unexpected provider unbonding period") - s.Require().Equal(consumertypes.DefaultConsumerUnbondingPeriod, consumerUnbondingPeriod, "unexpected consumer unbonding period") var jumpPeriod time.Duration if chainType == Provider { jumpPeriod = providerUnbondingPeriod } else { jumpPeriod = consumerUnbondingPeriod } - // Make sure the clients do not expire - jumpPeriod = jumpPeriod/4 + time.Hour - for i := 0; i < 4; i++ { - s.coordinator.IncrementTimeBy(jumpPeriod) - // Update the provider client on the consumer - err := s.path.EndpointA.UpdateClient() - s.Require().NoError(err) - // Update the consumer client on the provider - err = s.path.EndpointB.UpdateClient() - s.Require().NoError(err) - } + incrementTime(s, jumpPeriod) } func checkStakingUnbondingOps(s *CCVTestSuite, id uint64, found bool, onHold bool, msgAndArgs ...interface{}) { @@ -350,25 +337,74 @@ func (suite *CCVTestSuite) commitSlashPacket(ctx sdk.Context, packetData ccv.Sla return channeltypes.CommitPacket(suite.consumerChain.App.AppCodec(), packet) } -// incrementTimeBy increments the overall time by jumpPeriod -func incrementTimeBy(s *CCVTestSuite, jumpPeriod time.Duration) { - // Get unboding period from staking keeper - consumerUnbondingPeriod := s.consumerApp.GetConsumerKeeper().GetUnbondingPeriod(s.consumerChain.GetContext()) - split := 1 - trustingPeriodFraction := s.providerApp.GetProviderKeeper().GetTrustingPeriodFraction(s.providerCtx()) - if jumpPeriod > consumerUnbondingPeriod/time.Duration(trustingPeriodFraction) { - // Make sure the clients do not expire - split = 4 - jumpPeriod = jumpPeriod / 4 +// incrementTime increments the overall time by jumpPeriod +// while updating to not expire the clients +func incrementTime(s *CCVTestSuite, jumpPeriod time.Duration) { + // get trusting period of client on provider endpoint + cs, ok := s.providerApp.GetIBCKeeper().ClientKeeper.GetClientState(s.providerCtx(), s.path.EndpointB.ClientID) + s.Require().True(ok) + providerEndpointTP := cs.(*ibctm.ClientState).TrustingPeriod + // get trusting period of client on consumer endpoint + cs, ok = s.consumerApp.GetIBCKeeper().ClientKeeper.GetClientState(s.consumerCtx(), s.path.EndpointA.ClientID) + s.Require().True(ok) + consumerEndpointTP := cs.(*ibctm.ClientState).TrustingPeriod + // find the minimum trusting period + var minTP time.Duration + if providerEndpointTP < consumerEndpointTP { + minTP = providerEndpointTP + } else { + minTP = consumerEndpointTP } - for i := 0; i < split; i++ { - s.coordinator.IncrementTimeBy(jumpPeriod) - // Update the provider client on the consumer + // jumpStep is the maximum interval at which both clients are updated + jumpStep := minTP / 2 + for jumpPeriod > 0 { + var step time.Duration + if jumpPeriod < jumpStep { + step = jumpPeriod + } else { + step = jumpStep + } + s.coordinator.IncrementTimeBy(step) + // update the provider client on the consumer err := s.path.EndpointA.UpdateClient() s.Require().NoError(err) - // Update the consumer client on the provider + // update the consumer client on the provider err = s.path.EndpointB.UpdateClient() s.Require().NoError(err) + jumpPeriod -= step + } +} + +// incrementTimeWithoutUpdate increments the overall time by jumpPeriod +// without updating the client to the `noUpdate` chain +func incrementTimeWithoutUpdate(s *CCVTestSuite, jumpPeriod time.Duration, noUpdate ChainType) { + var trustingPeriod time.Duration + var endpointToUpdate *ibctesting.Endpoint + if noUpdate == Consumer { + cs, ok := s.consumerApp.GetIBCKeeper().ClientKeeper.GetClientState(s.consumerCtx(), s.path.EndpointA.ClientID) + s.Require().True(ok) + trustingPeriod = cs.(*ibctm.ClientState).TrustingPeriod + endpointToUpdate = s.path.EndpointA + } else { + cs, ok := s.providerApp.GetIBCKeeper().ClientKeeper.GetClientState(s.providerCtx(), s.path.EndpointB.ClientID) + s.Require().True(ok) + trustingPeriod = cs.(*ibctm.ClientState).TrustingPeriod + endpointToUpdate = s.path.EndpointB + } + // jumpStep is the maximum interval at which the client on endpointToUpdate is updated + jumpStep := trustingPeriod / 2 + for jumpPeriod > 0 { + var step time.Duration + if jumpPeriod < jumpStep { + step = jumpPeriod + } else { + step = jumpStep + } + s.coordinator.IncrementTimeBy(step) + // update the client + err := endpointToUpdate.UpdateClient() + s.Require().NoError(err) + jumpPeriod -= step } } diff --git a/tests/e2e/expired_client.go b/tests/e2e/expired_client.go new file mode 100644 index 0000000000..579df936ab --- /dev/null +++ b/tests/e2e/expired_client.go @@ -0,0 +1,278 @@ +package e2e + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" + ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" + ibctesting "github.com/cosmos/ibc-go/v3/testing" + ccv "github.com/cosmos/interchain-security/x/ccv/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +// TestVSCPacketSendWithExpiredClient tests queueing of VSCPackets when the consumer client is expired. +// While the consumer client is expired (or inactive for some reason) all packets will be queued and +// and cleared once the consumer client is established. +func (s *CCVTestSuite) TestVSCPacketSendExpiredClient() { + providerKeeper := s.providerApp.GetProviderKeeper() + + s.SetupCCVChannel() + + expireClient(s, Consumer) + + // bond some tokens on provider to change validator powers + bondAmt := sdk.NewInt(1000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + delegate(s, delAddr, bondAmt) + + // try to send CCV packet to consumer + s.providerChain.NextBlock() + + // check that the packet was added to the list of pending VSC packets + packets := providerKeeper.GetPendingPackets(s.providerCtx(), s.consumerChain.ChainID) + s.Require().NotEmpty(packets, "no pending VSC packets found") + s.Require().Equal(1, len(packets), "unexpected number of pending VSC packets") + + // try again to send CCV packet to consumer + s.providerChain.NextBlock() + + // check that the packet is still in the list of pending VSC packets + packets = providerKeeper.GetPendingPackets(s.providerCtx(), s.consumerChain.ChainID) + s.Require().NotEmpty(packets, "no pending VSC packets found") + s.Require().Equal(1, len(packets), "unexpected number of pending VSC packets") + + // bond more tokens on provider to change validator powers + delegate(s, delAddr, bondAmt) + + // try again to send CCV packets to consumer + s.providerChain.NextBlock() + + // check that the packets are still in the list of pending VSC packets + packets = providerKeeper.GetPendingPackets(s.providerCtx(), s.consumerChain.ChainID) + s.Require().NotEmpty(packets, "no pending VSC packets found") + s.Require().Equal(2, len(packets), "unexpected number of pending VSC packets") + + // upgrade expired client to the consumer + upgradeExpiredClient(s, Consumer) + + // go to next block + s.providerChain.NextBlock() + + // check that the packets are not in the list of pending VSC packets + packets = providerKeeper.GetPendingPackets(s.providerCtx(), s.consumerChain.ChainID) + s.Require().Empty(packets, "unexpected pending VSC packets found") + + // check that validator updates work + // - bond more tokens on provider to change validator powers + delegate(s, delAddr, bondAmt) + // - send CCV packet to consumer + s.providerChain.NextBlock() + // - relay all VSC packet from provider to consumer + relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 3) + // - increment time so that the unbonding period ends on the consumer + incrementTimeByUnbondingPeriod(s, Consumer) + // - relay all VSCMatured packet from consumer to provider + relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 3) +} + +// TestConsumerPacketSendExpiredClient tests the consumer sending packets when the provider client is expired. +// While the provider client is expired all packets will be queued and and cleared once the provider client is upgraded. +func (s *CCVTestSuite) TestConsumerPacketSendExpiredClient() { + providerKeeper := s.providerApp.GetProviderKeeper() + consumerKeeper := s.consumerApp.GetConsumerKeeper() + + s.SetupCCVChannel() + + // bond some tokens on provider to change validator powers + bondAmt := sdk.NewInt(1000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + delegate(s, delAddr, bondAmt) + + // send CCV packet to consumer + s.providerChain.NextBlock() + + // bond more tokens on provider to change validator powers + delegate(s, delAddr, bondAmt) + + // send CCV packets to consumer + s.providerChain.NextBlock() + + // check that the packets are not in the list of pending VSC packets + providerPackets := providerKeeper.GetPendingPackets(s.providerCtx(), s.consumerChain.ChainID) + s.Require().Empty(providerPackets, "pending VSC packets found") + + // relay all VSC packet from provider to consumer + relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 2) + + // expire client to provider + expireClient(s, Provider) + + // check that the client to the consumer is active + checkClientExpired(s, Consumer, false) + + // increment time so that the unbonding period ends on the consumer; + // do not try to update the client to the provider since it's expired + consumerUnbondingPeriod := s.consumerApp.GetConsumerKeeper().GetUnbondingPeriod(s.consumerCtx()) + incrementTimeWithoutUpdate(s, consumerUnbondingPeriod+time.Hour, Provider) + + // check that the packets were added to the list of pending data packets + consumerPackets := consumerKeeper.GetPendingPackets(s.consumerCtx()) + s.Require().NotEmpty(consumerPackets) + s.Require().Equal(2, len(consumerPackets.GetList()), "unexpected number of pending data packets") + + // try to send slash packet for downtime infraction + addr := ed25519.GenPrivKey().PubKey().Address() + val := abci.Validator{Address: addr} + consumerKeeper.QueueSlashPacket(s.consumerCtx(), val, 2, stakingtypes.Downtime) + // try to send slash packet for the same downtime infraction + consumerKeeper.QueueSlashPacket(s.consumerCtx(), val, 3, stakingtypes.Downtime) + // try to send slash packet for the double-sign infraction + consumerKeeper.QueueSlashPacket(s.consumerCtx(), val, 3, stakingtypes.DoubleSign) + + // check that the packets were added to the list of pending data packets + consumerPackets = consumerKeeper.GetPendingPackets(s.consumerCtx()) + s.Require().NotEmpty(consumerPackets) + s.Require().Equal(4, len(consumerPackets.GetList()), "unexpected number of pending data packets") + + // upgrade expired client to the consumer + upgradeExpiredClient(s, Provider) + + // go to next block to trigger SendPendingDataPackets + s.consumerChain.NextBlock() + + // check that the list of pending data packets is emptied + consumerPackets = consumerKeeper.GetPendingPackets(s.consumerCtx()) + s.Require().Empty(consumerPackets) + s.Require().Equal(0, len(consumerPackets.GetList()), "unexpected number of pending data packets") + + // relay all packet from consumer to provider + relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 4) + + // check that everything works + // - bond more tokens on provider to change validator powers + delegate(s, delAddr, bondAmt) + // - send CCV packet to consumer + s.providerChain.NextBlock() + // - relay 1 VSC packet from provider to consumer + relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 1) + // - increment time so that the unbonding period ends on the provider + incrementTimeByUnbondingPeriod(s, Consumer) + // - relay 1 VSCMatured packet from consumer to provider + relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 1) +} + +// expireClient expires the client to the `clientTo` chain +func expireClient(s *CCVTestSuite, clientTo ChainType) { + var hostEndpoint *ibctesting.Endpoint + var hostChain *ibctesting.TestChain + if clientTo == Consumer { + hostEndpoint = s.path.EndpointB + hostChain = s.providerChain + } else { + hostEndpoint = s.path.EndpointA + hostChain = s.consumerChain + } + cs, ok := hostChain.App.GetIBCKeeper().ClientKeeper.GetClientState(hostChain.GetContext(), hostEndpoint.ClientID) + s.Require().True(ok) + trustingPeriod := cs.(*ibctm.ClientState).TrustingPeriod + + // increment time without updating the `clientTo` client + incrementTimeWithoutUpdate(s, trustingPeriod+time.Hour, clientTo) + + // check that the client is not active + checkClientExpired(s, clientTo, true) +} + +// checkClientIsExpired checks whether the client to `clientTo` is expired +func checkClientExpired(s *CCVTestSuite, clientTo ChainType, expectedExpired bool) { + var hostEndpoint *ibctesting.Endpoint + var hostChain *ibctesting.TestChain + if clientTo == Consumer { + hostEndpoint = s.path.EndpointB + hostChain = s.providerChain + } else { + hostEndpoint = s.path.EndpointA + hostChain = s.consumerChain + } + // check that the client to the consumer is not active + cs, ok := hostChain.App.GetIBCKeeper().ClientKeeper.GetClientState(hostChain.GetContext(), hostEndpoint.ClientID) + s.Require().True(ok) + clientStore := hostChain.App.GetIBCKeeper().ClientKeeper.ClientStore(hostChain.GetContext(), hostEndpoint.ClientID) + status := cs.Status(hostChain.GetContext(), clientStore, hostChain.App.AppCodec()) + if expectedExpired { + s.Require().NotEqual(ibcexported.Active, status, "client is active") + } else { + s.Require().Equal(ibcexported.Active, status, "client is not active") + } +} + +// upgradeExpiredClient upgrades an expired client to `clientTo` +func upgradeExpiredClient(s *CCVTestSuite, clientTo ChainType) { + subjectPath := s.path + substitutePath := ibctesting.NewPath(s.consumerChain, s.providerChain) + var subject, subjectCounterparty string + var hostNewEndpoint, targetNewEndpoint *ibctesting.Endpoint + var hostChain *ibctesting.TestChain + var targetChain *ibctesting.TestChain + if clientTo == Consumer { + subject = subjectPath.EndpointB.ClientID // provider endpoint client + subjectCounterparty = subjectPath.EndpointA.ClientID // consumer endpoint client + hostNewEndpoint = substitutePath.EndpointB + targetNewEndpoint = substitutePath.EndpointA + hostChain = s.providerChain + targetChain = s.consumerChain + } else { + subject = subjectPath.EndpointA.ClientID // consumer endpoint client + subjectCounterparty = subjectPath.EndpointB.ClientID // provider endpoint client + hostNewEndpoint = substitutePath.EndpointA + targetNewEndpoint = substitutePath.EndpointB + hostChain = s.consumerChain + targetChain = s.providerChain + } + + subjectClientState := hostChain.GetClientState(subject) + + // create substitute client with same unbonding period + hostTmConfig, ok := hostNewEndpoint.ClientConfig.(*ibctesting.TendermintConfig) + s.Require().True(ok) + hostTmConfig.UnbondingPeriod = subjectClientState.(*ibctm.ClientState).UnbondingPeriod + hostTmConfig.TrustingPeriod = subjectClientState.(*ibctm.ClientState).TrustingPeriod + targetTmConfig, ok := targetNewEndpoint.ClientConfig.(*ibctesting.TendermintConfig) + s.Require().True(ok) + subjectCounterpartyCS := targetChain.GetClientState(subjectCounterparty) + targetTmConfig.UnbondingPeriod = subjectCounterpartyCS.(*ibctm.ClientState).UnbondingPeriod + targetTmConfig.TrustingPeriod = subjectCounterpartyCS.(*ibctm.ClientState).TrustingPeriod + s.coordinator.SetupClients(substitutePath) + substitute := hostNewEndpoint.ClientID + + // update substitute twice + err := hostNewEndpoint.UpdateClient() + s.Require().NoError(err) + err = hostNewEndpoint.UpdateClient() + s.Require().NoError(err) + substituteClientState := hostChain.GetClientState(substitute) + + tmClientState, ok := subjectClientState.(*ibctm.ClientState) + s.Require().True(ok) + tmClientState.AllowUpdateAfterMisbehaviour = true + tmClientState.AllowUpdateAfterExpiry = true + tmClientState.FrozenHeight = tmClientState.LatestHeight + hostChain.App.GetIBCKeeper().ClientKeeper.SetClientState(hostChain.GetContext(), subject, tmClientState) + + tmClientState, ok = substituteClientState.(*ibctm.ClientState) + s.Require().True(ok) + tmClientState.AllowUpdateAfterMisbehaviour = true + tmClientState.AllowUpdateAfterExpiry = true + hostChain.App.GetIBCKeeper().ClientKeeper.SetClientState(hostChain.GetContext(), substitute, tmClientState) + + content := clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute) + + updateProp, ok := content.(*clienttypes.ClientUpdateProposal) + s.Require().True(ok) + err = hostChain.App.GetIBCKeeper().ClientKeeper.ClientUpdateProposal(hostChain.GetContext(), updateProp) + s.Require().NoError(err) +} diff --git a/tests/e2e/slashing.go b/tests/e2e/slashing.go index 40cc23e5a2..87cd0f658a 100644 --- a/tests/e2e/slashing.go +++ b/tests/e2e/slashing.go @@ -496,6 +496,18 @@ func (suite *CCVTestSuite) TestValidatorDowntime() { return false }) + // check that slash packet is queued + pendingPackets := consumerKeeper.GetPendingPackets(ctx) + suite.Require().NotEmpty(pendingPackets.List, "pending packets empty") + suite.Require().Len(pendingPackets.List, 1, "pending packets len should be 1 is %d", len(pendingPackets.List)) + + // clear queue, commit packets + suite.consumerApp.GetConsumerKeeper().SendPackets(ctx) + + // check queue was cleared + pendingPackets = suite.consumerApp.GetConsumerKeeper().GetPendingPackets(ctx) + suite.Require().Empty(pendingPackets.List, "pending packets NOT empty") + // verify that the slash packet was sent gotCommit := consumerIBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) suite.Require().NotNil(gotCommit, "did not found slash packet commitment") @@ -571,15 +583,28 @@ func (suite *CCVTestSuite) TestValidatorDoubleSigning() { // expect to send slash packet when handling double-sign evidence suite.consumerApp.GetE2eEvidenceKeeper().HandleEquivocationEvidence(ctx, e) - // check that slash packet is sent + // check slash packet is queued + pendingPackets := suite.consumerApp.GetConsumerKeeper().GetPendingPackets(ctx) + suite.Require().NotEmpty(pendingPackets.List, "pending packets empty") + suite.Require().Len(pendingPackets.List, 1, "pending packets len should be 1 is %d", len(pendingPackets.List)) + + // clear queue, commit packets + suite.consumerApp.GetConsumerKeeper().SendPackets(ctx) + + // check queue was cleared + pendingPackets = suite.consumerApp.GetConsumerKeeper().GetPendingPackets(ctx) + suite.Require().Empty(pendingPackets.List, "pending packets NOT empty") + + // check slash packet is sent gotCommit := suite.consumerApp.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) suite.NotNil(gotCommit) suite.Require().EqualValues(expCommit, gotCommit) } -// TestSendSlashPacket tests the functionality of SendSlashPacket and asserts state changes related to that method -func (suite *CCVTestSuite) TestSendSlashPacket() { +// TestQueueAndSendSlashPacket tests the integration of QueueSlashPacket with SendPackets. +// In normal operation slash packets are queued in BeginBlock and sent in EndBlock. +func (suite *CCVTestSuite) TestQueueAndSendSlashPacket() { suite.SetupCCVChannel() consumerKeeper := suite.consumerApp.GetConsumerKeeper() @@ -606,7 +631,7 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { addr := ed25519.GenPrivKey().PubKey().Address() val := abci.Validator{ Address: addr} - consumerKeeper.SendSlashPacket(ctx, val, 0, infraction) + consumerKeeper.QueueSlashPacket(ctx, val, 0, infraction) slashedVals = append(slashedVals, slashedVal{validator: val, infraction: infraction}) } infraction = stakingtypes.DoubleSign @@ -615,12 +640,14 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { // expect to store a duplicate for each slash request // in order to test the outstanding downtime logic for _, sv := range slashedVals { - consumerKeeper.SendSlashPacket(ctx, sv.validator, 0, sv.infraction) + consumerKeeper.QueueSlashPacket(ctx, sv.validator, 0, sv.infraction) } - // verify that all requests are stored - requests := consumerKeeper.GetPendingSlashRequests(ctx) - suite.Require().Len(requests.GetRequests(), 16) + // verify that all requests are stored except for + // the downtime slash request duplicates + dataPackets := consumerKeeper.GetPendingPackets(ctx) + suite.Require().NotEmpty(dataPackets) + suite.Require().Len(dataPackets.GetList(), 12) // save consumer next sequence seq, _ := consumerIBCKeeper.ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) @@ -628,35 +655,24 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { // establish ccv channel by sending an empty VSC packet to consumer endpoint suite.SendEmptyVSCPacket() - // check that each pending slash requests is sent once - // and that the downtime slash request duplicates are skipped (due to the outstanding downtime flag) - for i := 0; i < 16; i++ { + // check that each pending data packet is sent once + for i := 0; i < 12; i++ { commit := consumerIBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq+uint64(i)) - if i > 11 { - suite.Require().Nil(commit) - continue - } suite.Require().NotNil(commit) } // check that outstanding downtime flags // are all set to true for validators slashed for downtime requests - for _, r := range requests.GetRequests() { - downtime := r.Infraction == stakingtypes.Downtime - if downtime { - consAddr := sdk.ConsAddress(r.Packet.Validator.Address) - suite.Require().True(consumerKeeper.OutstandingDowntime(ctx, consAddr)) - } + for i := 0; i < 4; i++ { + consAddr := sdk.ConsAddress(slashedVals[i].validator.Address) + suite.Require().True(consumerKeeper.OutstandingDowntime(ctx, consAddr)) } - // check that pending slash requests get cleared after being sent - requests = consumerKeeper.GetPendingSlashRequests(ctx) - suite.Require().Len(requests.GetRequests(), 0) - - // check that slash requests aren't stored when channel is established - consumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.Downtime) - consumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.DoubleSign) + // send all pending packets - only slash packets should be queued in this test + consumerKeeper.SendPackets(ctx) - requests = consumerKeeper.GetPendingSlashRequests(ctx) - suite.Require().Len(requests.GetRequests(), 0) + // check that pending data packets got cleared + dataPackets = consumerKeeper.GetPendingPackets(ctx) + suite.Require().Empty(dataPackets) + suite.Require().Len(dataPackets.GetList(), 0) } diff --git a/tests/e2e/stop_consumer.go b/tests/e2e/stop_consumer.go index 107f519446..f35e48b34d 100644 --- a/tests/e2e/stop_consumer.go +++ b/tests/e2e/stop_consumer.go @@ -77,7 +77,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() { func(suite *CCVTestSuite) error { providerKeeper.SetSlashAcks(s.providerCtx(), consumerChainID, []string{"validator-1", "validator-2", "validator-3"}) providerKeeper.SetLockUnbondingOnTimeout(s.providerCtx(), consumerChainID) - providerKeeper.AppendPendingVSC(s.providerCtx(), consumerChainID, ccv.ValidatorSetChangePacketData{ValsetUpdateId: 1}) + providerKeeper.AppendPendingPackets(s.providerCtx(), consumerChainID, ccv.ValidatorSetChangePacketData{ValsetUpdateId: 1}) return nil }, }, @@ -172,7 +172,7 @@ func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, lockUbd bool, s.Require().Nil(providerKeeper.GetSlashAcks(s.providerCtx(), chainID)) s.Require().Zero(providerKeeper.GetInitChainHeight(s.providerCtx(), chainID)) - s.Require().Nil(providerKeeper.GetPendingVSCs(s.providerCtx(), chainID)) + s.Require().Nil(providerKeeper.GetPendingPackets(s.providerCtx(), chainID)) } // TestProviderChannelClosed checks that a consumer chain panics diff --git a/tests/e2e/unbonding.go b/tests/e2e/unbonding.go index 566a0a130e..cbd34025f5 100644 --- a/tests/e2e/unbonding.go +++ b/tests/e2e/unbonding.go @@ -9,8 +9,8 @@ import ( ccv "github.com/cosmos/interchain-security/x/ccv/types" ) -// TestUndelegationNormalOperation tests that undelegations complete after -// the unbonding period elapses on both the consumer and provider, without +// TestUndelegationNormalOperation tests that undelegations complete after +// the unbonding period elapses on both the consumer and provider, without // VSC packets timing out. func (s *CCVTestSuite) TestUndelegationNormalOperation() { unbondConsumer := func(expectedPackets int) { @@ -159,7 +159,7 @@ func (s *CCVTestSuite) TestUndelegationVscTimeout() { "unexpected balance after provider unbonding") // increment time - incrementTimeBy(s, vscTimeout) + incrementTime(s, vscTimeout) // check whether the chain was removed chainID := s.consumerChain.ChainID @@ -233,8 +233,8 @@ func (s *CCVTestSuite) TestUndelegationDuringInit() { s.providerChain.NextBlock() // check that the VSC packet is stored in state as pending - pendingVSCs, _ := providerKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) - s.Require().True(len(pendingVSCs) == 1, "no pending VSC packet found; test: %s", tc.name) + pendingVSCs := providerKeeper.GetPendingPackets(s.providerCtx(), s.consumerChain.ChainID) + s.Require().Lenf(pendingVSCs, 1, "no pending VSC packet found; test: %s", tc.name) // delegate again to create another VSC packet delegate(s, delAddr, bondAmt) @@ -243,8 +243,8 @@ func (s *CCVTestSuite) TestUndelegationDuringInit() { s.providerChain.NextBlock() // check that the VSC packet is stored in state as pending - pendingVSCs, _ = providerKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) - s.Require().True(len(pendingVSCs) == 2, "only one pending VSC packet found; test: %s", tc.name) + pendingVSCs = providerKeeper.GetPendingPackets(s.providerCtx(), s.consumerChain.ChainID) + s.Require().Lenf(pendingVSCs, 2, "only one pending VSC packet found; test: %s", tc.name) // increment time so that the unbonding period ends on the provider incrementTimeByUnbondingPeriod(s, Provider) diff --git a/tests/e2e/valset_update.go b/tests/e2e/valset_update.go index 22fe4e5cc2..072e943d2a 100644 --- a/tests/e2e/valset_update.go +++ b/tests/e2e/valset_update.go @@ -34,8 +34,9 @@ func (s *CCVTestSuite) TestPacketRoundtrip() { relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 1) } -// TestSendVSCMaturedPackets tests the behavior of SendVSCMaturedPackets and related state checks -func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { +// TestQueueAndSendVSCMaturedPackets tests the behavior of EndBlock QueueVSCMaturedPackets call +// and its integration with SendPackets call. +func (suite *CCVTestSuite) TestQueueAndSendVSCMaturedPackets() { consumerKeeper := suite.consumerApp.GetConsumerKeeper() @@ -75,7 +76,7 @@ func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { suite.Require().True(ack.Success(), "OnRecvVSCPacket did not return a Success Acknowledgment") // increase time - incrementTimeBy(suite, time.Hour) + incrementTime(suite, time.Hour) // update time and send second packet pd.ValidatorUpdates[0].Power = 15 @@ -87,7 +88,7 @@ func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { suite.Require().True(ack.Success(), "OnRecvVSCPacket did not return a Success Acknowledgment") // increase time - incrementTimeBy(suite, 24*time.Hour) + incrementTime(suite, 24*time.Hour) // update time and send third packet pd.ValidatorUpdates[1].Power = 40 @@ -101,17 +102,15 @@ func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { // increase time such that first two packets are unbonded but third is not. unbondingPeriod := consumerKeeper.GetUnbondingPeriod(suite.consumerChain.GetContext()) // increase time - incrementTimeBy(suite, unbondingPeriod-time.Hour) + incrementTime(suite, unbondingPeriod-time.Hour) - err = consumerKeeper.SendVSCMaturedPackets(suite.consumerChain.GetContext()) - suite.Require().NoError(err) - - // ensure first two packets are unbonded and VSCMatured packets are sent + // ensure first two packets are unbonded and VSCMatured packets are queued // unbonded time is deleted time1 := consumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 1) time2 := consumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 2) suite.Require().Equal(uint64(0), time1, "maturity time not deleted for mature packet 1") suite.Require().Equal(uint64(0), time2, "maturity time not deleted for mature packet 2") + // ensure that third packet did not get unbonded and is still in store time3 := consumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 3) suite.Require().True(time3 > uint64(suite.consumerChain.GetContext().BlockTime().UnixNano()), "maturity time for packet 3 is not after current time") diff --git a/testutil/e2e/interfaces.go b/testutil/e2e/interfaces.go index ed5f472de9..f90a59ed13 100644 --- a/testutil/e2e/interfaces.go +++ b/testutil/e2e/interfaces.go @@ -13,6 +13,7 @@ import ( paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking/types" + upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" ibctesting "github.com/cosmos/ibc-go/v3/testing" consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" @@ -61,6 +62,8 @@ type ConsumerApp interface { GetE2eSlashingKeeper() E2eSlashingKeeper // Returns an evidence keeper interface with more capabilities than the expected_keepers interface GetE2eEvidenceKeeper() E2eEvidenceKeeper + // Returns the upgrade keeper interface + GetUpgradeKeeper() upgradekeeper.Keeper } type DemocConsumerApp interface { diff --git a/x/ccv/consumer/keeper/genesis.go b/x/ccv/consumer/keeper/genesis.go index e06c5c4ab7..0320c719e7 100644 --- a/x/ccv/consumer/keeper/genesis.go +++ b/x/ccv/consumer/keeper/genesis.go @@ -176,7 +176,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt panic("provider consensus state is not tendermint consensus state") } // export client states and pending slashing requests into a new chain genesis - genesis = consumertypes.NewInitialGenesisState(tmCs, tmConsState, valset, k.GetPendingSlashRequests(ctx), params) + genesis = consumertypes.NewInitialGenesisState(tmCs, tmConsState, valset, params) } return diff --git a/x/ccv/consumer/keeper/genesis_test.go b/x/ccv/consumer/keeper/genesis_test.go index 9640fe70d2..139446e7ea 100644 --- a/x/ccv/consumer/keeper/genesis_test.go +++ b/x/ccv/consumer/keeper/genesis_test.go @@ -5,7 +5,6 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" host "github.com/cosmos/ibc-go/v3/modules/core/24-host" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" @@ -41,9 +40,6 @@ func TestInitGenesis(t *testing.T) { // create consensus state using a single validator consensusState := testutil.GetConsensusState(clientID, time.Time{}, validator) - slashRequests := consumertypes.SlashRequests{ - Requests: []consumertypes.SlashRequest{{Infraction: stakingtypes.Downtime}}, - } matPacket := consumertypes.MaturingVSCPacket{ VscId: uint64(1), MaturityTime: uint64(time.Now().UnixNano()), @@ -76,7 +72,7 @@ func TestInitGenesis(t *testing.T) { ) }, genesis: consumertypes.NewInitialGenesisState(testutil.GetClientState(""), consensusState, - []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, slashRequests, params), + []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, params), assertStates: func(ctx sdk.Context, ck consumerkeeper.Keeper, gs *consumertypes.GenesisState) { require.Equal(t, gs.Params, ck.GetParams(ctx)) @@ -149,9 +145,6 @@ func TestExportGenesis(t *testing.T) { channelID := "channelID" // define the states exported into genesis - slashRequests := consumertypes.SlashRequests{ - Requests: []consumertypes.SlashRequest{{Infraction: stakingtypes.Downtime}}, - } restartHeight := uint64(0) matPacket := consumertypes.MaturingVSCPacket{ VscId: uint64(1), @@ -192,10 +185,6 @@ func TestExportGenesis(t *testing.T) { require.NoError(t, err) ck.SetCCValidator(ctx, cVal) ck.SetProviderClientID(ctx, clientID) - ck.SetPendingSlashRequests( - ctx, - slashRequests, - ) // set the mock calls executed during the export gomock.InOrder( @@ -205,7 +194,7 @@ func TestExportGenesis(t *testing.T) { }, expGenesis: consumertypes.NewInitialGenesisState(testutil.GetClientState(""), consensusState, - []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, slashRequests, params), + []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, params), }, { name: "export a chain that has an established CCV channel", diff --git a/x/ccv/consumer/keeper/keeper.go b/x/ccv/consumer/keeper/keeper.go index ca576e1fb4..105853ff92 100644 --- a/x/ccv/consumer/keeper/keeper.go +++ b/x/ccv/consumer/keeper/keeper.go @@ -393,43 +393,43 @@ func (k Keeper) GetAllCCValidator(ctx sdk.Context) (validators []types.CrossChai return validators } -// SetPendingSlashRequests sets the pending slash requests in store -func (k Keeper) SetPendingSlashRequests(ctx sdk.Context, requests types.SlashRequests) { +// SetPendingPackets sets the pending CCV packets +func (k Keeper) SetPendingPackets(ctx sdk.Context, packets types.ConsumerPackets) { store := ctx.KVStore(k.storeKey) - bz, err := requests.Marshal() + bz, err := packets.Marshal() if err != nil { - panic(fmt.Errorf("failed to encode slash request json: %w", err)) + panic(fmt.Errorf("failed to encode packet: %w", err)) } - store.Set([]byte{types.PendingSlashRequestsBytePrefix}, bz) + store.Set([]byte{types.PendingDataPacketsBytePrefix}, bz) } -// GetPendingSlashRequest returns the pending slash requests in store -func (k Keeper) GetPendingSlashRequests(ctx sdk.Context) types.SlashRequests { +// GetPendingPackets returns the pending CCV packets from the store +func (k Keeper) GetPendingPackets(ctx sdk.Context) types.ConsumerPackets { + var packets types.ConsumerPackets + store := ctx.KVStore(k.storeKey) - bz := store.Get([]byte{types.PendingSlashRequestsBytePrefix}) + bz := store.Get([]byte{types.PendingDataPacketsBytePrefix}) if bz == nil { - return types.SlashRequests{} + return packets } - var sr types.SlashRequests - err := sr.Unmarshal(bz) + err := packets.Unmarshal(bz) if err != nil { - panic(fmt.Errorf("failed to decode slash request json: %w", err)) + panic(fmt.Errorf("failed to unmarshal pending data packets: %w", err)) } - return sr + return packets } -// ClearPendingSlashRequests clears the pending slash requests in store -func (k Keeper) DeletePendingSlashRequests(ctx sdk.Context) { +// DeletePendingDataPackets clears the pending data packets in store +func (k Keeper) DeletePendingDataPackets(ctx sdk.Context) { store := ctx.KVStore(k.storeKey) - store.Delete([]byte{types.PendingSlashRequestsBytePrefix}) + store.Delete([]byte{types.PendingDataPacketsBytePrefix}) } -// AppendPendingSlashRequests appends the given slash request to the pending slash requests in store -func (k Keeper) AppendPendingSlashRequests(ctx sdk.Context, req types.SlashRequest) { - sr := k.GetPendingSlashRequests(ctx) - srArray := sr.GetRequests() - srArray = append(srArray, req) - k.SetPendingSlashRequests(ctx, types.SlashRequests{Requests: srArray}) +// AppendPendingDataPacket appends the given data packet to the pending data packets in store +func (k Keeper) AppendPendingPacket(ctx sdk.Context, packet types.ConsumerPacket) { + pending := k.GetPendingPackets(ctx) + list := append(pending.GetList(), packet) + k.SetPendingPackets(ctx, types.ConsumerPackets{List: list}) } diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index 431f0b6dd5..1594b57298 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -5,6 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" conntypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/x/ccv/consumer/types" @@ -153,40 +154,63 @@ func TestCrossChainValidator(t *testing.T) { require.False(t, found) } -// TestPendingSlashRequests tests the getter, setter, appending method, and deletion method for pending slash requests -func TestPendingSlashRequests(t *testing.T) { +func TestSetPendingPackets(t *testing.T) { consumerKeeper, ctx, ctrl, _ := testkeeper.GetConsumerKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() - // prepare test setup by storing 10 pending slash requests - requests := []types.SlashRequest{} - for i := 0; i < 10; i++ { - requests = append(requests, types.SlashRequest{}) - consumerKeeper.SetPendingSlashRequests(ctx, types.SlashRequests{Requests: requests}) + // prepare test setup + dataPackets := []types.ConsumerPacket{ + { + Type: types.VscMaturedPacket, + Data: ccv.NewVSCMaturedPacketData(1).GetBytes(), + }, + { + Type: types.VscMaturedPacket, + Data: ccv.NewVSCMaturedPacketData(2).GetBytes(), + }, + { + Type: types.SlashPacket, + Data: ccv.NewSlashPacketData( + abci.Validator{Address: ed25519.GenPrivKey().PubKey().Address(), Power: int64(0)}, + 3, + stakingtypes.DoubleSign, + ).GetBytes(), + }, + { + Type: types.VscMaturedPacket, + Data: ccv.NewVSCMaturedPacketData(3).GetBytes(), + }, } + consumerKeeper.SetPendingPackets(ctx, types.ConsumerPackets{List: dataPackets}) - // test set, append and clear operations - testCases := []struct { - operation func() - expLen int - }{{ - operation: func() {}, - expLen: 10, - }, { - operation: func() { consumerKeeper.AppendPendingSlashRequests(ctx, types.SlashRequest{}) }, - expLen: 11, - }, { - operation: func() { consumerKeeper.DeletePendingSlashRequests(ctx) }, - expLen: 0, - }, - } + storedDataPackets := consumerKeeper.GetPendingPackets(ctx) + require.NotEmpty(t, storedDataPackets) + require.Equal(t, dataPackets, storedDataPackets.List) - for _, tc := range testCases { - tc.operation() - requests := consumerKeeper.GetPendingSlashRequests(ctx) - require.Len(t, requests.Requests, tc.expLen) - } + slashPacket := ccv.NewSlashPacketData( + abci.Validator{Address: ed25519.GenPrivKey().PubKey().Address(), + Power: int64(2)}, + uint64(4), + stakingtypes.Downtime, + ) + dataPackets = append(dataPackets, types.ConsumerPacket{Type: types.SlashPacket, Data: slashPacket.GetBytes()}) + consumerKeeper.AppendPendingPacket(ctx, dataPackets[len(dataPackets)-1]) + storedDataPackets = consumerKeeper.GetPendingPackets(ctx) + require.NotEmpty(t, storedDataPackets) + require.Equal(t, dataPackets, storedDataPackets.List) + + vscMaturedPakcet := ccv.NewVSCMaturedPacketData(4) + dataPackets = append(dataPackets, types.ConsumerPacket{Type: types.VscMaturedPacket, Data: vscMaturedPakcet.GetBytes()}) + consumerKeeper.AppendPendingPacket(ctx, dataPackets[len(dataPackets)-1]) + storedDataPackets = consumerKeeper.GetPendingPackets(ctx) + require.NotEmpty(t, storedDataPackets) + require.Equal(t, dataPackets, storedDataPackets.List) + + consumerKeeper.DeletePendingDataPackets(ctx) + storedDataPackets = consumerKeeper.GetPendingPackets(ctx) + require.Empty(t, storedDataPackets) + require.Len(t, storedDataPackets.List, 0) } // TestVerifyProviderChain tests the VerifyProviderChain method for the consumer keeper diff --git a/x/ccv/consumer/keeper/relay.go b/x/ccv/consumer/keeper/relay.go index 24f185ede1..6d1b8e7c0a 100644 --- a/x/ccv/consumer/keeper/relay.go +++ b/x/ccv/consumer/keeper/relay.go @@ -3,11 +3,11 @@ package keeper import ( "encoding/binary" "fmt" - "strconv" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" "github.com/cosmos/ibc-go/v3/modules/core/exported" "github.com/cosmos/interchain-security/x/ccv/consumer/types" @@ -35,8 +35,6 @@ func (k Keeper) OnRecvVSCPacket(ctx sdk.Context, packet channeltypes.Packet, new // the first packet from the provider chain // - mark the CCV channel as established k.SetProviderChannel(ctx, packet.DestinationChannel) - // - send pending slash requests in states - k.SendPendingSlashRequests(ctx) // emit event on first VSC packet to signal that CCV is working ctx.EventManager().EmitEvent( @@ -81,20 +79,12 @@ func (k Keeper) OnRecvVSCPacket(ctx sdk.Context, packet channeltypes.Packet, new return ack } -// SendVSCMaturedPackets will iterate over the persisted maturity times of previously -// received VSC packets in order, and write acknowledgements for all matured VSC packets. +// QueueVSCMaturedPackets appends matured VSCs to an internal queue. // // Note: Per spec, a VSC reaching maturity on a consumer chain means that all the unbonding // operations that resulted in validator updates included in that VSC have matured on // the consumer chain. -func (k Keeper) SendVSCMaturedPackets(ctx sdk.Context) error { - - // This method is a no-op if there is no established channel to the provider. - channelID, ok := k.GetProviderChannel(ctx) - if !ok { - return nil - } - +func (k Keeper) QueueVSCMaturedPackets(ctx sdk.Context) { store := ctx.KVStore(k.storeKey) maturityIterator := sdk.KVStorePrefixIterator(store, []byte{types.PacketMaturityTimeBytePrefix}) defer maturityIterator.Close() @@ -104,43 +94,26 @@ func (k Keeper) SendVSCMaturedPackets(ctx sdk.Context) error { for maturityIterator.Valid() { vscId := types.IdFromPacketMaturityTimeKey(maturityIterator.Key()) if currentTime >= binary.BigEndian.Uint64(maturityIterator.Value()) { - // send VSCMatured packet - // - construct validator set change packet data - packetData := ccv.NewVSCMaturedPacketData(vscId) - // - send packet over IBC - err := utils.SendIBCPacket( - ctx, - k.scopedKeeper, - k.channelKeeper, - channelID, // source channel id - ccv.ConsumerPortID, // source port id - packetData.GetBytes(), - k.GetCCVTimeoutPeriod(ctx), - ) - if err != nil { - return err - } + // construct validator set change packet data + vscPacket := ccv.NewVSCMaturedPacketData(vscId) + + // append VSCMatured packet to pending packets + // sending packets is attempted each EndBlock + // unsent packets remain in the queue until sent + k.AppendPendingPacket(ctx, types.ConsumerPacket{ + Type: types.VscMaturedPacket, + Data: vscPacket.GetBytes(), + }) k.DeletePacketMaturityTime(ctx, vscId) - ctx.EventManager().EmitEvent( - sdk.NewEvent( - ccv.EventTypeSendMaturedVSCPacket, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - sdk.NewAttribute(ccv.AttributeChainID, ctx.ChainID()), - sdk.NewAttribute(ccv.AttributeConsumerHeight, strconv.Itoa(int(ctx.BlockHeight()))), - sdk.NewAttribute(ccv.AttributeValSetUpdateID, strconv.Itoa(int(vscId))), - sdk.NewAttribute(ccv.AttributeTimestamp, strconv.Itoa(int(currentTime))), - ), - ) } else { break } maturityIterator.Next() } - return nil } -// SendSlashPacket sends a slash packet containing the given validator data and slashing info -func (k Keeper) SendSlashPacket(ctx sdk.Context, validator abci.Validator, valsetUpdateID uint64, infraction stakingtypes.InfractionType) { +// QueueSlashPacket appends a slash packet containing the given validator data and slashing info to queue. +func (k Keeper) QueueSlashPacket(ctx sdk.Context, validator abci.Validator, valsetUpdateID uint64, infraction stakingtypes.InfractionType) { consAddr := sdk.ConsAddress(validator.Address) downtime := infraction == stakingtypes.Downtime @@ -149,102 +122,63 @@ func (k Keeper) SendSlashPacket(ctx sdk.Context, validator abci.Validator, valse return } - // construct slash packet data - packetData := ccv.NewSlashPacketData(validator, valsetUpdateID, infraction) - - // check that provider channel is established - // if not, append slashing packet to pending slash requests - channelID, ok := k.GetProviderChannel(ctx) - if !ok { - k.AppendPendingSlashRequests(ctx, types.SlashRequest{ - Packet: &packetData, - Infraction: infraction}, - ) - return - } - - // send packet over IBC - err := utils.SendIBCPacket( - ctx, - k.scopedKeeper, - k.channelKeeper, - channelID, // source channel id - ccv.ConsumerPortID, // source port id - packetData.GetBytes(), - k.GetCCVTimeoutPeriod(ctx), - ) - if err != nil { - panic(err) - } - - // set outstanding downtime if slash request sent is for downtime if downtime { + // set outstanding downtime to not send multiple + // slashing requests for the same downtime infraction k.SetOutstandingDowntime(ctx, consAddr) } - // if provider channel is not established the emmission - // will instead take place in SendPendingSlashRequests - ctx.EventManager().EmitEvent( - sdk.NewEvent( - ccv.EventTypeSendSlashPacket, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - sdk.NewAttribute(ccv.AttributeValidatorAddress, sdk.ConsAddress(validator.Address).String()), - sdk.NewAttribute(ccv.AttributeValSetUpdateID, strconv.Itoa(int(valsetUpdateID))), - sdk.NewAttribute(ccv.AttributeInfractionType, infraction.String()), - ), - ) + // construct slash packet data + slashPacket := ccv.NewSlashPacketData(validator, valsetUpdateID, infraction) + + // append the Slash packet data to pending data packets + // to be sent once the CCV channel is established + k.AppendPendingPacket(ctx, types.ConsumerPacket{ + Type: types.SlashPacket, + Data: slashPacket.GetBytes(), + }) } -// SendPendingSlashRequests iterates over the stored pending slash requests in reverse order -// and sends the embedded slash packets to the provider chain -func (k Keeper) SendPendingSlashRequests(ctx sdk.Context) { +// SendPackets iterates queued packets and sends them in FIFO order. +// received VSC packets in order, and write acknowledgements for all matured VSC packets. +// +// This method is a no-op if there is no established channel to provider or the queue is empty. +// +// Note: Per spec, a VSC reaching maturity on a consumer chain means that all the unbonding +// operations that resulted in validator updates included in that VSC have matured on +// the consumer chain. +func (k Keeper) SendPackets(ctx sdk.Context) { + channelID, ok := k.GetProviderChannel(ctx) if !ok { - panic(fmt.Errorf("%s: CCV channel not set", channeltypes.ErrChannelNotFound)) + return } - // iterate over pending slash requests in reverse order - requests := k.GetPendingSlashRequests(ctx).Requests - for i := len(requests) - 1; i >= 0; i-- { - slashReq := requests[i] - - // send the emebdded slash packet to the CCV channel - // if the outstanding downtime flag is false for the validator - downtime := slashReq.Infraction == stakingtypes.Downtime - if !downtime || !k.OutstandingDowntime(ctx, sdk.ConsAddress(slashReq.Packet.Validator.Address)) { - // send packet over IBC - err := utils.SendIBCPacket( - ctx, - k.scopedKeeper, - k.channelKeeper, - channelID, // source channel id - ccv.ConsumerPortID, // source port id - slashReq.Packet.GetBytes(), - k.GetCCVTimeoutPeriod(ctx), - ) - if err != nil { - panic(err) - } + pending := k.GetPendingPackets(ctx) + for _, p := range pending.GetList() { + // send packet over IBC + err := utils.SendIBCPacket( + ctx, + k.scopedKeeper, + k.channelKeeper, + channelID, // source channel id + ccv.ConsumerPortID, // source port id + p.Data, + k.GetCCVTimeoutPeriod(ctx), + ) - // set validator outstanding downtime flag to true - if downtime { - k.SetOutstandingDowntime(ctx, sdk.ConsAddress(slashReq.Packet.Validator.Address)) + if err != nil { + if clienttypes.ErrClientNotActive.Is(err) { + // leave the packet data stored to be sent once the client is upgraded + return } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - ccv.EventTypeSendSlashPacket, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - sdk.NewAttribute(ccv.AttributeValidatorAddress, sdk.ConsAddress(slashReq.Packet.Validator.Address).String()), - sdk.NewAttribute(ccv.AttributeValSetUpdateID, strconv.Itoa(int(slashReq.Packet.ValsetUpdateId))), - sdk.NewAttribute(ccv.AttributeInfractionType, slashReq.Packet.Infraction.String()), - ), - ) + // something went wrong when sending the packet + panic(fmt.Errorf("packet could not be sent over IBC: %w", err)) } } - // clear pending slash requests - k.DeletePendingSlashRequests(ctx) + // clear pending data packets + k.DeletePendingDataPackets(ctx) } // OnAcknowledgementPacket executes application logic for acknowledgments of sent VSCMatured and Slash packets diff --git a/x/ccv/consumer/keeper/validators.go b/x/ccv/consumer/keeper/validators.go index 7956d00416..2d2cfbdc93 100644 --- a/x/ccv/consumer/keeper/validators.go +++ b/x/ccv/consumer/keeper/validators.go @@ -78,13 +78,14 @@ func (k Keeper) ValidatorByConsAddr(sdk.Context, sdk.ConsAddress) stakingtypes.V return stakingtypes.Validator{} } -// Slash sends a slashing request to the provider chain +// Slash queues a slashing request for the the provider chain +// All queued slashing requests will be cleared in EndBlock func (k Keeper) Slash(ctx sdk.Context, addr sdk.ConsAddress, infractionHeight, power int64, _ sdk.Dec, infraction stakingtypes.InfractionType) { if infraction == stakingtypes.InfractionEmpty { return } - k.SendSlashPacket( + k.QueueSlashPacket( ctx, abci.Validator{ Address: addr.Bytes(), diff --git a/x/ccv/consumer/module.go b/x/ccv/consumer/module.go index ae6f6bfda8..30865b43cf 100644 --- a/x/ccv/consumer/module.go +++ b/x/ccv/consumer/module.go @@ -171,7 +171,7 @@ func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { } // EndBlock implements the AppModule interface -// Flush PendingChanges to ABCI, and write acknowledgements for any packets that have finished unbonding. +// Flush PendingChanges to ABCI, send pending packets, write acknowledgements for packets that have finished unbonding. func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { // distribution transmission err := am.keeper.DistributeToProviderValidatorSet(ctx) @@ -179,10 +179,12 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V panic(err) } - err = am.keeper.SendVSCMaturedPackets(ctx) - if err != nil { - panic(err) - } + // NOTE: Slash packets are queued in BeginBlock + // Packet ordering is managed by the PendingPackets queue. + am.keeper.QueueVSCMaturedPackets(ctx) + + // panics on invalid packets and unexpected send errors + am.keeper.SendPackets(ctx) data, ok := am.keeper.GetPendingChanges(ctx) if !ok { diff --git a/x/ccv/consumer/types/consumer.pb.go b/x/ccv/consumer/types/consumer.pb.go index 8def5aad90..fb57b2fa20 100644 --- a/x/ccv/consumer/types/consumer.pb.go +++ b/x/ccv/consumer/types/consumer.pb.go @@ -6,8 +6,7 @@ package types import ( fmt "fmt" types "github.com/cosmos/cosmos-sdk/codec/types" - types2 "github.com/cosmos/cosmos-sdk/x/staking/types" - types1 "github.com/cosmos/interchain-security/x/ccv/types" + _ "github.com/cosmos/interchain-security/x/ccv/types" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" @@ -31,6 +30,38 @@ var _ = time.Kitchen // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// ConsumerPacketType indicates interchain security specific packet types. +type ConsumerPacketType int32 + +const ( + // UNSPECIFIED packet type + UnspecifiedPacket ConsumerPacketType = 0 + // Slash packet + SlashPacket ConsumerPacketType = 1 + // VSCMatured packet + VscMaturedPacket ConsumerPacketType = 2 +) + +var ConsumerPacketType_name = map[int32]string{ + 0: "CONSUMER_PACKET_TYPE_UNSPECIFIED", + 1: "CONSUMER_PACKET_TYPE_SLASH", + 2: "CONSUMER_PACKET_TYPE_VSCM", +} + +var ConsumerPacketType_value = map[string]int32{ + "CONSUMER_PACKET_TYPE_UNSPECIFIED": 0, + "CONSUMER_PACKET_TYPE_SLASH": 1, + "CONSUMER_PACKET_TYPE_VSCM": 2, +} + +func (x ConsumerPacketType) String() string { + return proto.EnumName(ConsumerPacketType_name, int32(x)) +} + +func (ConsumerPacketType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_5b27a82b276e7f93, []int{0} +} + // Params defines the parameters for CCV consumer module type Params struct { // TODO: Remove enabled flag and find a better way to setup e2e tests @@ -269,24 +300,24 @@ func (m *CrossChainValidator) GetPubkey() *types.Any { return nil } -// SlashRequest defines a slashing request for CCV consumer module -type SlashRequest struct { - Packet *types1.SlashPacketData `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet,omitempty"` - Infraction types2.InfractionType `protobuf:"varint,2,opt,name=infraction,proto3,enum=cosmos.staking.v1beta1.InfractionType" json:"infraction,omitempty"` +// ConsumerPacket contains raw packet bytes and packet type. +type ConsumerPacket struct { + Type ConsumerPacketType `protobuf:"varint,1,opt,name=type,proto3,enum=interchain_security.ccv.consumer.v1.ConsumerPacketType" json:"type,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` } -func (m *SlashRequest) Reset() { *m = SlashRequest{} } -func (m *SlashRequest) String() string { return proto.CompactTextString(m) } -func (*SlashRequest) ProtoMessage() {} -func (*SlashRequest) Descriptor() ([]byte, []int) { +func (m *ConsumerPacket) Reset() { *m = ConsumerPacket{} } +func (m *ConsumerPacket) String() string { return proto.CompactTextString(m) } +func (*ConsumerPacket) ProtoMessage() {} +func (*ConsumerPacket) Descriptor() ([]byte, []int) { return fileDescriptor_5b27a82b276e7f93, []int{3} } -func (m *SlashRequest) XXX_Unmarshal(b []byte) error { +func (m *ConsumerPacket) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *SlashRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ConsumerPacket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_SlashRequest.Marshal(b, m, deterministic) + return xxx_messageInfo_ConsumerPacket.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -296,49 +327,49 @@ func (m *SlashRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } -func (m *SlashRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_SlashRequest.Merge(m, src) +func (m *ConsumerPacket) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsumerPacket.Merge(m, src) } -func (m *SlashRequest) XXX_Size() int { +func (m *ConsumerPacket) XXX_Size() int { return m.Size() } -func (m *SlashRequest) XXX_DiscardUnknown() { - xxx_messageInfo_SlashRequest.DiscardUnknown(m) +func (m *ConsumerPacket) XXX_DiscardUnknown() { + xxx_messageInfo_ConsumerPacket.DiscardUnknown(m) } -var xxx_messageInfo_SlashRequest proto.InternalMessageInfo +var xxx_messageInfo_ConsumerPacket proto.InternalMessageInfo -func (m *SlashRequest) GetPacket() *types1.SlashPacketData { +func (m *ConsumerPacket) GetType() ConsumerPacketType { if m != nil { - return m.Packet + return m.Type } - return nil + return UnspecifiedPacket } -func (m *SlashRequest) GetInfraction() types2.InfractionType { +func (m *ConsumerPacket) GetData() []byte { if m != nil { - return m.Infraction + return m.Data } - return types2.InfractionEmpty + return nil } -// SlashRequests is a list of slash requests for CCV consumer module -type SlashRequests struct { - Requests []SlashRequest `protobuf:"bytes,1,rep,name=requests,proto3" json:"requests"` +// ConsumerPackets is a list of data packets. +type ConsumerPackets struct { + List []ConsumerPacket `protobuf:"bytes,1,rep,name=list,proto3" json:"list"` } -func (m *SlashRequests) Reset() { *m = SlashRequests{} } -func (m *SlashRequests) String() string { return proto.CompactTextString(m) } -func (*SlashRequests) ProtoMessage() {} -func (*SlashRequests) Descriptor() ([]byte, []int) { +func (m *ConsumerPackets) Reset() { *m = ConsumerPackets{} } +func (m *ConsumerPackets) String() string { return proto.CompactTextString(m) } +func (*ConsumerPackets) ProtoMessage() {} +func (*ConsumerPackets) Descriptor() ([]byte, []int) { return fileDescriptor_5b27a82b276e7f93, []int{4} } -func (m *SlashRequests) XXX_Unmarshal(b []byte) error { +func (m *ConsumerPackets) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *SlashRequests) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ConsumerPackets) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_SlashRequests.Marshal(b, m, deterministic) + return xxx_messageInfo_ConsumerPackets.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -348,31 +379,32 @@ func (m *SlashRequests) XXX_Marshal(b []byte, deterministic bool) ([]byte, error return b[:n], nil } } -func (m *SlashRequests) XXX_Merge(src proto.Message) { - xxx_messageInfo_SlashRequests.Merge(m, src) +func (m *ConsumerPackets) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsumerPackets.Merge(m, src) } -func (m *SlashRequests) XXX_Size() int { +func (m *ConsumerPackets) XXX_Size() int { return m.Size() } -func (m *SlashRequests) XXX_DiscardUnknown() { - xxx_messageInfo_SlashRequests.DiscardUnknown(m) +func (m *ConsumerPackets) XXX_DiscardUnknown() { + xxx_messageInfo_ConsumerPackets.DiscardUnknown(m) } -var xxx_messageInfo_SlashRequests proto.InternalMessageInfo +var xxx_messageInfo_ConsumerPackets proto.InternalMessageInfo -func (m *SlashRequests) GetRequests() []SlashRequest { +func (m *ConsumerPackets) GetList() []ConsumerPacket { if m != nil { - return m.Requests + return m.List } return nil } func init() { + proto.RegisterEnum("interchain_security.ccv.consumer.v1.ConsumerPacketType", ConsumerPacketType_name, ConsumerPacketType_value) proto.RegisterType((*Params)(nil), "interchain_security.ccv.consumer.v1.Params") proto.RegisterType((*LastTransmissionBlockHeight)(nil), "interchain_security.ccv.consumer.v1.LastTransmissionBlockHeight") proto.RegisterType((*CrossChainValidator)(nil), "interchain_security.ccv.consumer.v1.CrossChainValidator") - proto.RegisterType((*SlashRequest)(nil), "interchain_security.ccv.consumer.v1.SlashRequest") - proto.RegisterType((*SlashRequests)(nil), "interchain_security.ccv.consumer.v1.SlashRequests") + proto.RegisterType((*ConsumerPacket)(nil), "interchain_security.ccv.consumer.v1.ConsumerPacket") + proto.RegisterType((*ConsumerPackets)(nil), "interchain_security.ccv.consumer.v1.ConsumerPackets") } func init() { @@ -380,55 +412,60 @@ func init() { } var fileDescriptor_5b27a82b276e7f93 = []byte{ - // 765 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcd, 0x6e, 0xeb, 0x44, - 0x14, 0x8e, 0x49, 0x9b, 0xa6, 0x93, 0x02, 0x65, 0x08, 0xad, 0x5b, 0x24, 0x27, 0x0d, 0x15, 0x8a, - 0x84, 0x6a, 0x2b, 0xa9, 0xd8, 0x74, 0xd7, 0xa4, 0x54, 0xe5, 0x47, 0x10, 0xdc, 0x88, 0x05, 0x2c, - 0xac, 0xf1, 0x78, 0xe2, 0x8c, 0xe2, 0xcc, 0x98, 0x99, 0xb1, 0xc1, 0x6f, 0xc1, 0x12, 0x89, 0x17, - 0xe0, 0x01, 0x78, 0x88, 0x8a, 0x55, 0x97, 0x77, 0xd5, 0x7b, 0xd5, 0xbe, 0xc1, 0xd5, 0x7d, 0x80, - 0x2b, 0xff, 0xa5, 0x49, 0xef, 0x8d, 0xd4, 0xdd, 0x39, 0x3a, 0xdf, 0xf7, 0xd9, 0xdf, 0x39, 0x67, - 0x0e, 0xe8, 0x53, 0xa6, 0x88, 0xc0, 0x53, 0x44, 0x99, 0x23, 0x09, 0x8e, 0x04, 0x55, 0x89, 0x85, - 0x71, 0x6c, 0x61, 0xce, 0x64, 0x34, 0x27, 0xc2, 0x8a, 0x7b, 0x8b, 0xd8, 0x0c, 0x05, 0x57, 0x1c, - 0x7e, 0xf1, 0x1e, 0x8e, 0x89, 0x71, 0x6c, 0x2e, 0x70, 0x71, 0xef, 0xf0, 0x78, 0x9d, 0x70, 0xaa, - 0x87, 0xe3, 0x5c, 0xea, 0xf0, 0xc0, 0xe7, 0xdc, 0x0f, 0x88, 0x95, 0x65, 0x6e, 0x34, 0xb1, 0x10, - 0x4b, 0x8a, 0xd2, 0x31, 0xe6, 0x72, 0xce, 0xa5, 0x25, 0x15, 0x9a, 0x51, 0xe6, 0x5b, 0x71, 0xcf, - 0x25, 0x0a, 0xf5, 0xca, 0xbc, 0x40, 0x35, 0x7d, 0xee, 0xf3, 0x2c, 0xb4, 0xd2, 0xa8, 0x94, 0xcd, - 0xb9, 0x4e, 0x5e, 0xc8, 0x93, 0xa2, 0x64, 0x3c, 0xfd, 0xa2, 0x17, 0x09, 0xa4, 0x28, 0x67, 0x79, - 0xbd, 0xf3, 0x66, 0x03, 0xd4, 0x46, 0x48, 0xa0, 0xb9, 0x84, 0x3a, 0xd8, 0x22, 0x0c, 0xb9, 0x01, - 0xf1, 0x74, 0xad, 0xad, 0x75, 0xeb, 0x76, 0x99, 0xc2, 0x9f, 0xc0, 0xb1, 0x1b, 0x70, 0x3c, 0x93, - 0x4e, 0x48, 0x84, 0xe3, 0x51, 0xa9, 0x04, 0x75, 0xa3, 0x54, 0xc5, 0x51, 0x02, 0x31, 0x39, 0xa7, - 0x52, 0x52, 0xce, 0xf4, 0x0f, 0xda, 0x5a, 0xb7, 0x6a, 0x1f, 0xe5, 0xd8, 0x11, 0x11, 0x17, 0x4b, - 0xc8, 0xf1, 0x12, 0x10, 0x7e, 0x07, 0x8e, 0xd6, 0xaa, 0x38, 0x78, 0x8a, 0x18, 0x23, 0x81, 0x5e, - 0x6d, 0x6b, 0xdd, 0x6d, 0xbb, 0xe5, 0xad, 0x11, 0x19, 0xe6, 0x30, 0x78, 0x06, 0x0e, 0x43, 0xc1, - 0x63, 0xea, 0x11, 0xe1, 0x4c, 0x08, 0x71, 0x42, 0xce, 0x03, 0x07, 0x79, 0x9e, 0x70, 0xa4, 0x12, - 0xfa, 0x46, 0x26, 0xb2, 0x57, 0x22, 0x2e, 0x09, 0x19, 0x71, 0x1e, 0x9c, 0x7b, 0x9e, 0xb8, 0x56, - 0x02, 0xfe, 0x0c, 0x20, 0xc6, 0xb1, 0xa3, 0xe8, 0x9c, 0xf0, 0x48, 0xa5, 0xee, 0x28, 0xf7, 0xf4, - 0xcd, 0xb6, 0xd6, 0x6d, 0xf4, 0x0f, 0xcc, 0xbc, 0x75, 0x66, 0xd9, 0x3a, 0xf3, 0xa2, 0x68, 0xdd, - 0xa0, 0x7e, 0x73, 0xd7, 0xaa, 0xfc, 0xfd, 0xb2, 0xa5, 0xd9, 0xbb, 0x18, 0xc7, 0xe3, 0x9c, 0x3d, - 0xca, 0xc8, 0xf0, 0x37, 0xb0, 0x9f, 0xb9, 0x99, 0x10, 0xf1, 0x54, 0xb7, 0xf6, 0x7c, 0xdd, 0xcf, - 0x4a, 0x8d, 0x55, 0xf1, 0x2b, 0xd0, 0x2e, 0x97, 0xce, 0x11, 0x64, 0xa5, 0x85, 0x13, 0x81, 0x70, - 0x1a, 0xe8, 0x5b, 0x99, 0x63, 0xa3, 0xc4, 0xd9, 0x2b, 0xb0, 0xcb, 0x02, 0x05, 0x4f, 0x00, 0x9c, - 0x52, 0xa9, 0xb8, 0xa0, 0x18, 0x05, 0x0e, 0x61, 0x4a, 0x50, 0x22, 0xf5, 0x7a, 0x36, 0xc0, 0x4f, - 0x1e, 0x2b, 0xdf, 0xe4, 0x05, 0xf8, 0x23, 0xd8, 0x8d, 0x98, 0xcb, 0x99, 0x47, 0x99, 0x5f, 0xda, - 0xd9, 0x7e, 0xbe, 0x9d, 0x8f, 0x17, 0xe4, 0xdc, 0x48, 0xe7, 0x6b, 0xf0, 0xf9, 0x0f, 0x48, 0xaa, - 0xe5, 0x79, 0x0e, 0xd2, 0xad, 0xb9, 0x22, 0xd4, 0x9f, 0x2a, 0xb8, 0x07, 0x6a, 0xd3, 0x2c, 0xca, - 0x36, 0xb1, 0x6a, 0x17, 0x59, 0xe7, 0x5f, 0x0d, 0x7c, 0x3a, 0x14, 0x5c, 0xca, 0x61, 0xfa, 0xd0, - 0x7e, 0x41, 0x01, 0xf5, 0x90, 0xe2, 0x22, 0x5d, 0xdd, 0x74, 0xe2, 0x44, 0xca, 0x8c, 0xb0, 0x63, - 0x97, 0x29, 0x6c, 0x82, 0xcd, 0x90, 0xff, 0x41, 0x44, 0xb1, 0x9b, 0x79, 0x02, 0x11, 0xa8, 0x85, - 0x91, 0x3b, 0x23, 0x49, 0xb6, 0x64, 0x8d, 0x7e, 0xf3, 0x1d, 0x13, 0xe7, 0x2c, 0x19, 0x9c, 0xbe, - 0xbe, 0x6b, 0xed, 0x27, 0x68, 0x1e, 0x9c, 0x75, 0xd2, 0x6e, 0x12, 0x26, 0x23, 0xe9, 0xe4, 0xbc, - 0xce, 0xff, 0xff, 0x9d, 0x34, 0x8b, 0x87, 0x86, 0x45, 0x12, 0x2a, 0x6e, 0x8e, 0x22, 0xf7, 0x7b, - 0x92, 0xd8, 0x85, 0x70, 0xe7, 0x1f, 0x0d, 0xec, 0x5c, 0x07, 0x48, 0x4e, 0x6d, 0xf2, 0x7b, 0x44, - 0xa4, 0x82, 0x43, 0x50, 0x0b, 0x11, 0x9e, 0x91, 0xdc, 0x53, 0xa3, 0xff, 0x95, 0xb9, 0xee, 0xae, - 0xc4, 0x3d, 0x33, 0x63, 0x8e, 0x32, 0xf8, 0x05, 0x52, 0xc8, 0x2e, 0xa8, 0xf0, 0x12, 0x00, 0xca, - 0x16, 0xa3, 0x4e, 0x3d, 0x7d, 0xd4, 0xff, 0xd2, 0x2c, 0x7e, 0xa4, 0x3c, 0x15, 0xc5, 0xe9, 0x30, - 0xbf, 0x5d, 0x20, 0xc7, 0x49, 0x48, 0xec, 0x25, 0x66, 0xc7, 0x03, 0x1f, 0x2e, 0xff, 0x9c, 0x84, - 0xd7, 0xa0, 0x2e, 0x8a, 0x58, 0xd7, 0xda, 0xd5, 0x6e, 0xa3, 0xdf, 0x33, 0x9f, 0x71, 0xf7, 0xcc, - 0x65, 0x95, 0xc1, 0x46, 0x3a, 0x70, 0x7b, 0x21, 0x34, 0x18, 0xdf, 0xdc, 0x1b, 0xda, 0xed, 0xbd, - 0xa1, 0xbd, 0xba, 0x37, 0xb4, 0xbf, 0x1e, 0x8c, 0xca, 0xed, 0x83, 0x51, 0x79, 0xf1, 0x60, 0x54, - 0x7e, 0x3d, 0xf3, 0xa9, 0x9a, 0x46, 0xae, 0x89, 0xf9, 0xbc, 0xb8, 0x57, 0xd6, 0xe3, 0xd7, 0x4e, - 0x16, 0x07, 0xf4, 0xcf, 0xd5, 0xdb, 0xac, 0x92, 0x90, 0x48, 0xb7, 0x96, 0x0d, 0xe9, 0xf4, 0x6d, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xe5, 0x65, 0xb8, 0xcc, 0x05, 0x00, 0x00, + // 838 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0x41, 0x6f, 0xdb, 0x36, + 0x14, 0xb6, 0x1a, 0xd7, 0x4d, 0x99, 0xa2, 0x71, 0x39, 0xb7, 0x75, 0x3c, 0x40, 0x51, 0xbd, 0x1e, + 0x8c, 0x01, 0x91, 0x51, 0x07, 0xc3, 0x80, 0xec, 0x14, 0x3b, 0x0e, 0xd2, 0xa5, 0x49, 0x35, 0xd9, + 0x09, 0xb0, 0xed, 0xa0, 0x51, 0x14, 0x6d, 0x13, 0x91, 0x49, 0x8d, 0xa4, 0xbc, 0xe9, 0x1f, 0x0c, + 0x39, 0xed, 0xb8, 0x4b, 0x4e, 0xbb, 0xec, 0x07, 0xec, 0xba, 0x7b, 0xb1, 0x53, 0x8f, 0x3b, 0x75, + 0x43, 0xf2, 0x0f, 0x86, 0xfd, 0x80, 0x41, 0x94, 0xe4, 0xc6, 0x6d, 0x02, 0x04, 0xbd, 0xbd, 0x87, + 0xf7, 0x7d, 0x9f, 0xf8, 0xbe, 0xf7, 0x48, 0x81, 0x0e, 0x65, 0x8a, 0x08, 0x3c, 0x41, 0x94, 0x79, + 0x92, 0xe0, 0x58, 0x50, 0x95, 0xb4, 0x31, 0x9e, 0xb5, 0x31, 0x67, 0x32, 0x9e, 0x12, 0xd1, 0x9e, + 0x3d, 0x9b, 0xc7, 0x76, 0x24, 0xb8, 0xe2, 0xf0, 0x93, 0x2b, 0x38, 0x36, 0xc6, 0x33, 0x7b, 0x8e, + 0x9b, 0x3d, 0x6b, 0x3c, 0xbd, 0x4e, 0x38, 0xd5, 0xc3, 0xb3, 0x4c, 0xaa, 0xb1, 0x36, 0xe6, 0x7c, + 0x1c, 0x92, 0xb6, 0xce, 0xfc, 0x78, 0xd4, 0x46, 0x2c, 0xc9, 0x4b, 0xb5, 0x31, 0x1f, 0x73, 0x1d, + 0xb6, 0xd3, 0xa8, 0x20, 0x60, 0x2e, 0xa7, 0x5c, 0x7a, 0x59, 0x21, 0x4b, 0xf2, 0x92, 0xf9, 0xae, + 0x56, 0x10, 0x0b, 0xa4, 0x28, 0x67, 0x59, 0xbd, 0xf9, 0x5f, 0x19, 0x54, 0x1c, 0x24, 0xd0, 0x54, + 0xc2, 0x3a, 0xb8, 0x43, 0x18, 0xf2, 0x43, 0x12, 0xd4, 0x0d, 0xcb, 0x68, 0x2d, 0xbb, 0x45, 0x0a, + 0x5f, 0x82, 0xa7, 0x7e, 0xc8, 0xf1, 0x89, 0xf4, 0x22, 0x22, 0xbc, 0x80, 0x4a, 0x25, 0xa8, 0x1f, + 0xa7, 0x2a, 0x9e, 0x12, 0x88, 0xc9, 0x29, 0x95, 0x92, 0x72, 0x56, 0xbf, 0x65, 0x19, 0xad, 0x25, + 0xf7, 0x49, 0x86, 0x75, 0x88, 0xd8, 0xb9, 0x84, 0x1c, 0x5e, 0x02, 0xc2, 0x2f, 0xc1, 0x93, 0x6b, + 0x55, 0x3c, 0x3c, 0x41, 0x8c, 0x91, 0xb0, 0xbe, 0x64, 0x19, 0xad, 0xbb, 0xee, 0x7a, 0x70, 0x8d, + 0x48, 0x2f, 0x83, 0xc1, 0x2d, 0xd0, 0x88, 0x04, 0x9f, 0xd1, 0x80, 0x08, 0x6f, 0x44, 0x88, 0x17, + 0x71, 0x1e, 0x7a, 0x28, 0x08, 0x84, 0x27, 0x95, 0xa8, 0x97, 0xb5, 0xc8, 0xa3, 0x02, 0xb1, 0x4b, + 0x88, 0xc3, 0x79, 0xb8, 0x1d, 0x04, 0x62, 0xa0, 0x04, 0xfc, 0x0a, 0x40, 0x8c, 0x67, 0x9e, 0xa2, + 0x53, 0xc2, 0x63, 0x95, 0x76, 0x47, 0x79, 0x50, 0xbf, 0x6d, 0x19, 0xad, 0x95, 0xce, 0x9a, 0x9d, + 0x59, 0x67, 0x17, 0xd6, 0xd9, 0x3b, 0xb9, 0x75, 0xdd, 0xe5, 0x57, 0x6f, 0xd6, 0x4b, 0xbf, 0xfc, + 0xbd, 0x6e, 0xb8, 0x55, 0x8c, 0x67, 0xc3, 0x8c, 0xed, 0x68, 0x32, 0xfc, 0x16, 0x3c, 0xd6, 0xdd, + 0x8c, 0x88, 0x78, 0x57, 0xb7, 0x72, 0x73, 0xdd, 0x87, 0x85, 0xc6, 0xa2, 0xf8, 0x1e, 0xb0, 0x8a, + 0x75, 0xf2, 0x04, 0x59, 0xb0, 0x70, 0x24, 0x10, 0x4e, 0x83, 0xfa, 0x1d, 0xdd, 0xb1, 0x59, 0xe0, + 0xdc, 0x05, 0xd8, 0x6e, 0x8e, 0x82, 0x1b, 0x00, 0x4e, 0xa8, 0x54, 0x5c, 0x50, 0x8c, 0x42, 0x8f, + 0x30, 0x25, 0x28, 0x91, 0xf5, 0x65, 0x3d, 0xc0, 0x07, 0x6f, 0x2b, 0xfd, 0xac, 0x00, 0x0f, 0x41, + 0x35, 0x66, 0x3e, 0x67, 0x01, 0x65, 0xe3, 0xa2, 0x9d, 0xbb, 0x37, 0x6f, 0x67, 0x75, 0x4e, 0xce, + 0x1a, 0x69, 0x7e, 0x06, 0x3e, 0x7e, 0x81, 0xa4, 0xba, 0x3c, 0xcf, 0x6e, 0xba, 0x35, 0x7b, 0x84, + 0x8e, 0x27, 0x0a, 0x3e, 0x02, 0x95, 0x89, 0x8e, 0xf4, 0x26, 0x2e, 0xb9, 0x79, 0xd6, 0xfc, 0xcd, + 0x00, 0x1f, 0xf5, 0x04, 0x97, 0xb2, 0x97, 0x5e, 0xa1, 0x63, 0x14, 0xd2, 0x00, 0x29, 0x2e, 0xd2, + 0xd5, 0x4d, 0x27, 0x4e, 0xa4, 0xd4, 0x84, 0x7b, 0x6e, 0x91, 0xc2, 0x1a, 0xb8, 0x1d, 0xf1, 0x1f, + 0x88, 0xc8, 0x77, 0x33, 0x4b, 0x20, 0x02, 0x95, 0x28, 0xf6, 0x4f, 0x48, 0xa2, 0x97, 0x6c, 0xa5, + 0x53, 0x7b, 0xaf, 0x89, 0x6d, 0x96, 0x74, 0x37, 0xff, 0x7d, 0xb3, 0xfe, 0x38, 0x41, 0xd3, 0x70, + 0xab, 0x99, 0xba, 0x49, 0x98, 0x8c, 0xa5, 0x97, 0xf1, 0x9a, 0x7f, 0xfe, 0xbe, 0x51, 0xcb, 0x2f, + 0x1a, 0x16, 0x49, 0xa4, 0xb8, 0xed, 0xc4, 0xfe, 0x3e, 0x49, 0xdc, 0x5c, 0xb8, 0xf9, 0x3d, 0xb8, + 0xdf, 0xcb, 0x47, 0xe0, 0x20, 0x7c, 0x42, 0x14, 0xdc, 0x07, 0x65, 0x95, 0x44, 0x44, 0x9f, 0xf0, + 0x7e, 0xe7, 0x73, 0xfb, 0x06, 0x0f, 0x86, 0xbd, 0x28, 0x31, 0x4c, 0x22, 0xe2, 0x6a, 0x11, 0x08, + 0x41, 0x39, 0x40, 0x0a, 0xe9, 0xb6, 0xee, 0xb9, 0x3a, 0x6e, 0x7e, 0x07, 0x56, 0x17, 0xf1, 0x12, + 0x1e, 0x80, 0x72, 0x48, 0x65, 0x6a, 0xe3, 0x52, 0x6b, 0xa5, 0xb3, 0xf9, 0x01, 0xdf, 0xec, 0x96, + 0xd3, 0x29, 0xba, 0x5a, 0xe6, 0xd3, 0x3f, 0x0c, 0x00, 0xdf, 0x3f, 0x12, 0xfc, 0x02, 0x58, 0xbd, + 0x97, 0x87, 0x83, 0xa3, 0x83, 0xbe, 0xeb, 0x39, 0xdb, 0xbd, 0xfd, 0xfe, 0xd0, 0x1b, 0x7e, 0xed, + 0xf4, 0xbd, 0xa3, 0xc3, 0x81, 0xd3, 0xef, 0x3d, 0xdf, 0x7d, 0xde, 0xdf, 0xa9, 0x96, 0x1a, 0x0f, + 0x4f, 0xcf, 0xac, 0x07, 0x47, 0x4c, 0x46, 0x04, 0xd3, 0x11, 0x25, 0x41, 0x6e, 0x4b, 0x1b, 0x34, + 0xae, 0x24, 0x0f, 0x5e, 0x6c, 0x0f, 0xf6, 0xaa, 0x46, 0x63, 0xf5, 0xf4, 0xcc, 0x5a, 0x19, 0x84, + 0x48, 0x4e, 0x72, 0xc2, 0x26, 0x58, 0xbb, 0x92, 0x70, 0x3c, 0xe8, 0x1d, 0x54, 0x6f, 0x35, 0x6a, + 0xa7, 0x67, 0x56, 0xf5, 0x58, 0xe2, 0x03, 0xa4, 0x62, 0x51, 0x7c, 0xa5, 0x51, 0xfe, 0xe9, 0x57, + 0xb3, 0xd4, 0x1d, 0xbe, 0x3a, 0x37, 0x8d, 0xd7, 0xe7, 0xa6, 0xf1, 0xcf, 0xb9, 0x69, 0xfc, 0x7c, + 0x61, 0x96, 0x5e, 0x5f, 0x98, 0xa5, 0xbf, 0x2e, 0xcc, 0xd2, 0x37, 0x5b, 0x63, 0xaa, 0x26, 0xb1, + 0x6f, 0x63, 0x3e, 0xcd, 0x1f, 0xd0, 0xf6, 0x5b, 0xaf, 0x36, 0xe6, 0x6f, 0xf5, 0x8f, 0x8b, 0xbf, + 0x81, 0x74, 0x14, 0xd2, 0xaf, 0xe8, 0xad, 0xd9, 0xfc, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x1e, 0xa4, + 0x31, 0x80, 0x37, 0x06, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -594,7 +631,7 @@ func (m *CrossChainValidator) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *SlashRequest) Marshal() (dAtA []byte, err error) { +func (m *ConsumerPacket) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -604,37 +641,32 @@ func (m *SlashRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *SlashRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *ConsumerPacket) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *SlashRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ConsumerPacket) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.Infraction != 0 { - i = encodeVarintConsumer(dAtA, i, uint64(m.Infraction)) + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintConsumer(dAtA, i, uint64(len(m.Data))) i-- - dAtA[i] = 0x10 + dAtA[i] = 0x12 } - if m.Packet != nil { - { - size, err := m.Packet.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintConsumer(dAtA, i, uint64(size)) - } + if m.Type != 0 { + i = encodeVarintConsumer(dAtA, i, uint64(m.Type)) i-- - dAtA[i] = 0xa + dAtA[i] = 0x8 } return len(dAtA) - i, nil } -func (m *SlashRequests) Marshal() (dAtA []byte, err error) { +func (m *ConsumerPackets) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -644,20 +676,20 @@ func (m *SlashRequests) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *SlashRequests) MarshalTo(dAtA []byte) (int, error) { +func (m *ConsumerPackets) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *SlashRequests) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ConsumerPackets) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.Requests) > 0 { - for iNdEx := len(m.Requests) - 1; iNdEx >= 0; iNdEx-- { + if len(m.List) > 0 { + for iNdEx := len(m.List) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.Requests[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.List[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -750,30 +782,30 @@ func (m *CrossChainValidator) Size() (n int) { return n } -func (m *SlashRequest) Size() (n int) { +func (m *ConsumerPacket) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.Packet != nil { - l = m.Packet.Size() - n += 1 + l + sovConsumer(uint64(l)) + if m.Type != 0 { + n += 1 + sovConsumer(uint64(m.Type)) } - if m.Infraction != 0 { - n += 1 + sovConsumer(uint64(m.Infraction)) + l = len(m.Data) + if l > 0 { + n += 1 + l + sovConsumer(uint64(l)) } return n } -func (m *SlashRequests) Size() (n int) { +func (m *ConsumerPackets) Size() (n int) { if m == nil { return 0 } var l int _ = l - if len(m.Requests) > 0 { - for _, e := range m.Requests { + if len(m.List) > 0 { + for _, e := range m.List { l = e.Size() n += 1 + l + sovConsumer(uint64(l)) } @@ -1298,7 +1330,7 @@ func (m *CrossChainValidator) Unmarshal(dAtA []byte) error { } return nil } -func (m *SlashRequest) Unmarshal(dAtA []byte) error { +func (m *ConsumerPacket) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1321,17 +1353,17 @@ func (m *SlashRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: SlashRequest: wiretype end group for non-group") + return fmt.Errorf("proto: ConsumerPacket: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: SlashRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ConsumerPacket: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Packet", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) } - var msglen int + m.Type = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowConsumer @@ -1341,33 +1373,16 @@ func (m *SlashRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + m.Type |= ConsumerPacketType(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { - return ErrInvalidLengthConsumer - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthConsumer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Packet == nil { - m.Packet = &types1.SlashPacketData{} - } - if err := m.Packet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Infraction", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) } - m.Infraction = 0 + var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowConsumer @@ -1377,11 +1392,26 @@ func (m *SlashRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Infraction |= types2.InfractionType(b&0x7F) << shift + byteLen |= int(b&0x7F) << shift if b < 0x80 { break } } + if byteLen < 0 { + return ErrInvalidLengthConsumer + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthConsumer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipConsumer(dAtA[iNdEx:]) @@ -1403,7 +1433,7 @@ func (m *SlashRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *SlashRequests) Unmarshal(dAtA []byte) error { +func (m *ConsumerPackets) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1426,15 +1456,15 @@ func (m *SlashRequests) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: SlashRequests: wiretype end group for non-group") + return fmt.Errorf("proto: ConsumerPackets: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: SlashRequests: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ConsumerPackets: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Requests", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field List", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1461,8 +1491,8 @@ func (m *SlashRequests) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Requests = append(m.Requests, SlashRequest{}) - if err := m.Requests[len(m.Requests)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.List = append(m.List, ConsumerPacket{}) + if err := m.List[len(m.List)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/ccv/consumer/types/genesis.go b/x/ccv/consumer/types/genesis.go index a2fdbe38a9..1576b57ad0 100644 --- a/x/ccv/consumer/types/genesis.go +++ b/x/ccv/consumer/types/genesis.go @@ -13,7 +13,7 @@ import ( // NewInitialGenesisState returns a consumer GenesisState for a completely new consumer chain. func NewInitialGenesisState(cs *ibctmtypes.ClientState, consState *ibctmtypes.ConsensusState, - initValSet []abci.ValidatorUpdate, slashRequests SlashRequests, params Params) *GenesisState { + initValSet []abci.ValidatorUpdate, params Params) *GenesisState { return &GenesisState{ Params: params, @@ -21,12 +21,12 @@ func NewInitialGenesisState(cs *ibctmtypes.ClientState, consState *ibctmtypes.Co ProviderClientState: cs, ProviderConsensusState: consState, InitialValSet: initValSet, - PendingSlashRequests: slashRequests, } } // NewRestartGenesisState returns a consumer GenesisState that has already been established. -func NewRestartGenesisState(clientID, channelID string, +func NewRestartGenesisState( + clientID, channelID string, maturingPackets []MaturingVSCPacket, initValSet []abci.ValidatorUpdate, heightToValsetUpdateIDs []HeightToValsetUpdateID, diff --git a/x/ccv/consumer/types/genesis.pb.go b/x/ccv/consumer/types/genesis.pb.go index 5a5f0bb33c..74fef7f071 100644 --- a/x/ccv/consumer/types/genesis.pb.go +++ b/x/ccv/consumer/types/genesis.pb.go @@ -44,8 +44,6 @@ type GenesisState struct { HeightToValsetUpdateId []HeightToValsetUpdateID `protobuf:"bytes,9,rep,name=height_to_valset_update_id,json=heightToValsetUpdateId,proto3" json:"height_to_valset_update_id"` // OutstandingDowntimes nil on new chain, filled on restart. OutstandingDowntimeSlashing []OutstandingDowntime `protobuf:"bytes,10,rep,name=outstanding_downtime_slashing,json=outstandingDowntimeSlashing,proto3" json:"outstanding_downtime_slashing"` - // PendingSlashRequests filled in on new chain, nil on restart. - PendingSlashRequests SlashRequests `protobuf:"bytes,11,opt,name=pending_slash_requests,json=pendingSlashRequests,proto3" json:"pending_slash_requests"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -151,13 +149,6 @@ func (m *GenesisState) GetOutstandingDowntimeSlashing() []OutstandingDowntime { return nil } -func (m *GenesisState) GetPendingSlashRequests() SlashRequests { - if m != nil { - return m.PendingSlashRequests - } - return SlashRequests{} -} - // MaturingVSCPacket defines the genesis information for the // unbonding VSC packet type MaturingVSCPacket struct { @@ -324,53 +315,51 @@ func init() { } var fileDescriptor_2db73a6057a27482 = []byte{ - // 729 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcf, 0x4f, 0x1b, 0x39, - 0x14, 0xce, 0x2c, 0x21, 0x10, 0x03, 0x0b, 0x18, 0x36, 0x9a, 0x25, 0xda, 0x6c, 0x36, 0x5c, 0x22, - 0x6d, 0x3b, 0xa3, 0xa4, 0x52, 0x55, 0xb5, 0x52, 0xa5, 0x02, 0x52, 0x9b, 0x43, 0x29, 0x9a, 0x40, - 0x0e, 0x5c, 0x46, 0x8e, 0xc7, 0x9a, 0xb1, 0x3a, 0x63, 0xa7, 0x63, 0xcf, 0x50, 0x0e, 0xbd, 0xf4, - 0x2f, 0xe8, 0x9f, 0xc5, 0xa1, 0x07, 0x8e, 0x3d, 0x55, 0x15, 0xfc, 0x23, 0xd5, 0xd8, 0xce, 0xaf, - 0x12, 0xa9, 0xb9, 0xd9, 0x7e, 0xef, 0xfb, 0xbe, 0xf7, 0xbe, 0x67, 0x1b, 0x74, 0x28, 0x93, 0x24, - 0xc5, 0x11, 0xa2, 0xcc, 0x17, 0x04, 0x67, 0x29, 0x95, 0xd7, 0x2e, 0xc6, 0xb9, 0x8b, 0x39, 0x13, - 0x59, 0x42, 0x52, 0x37, 0xef, 0xb8, 0x21, 0x61, 0x44, 0x50, 0xe1, 0x8c, 0x52, 0x2e, 0x39, 0x3c, - 0x5c, 0x00, 0x71, 0x30, 0xce, 0x9d, 0x31, 0xc4, 0xc9, 0x3b, 0x07, 0x2e, 0x1d, 0x62, 0x37, 0xa6, - 0x61, 0x24, 0x71, 0x4c, 0x09, 0x93, 0xc2, 0x95, 0x84, 0x05, 0x24, 0x4d, 0x28, 0x93, 0x05, 0xe5, - 0x74, 0xa7, 0x59, 0x0f, 0xfe, 0x2b, 0x00, 0x98, 0xa7, 0xc4, 0xc5, 0x11, 0x62, 0x8c, 0xc4, 0x45, - 0x96, 0x59, 0x9a, 0x94, 0xfd, 0x90, 0x87, 0x5c, 0x2d, 0xdd, 0x62, 0x65, 0x4e, 0xbb, 0xcb, 0x74, - 0x30, 0x29, 0x4d, 0x63, 0xea, 0x33, 0xc5, 0xa0, 0x21, 0xa6, 0xae, 0xbc, 0x1e, 0x11, 0xd3, 0x5f, - 0xeb, 0xeb, 0x1a, 0xd8, 0x7c, 0xad, 0x3b, 0xee, 0x4b, 0x24, 0x09, 0xec, 0x81, 0xca, 0x08, 0xa5, - 0x28, 0x11, 0xb6, 0xd5, 0xb4, 0xda, 0x1b, 0xdd, 0xff, 0x9d, 0x25, 0x1c, 0x70, 0xce, 0x14, 0xe4, - 0xa8, 0x7c, 0xf3, 0xfd, 0xdf, 0x92, 0x67, 0x08, 0xe0, 0x23, 0x00, 0x47, 0x29, 0xcf, 0x69, 0x40, - 0x52, 0x5f, 0x1b, 0xe3, 0xd3, 0xc0, 0xfe, 0xa3, 0x69, 0xb5, 0xab, 0xde, 0xce, 0x38, 0x72, 0xac, - 0x02, 0xbd, 0x00, 0x3a, 0x60, 0x6f, 0x9a, 0xad, 0xad, 0x28, 0xd2, 0x57, 0x54, 0xfa, 0xee, 0x24, - 0x5d, 0x47, 0x7a, 0x01, 0xac, 0x83, 0x2a, 0x23, 0x57, 0xbe, 0x2a, 0xcc, 0x2e, 0x37, 0xad, 0xf6, - 0xba, 0xb7, 0xce, 0xc8, 0xd5, 0x71, 0xb1, 0x87, 0x3e, 0xf8, 0xeb, 0x57, 0x69, 0x51, 0xb4, 0x67, - 0xaf, 0x8e, 0x9b, 0x1a, 0x62, 0x67, 0x76, 0x62, 0xce, 0xcc, 0x8c, 0xf2, 0x8e, 0xa3, 0xab, 0x52, - 0x8e, 0x78, 0x7b, 0xf3, 0xa5, 0x6a, 0x9b, 0x22, 0x60, 0x4f, 0x05, 0x38, 0x13, 0x84, 0x89, 0x4c, - 0x18, 0x8d, 0x8a, 0xd2, 0x70, 0x7e, 0xab, 0x31, 0x86, 0x69, 0x99, 0xda, 0x44, 0x66, 0xee, 0x1c, - 0x86, 0x60, 0x27, 0x41, 0x32, 0x4b, 0x29, 0x0b, 0xfd, 0x11, 0xc2, 0xef, 0x89, 0x14, 0xf6, 0x5a, - 0x73, 0xa5, 0xbd, 0xd1, 0x7d, 0xba, 0xd4, 0x68, 0xde, 0x1a, 0xf0, 0xa0, 0x7f, 0x7c, 0xa6, 0xe0, - 0x66, 0x4a, 0xdb, 0x63, 0x56, 0x7d, 0x2a, 0xe0, 0x29, 0xd8, 0xa6, 0x8c, 0x4a, 0x8a, 0x62, 0x3f, - 0x47, 0xb1, 0x2f, 0x88, 0xb4, 0xd7, 0x95, 0x4e, 0x73, 0xb6, 0xf0, 0xe2, 0x06, 0x39, 0x03, 0x14, - 0xd3, 0x00, 0x49, 0x9e, 0x5e, 0x8c, 0x02, 0x24, 0x89, 0x61, 0xdc, 0x32, 0xf0, 0x01, 0x8a, 0xfb, - 0x44, 0xc2, 0x4f, 0xe0, 0x20, 0x22, 0x45, 0xfb, 0xbe, 0xe4, 0x05, 0xa3, 0x20, 0xd2, 0xcf, 0x54, - 0x7e, 0x31, 0xd7, 0xaa, 0xa2, 0x7e, 0xb1, 0x54, 0x0b, 0x6f, 0x14, 0xcd, 0x39, 0x1f, 0x28, 0x12, - 0xad, 0xd9, 0x3b, 0x31, 0xaa, 0xb5, 0x68, 0x51, 0x34, 0x80, 0x9f, 0x2d, 0xf0, 0x0f, 0xcf, 0xa4, - 0x90, 0x88, 0x05, 0x85, 0x77, 0x01, 0xbf, 0x62, 0x92, 0x26, 0xc4, 0x17, 0x31, 0x12, 0x11, 0x65, - 0xa1, 0x0d, 0x54, 0x09, 0xcf, 0x96, 0x2a, 0xe1, 0xdd, 0x94, 0xe9, 0xc4, 0x10, 0x19, 0xfd, 0x3a, - 0x7f, 0x18, 0xea, 0x1b, 0x09, 0xc8, 0x40, 0x6d, 0x44, 0xb4, 0xbe, 0x92, 0xf5, 0x53, 0xf2, 0x21, - 0x23, 0x42, 0x0a, 0x7b, 0x43, 0x5d, 0x92, 0xee, 0x52, 0xe2, 0x8a, 0xce, 0x33, 0x48, 0x23, 0xbb, - 0x6f, 0x78, 0xe7, 0x62, 0xad, 0x53, 0xb0, 0xfb, 0x60, 0xde, 0x70, 0x1f, 0xac, 0xe6, 0x02, 0xf7, - 0x02, 0xf5, 0xa2, 0xcb, 0x9e, 0xde, 0xc0, 0x43, 0xb0, 0xa5, 0x6f, 0x80, 0xbc, 0xf6, 0x8b, 0x9a, - 0xd5, 0xc3, 0x2c, 0x7b, 0x9b, 0xe3, 0xc3, 0x73, 0x9a, 0x90, 0xd6, 0x25, 0xa8, 0x2d, 0x36, 0x1f, - 0xd6, 0x40, 0x45, 0x1b, 0x6f, 0x58, 0xcd, 0x0e, 0xb6, 0xc1, 0xce, 0x83, 0x59, 0x6b, 0xe6, 0x3f, - 0xf3, 0xb9, 0x01, 0xb5, 0x2e, 0xc0, 0xde, 0x02, 0x57, 0xe1, 0x4b, 0x50, 0xcf, 0xc7, 0xd7, 0x6b, - 0xe6, 0x69, 0xa1, 0x20, 0x48, 0x89, 0xd0, 0xbf, 0x52, 0xd5, 0xfb, 0x7b, 0x92, 0x32, 0x79, 0x2d, - 0xaf, 0x74, 0xc2, 0xd1, 0xf9, 0xcd, 0x5d, 0xc3, 0xba, 0xbd, 0x6b, 0x58, 0x3f, 0xee, 0x1a, 0xd6, - 0x97, 0xfb, 0x46, 0xe9, 0xf6, 0xbe, 0x51, 0xfa, 0x76, 0xdf, 0x28, 0x5d, 0x3e, 0x0f, 0xa9, 0x8c, - 0xb2, 0xa1, 0x83, 0x79, 0xe2, 0x62, 0x2e, 0x12, 0x2e, 0xdc, 0xa9, 0xfb, 0x8f, 0x27, 0xdf, 0xe9, - 0xc7, 0xf9, 0x0f, 0x55, 0xfd, 0x96, 0xc3, 0x8a, 0xfa, 0x2e, 0x9f, 0xfc, 0x0c, 0x00, 0x00, 0xff, - 0xff, 0x09, 0x61, 0x41, 0x6b, 0x43, 0x06, 0x00, 0x00, + // 693 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcf, 0x6f, 0xd3, 0x30, + 0x14, 0x6e, 0x58, 0x57, 0x56, 0x6f, 0x63, 0x9b, 0x37, 0xaa, 0xb0, 0x8a, 0x52, 0xba, 0x4b, 0x25, + 0x20, 0x51, 0x87, 0x84, 0x10, 0x48, 0x48, 0x6c, 0x93, 0xa0, 0x07, 0xc6, 0xd4, 0x6e, 0x3d, 0xec, + 0x12, 0xb9, 0x8e, 0x95, 0x58, 0x24, 0x76, 0x15, 0x3b, 0x19, 0x3b, 0x70, 0xe1, 0x2f, 0xe0, 0xcf, + 0xda, 0x71, 0x47, 0x0e, 0x08, 0xa1, 0xed, 0x1f, 0x41, 0xb1, 0x9d, 0xfe, 0x60, 0x95, 0xe8, 0x2d, + 0xf6, 0x7b, 0xdf, 0xf7, 0xbd, 0xf7, 0x3d, 0xe7, 0x81, 0x0e, 0x65, 0x92, 0x24, 0x38, 0x44, 0x94, + 0x79, 0x82, 0xe0, 0x34, 0xa1, 0xf2, 0xd2, 0xc5, 0x38, 0x73, 0x31, 0x67, 0x22, 0x8d, 0x49, 0xe2, + 0x66, 0x1d, 0x37, 0x20, 0x8c, 0x08, 0x2a, 0x9c, 0x51, 0xc2, 0x25, 0x87, 0x7b, 0x73, 0x20, 0x0e, + 0xc6, 0x99, 0x53, 0x40, 0x9c, 0xac, 0xb3, 0xeb, 0xd2, 0x21, 0x76, 0x23, 0x1a, 0x84, 0x12, 0x47, + 0x94, 0x30, 0x29, 0x5c, 0x49, 0x98, 0x4f, 0x92, 0x98, 0x32, 0x99, 0x53, 0x4e, 0x4e, 0x9a, 0x75, + 0xf7, 0x69, 0x0e, 0xc0, 0x3c, 0x21, 0x2e, 0x0e, 0x11, 0x63, 0x24, 0xca, 0xb3, 0xcc, 0xa7, 0x49, + 0xd9, 0x09, 0x78, 0xc0, 0xd5, 0xa7, 0x9b, 0x7f, 0x99, 0xdb, 0xfd, 0x45, 0x3a, 0x18, 0x97, 0xa6, + 0x31, 0xf5, 0xa9, 0x62, 0xd0, 0x10, 0x53, 0x57, 0x5e, 0x8e, 0x88, 0xe9, 0xaf, 0xf5, 0xab, 0x02, + 0xd6, 0x3e, 0xe8, 0x8e, 0xfb, 0x12, 0x49, 0x02, 0xbb, 0xa0, 0x32, 0x42, 0x09, 0x8a, 0x85, 0x6d, + 0x35, 0xad, 0xf6, 0xea, 0xfe, 0x33, 0x67, 0x01, 0x07, 0x9c, 0x13, 0x05, 0x39, 0x28, 0x5f, 0xfd, + 0x7e, 0x52, 0xea, 0x19, 0x02, 0xf8, 0x1c, 0xc0, 0x51, 0xc2, 0x33, 0xea, 0x93, 0xc4, 0xd3, 0xc6, + 0x78, 0xd4, 0xb7, 0xef, 0x35, 0xad, 0x76, 0xb5, 0xb7, 0x59, 0x44, 0x0e, 0x55, 0xa0, 0xeb, 0x43, + 0x07, 0x6c, 0x4f, 0xb2, 0xb5, 0x15, 0x79, 0xfa, 0x92, 0x4a, 0xdf, 0x1a, 0xa7, 0xeb, 0x48, 0xd7, + 0x87, 0x75, 0x50, 0x65, 0xe4, 0xc2, 0x53, 0x85, 0xd9, 0xe5, 0xa6, 0xd5, 0x5e, 0xe9, 0xad, 0x30, + 0x72, 0x71, 0x98, 0x9f, 0xa1, 0x07, 0x1e, 0xfe, 0x2b, 0x2d, 0xf2, 0xf6, 0xec, 0xe5, 0xa2, 0xa9, + 0x21, 0x76, 0xa6, 0x27, 0xe6, 0x4c, 0xcd, 0x28, 0xeb, 0x38, 0xba, 0x2a, 0xe5, 0x48, 0x6f, 0x7b, + 0xb6, 0x54, 0x6d, 0x53, 0x08, 0xec, 0x89, 0x00, 0x67, 0x82, 0x30, 0x91, 0x0a, 0xa3, 0x51, 0x51, + 0x1a, 0xce, 0x7f, 0x35, 0x0a, 0x98, 0x96, 0xa9, 0x8d, 0x65, 0x66, 0xee, 0x61, 0x00, 0x36, 0x63, + 0x24, 0xd3, 0x84, 0xb2, 0xc0, 0x1b, 0x21, 0xfc, 0x85, 0x48, 0x61, 0xdf, 0x6f, 0x2e, 0xb5, 0x57, + 0xf7, 0x5f, 0x2d, 0x34, 0x9a, 0x4f, 0x06, 0x3c, 0xe8, 0x1f, 0x9e, 0x28, 0xb8, 0x99, 0xd2, 0x46, + 0xc1, 0xaa, 0x6f, 0x05, 0x3c, 0x06, 0x1b, 0x94, 0x51, 0x49, 0x51, 0xe4, 0x65, 0x28, 0xf2, 0x04, + 0x91, 0xf6, 0x8a, 0xd2, 0x69, 0x4e, 0x17, 0x9e, 0xbf, 0x20, 0x67, 0x80, 0x22, 0xea, 0x23, 0xc9, + 0x93, 0xb3, 0x91, 0x8f, 0x24, 0x31, 0x8c, 0xeb, 0x06, 0x3e, 0x40, 0x51, 0x9f, 0x48, 0xf8, 0x0d, + 0xec, 0x86, 0x24, 0x6f, 0xdf, 0x93, 0x3c, 0x67, 0x14, 0x44, 0x7a, 0xa9, 0xca, 0xcf, 0xe7, 0x5a, + 0x55, 0xd4, 0x6f, 0x17, 0x6a, 0xe1, 0xa3, 0xa2, 0x39, 0xe5, 0x03, 0x45, 0xa2, 0x35, 0xbb, 0x47, + 0x46, 0xb5, 0x16, 0xce, 0x8b, 0xfa, 0xf0, 0xbb, 0x05, 0x1e, 0xf3, 0x54, 0x0a, 0x89, 0x98, 0x9f, + 0x7b, 0xe7, 0xf3, 0x0b, 0x26, 0x69, 0x4c, 0x3c, 0x11, 0x21, 0x11, 0x52, 0x16, 0xd8, 0x40, 0x95, + 0xf0, 0x7a, 0xa1, 0x12, 0x3e, 0x4f, 0x98, 0x8e, 0x0c, 0x91, 0xd1, 0xaf, 0xf3, 0xbb, 0xa1, 0xbe, + 0x91, 0x68, 0x1d, 0x83, 0xad, 0x3b, 0xfe, 0xc3, 0x1d, 0xb0, 0x9c, 0x09, 0xdc, 0xf5, 0xd5, 0x1f, + 0x56, 0xee, 0xe9, 0x03, 0xdc, 0x03, 0xeb, 0x7a, 0x22, 0xf2, 0xd2, 0xcb, 0x39, 0xd4, 0x8f, 0x52, + 0xee, 0xad, 0x15, 0x97, 0xa7, 0x34, 0x26, 0xad, 0x73, 0x50, 0x9b, 0x6f, 0x06, 0xac, 0x81, 0x8a, + 0x36, 0xc2, 0xb0, 0x9a, 0x13, 0x6c, 0x83, 0xcd, 0x3b, 0xde, 0x6b, 0xe6, 0x07, 0xd9, 0x8c, 0x61, + 0xad, 0x33, 0xb0, 0x3d, 0xa7, 0x4b, 0xf8, 0x0e, 0xd4, 0xb3, 0x62, 0xdc, 0x53, 0x4f, 0x1d, 0xf9, + 0x7e, 0x42, 0x84, 0xde, 0x12, 0xd5, 0xde, 0xa3, 0x71, 0xca, 0xf8, 0xf5, 0xbe, 0xd7, 0x09, 0x07, + 0xa7, 0x57, 0x37, 0x0d, 0xeb, 0xfa, 0xa6, 0x61, 0xfd, 0xb9, 0x69, 0x58, 0x3f, 0x6e, 0x1b, 0xa5, + 0xeb, 0xdb, 0x46, 0xe9, 0xe7, 0x6d, 0xa3, 0x74, 0xfe, 0x26, 0xa0, 0x32, 0x4c, 0x87, 0x0e, 0xe6, + 0xb1, 0x8b, 0xb9, 0x88, 0xb9, 0x70, 0x27, 0xa3, 0x78, 0x31, 0x5e, 0x6f, 0x5f, 0x67, 0x17, 0x9c, + 0xda, 0x5e, 0xc3, 0x8a, 0x5a, 0x5f, 0x2f, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xd5, 0xa8, 0x41, + 0x3e, 0xd3, 0x05, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -393,16 +382,6 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - { - size, err := m.PendingSlashRequests.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x5a if len(m.OutstandingDowntimeSlashing) > 0 { for iNdEx := len(m.OutstandingDowntimeSlashing) - 1; iNdEx >= 0; iNdEx-- { { @@ -678,8 +657,6 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } - l = m.PendingSlashRequests.Size() - n += 1 + l + sovGenesis(uint64(l)) return n } @@ -1086,39 +1063,6 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 11: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PendingSlashRequests", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.PendingSlashRequests.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/ccv/consumer/types/genesis_test.go b/x/ccv/consumer/types/genesis_test.go index 165e4abcce..410ba28a7e 100644 --- a/x/ccv/consumer/types/genesis_test.go +++ b/x/ccv/consumer/types/genesis_test.go @@ -55,29 +55,29 @@ func TestValidateInitialGenesisState(t *testing.T) { }{ { "valid new consumer genesis state", - types.NewInitialGenesisState(cs, consensusState, valUpdates, types.SlashRequests{}, params), + types.NewInitialGenesisState(cs, consensusState, valUpdates, params), false, }, { "invalid new consumer genesis state: nil client state", - types.NewInitialGenesisState(nil, consensusState, valUpdates, types.SlashRequests{}, params), + types.NewInitialGenesisState(nil, consensusState, valUpdates, params), true, }, { "invalid new consumer genesis state: invalid client state", types.NewInitialGenesisState(&ibctmtypes.ClientState{ChainId: "badClientState"}, - consensusState, valUpdates, types.SlashRequests{}, params), + consensusState, valUpdates, params), true, }, { "invalid new consumer genesis state: nil consensus state", - types.NewInitialGenesisState(cs, nil, valUpdates, types.SlashRequests{}, params), + types.NewInitialGenesisState(cs, nil, valUpdates, params), true, }, { "invalid new consumer genesis state: invalid consensus state", types.NewInitialGenesisState(cs, &ibctmtypes.ConsensusState{Timestamp: time.Now()}, - valUpdates, types.SlashRequests{}, params), + valUpdates, params), true, }, { @@ -93,7 +93,6 @@ func TestValidateInitialGenesisState(t *testing.T) { valUpdates, nil, nil, - types.SlashRequests{}, }, true, }, @@ -110,7 +109,6 @@ func TestValidateInitialGenesisState(t *testing.T) { valUpdates, nil, nil, - types.SlashRequests{}, }, true, }, @@ -127,13 +125,12 @@ func TestValidateInitialGenesisState(t *testing.T) { valUpdates, nil, nil, - types.SlashRequests{}, }, true, }, { "invalid new consumer genesis state: nil initial validator set", - types.NewInitialGenesisState(cs, consensusState, nil, types.SlashRequests{}, params), + types.NewInitialGenesisState(cs, consensusState, nil, params), true, }, { @@ -141,12 +138,12 @@ func TestValidateInitialGenesisState(t *testing.T) { types.NewInitialGenesisState( cs, ibctmtypes.NewConsensusState( time.Now(), commitmenttypes.NewMerkleRoot([]byte("apphash")), []byte("wrong_hash")), - valUpdates, types.SlashRequests{}, params), + valUpdates, params), true, }, { "invalid new consumer genesis state: invalid params", - types.NewInitialGenesisState(cs, consensusState, valUpdates, types.SlashRequests{}, + types.NewInitialGenesisState(cs, consensusState, valUpdates, types.NewParams( true, types.DefaultBlocksPerDistributionTransmission, @@ -247,7 +244,6 @@ func TestValidateRestartGenesisState(t *testing.T) { valUpdates, nil, nil, - types.SlashRequests{}, }, true, }, @@ -264,7 +260,6 @@ func TestValidateRestartGenesisState(t *testing.T) { valUpdates, nil, nil, - types.SlashRequests{}, }, true, }, diff --git a/x/ccv/consumer/types/keys.go b/x/ccv/consumer/types/keys.go index 422cbd1528..46fb5e9b8a 100644 --- a/x/ccv/consumer/types/keys.go +++ b/x/ccv/consumer/types/keys.go @@ -59,9 +59,11 @@ const ( // OutstandingDowntimePrefix is the byte prefix that will store the validators outstanding downtime by consensus address OutstandingDowntimeBytePrefix - // PendingSlashRequestsPrefix is the byte prefix that will store a list of slash request that must be sent - // to the provider chain once the CCV channel is established - PendingSlashRequestsBytePrefix + // PendingDataPacketsBytePrefix is the byte prefix for storing + // a list of data packets that cannot be sent yet to the provider + // chain either because the CCV channel is not established or + // because the client is expired + PendingDataPacketsBytePrefix // CrossChainValidatorPrefix is the byte prefix that will store cross-chain validators by consensus address CrossChainValidatorBytePrefix diff --git a/x/ccv/consumer/types/keys_test.go b/x/ccv/consumer/types/keys_test.go index f3bcc0dd15..7df0e45607 100644 --- a/x/ccv/consumer/types/keys_test.go +++ b/x/ccv/consumer/types/keys_test.go @@ -32,7 +32,7 @@ func TestNoDuplicates(t *testing.T) { // any of which should be a single, unique byte. func getSingleByteKeys() [][]byte { - keys := make([][]byte, 12) + keys := make([][]byte, 32) i := 0 keys[i], i = PortKey(), i+1 @@ -45,8 +45,8 @@ func getSingleByteKeys() [][]byte { keys[i], i = []byte{PacketMaturityTimeBytePrefix}, i+1 keys[i], i = []byte{HeightValsetUpdateIDBytePrefix}, i+1 keys[i], i = []byte{OutstandingDowntimeBytePrefix}, i+1 - keys[i], i = []byte{PendingSlashRequestsBytePrefix}, i+1 - keys[i] = []byte{CrossChainValidatorBytePrefix} + keys[i], i = []byte{PendingDataPacketsBytePrefix}, i+1 + keys[i], i = []byte{CrossChainValidatorBytePrefix}, i+1 - return keys + return keys[:i] } diff --git a/x/ccv/provider/keeper/genesis.go b/x/ccv/provider/keeper/genesis.go index 3f91a0f02b..fdc82ca360 100644 --- a/x/ccv/provider/keeper/genesis.go +++ b/x/ccv/provider/keeper/genesis.go @@ -71,9 +71,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { k.SetUnbondingOpIndex(ctx, chainID, ubdOpIndex.ValsetUpdateId, ubdOpIndex.UnbondingOpIndex) } } else { - for _, vsc := range cs.PendingValsetChanges { - k.AppendPendingVSC(ctx, chainID, vsc) - } + k.AppendPendingPackets(ctx, chainID, cs.PendingValsetChanges...) } } @@ -112,12 +110,9 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { ) return true }) - } else { - if pendingVSC, found := k.GetPendingVSCs(ctx, chainID); found { - cs.PendingValsetChanges = pendingVSC - } } + cs.PendingValsetChanges = k.GetPendingPackets(ctx, chainID) consumerStates = append(consumerStates, cs) return true }) diff --git a/x/ccv/provider/keeper/genesis_test.go b/x/ccv/provider/keeper/genesis_test.go index 2ef06517d3..f8fa991b1f 100644 --- a/x/ccv/provider/keeper/genesis_test.go +++ b/x/ccv/provider/keeper/genesis_test.go @@ -137,8 +137,7 @@ func assertConsumerChainStates(ctx sdk.Context, t *testing.T, pk keeper.Keeper, require.Equal(t, cs.LockUnbondingOnTimeout, pk.GetLockUnbondingOnTimeout(ctx, chainID)) if expVSC := cs.GetPendingValsetChanges(); expVSC != nil { - gotVSC, found := pk.GetPendingVSCs(ctx, chainID) - require.True(t, found) + gotVSC := pk.GetPendingPackets(ctx, chainID) require.Equal(t, expVSC, gotVSC) } diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index fed221f9f8..59c5c4292b 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -682,12 +682,14 @@ func (k Keeper) DeleteInitChainHeight(ctx sdk.Context, chainID string) { store.Delete(types.InitChainHeightKey(chainID)) } -// GetPendingVSCs returns the list of pending ValidatorSetChange packets stored under chain ID -func (k Keeper) GetPendingVSCs(ctx sdk.Context, chainID string) (packets []ccv.ValidatorSetChangePacketData, found bool) { +// GetPendingPackets returns the list of pending ValidatorSetChange packets stored under chain ID +func (k Keeper) GetPendingPackets(ctx sdk.Context, chainID string) []ccv.ValidatorSetChangePacketData { + var packets []ccv.ValidatorSetChangePacketData + store := ctx.KVStore(k.storeKey) bz := store.Get(types.PendingVSCsKey(chainID)) if bz == nil { - return nil, false + return packets } buf := bytes.NewBuffer(bz) @@ -705,15 +707,15 @@ func (k Keeper) GetPendingVSCs(ctx sdk.Context, chainID string) (packets []ccv.V packets = append(packets, p) } - return packets, true + return packets } -// AppendPendingVSC adds the given ValidatorSetChange packet to the list +// AppendPendingPackets adds the given ValidatorSetChange packet to the list // of pending ValidatorSetChange packets stored under chain ID -func (k Keeper) AppendPendingVSC(ctx sdk.Context, chainID string, packet ccv.ValidatorSetChangePacketData) { - packets, _ := k.GetPendingVSCs(ctx, chainID) - // append works also on a nil list - packets = append(packets, packet) +func (k Keeper) AppendPendingPackets(ctx sdk.Context, chainID string, newPackets ...ccv.ValidatorSetChangePacketData) { + packets := append( + k.GetPendingPackets(ctx, chainID), + newPackets...) store := ctx.KVStore(k.storeKey) var data [][]byte @@ -732,16 +734,10 @@ func (k Keeper) AppendPendingVSC(ctx sdk.Context, chainID string, packet ccv.Val store.Set(types.PendingVSCsKey(chainID), buf.Bytes()) } -// ConsumePendingVSCs empties and returns the list of pending ValidatorSetChange packets for chain ID (if it exists) -func (k Keeper) ConsumePendingVSCs(ctx sdk.Context, chainID string) (packets []ccv.ValidatorSetChangePacketData) { - packets, found := k.GetPendingVSCs(ctx, chainID) - if !found { - // there is no list of pending ValidatorSetChange packets - return nil - } +// DeletePendingPackets deletes the list of pending ValidatorSetChange packets for chain ID +func (k Keeper) DeletePendingPackets(ctx sdk.Context, chainID string) { store := ctx.KVStore(k.storeKey) store.Delete(types.PendingVSCsKey(chainID)) - return packets } // GetLockUnbondingOnTimeout returns the mapping from the given consumer chain ID to a boolean value indicating whether diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index df91c5a4c4..a745cce00d 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -118,8 +118,8 @@ func TestPendingVSCs(t *testing.T) { chainID := "consumer" - _, found := providerKeeper.GetPendingVSCs(ctx, chainID) - require.False(t, found) + pending := providerKeeper.GetPendingPackets(ctx, chainID) + require.Len(t, pending, 0) pks := ibcsimapp.CreateTestPubKeys(4) var ppks [4]tmprotocrypto.PublicKey @@ -142,12 +142,9 @@ func TestPendingVSCs(t *testing.T) { ValsetUpdateId: 2, }, } - for _, packet := range packetList { - providerKeeper.AppendPendingVSC(ctx, chainID, packet) - } + providerKeeper.AppendPendingPackets(ctx, chainID, packetList...) - packets, found := providerKeeper.GetPendingVSCs(ctx, chainID) - require.True(t, found) + packets := providerKeeper.GetPendingPackets(ctx, chainID) require.Len(t, packets, 2) newPacket := ccv.ValidatorSetChangePacketData{ @@ -156,14 +153,15 @@ func TestPendingVSCs(t *testing.T) { }, ValsetUpdateId: 3, } - providerKeeper.AppendPendingVSC(ctx, chainID, newPacket) - vscs := providerKeeper.ConsumePendingVSCs(ctx, chainID) + providerKeeper.AppendPendingPackets(ctx, chainID, newPacket) + vscs := providerKeeper.GetPendingPackets(ctx, chainID) require.Len(t, vscs, 3) require.True(t, vscs[len(vscs)-1].ValsetUpdateId == 3) require.True(t, vscs[len(vscs)-1].GetValidatorUpdates()[0].PubKey.String() == ppks[3].String()) - _, found = providerKeeper.GetPendingVSCs(ctx, chainID) - require.False(t, found) + providerKeeper.DeletePendingPackets(ctx, chainID) + pending = providerKeeper.GetPendingPackets(ctx, chainID) + require.Len(t, pending, 0) } // TestInitHeight tests the getter and setter methods for the stored block heights (on provider) when a given consumer chain was started diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index 6793294561..f274ce64da 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -168,7 +168,7 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, lockUbd, clos k.DeleteInitChainHeight(ctx, chainID) k.ConsumeSlashAcks(ctx, chainID) - k.ConsumePendingVSCs(ctx, chainID) + k.DeletePendingPackets(ctx, chainID) // release unbonding operations if they aren't locked var vscIDs []uint64 diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index 346a08b198..7fa0e54c82 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -9,6 +9,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" "github.com/cosmos/ibc-go/v3/modules/core/exported" @@ -126,61 +127,32 @@ func (k Keeper) EndBlockVSU(ctx sdk.Context) { // notify the staking module to complete all matured unbonding ops k.completeMaturedUnbondingOps(ctx) - // send latest validator updates to every registered consumer chain - k.sendValidatorUpdates(ctx) + // collect validator updates + k.QueueVSCPackets(ctx) + + // try sending packets to all chains + // if CCV channel is not established for consumer chain + // the updates will remain queued until the channel is established + k.SendPackets(ctx) } -// SendValidatorUpdates sends latest validator updates to every registered consumer chain -func (k Keeper) sendValidatorUpdates(ctx sdk.Context) { - // get current ValidatorSetUpdateId - valUpdateID := k.GetValidatorSetUpdateId(ctx) - // get the validator updates from the staking module - valUpdates := k.stakingKeeper.GetValidatorUpdates(ctx) +// SendPackets iterates over chains and sends pending packets (VSCs) to +// consumer chains with established CCV channels +// if CCV channel is not established for consumer chain +// the updates will remain queued until the channel is established +func (k Keeper) SendPackets(ctx sdk.Context) { k.IterateConsumerChains(ctx, func(ctx sdk.Context, chainID, clientID string) (stop bool) { - // check whether there is an established CCV channel to this consumer chain + // check if CCV channel is established and send if channelID, found := k.GetChainToChannel(ctx, chainID); found { - // Send pending VSC packets to consumer chain - k.SendPendingVSCPackets(ctx, chainID, channelID) - } - - // check whether there are changes in the validator set; - // note that this also entails unbonding operations - // w/o changes in the voting power of the validators in the validator set - unbondingOps, _ := k.GetUnbondingOpsFromIndex(ctx, chainID, valUpdateID) - if len(valUpdates) != 0 || len(unbondingOps) != 0 { - // construct validator set change packet data - packetData := ccv.NewValidatorSetChangePacketData(valUpdates, valUpdateID, k.ConsumeSlashAcks(ctx, chainID)) - - // check whether there is an established CCV channel to this consumer chain - if channelID, found := k.GetChainToChannel(ctx, chainID); found { - // send this validator set change packet data to the consumer chain - err := utils.SendIBCPacket( - ctx, - k.scopedKeeper, - k.channelKeeper, - channelID, // source channel id - ccv.ProviderPortID, // source port id - packetData.GetBytes(), - k.GetParams(ctx).CcvTimeoutPeriod, - ) - if err != nil { - panic(fmt.Errorf("packet could not be sent over IBC: %w", err)) - } - // set the VSC send timestamp for this packet - k.SetVscSendTimestamp(ctx, chainID, packetData.ValsetUpdateId, ctx.BlockTime()) - } else { - // store the packet data to be sent once the CCV channel is established - k.AppendPendingVSC(ctx, chainID, packetData) - } + k.SendPacketsToChain(ctx, chainID, channelID) } - return true // do not stop the iteration + return true // continue iterating chains }) - k.IncrementValidatorSetUpdateId(ctx) } -// Sends all pending ValidatorSetChangePackets to the specified chain -func (k Keeper) SendPendingVSCPackets(ctx sdk.Context, chainID, channelID string) { - pendingPackets := k.ConsumePendingVSCs(ctx, chainID) +// SendPacketsToChain sends all queued packets to the specified chain +func (k Keeper) SendPacketsToChain(ctx sdk.Context, chainID, channelID string) { + pendingPackets := k.GetPendingPackets(ctx, chainID) for _, data := range pendingPackets { // send packet over IBC err := utils.SendIBCPacket( @@ -190,9 +162,16 @@ func (k Keeper) SendPendingVSCPackets(ctx sdk.Context, chainID, channelID string channelID, // source channel id ccv.ProviderPortID, // source port id data.GetBytes(), - k.GetParams(ctx).CcvTimeoutPeriod, + k.GetCCVTimeoutPeriod(ctx), ) + if err != nil { + if clienttypes.ErrClientNotActive.Is(err) { + // IBC client is expired! + // leave the packet data stored to be sent once the client is upgraded + // the client cannot expire during iteration (in the middle of a block) + return + } panic(fmt.Errorf("packet could not be sent over IBC: %w", err)) } // set the VSC send timestamp for this packet; @@ -200,6 +179,28 @@ func (k Keeper) SendPendingVSCPackets(ctx sdk.Context, chainID, channelID string // are actually sent over IBC k.SetVscSendTimestamp(ctx, chainID, data.ValsetUpdateId, ctx.BlockTime()) } + k.DeletePendingPackets(ctx, chainID) +} + +// QueueVSCPackets queues latest validator updates for every registered consumer chain +func (k Keeper) QueueVSCPackets(ctx sdk.Context) { + valUpdateID := k.GetValidatorSetUpdateId(ctx) // curent valset update ID + // check whether there are changes in the validator set; + valUpdates := k.stakingKeeper.GetValidatorUpdates(ctx) + + k.IterateConsumerChains(ctx, func(ctx sdk.Context, chainID, clientID string) (stop bool) { + // note that this also entails unbonding operations + // w/o changes in the voting power of the validators in the validator set + unbondingOps, _ := k.GetUnbondingOpsFromIndex(ctx, chainID, valUpdateID) + if len(valUpdates) != 0 || len(unbondingOps) != 0 { + // construct validator set change packet data + packet := ccv.NewValidatorSetChangePacketData(valUpdates, valUpdateID, k.ConsumeSlashAcks(ctx, chainID)) + k.AppendPendingPackets(ctx, chainID, packet) + } + return true // do not stop the iteration + }) + + k.IncrementValidatorSetUpdateId(ctx) } // EndBlockCIS contains the EndBlock logic needed for diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go new file mode 100644 index 0000000000..dbfd008167 --- /dev/null +++ b/x/ccv/provider/keeper/relay_test.go @@ -0,0 +1,83 @@ +package keeper_test + +import ( + "testing" + + "github.com/golang/mock/gomock" + + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + ibcsimapp "github.com/cosmos/ibc-go/v3/testing/simapp" + testkeeper "github.com/cosmos/interchain-security/testutil/keeper" + ccv "github.com/cosmos/interchain-security/x/ccv/types" + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/stretchr/testify/require" +) + +// TestQueueVSCPackets tests queueing validator set updates. +func TestQueueVSCPackets(t *testing.T) { + key := ibcsimapp.CreateTestPubKeys(1)[0] + tmPubKey, _ := cryptocodec.ToTmProtoPublicKey(key) + + testCases := []struct { + name string + packets []ccv.ValidatorSetChangePacketData + expectNextValsetUpdateId uint64 + expectedQueueSize int + }{ + { + + name: "no updates to send", + packets: []ccv.ValidatorSetChangePacketData{}, + expectNextValsetUpdateId: 1, + expectedQueueSize: 0, + }, + { + name: "have updates to send", + packets: []ccv.ValidatorSetChangePacketData{ + { + ValidatorUpdates: []abci.ValidatorUpdate{ + {PubKey: tmPubKey, Power: 1}, + }, + ValsetUpdateId: 1, + }, + }, + expectNextValsetUpdateId: 1, + expectedQueueSize: 1, + }, + } + + chainID := "consumer" + + for _, tc := range testCases { + keeperParams := testkeeper.NewInMemKeeperParams(t) + ctx := keeperParams.Ctx + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mocks := testkeeper.NewMockedKeepers(ctrl) + mockStakingKeeper := mocks.MockStakingKeeper + + mockUpdates := []abci.ValidatorUpdate{} + if len(tc.packets) != 0 { + mockUpdates = tc.packets[0].ValidatorUpdates + } + + gomock.InOrder( + mockStakingKeeper.EXPECT().GetValidatorUpdates(gomock.Eq(ctx)).Return(mockUpdates), + ) + + pk := testkeeper.NewInMemProviderKeeper(keeperParams, mocks) + // no-op if tc.packets is empty + pk.AppendPendingPackets(ctx, chainID, tc.packets...) + + pk.QueueVSCPackets(ctx) + pending := pk.GetPendingPackets(ctx, chainID) + require.Len(t, pending, tc.expectedQueueSize, "pending vsc queue mismatch (%v != %v) in case: '%s'", tc.expectedQueueSize, len(pending), tc.name) + + // next valset update ID -> default value in tests is 0 + // each call to QueueValidatorUpdates will increment the ValidatorUpdateID + valUpdateID := pk.GetValidatorSetUpdateId(ctx) + require.Equal(t, tc.expectNextValsetUpdateId, valUpdateID, "valUpdateID (%v != %v) mismatch in case: '%s'", tc.expectNextValsetUpdateId, valUpdateID, tc.name) + } +}