diff --git a/.github/ISSUE_TEMPLATE/issue-template.md b/.github/ISSUE_TEMPLATE/issue-template.md index 2ff6383329..742258bf15 100644 --- a/.github/ISSUE_TEMPLATE/issue-template.md +++ b/.github/ISSUE_TEMPLATE/issue-template.md @@ -11,3 +11,7 @@ assignees: '' # Closing criteria + +# TODOs +- [ ] Labels have been added for issue +- [ ] Issue has been added to the ICS project diff --git a/Dockerfile b/Dockerfile index cc537c7ccc..e4a5ef01e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,8 +9,6 @@ ENV CGO_ENABLED=0 ENV GOOS=linux ENV GOFLAGS="-buildvcs=false" -WORKDIR /downloads - # Copy in the repo under test ADD . /interchain-security @@ -24,11 +22,13 @@ RUN go mod tidy RUN make install # Get Hermes build -FROM informalsystems/hermes:1.0.0 AS hermes-builder +# FROM informalsystems/hermes:1.0.0 AS hermes-builder +# remove line below and use the line above once hermes is updated +FROM majita/hermes-unofficial:latest AS hermes-builder FROM --platform=linux/amd64 fedora:36 RUN dnf update -y -RUN dnf install -y which iproute iputils procps-ng vim-minimal tmux net-tools htop jq +RUN dnf install -y which iproute iputils procps-ng vim-minimal tmux net-tools htop jq openssl1.1 USER root # Copy Hermes and IS binaries to final image diff --git a/README.md b/README.md index add4c88354..cc6d7af437 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,9 @@ Unit tests are useful for simple standalone functionality, and CRUD operations. ### End to End (e2e) Tests -[e2e-tests](./tests/e2e/) utilize the [IBC Testing Package](https://github.com/cosmos/ibc-go/tree/main/testing), and test functionality that is wider in scope than a unit test, but still able to be validated in-memory. Ie. code where advancing blocks would be useful, simulated handshakes, simulated packet relays, etc. +[e2e-tests](./tests/e2e/) utilize the [IBC Testing Package](https://github.com/cosmos/ibc-go/tree/main/testing), and test functionality that is wider in scope than a unit test, but still able to be validated in-memory. Ie. code where advancing blocks would be useful, simulated handshakes, simulated packet relays, etc. + +To run e2e tests against your own consumer/provider implementations, use [instance_test.go](./tests/e2e/instance_test.go) as an example. All you'll need to do is make sure your applications implement the necessary interfaces defined in [interfaces.go](./testutil/e2e/interfaces.go), then pass in an appropriate callback to the testing suites. ### Differential Tests (WIP) diff --git a/app/consumer-democracy/app.go b/app/consumer-democracy/app.go index 515d325d2d..f3ac4b024b 100644 --- a/app/consumer-democracy/app.go +++ b/app/consumer-democracy/app.go @@ -84,6 +84,7 @@ import ( ccvdistrclient "github.com/cosmos/cosmos-sdk/x/distribution/client" ccvdistrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" ccvdistrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/interchain-security/testutil/e2e" ccvdistr "github.com/cosmos/interchain-security/x/ccv/democracy/distribution" ccvstakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" @@ -757,6 +758,53 @@ func (app *App) SimulationManager() *module.SimulationManager { return app.sm } +// DemocConsumerApp interface implementations for e2e tests + +// GetConsumerKeeper implements the ConsumerApp interface. +func (app *App) GetConsumerKeeper() ibcconsumerkeeper.Keeper { + return app.ConsumerKeeper +} + +// GetE2eBankKeeper implements the ConsumerApp interface. +func (app *App) GetE2eBankKeeper() e2e.E2eBankKeeper { + return app.BankKeeper +} + +// GetE2eAccountKeeper implements the ConsumerApp interface. +func (app *App) GetE2eAccountKeeper() e2e.E2eAccountKeeper { + return app.AccountKeeper +} + +// GetE2eSlashingKeeper implements the ConsumerApp interface. +func (app *App) GetE2eSlashingKeeper() e2e.E2eSlashingKeeper { + return app.SlashingKeeper +} + +// GetE2eEvidenceKeeper implements the ConsumerApp interface. +func (app *App) GetE2eEvidenceKeeper() e2e.E2eEvidenceKeeper { + return app.EvidenceKeeper +} + +// GetE2eStakingKeeper implements the ConsumerApp interface. +func (app *App) GetE2eStakingKeeper() e2e.E2eStakingKeeper { + return app.StakingKeeper +} + +// GetE2eDistributionKeeper implements the ConsumerApp interface. +func (app *App) GetE2eDistributionKeeper() e2e.E2eDistributionKeeper { + return app.DistrKeeper +} + +// GetE2eMintKeeper implements the ConsumerApp interface. +func (app *App) GetE2eMintKeeper() e2e.E2eMintKeeper { + return app.MintKeeper +} + +// GetE2eGovKeeper implements the ConsumerApp interface. +func (app *App) GetE2eGovKeeper() e2e.E2eGovKeeper { + return app.GovKeeper +} + // TestingApp functions // GetBaseApp implements the TestingApp interface. diff --git a/app/consumer-democracy/export.go b/app/consumer-democracy/export.go index c146ab7ad2..6f7f565239 100644 --- a/app/consumer-democracy/export.go +++ b/app/consumer-democracy/export.go @@ -49,7 +49,8 @@ func (app *App) ExportAppStateAndValidators( // prepare for fresh start at zero height // NOTE zero height genesis is a temporary feature which will be deprecated -// in favour of export at a block height +// +// in favour of export at a block height func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) { // applyAllowedAddrs := false diff --git a/app/consumer/app.go b/app/consumer/app.go index 7bf07e3851..4cd1dee606 100644 --- a/app/consumer/app.go +++ b/app/consumer/app.go @@ -77,6 +77,7 @@ import ( tmos "github.com/tendermint/tendermint/libs/os" dbm "github.com/tendermint/tm-db" + "github.com/cosmos/interchain-security/testutil/e2e" ibcconsumer "github.com/cosmos/interchain-security/x/ccv/consumer" ibcconsumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" ibcconsumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" @@ -651,6 +652,33 @@ func (app *App) SimulationManager() *module.SimulationManager { return app.sm } +// ConsumerApp interface implementations for e2e tests + +// GetConsumerKeeper implements the ConsumerApp interface. +func (app *App) GetConsumerKeeper() ibcconsumerkeeper.Keeper { + return app.ConsumerKeeper +} + +// GetE2eBankKeeper implements the ConsumerApp interface. +func (app *App) GetE2eBankKeeper() e2e.E2eBankKeeper { + return app.BankKeeper +} + +// GetE2eAccountKeeper implements the ConsumerApp interface. +func (app *App) GetE2eAccountKeeper() e2e.E2eAccountKeeper { + return app.AccountKeeper +} + +// GetE2eSlashingKeeper implements the ConsumerApp interface. +func (app *App) GetE2eSlashingKeeper() e2e.E2eSlashingKeeper { + return app.SlashingKeeper +} + +// GetE2eEvidenceKeeper implements the ConsumerApp interface. +func (app *App) GetE2eEvidenceKeeper() e2e.E2eEvidenceKeeper { + return app.EvidenceKeeper +} + // TestingApp functions // GetBaseApp implements the TestingApp interface. diff --git a/app/provider/app.go b/app/provider/app.go index ec7ab612d4..423f96fba9 100644 --- a/app/provider/app.go +++ b/app/provider/app.go @@ -106,6 +106,8 @@ import ( ibcproviderkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" + e2e "github.com/cosmos/interchain-security/testutil/e2e" + "github.com/tendermint/spm/cosmoscmd" // unnamed import of statik for swagger UI support @@ -142,7 +144,8 @@ var ( upgradeclient.CancelProposalHandler, ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, - ibcproviderclient.ProposalHandler, + ibcproviderclient.ConsumerAdditionProposalHandler, + ibcproviderclient.ConsumerRemovalProposalHandler, ), params.AppModuleBasic{}, crisis.AppModuleBasic{}, @@ -796,6 +799,33 @@ func (app *App) SimulationManager() *module.SimulationManager { return app.sm } +// ProviderApp interface implementations for e2e tests + +// GetProviderKeeper implements the ProviderApp interface. +func (app *App) GetProviderKeeper() ibcproviderkeeper.Keeper { + return app.ProviderKeeper +} + +// GetE2eStakingKeeper implements the ProviderApp interface. +func (app *App) GetE2eStakingKeeper() e2e.E2eStakingKeeper { + return app.StakingKeeper +} + +// GetE2eBankKeeper implements the ProviderApp interface. +func (app *App) GetE2eBankKeeper() e2e.E2eBankKeeper { + return app.BankKeeper +} + +// GetE2eSlashingKeeper implements the ProviderApp interface. +func (app *App) GetE2eSlashingKeeper() e2e.E2eSlashingKeeper { + return app.SlashingKeeper +} + +// GetE2eDistributionKeeper implements the ProviderApp interface. +func (app *App) GetE2eDistributionKeeper() e2e.E2eDistributionKeeper { + return app.DistrKeeper +} + // TestingApp functions // GetBaseApp implements the TestingApp interface. diff --git a/app/provider/export.go b/app/provider/export.go index f5e4ffc4b2..5ea9b63755 100644 --- a/app/provider/export.go +++ b/app/provider/export.go @@ -50,7 +50,8 @@ func (app *App) ExportAppStateAndValidators( // prepare for fresh start at zero height // NOTE zero height genesis is a temporary feature which will be deprecated -// in favour of export at a block height +// +// in favour of export at a block height func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) { applyAllowedAddrs := false diff --git a/docs/quality_assurance.md b/docs/quality_assurance.md index aeef7c1af9..45691f7528 100644 --- a/docs/quality_assurance.md +++ b/docs/quality_assurance.md @@ -1,21 +1,24 @@ # Interchain Security: Quality Assurance -This document contains the overview of the quality assurance process necessary for the release of Interchain Security v1. +This document contains the overview of the quality assurance process necessary for the release of Interchain Security v1. + +The quality assurance of Interchain Security is done using the following approaches: -The verification of Interchain Security is done using the following approaches: - code review - automatic software engineering tools (e.g., SonarCloud, gosec) - unit testing +- integration tests - differential testing using heuristics - incentivized testnet - protocol audit (with the Apalache team from Informal Systems) -The verification of Interchain Security is split across the following concerns: +The quality assurance of Interchain Security is split across the following concerns: + - Correct software engineering (e.g., error handling, serialization, deserialization). - The correct integration with IBC (i.e., [ibc-go](https://github.com/cosmos/ibc-go/tree/v3.0.0)). - The correct integration with Cosmos SDK (i.e., [cosmos-sdk](https://github.com/cosmos/cosmos-sdk/tree/v0.45.6)). -- The correctness of the provider chain, i.e., the provider CCV module does not break the liveness or the safety of the provider chain. -- The correctness of the Interchain Security protocol, i.e., the protocol follows the [specification](https://github.com/cosmos/ibc/blob/master/spec/appics-028-cross-chain-validation/README.md). +- The correctness of the provider chain, i.e., the provider CCV module does not break the liveness or the safety of the provider chain. +- The correctness of the Interchain Security protocol, i.e., the protocol follows the [specification](https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/README.md). - The correctness of the consumer chain, i.e., both liveness or safety hold. For an overview of the Interchain Security workflow, have a look at [the diagrams](#interchain-security-workflow) at the end of this document. @@ -26,115 +29,116 @@ For an overview of the Interchain Security workflow, have a look at [the diagram | ID | Concern | Code Review | Automatic Tools | Unit Testing | | -- | ------- | ----------- | --------------- | ------------ | -| 1.01 | Unexpected panics | `Scheduled` | `??` | `??` | +| 1.01 | Unexpected panics | `Scheduled` | `NA` | `NA` | | 1.02 | Handling errors | `Scheduled` | `gosec` | `Partial coverage` | -| 1.03 | Accessing store (setters, getters, iterators) | `Scheduled` | `??` | `Partial coverage` | -| 1.04 | Serialization / deserialization | `Scheduled` | `??` | `Partial coverage` | -| 1.05 | Storage leaks | `Scheduled` | `NA` | `??` | +| 1.03 | Accessing store (setters, getters, iterators) | `Scheduled` | `NA` | `Partial coverage` | +| 1.04 | Serialization / deserialization | `Scheduled` | `NA` | `Partial coverage` | +| 1.05 | Storage leaks | `Scheduled` | `NA` | `NA` | ### Integration with IBC Interchain Security is an IBC application and, thus, it relies on IBC to establish a separate channel between the provider chain and every consumer chain. Interchain Security relies on the IBC v3.0 golang [implementation](https://github.com/cosmos/ibc-go/tree/v3.0.0). IBC packets: + - ValidatorSetChangePacket - MaturedVSCPacket - SlashPacketData | ID | Concern | Code Review | Unit Testing | E2E Testing | Diff. Testing | Testnet | | -- | ------- | ----------- | ------------ | ----------- | ------------- | ------- | -| 2.01 | Create IBC clients | `Scheduled` (ibc-go team) | `Done` | `??` | `Future work` | `Scheduled` | -| 2.02 | Getting consumer `UnbondingPeriod` from IBC client | `Scheduled` (ibc-go team) | `Done`, see TestUnbondingTime` | `??` | `NA` | `NA` | -| 2.03 | Create CCV channel (handshake) | `Scheduled` (ibc-go team) | `Done` | `NA` | `Future work` | `Scheduled` | -| 2.04 | Sending IBC packets
- see `x/ccv/utils/utils.go:SendIBCPacket()` | `Scheduled` (ibc-go team) | `??` | `Done` | `Done` | `Scheduled` | -| 2.05 | Handling acknowledgments | `Scheduled` (ibc-go team) | `Partial Coverage` | `Partial coverage` | `Scheduled` | `Scheduled` | -| 2.06 | Handling timeouts | `Scheduled` (ibc-go team) | `??` |`??` | `Future work` | `Scheduled` | -| 2.07 | **Handling IBC client expiration** | `Scheduled` (ibc-go team)
high priority | `??` | `??` | `Future work` | `Scheduled` | -| 2.08 | ICS-20 channel creation | `Scheduled` (ibc-go team) | `??` | `??` |`Future work` | `Scheduled` | -| 2.09 | ICS-20 transfer | `Scheduled` (ibc-go team) | `??` | `??` | `NA` | `Scheduled` | -| 2.10 | Changes in IBC-GO testing suite | `Scheduled` (ibc-go team) | `NA` | `??` | `Partial coverage` | `NA` | +| 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.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.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` | ### Integration with Cosmos SDK -A prerequisite of the code review is to open a PR with all the [SDK changes](https://github.com/cosmos/cosmos-sdk/tree/interchain-security-rebase) needed by Interchain Security. +- [x] A prerequisite of the code review is to open a PR with all the [SDK changes](https://github.com/cosmos/cosmos-sdk/tree/interchain-security-rebase) needed by Interchain Security. -| ID | Concern | Code Review | Unit Testing | E2E Testing | Diff. Testing | Testnet | +| ID | Concern | Code Review | Unit Testing | E2E Testing | Diff. Testing | Testnet | | -- | ------- | ----------- | ------------ | ----------- | ------------- | ------- | -| 3.01 | Changes to staking module | `Scheduled` (sdk team) | `??` | `Partial coverage`
see [unbonding_test.go](../tests/e2e/unbonding_test.go)
redelegation could be expanded, validator unbonding missing | `Partial coverage` | `Scheduled` | -| 3.02 | Changes to slashing module | `Scheduled` (sdk team) | `??` | `Done`
see [TestValidatorDowntime](../tests/e2e/slashing_test.go#L502)
| `NA` | `Scheduled` | -| 3.03 | Changes to evidence module | `Scheduled` (sdk team) | `??` | `Done`
see [TestValidatorDoubleSigning](../tests/e2e/slashing_test.go#L584)
| `NA` | `Scheduled` | +| 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.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` | ### Provider Chain Correctness -The main concern addressed in this section is the correctness of the provider chain (e.g., the Cosmos Hub). In other words, when Interchain Security is enabled (i.e., the provider CCV module is enabled), the safety and liveness properties still hold. This _**MUST**_ be the case regardless of the number of consumer chains, i.e., +The main concern addressed in this section is the correctness of the provider chain (e.g., the Cosmos Hub). In other words, when Interchain Security is enabled (i.e., the provider CCV module is enabled), the safety and liveness properties still hold. This _**MUST**_ be the case regardless of the number of consumer chains, i.e., + - no consumer chain; - one single consumer chain; - multiple consumer chains. -| ID | Concern | Code Review | Unit | E2e | Diff. Testing | Testnet | Protocol audit | -| -- | ------- | ----------- | ---- | --- | ------------- | ------- | -------------- | -| 4.01 | Liveness of undelegations
- unbonding delegation entries are eventually removed from `UnbondingDelegation` | `Scheduled` | `NA` | `Done`
see [here](../tests/e2e/unbonding_test.go) | `Done` | `Scheduled` | `Scheduled` | -| 4.02 | Liveness of redelegations
- redelegations entries are eventually removed from `Redelegations` | `NA` | `Scheduled` | `Scheduled` | `Scheduled` | `Scheduled` | `Scheduled` | -| 4.03 | Liveness of validator unbondings
- unbonding validators with no delegations are eventually removed from `Validators` | `NA` | `Scheduled` | `Scheduled` | `Done` | `Scheduled` | `Scheduled` | -| 4.04 | Unbonding operations (undelegations, redelegations, validator unbondings) should eventually complete even if the CCV channel is never established (due to error)
- expected outcome: the pending VSC packets eventually timeout, which leads to the consumer chain removal | `Scheduled` | `NA` | `??` | `Future work` | `Scheduled` | `Scheduled`
high priority | -| 4.05 | Unbonding operations (undelegations, redelegations, validator unbondings) should eventually complete even if one of the clients expire
- expected outcome: the pending VSC packets eventually timeout, which leads to the consumer chain removal | `Scheduled` | `??` | `??` | `Future work` | `Scheduled` | `Scheduled`
high priority | -| 4.06 | A validator cannot get slashed more than once for double signing, regardless of how many times it double signs on different chains (consumers or provider) | `Scheduled` | `NA` |`Done`
see [here](../tests/e2e/slashing_test.go#L317) | `Done` | `Scheduled` | `NA` | -| 4.07 | A validator cannot get slashed multiple times for downtime on the same consumer chain without requesting to `Unjail` itself on the provider chain in between | `Scheduled` | `NA` | `Done`
see [here](../tests/e2e/slashing_test.go#642)| `Partial coverage` | `Scheduled` | `NA` | +| ID | Concern | Code Review | Unit Testing | E2e | Diff. Testing | Testnet | Protocol audit | +| -- | ------- | ----------- | ------------ | --- | ------------- | ------- | -------------- | +| 4.01 | Liveness of undelegations
- unbonding delegation entries are eventually removed from `UnbondingDelegation` | `Scheduled` | `NA` | `Done`
[unbonding_test.go](../tests/e2e/unbonding_test.go) | `Done` | `Scheduled` | `NA` | +| 4.02 | Liveness of redelegations
- redelegations entries are eventually removed from `Redelegations` | `Scheduled` | `NA` | `Scheduled` | `Scheduled` | `Scheduled` | `NA` | +| 4.03 | Liveness of validator unbondings
- unbonding validators with no delegations are eventually removed from `Validators` | `Scheduled` | `NA` | `NA` | `Done` | `Scheduled` | `NA` | +| 4.04 | Unbonding operations (undelegations, redelegations, validator unbondings) should eventually complete even if the CCV channel is never established (due to error)
- expected outcome: the channel initialization sub-protocol eventually times out, which leads to the consumer chain removal | `Scheduled` | `NA` | `Done` [TestUndelegationDuringInit](../tests/e2e/unbonding_test.go#145) | `Future work` | `Scheduled` | `Done` | +| 4.05 | Unbonding operations (undelegations, redelegations, validator unbondings) should eventually complete even if one of the clients expire
- expected outcome: the pending VSC packets eventually timeout, which leads to the consumer chain removal | `Scheduled` | `NA` | `Done` [TestUndelegationVscTimeout](../tests/e2e/unbonding.go#127) | `Future work` | `Scheduled` | `NA` | +| 4.06 | A validator cannot get slashed more than once for double signing, regardless of how many times it double signs on different chains (consumers or provider) | `Scheduled` | `NA` |`Done`
[TestHandleSlashPacketErrors](../tests/e2e/slashing_test.go#L317) | `Done` | `Scheduled` | `NA` | +| 4.07 | A validator cannot get slashed multiple times for downtime on the same consumer chain without requesting to `Unjail` itself on the provider chain in between | `Scheduled` | `NA` | `Partial coverage`
[TestSendSlashPacket](../tests/e2e/slashing_test.go#L648) | `Partial coverage` | `Scheduled` | `NA` | | 4.08 | A validator can be slashed multiple times for downtime on different chains | `Scheduled` | `NA` | `Future work` | `NA` | `Scheduled` | `NA` | -| 4.09 | The provider chain can easily be restarted with IS enabled
- `ExportGenesis` & `InitGenesis` | `Scheduled` | `??` | `Future work` | `Future work` | `Scheduled` | `NA` | -| 4.10 | The provider chain's correctness is not affected by a consumer chain shutting down | `Scheduled` | `NA` | `Future work` | `Future work` | `Scheduled` | `NA` | -| 4.11 | The provider chain can graciously handle a CCV packet timing out (without shuting down)
- expected outcome: consumer chain shuts down and its state in provider CCV module is removed | `Scheduled` | `??` | `Future work` | `Future work` | `Scheduled` | `NA` | -| 4.12 | The provider chain can graciously handle a `ConsumerRemovalProposal`
- expected outcome: consumer chain shuts down and its state in provider CCV module is removed | `Scheduled` | `Done`
see [here](../x/ccv/provider/keeper/proposal_test.go#L313) | `NA` | `Future work` | `Scheduled` | `NA` | -| 4.13 | The provider chain can graciously handle a `ConsumerAdditionProposal`
- expected outcome: a consumer chain is registered and a client is created | `Scheduled` |`Done`
see [here](../x/ccv/provider/keeper/proposal_test.go#L31) | `NA` | `Future work` | `Scheduled` | `NA` | +| 4.09 | The provider chain can easily be restarted with IS enabled
- `ExportGenesis` & `InitGenesis`
- requires https://github.com/informalsystems/hermes/issues/1152| `Scheduled` | `Done`
[TestInitAndExportGenesis](../x/ccv/provider/keeper/genesis_test.go#L20) | `Future work` | `Future work` | `Scheduled` | `NA` | +| 4.10 | The provider chain can graciously handle a CCV packet timing out (without shuting down)
- expected outcome: consumer chain shuts down and its state in provider CCV module is removed | `Scheduled` | `Scheduled` | `NA` | `Future work` | `Scheduled` | `NA` | +| 4.11 | The provider chain can graciously handle a `ConsumerRemovalProposal`
- expected outcome: consumer chain shuts down and its state in provider CCV module is removed | `Scheduled` | `Done`
[TestHandleConsumerRemovalProposal](../x/ccv/provider/keeper/proposal_test.go#L313) | `NA` | `Future work` | `Scheduled` | `NA` | +| 4.12 | The provider chain can graciously handle a `ConsumerAdditionProposal`
- expected outcome: a consumer chain is registered and a client is created | `Scheduled` |`Done`
[TestHandleConsumerAdditionProposal](../x/ccv/provider/keeper/proposal_test.go#L31) | `NA` | `Future work` | `Scheduled` | `NA` | ### Interchain Security Protocol Correctness -The main concern addressed in this section is the correctness of the Interchain Security protocol. In other words, the implementation should be aligned with the Interchain Security [specification](https://github.com/cosmos/ibc/blob/master/spec/appics-028-cross-chain-validation/README.md). +The main concern addressed in this section is the correctness of the Interchain Security protocol. In other words, the implementation should be aligned with the Interchain Security [specification](https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/README.md). + +The implementation MUST guarantee the _Channel Uniqueness_ property, i.e., the channel between the provider chain and a consumer chain MUST be unique. -The implementation MUST guarantee the *Channel Uniqueness* property, i.e., the channel between the provider chain and a consumer chain MUST be unique. +In addition, the implementation MUST guarantee the following [system properties](https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/system_model_and_properties.md#system-properties): -In addition, the implementation MUST guarantee the following [system properties](https://github.com/cosmos/ibc/blob/master/spec/appics-028-cross-chain-validation/system_model_and_properties.md#system-properties): -- *Validator Set Replication* -- *Bond-Based Consumer Voting Power* -- *Slashable Consumer Misbehavior* -- *Consumer Rewards Distribution* +- _Validator Set Replication_ +- _Bond-Based Consumer Voting Power_ +- _Slashable Consumer Misbehavior_ +- _Consumer Rewards Distribution_ --- -| ID | Concern re. *Channel Uniqueness* | Code Review | Unit Testing | E2e Testing | Diff. Testing | Testnet | Protocol audit | +| ID | Concern re. _Channel Uniqueness_ | Code Review | Unit Testing | E2e Testing | Diff. Testing | Testnet | Protocol audit | | -- | -------------------------------- | ----------- | ------------ | ----------- | ------------- | ------- | -------------- | -| 5.01 | `HandleConsumerAdditionProposal()` should fail if a consumer with `chainId` is already registered | `Scheduled` | `DONE` see [here](../x/ccv/provider/keeper/proposal_test.go#L138) | `??` | `NA` | `Scheduled` | `Scheduled`
high priority | -| 5.02 | The channel handshake for a consumer with `chainId` should fail if there is already an established CCV channel for `chainId` | `Scheduled` | `DONE` see [here](../x/ccv/provider/ibc_module_test.go#L103) and [here](../x/ccv/consumer/ibc_module_test.go#L59) | `??` | `NA` | `Scheduled` | `Scheduled`
high priority | -| 5.03 | *Channel Uniqueness* should hold even if a consumer chain restarts | `Scheduled` | `NA` | `??` | `NA` | `Scheduled` | `NA` | -| 5.04 | *Channel Uniqueness* should hold even when a client expires | `Scheduled` | `??` | `NA` | `NA` | `Scheduled` | `NA` | +| 5.01 | `HandleConsumerAdditionProposal()` should fail if a consumer with `chainId` is already registered | `Scheduled` | `Done` [TestCreateConsumerClient](../x/ccv/provider/keeper/proposal_test.go#L116) | `NA` | `NA` | `Scheduled` | `NA` | +| 5.02 | The channel handshake for a consumer with `chainId` should fail if there is already an established CCV channel for `chainId` | `Scheduled` | `Done` [TestOnChanOpenTry](../x/ccv/provider/ibc_module_test.go#L103), [TestOnChanOpenInit](../x/ccv/consumer/ibc_module_test.go#L59) | `NA` | `NA` | `Scheduled` | `NA` | +| 5.03 | _Channel Uniqueness_ should hold even if a consumer chain restarts | `Scheduled` | `NA` | `Scheduled` | `NA` | `Scheduled` | `NA` | +| 5.04 | _Channel Uniqueness_ should hold even when a client expires | `Scheduled` | `NA` | `Scheduled` | `NA` | `Scheduled` | `NA` | --- -| ID | Concern re. *Validator Set Replication* | Code Review | Unit Testing | E2e Testing | Diff. testing | Testnet | Protocol audit | +| ID | Concern re. _Validator Set Replication_ | Code Review | Unit Testing | E2e Testing | Diff. testing | Testnet | Protocol audit | | -- | --------------------------------------- | ----------- | ------------ | ----------- | ------------- | ------- | -------------- | | 6.01 | Every validator set on any consumer chain MUST either be or have been a validator set on the provider chain. | `Scheduled` | `NA` | `NA` | `Done` | `Scheduled` | `Scheduled` | -| 6.02 | Any update in the power of a validator `val` on the provider, as a result of
- (increase) `Delegate()` / `Redelegate()` to `val`
- (increase) `val` joining the provider validator set
- (decrease) `Undelegate()` / `Redelegate()` from `val`
- (decrease) `Slash(val)`
- (decrease) `val` leaving the provider validator set
MUST be present in a `ValidatorSetChangePacket` that is sent to all registered consumer chains | `Scheduled` | `NA` | `NA` | `Done` | `Scheduled` | `Scheduled` | -| 6.03 | Every consumer chain receives the same sequence of `ValidatorSetChangePacket`s in the same order. | `Scheduled` | `NA` | `NA` | `NA` | `Scheduled` | `Scheduled`
high priority | +| 6.02 | Any update in the power of a validator `val` on the provider, as a result of
- (increase) `Delegate()` / `Redelegate()` to `val`
- (increase) `val` joining the provider validator set
- (decrease) `Undelegate()` / `Redelegate()` from `val`
- (decrease) `Slash(val)`
- (decrease) `val` leaving the provider validator set
MUST be present in a `ValidatorSetChangePacket` that is sent to all registered consumer chains | `Scheduled` | `NA` | `NA` | `Done` | `Scheduled` | `Scheduled` | +| 6.03 | Every consumer chain receives the same sequence of `ValidatorSetChangePacket`s in the same order. | `Scheduled` | `NA` | `NA` | `NA` | `Scheduled` | `Scheduled`
high priority | --- -| ID | Concern re. *Bond-Based Consumer Voting Power* | Code Review | Unit Testing | E2e Testing | Diff. Testing | Testnet | Protocol audit | +| ID | Concern re. _Bond-Based Consumer Voting Power_ | Code Review | Unit Testing | E2e Testing | Diff. Testing | Testnet | Protocol audit | | -- | ---------------------------------------------- | ----------- | ------------ | ----------- | ------------- | ------- | -------------- | -| 7.01 | For every `ValidatorSetChangePacket` received by a consumer chain at time `t`, a `MaturedVSCPacket` is sent back to the provider in the first block with a timestamp `>= t + UnbondingPeriod` | `Scheduled` | `??` | `Scheduled` | `Done` | `Scheduled` | `Scheduled` | -| 7.02 | If an unbonding operation resulted in a `ValidatorSetChangePacket` sent to all registered consumer chains, then it cannot complete before receiving matching `MaturedVSCPacket`s from these consumer chains (unless some of these consumer chains are removed) | `Scheduled` | `??` | `Scheduled` | `Done` | `Scheduled` | `Scheduled` | +| 7.01 | For every `ValidatorSetChangePacket` received by a consumer chain at time `t`, a `MaturedVSCPacket` is sent back to the provider in the first block with a timestamp `>= t + UnbondingPeriod` | `Scheduled` | `NA` | `NA` | `Done` | `Scheduled` | `Scheduled` | +| 7.02 | If an unbonding operation resulted in a `ValidatorSetChangePacket` sent to all registered consumer chains, then it cannot complete before receiving matching `MaturedVSCPacket`s from these consumer chains (unless some of these consumer chains are removed) | `Scheduled` | `NA` | `NA` | `Done` | `Scheduled` | `Scheduled` | --- -| ID | Concern re. *Slashable Consumer Misbehavior* | Code Review | Unit Testing | E2e Testing | Diff. testing | Testnet | Protocol audit | +| ID | Concern re. _Slashable Consumer Misbehavior_ | Code Review | Unit Testing | E2e Testing | Diff. testing | Testnet | Protocol audit | | -- | -------------------------------------------- | ----------- | ------------ | ----------- | ------------- | ------- | -------------- | -| 8.01 | Multiple downtime infractions committed by the same validator `val` on the same consumer chain without `val` requesting to `Unjail` itself result in a single `SlashPacket` | `Scheduled` | `??` | `??` | `??` | `Done` | `Scheduled` | `Scheduled` | -| 8.02 | If evidence of misbehavior is submitted on a consumer chain within the unbonding period targeting an amount `x` of staked tokens, the amount `x` cannot be unlocked on the provider before the corresponding `SlashPacket` is received
- `SlashPacket` will not arrive after the corresponding `MaturedVSCPacket`s | `Scheduled` | `??` | `??` | `??` | `Done` | `Scheduled` | `Scheduled` | +| 8.01 | Multiple downtime infractions committed by the same validator `val` on the same consumer chain without `val` requesting to `Unjail` itself result in a single `SlashPacket` | `Scheduled` | `NA` | `NA` | `Done` | `Scheduled` | `NA` | +| 8.02 | If evidence of misbehavior is submitted on a consumer chain within the unbonding period targeting an amount `x` of staked tokens, the amount `x` cannot be unlocked on the provider before the corresponding `SlashPacket` is received
- `SlashPacket` will not arrive after the corresponding `MaturedVSCPacket`s | `Scheduled` | `NA` | `NA` | `Done` | `Scheduled` | `NA` | --- -| ID | Concern re. *Consumer Rewards Distribution* | Code Review | Unit Testing | E2e Testing | Diff. testing | Testnet | Protocol audit | +| ID | Concern re. _Consumer Rewards Distribution_ | Code Review | Unit Testing | E2e Testing | Diff. testing | Testnet | Protocol audit | | -- | ------------------------------------------- | ----------- | ------------ | ----------- | ------------- | ------- | -------------- | -| 9.01 | Validators on the provider chain receive rewards for participating in IS | `Scheduled` | `NA` | `Scheduled` | `NA` | `Scheduled` | `NA` | +| 9.01 | Validators on the provider chain receive rewards for participating in IS | `Scheduled` | `NA` | `Done` [TestRewardsDistribution](../tests/e2e/distribution_test.go#17) | `NA` | `Scheduled` | `NA` | | 9.02 | The rewards sent to the provider chain are escrowed on the consumer chains (no double spend) | `Scheduled` | `NA` | `Scheduled` | `NA` | `Scheduled` | `NA` | --- @@ -142,18 +146,19 @@ In addition, the implementation MUST guarantee the following [system properties] ### Consumer Chain Correctness The main concern addressed in this section is the correctness of the consumer chains. In other words, when Interchain Security is enabled (i.e., the consumer CCV module is enabled), the safety and liveness properties still hold. This also covers various flavor of consumer chains: + - minimum viable consumer chain ([mvcc](https://github.com/cosmos/interchain-security/issues/139)) - governance-enabled consumer chain ([gov-cc](https://github.com/cosmos/interchain-security/issues/141)), with the modified staking and distribution modules (see `x/ccv/staking` and `x/ccv/distribution`); also, must look at the [atom-gov module](https://github.com/cosmos/interchain-security/issues/162) - CosmWasm-enabled consumer chain ([wasm-cc](https://github.com/cosmos/interchain-security/issues/143)), with the CosmWasm module enabled | ID | Concern | Code Review | Unit Testing | E2e Testing | Diff. testing | Testnet | Protocol audit | | -- | ------- | ----------- | ------------ | ----------- | ------------- | ------- | -------------- | -| 10.01 | Consumer chain liveness (blocks are being produced) | `Scheduled` | `NA` | `NA` | `??` | `Scheduled` | `NA` | -| 10.02 | A chain has the ability to restart as a consumer chain with no more than 24 hours downtime | `Scheduled` | `NA` | `NA` | `??` | `Scheduled` | `NA` | -| 10.03 | A consumer chain has the ability to restart as a normal chain after shutting down, either controlled (via `ConsumerRemovalProposal`) or due to timing out | `Scheduled` | `??` | `??` | `??` | `Scheduled` | `NA` | -| 10.04 | A consumer chain has the ability to restart as a consumer chain with the same `chainId` after shutting down, either controlled (via `ConsumerRemovalProposal`) or due to timing out | `Scheduled` | `??` | `??` | `??` | `Scheduled` | `NA` | -| 10.05 | Governance on `gov-cc` | `Scheduled` | `??` | `??` | `??` | `Scheduled` | `NA` | -| 10.06 | CosmWasm on `wasm-cc` | `Scheduled` | `??` | `??` | `??` | `Scheduled` | `NA` | +| 10.01 | Consumer chain liveness (blocks are being produced) | `Scheduled` | `NA` | `NA` | `NA` | `Scheduled` | `NA` | +| 10.02 | A chain has the ability to restart as a consumer chain with no more than 24 hours downtime | `Scheduled` | `NA` | `NA` | `NA` | `Scheduled` | `NA` | +| 10.03 | A consumer chain has the ability to restart as a normal chain after shutting down, either controlled (via `ConsumerRemovalProposal`) or due to timing out | `Scheduled` | `NA` | `NA` | `NA` | `Scheduled` | `NA` | +| 10.04 | A consumer chain has the ability to restart as a consumer chain with the same `chainId` after shutting down, either controlled (via `ConsumerRemovalProposal`) or due to timing out | `Scheduled` | `NA` | `Scheduled` | `NA` | `Scheduled` | `NA` | +| 10.05 | Governance on `gov-cc` | `Scheduled` | `NA` | `Partial Coverage` [TestDemocracyGovernanceWhitelisting](../tests/e2e/distribution_test.go#133) | `Scheduled` | `Scheduled` | `NA` | +| 10.06 | CosmWasm on `wasm-cc` | `Scheduled` | `NA` | `Scheduled` | `NA` | `Scheduled` | `NA` | | TBA ... > TODO create clear concerns for `gov-cc` and `wasm-cc` once the implementations are done @@ -166,4 +171,4 @@ The following diagrams show (in orange) the events that influence the operation ![Normal Operation](./figures/is_normalop_overview.png?raw=true) -![Remove Consumer Chains](./figures/is_remove_overview.png?raw=true) \ No newline at end of file +![Remove Consumer Chains](./figures/is_remove_overview.png?raw=true) diff --git a/go.mod b/go.mod index 2ebb536dbc..c9272abd87 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,7 @@ module github.com/cosmos/interchain-security go 1.18 require ( - github.com/cosmos/cosmos-sdk v0.45.2-0.20220901181011-06d4a64bf808 - github.com/cosmos/ibc-go v1.2.2 + github.com/cosmos/cosmos-sdk v0.45.7-0.20221104161803-456ca5663c5e github.com/cosmos/ibc-go/v3 v3.0.0-alpha1.0.20220210141024-fb2f0416254b github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.2 @@ -14,11 +13,11 @@ require ( github.com/kylelemons/godebug v1.1.0 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.4.1 - github.com/spf13/cobra v1.3.0 - github.com/stretchr/testify v1.7.0 + github.com/spf13/cobra v1.4.0 + github.com/stretchr/testify v1.7.1 github.com/tendermint/spm v0.1.9 - github.com/tendermint/tendermint v0.34.14 - github.com/tendermint/tm-db v0.6.4 + github.com/tendermint/tendermint v0.34.19 + github.com/tendermint/tm-db v0.6.6 github.com/tidwall/gjson v1.6.7 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect @@ -30,6 +29,7 @@ require ( ) require ( + github.com/confio/ics23/go v0.7.0 github.com/golang/mock v1.6.0 github.com/oxyno-zeta/gomock-extra-matcher v1.1.0 github.com/regen-network/cosmos-proto v0.3.1 @@ -40,7 +40,7 @@ require ( github.com/99designs/keyring v1.1.6 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect github.com/DataDog/zstd v1.4.5 // indirect - github.com/Workiva/go-datastructures v1.0.52 // indirect + github.com/Workiva/go-datastructures v1.0.53 // indirect github.com/armon/go-metrics v0.3.10 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect @@ -48,7 +48,6 @@ require ( github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect - github.com/confio/ics23/go v0.7.0 // indirect github.com/cosmos/btcutil v1.0.4 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/iavl v0.17.3 // indirect @@ -64,8 +63,9 @@ require ( github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect github.com/felixge/httpsnoop v1.0.1 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/go-kit/kit v0.10.0 // indirect - github.com/go-logfmt/logfmt v0.5.0 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.0 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-playground/validator/v10 v10.4.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/gateway v1.1.0 // indirect @@ -73,7 +73,7 @@ require ( github.com/google/btree v1.0.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/websocket v1.4.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.2 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect @@ -87,26 +87,26 @@ require ( github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect - github.com/klauspost/compress v1.11.7 // indirect - github.com/lib/pq v1.10.2 // indirect + github.com/klauspost/compress v1.13.6 // indirect + github.com/lib/pq v1.10.4 // indirect github.com/libp2p/go-buffer-pool v0.0.2 // indirect github.com/magiconair/properties v1.8.5 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect - github.com/minio/highwayhash v1.0.1 // indirect + github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.29.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect - github.com/rs/cors v1.7.0 // indirect + github.com/rs/cors v1.8.2 // indirect github.com/rs/zerolog v1.25.0 // indirect github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect github.com/spf13/afero v1.6.0 // indirect @@ -122,7 +122,7 @@ require ( github.com/tidwall/match v1.0.3 // indirect github.com/tidwall/pretty v1.0.2 // indirect github.com/zondax/hid v0.9.0 // indirect - go.etcd.io/bbolt v1.3.5 // indirect + go.etcd.io/bbolt v1.3.6 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect gopkg.in/ini.v1 v1.66.2 // indirect diff --git a/go.sum b/go.sum index 6c55c682da..1f5f9f31d8 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ 4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -28,7 +29,6 @@ cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aD cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= @@ -58,6 +58,9 @@ filippo.io/edwards25519 v1.0.0-beta.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOG github.com/Antonboom/errname v0.1.4/go.mod h1:jRXo3m0E0EuCnK3wbsSVH3X55Z4iTDLl6ZfCxwFj4TM= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= @@ -74,14 +77,18 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -89,8 +96,9 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0 github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= +github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= @@ -103,13 +111,16 @@ github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9 github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/Workiva/go-datastructures v1.0.53 h1:J6Y/52yX10Xc5JjXmGtWoSSxs3mZnGSaq37xZZh7Yig= +github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1:eSYp2T6f0apnuW8TzhV3f6Aff2SE8Dwio++U4ha4yEM= -github.com/adlio/schema v1.1.13 h1:LeNMVg5Z1FX+Qgz8tJUijBLRdcpbFUElz+d1489On98= github.com/adlio/schema v1.1.13/go.mod h1:L5Z7tw+7lRK1Fnpi/LT/ooCP1elkXn0krMWBQHUhEDE= +github.com/adlio/schema v1.3.0 h1:eSVYLxYWbm/6ReZBCkLw4Fz7uqC+ZNoPvA39bOwi52A= +github.com/adlio/schema v1.3.0/go.mod h1:51QzxkpeFs6lRY11kPye26IaFPOV+HqEj01t5aXXKfs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -141,7 +152,12 @@ github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= +github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -175,8 +191,10 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -194,6 +212,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -213,8 +232,9 @@ github.com/confio/ics23/go v0.7.0 h1:00d2kukk7sPoHWL4zZBZwzxnpA2pec1NPdwbSokJ5w8 github.com/confio/ics23/go v0.7.0/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/continuity v0.2.1 h1:/EeEo2EtN3umhbbgCveyjifoMYg0pS+nMMEemaYw634= +github.com/containerd/continuity v0.2.1/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -232,8 +252,8 @@ github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/Tv github.com/cosmos/cosmos-sdk v0.44.2/go.mod h1:fwQJdw+aECatpTvQTo1tSfHEsxACdZYU80QCZUPnHr4= github.com/cosmos/cosmos-sdk v0.44.3/go.mod h1:bA3+VenaR/l/vDiYzaiwbWvRPWHMBX2jG0ygiFtiBp0= github.com/cosmos/cosmos-sdk v0.45.0/go.mod h1:XXS/asyCqWNWkx2rW6pSuen+EVcpAFxq6khrhnZgHaQ= -github.com/cosmos/cosmos-sdk v0.45.2-0.20220901181011-06d4a64bf808 h1:PW5p0/qt5iJZS7f4bDjo/OYhMhzlmCewh8PZrpBluxo= -github.com/cosmos/cosmos-sdk v0.45.2-0.20220901181011-06d4a64bf808/go.mod h1:XXS/asyCqWNWkx2rW6pSuen+EVcpAFxq6khrhnZgHaQ= +github.com/cosmos/cosmos-sdk v0.45.7-0.20221104161803-456ca5663c5e h1:075VahQ5RUxFEz3wUcbpk5RlS0XqWHKGkf2omHV7ho4= +github.com/cosmos/cosmos-sdk v0.45.7-0.20221104161803-456ca5663c5e/go.mod h1:bPeeVMEtVvH3y3xAGHVbK+/CZlpaazzh77hG8ZrcJpI= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -243,7 +263,6 @@ github.com/cosmos/iavl v0.15.3/go.mod h1:OLjQiAQ4fGD2KDZooyJG9yz+p2ao2IAYSbke8mV github.com/cosmos/iavl v0.17.1/go.mod h1:7aisPZK8yCpQdy3PMvKeO+bhq1NwDjUwjzxwwROUxFk= github.com/cosmos/iavl v0.17.3 h1:s2N819a2olOmiauVa0WAhoIJq9EhSXE9HDBAoR9k+8Y= github.com/cosmos/iavl v0.17.3/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w= -github.com/cosmos/ibc-go v1.2.2 h1:bs6TZ8Es1kycIu2AHlRZ9dzJ+mveqlLN/0sjWtRH88o= github.com/cosmos/ibc-go v1.2.2/go.mod h1:XmYjsRFOs6Q9Cz+CSsX21icNoH27vQKb3squgnCOCbs= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8= @@ -269,6 +288,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= +github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v2 v2.2007.1/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= @@ -283,6 +303,7 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= @@ -325,9 +346,11 @@ github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4 github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -348,13 +371,17 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= +github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0 h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -369,7 +396,7 @@ github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8w github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= @@ -383,6 +410,7 @@ github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslW github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= @@ -396,6 +424,10 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -518,8 +550,9 @@ github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= @@ -559,7 +592,8 @@ github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uM github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= @@ -568,6 +602,7 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= @@ -609,6 +644,7 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -622,6 +658,7 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/informalsystems/ibc-go/v3 v3.0.0-beta1.0.20220816140824-aba9c2f2b943 h1:9/koLqwfRnGLXJnXz5xrRb+ZBmtjMzItXByzxCh1hk0= github.com/informalsystems/ibc-go/v3 v3.0.0-beta1.0.20220816140824-aba9c2f2b943/go.mod h1:Ce4PJmh24ha1l9w/DyvY+sMs5hjJvw1LuDcDmjwIA+s= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= @@ -660,6 +697,7 @@ github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= @@ -672,8 +710,10 @@ github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -700,8 +740,9 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= +github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -739,6 +780,7 @@ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -749,12 +791,14 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= -github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= +github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= @@ -768,6 +812,7 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= @@ -780,6 +825,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= @@ -798,10 +844,16 @@ github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= +github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nats.go v1.12.1/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= +github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= @@ -842,19 +894,23 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k= +github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ= @@ -876,13 +932,16 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -903,8 +962,9 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -922,8 +982,10 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8 github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.29.0 h1:3jqPBvKT4OHAbje2Ql7KeaaSicDBCxMYwEJU1zRJceE= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -932,8 +994,9 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= @@ -961,8 +1024,9 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -975,7 +1039,7 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryancurrah/gomodguard v1.2.3/go.mod h1:rYbA/4Tg5c54mV1sv4sQTP5WOPBcoLtnBZ7/TEhXAbg= github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= +github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= @@ -1022,8 +1086,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= -github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1036,7 +1100,6 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= github.com/ssgreg/nlreturn/v2 v2.1.0/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= @@ -1045,7 +1108,9 @@ github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8 github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -1057,8 +1122,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -1079,12 +1145,14 @@ github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxm github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= github.com/tendermint/tendermint v0.34.13/go.mod h1:6RVVRBqwtKhA+H59APKumO+B7Nye4QXSFc6+TYxAxCI= -github.com/tendermint/tendermint v0.34.14 h1:GCXmlS8Bqd2Ix3TQCpwYLUNHe+Y+QyJsm5YE+S/FkPo= github.com/tendermint/tendermint v0.34.14/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= +github.com/tendermint/tendermint v0.34.19 h1:y0P1qI5wSa9IRuhKnTDA6IUcOrLi1hXJuALR+R7HFEk= +github.com/tendermint/tendermint v0.34.19/go.mod h1:R5+wgIwSxMdKQcmOaeudL0Cjkr3HDkhpcdum6VeU3R4= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= -github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ= github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= +github.com/tendermint/tm-db v0.6.6 h1:EzhaOfR0bdKyATqcd5PNeyeq8r+V4bRPHBfyFdD9kGM= +github.com/tendermint/tm-db v0.6.6/go.mod h1:wP8d49A85B7/erz/r4YbKssKw6ylsO/hKtFk7E1aWZI= github.com/tetafro/godot v1.4.9/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/tidwall/gjson v1.6.7 h1:Mb1M9HZCRWEcXQ8ieJo7auYyyiSux6w9XN3AdTpxJrE= github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= @@ -1094,6 +1162,7 @@ github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/Lx1fg= github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= github.com/tklauser/go-sysconf v0.3.7/go.mod h1:JZIdXh4RmBvZDBZ41ld2bGxRV3n4daiiqA3skYhAoQ4= github.com/tklauser/numcpus v0.2.3/go.mod h1:vpEPS/JC+oZGGQ/My/vJnNsvMDQL6PwOqt8dsCw5j+E= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1102,7 +1171,9 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1 github.com/tomarrell/wrapcheck/v2 v2.3.0/go.mod h1:aF5rnkdtqNWP/gC7vPUO5pKsB0Oac2FDTQP4F+dpZMU= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/tommy-muehle/go-mnd/v2 v2.4.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -1144,8 +1215,9 @@ github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWp go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -1154,6 +1226,7 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3 go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1169,14 +1242,18 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1193,6 +1270,7 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1201,11 +1279,17 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= @@ -1217,6 +1301,7 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1300,8 +1385,12 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1368,6 +1457,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1395,6 +1485,7 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1424,10 +1515,13 @@ golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc= golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1449,9 +1543,11 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1528,6 +1624,7 @@ golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1551,6 +1648,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -1585,7 +1686,7 @@ google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqiv google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1662,12 +1763,11 @@ google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I= @@ -1745,7 +1845,9 @@ mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7/go.mod h1:hBpJkZE8H/sb+VRFvw nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/proto/interchain_security/ccv/consumer/v1/consumer.proto b/proto/interchain_security/ccv/consumer/v1/consumer.proto index 57d0f0fbd3..ae2a2b7bad 100644 --- a/proto/interchain_security/ccv/consumer/v1/consumer.proto +++ b/proto/interchain_security/ccv/consumer/v1/consumer.proto @@ -9,6 +9,7 @@ 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"; // Params defines the parameters for CCV consumer module message Params { @@ -29,6 +30,28 @@ message Params { // provider handshake procedure. string distribution_transmission_channel = 3; string provider_fee_pool_addr_str = 4; + // Sent CCV related IBC packets will timeout after this duration + google.protobuf.Duration ccv_timeout_period = 5 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + + // Sent transfer related IBC packets will timeout after this duration + google.protobuf.Duration transfer_timeout_period = 6 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + + // The fraction of tokens allocated to the consumer redistribution address + // during distribution events. The fraction is a string representing a + // decimal number. For example "0.75" would represent 75%. + string consumer_redistribution_fraction = 7; + + // The number of historical info entries to persist in store. + // This param is a part of the cosmos sdk staking module. In the case of + // a ccv enabled consumer chain, the ccv module acts as the staking module. + int64 historical_entries = 8; + + // Unbonding period for the consumer, + // which should be smaller than that of the provider in general. + google.protobuf.Duration unbonding_period = 9 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; } // LastTransmissionBlockHeight is the last time validator holding diff --git a/proto/interchain_security/ccv/consumer/v1/genesis.proto b/proto/interchain_security/ccv/consumer/v1/genesis.proto index c71aecd64a..3f2ad667f7 100644 --- a/proto/interchain_security/ccv/consumer/v1/genesis.proto +++ b/proto/interchain_security/ccv/consumer/v1/genesis.proto @@ -35,6 +35,9 @@ message GenesisState { // PendingSlashRequests filled in on new chain, nil on restart. interchain_security.ccv.consumer.v1.SlashRequests pending_slash_requests = 11 [ (gogoproto.nullable) = false ]; + // LastTransmissionBlockHeight nil on new chain, filled on restart. + interchain_security.ccv.consumer.v1.LastTransmissionBlockHeight last_transmission_block_height = 12 + [ (gogoproto.nullable) = false ]; } // MaturingVSCPacket defines the genesis information for the diff --git a/proto/interchain_security/ccv/consumer/v1/query.proto b/proto/interchain_security/ccv/consumer/v1/query.proto new file mode 100644 index 0000000000..5d079e76f9 --- /dev/null +++ b/proto/interchain_security/ccv/consumer/v1/query.proto @@ -0,0 +1,41 @@ +syntax = "proto3"; + +package interchain_security.ccv.consumer.v1; +option go_package = "github.com/cosmos/interchain-security/x/ccv/consumer/types"; + +import "google/api/annotations.proto"; + + +service Query { + // ConsumerGenesis queries the genesis state needed to start a consumer chain + // whose proposal has been accepted + rpc QueryNextFeeDistribution(QueryNextFeeDistributionEstimateRequest) + returns (QueryNextFeeDistributionEstimateResponse) { + option (google.api.http).get = + "/interchain_security/ccv/consumer/next-fee-distribution"; + } +} + +// NextFeeDistributionEstimate holds information about next fee distribution +message NextFeeDistributionEstimate { + // current block height at the time of querying + int64 currentHeight = 1; + // block height at which last distribution took place + int64 lastHeight = 2; + // block height at which next distribution will take place + int64 nextHeight = 3; + // ratio between consumer and provider fee distribution + string distribution_fraction = 4; + // total accruead fees at the time of querying + string total = 5; + // amount distibuted to provider chain + string toProvider = 6; + // amount distributed (kept) by consumer chain + string toConsumer = 7; +} + +message QueryNextFeeDistributionEstimateRequest { } + +message QueryNextFeeDistributionEstimateResponse { + NextFeeDistributionEstimate data = 1; +} diff --git a/proto/interchain_security/ccv/provider/v1/genesis.proto b/proto/interchain_security/ccv/provider/v1/genesis.proto index dedfc72120..55604e0f2d 100644 --- a/proto/interchain_security/ccv/provider/v1/genesis.proto +++ b/proto/interchain_security/ccv/provider/v1/genesis.proto @@ -40,7 +40,7 @@ message GenesisState { // consumer chain message ConsumerState { - // ChannelID defines the chain ID for the consumer chain + // ChainlID defines the chain ID for the consumer chain string chain_id = 1; // ChannelID defines the IBC channel ID for the consumer chain string channel_id = 2; diff --git a/proto/interchain_security/ccv/provider/v1/provider.proto b/proto/interchain_security/ccv/provider/v1/provider.proto index 0c0beb2bb3..753d1a28e4 100644 --- a/proto/interchain_security/ccv/provider/v1/provider.proto +++ b/proto/interchain_security/ccv/provider/v1/provider.proto @@ -6,6 +6,7 @@ option go_package = "github.com/cosmos/interchain-security/x/ccv/provider/types" import "gogoproto/gogo.proto"; import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; import "ibc/core/client/v1/client.proto"; import "ibc/lightclients/tendermint/v1/tendermint.proto"; @@ -39,7 +40,6 @@ message ConsumerAdditionProposal { // on the provider chain would be necessary to release the locked funds. bool lock_unbonding_on_timeout = 8; } - // ConsumerRemovalProposal is a governance proposal on the provider chain to remove (and stop) a consumer chain. // If it passes, all the consumer chain's state is removed from the provider chain. The outstanding unbonding // operation funds are released if the LockUnbondingOnTimeout parameter is set to false for the consumer chain ID. @@ -58,6 +58,20 @@ message ConsumerAdditionProposal { // Params defines the parameters for CCV Provider module message Params { ibc.lightclients.tendermint.v1.ClientState template_client = 1; + // TrustingPeriodFraction is used to compute the consumer and provider IBC client's TrustingPeriod from the chain defined UnbondingPeriod + int64 trusting_period_fraction = 2; + // Sent IBC packets will timeout after this duration + google.protobuf.Duration ccv_timeout_period = 3 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + // The channel initialization (IBC channel opening handshake) will timeout after this duration + google.protobuf.Duration init_timeout_period = 4 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + // The VSC packets sent by the provider will timeout after this duration. + // Note that unlike ccv_timeout_period which is an IBC param, + // the vsc_timeout_period is a provider-side param that enables the provider + // to timeout VSC packets even when a consumer chain is not live. + google.protobuf.Duration vsc_timeout_period = 5 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; } message HandshakeMetadata { @@ -69,4 +83,16 @@ message HandshakeMetadata { // successfully slashed on the provider chain message SlashAcks { repeated string addresses = 1; -} \ No newline at end of file +} + +// ConsumerAdditionProposals holds pending governance proposals on the provider chain to spawn a new chain. +message ConsumerAdditionProposals { + // proposals waiting for spawn_time to pass + repeated ConsumerAdditionProposal pending = 1; +} + +// ConsumerRemovalProposals holds pending governance proposals on the provider chain to remove (and stop) a consumer chain. +message ConsumerRemovalProposals { + // proposals waiting for stop_time to pass + repeated ConsumerRemovalProposal pending = 1; +} diff --git a/proto/interchain_security/ccv/provider/v1/query.proto b/proto/interchain_security/ccv/provider/v1/query.proto index 70f36e2967..687f158bef 100644 --- a/proto/interchain_security/ccv/provider/v1/query.proto +++ b/proto/interchain_security/ccv/provider/v1/query.proto @@ -6,15 +6,39 @@ option go_package = "github.com/cosmos/interchain-security/x/ccv/provider/types" import "google/api/annotations.proto"; import "gogoproto/gogo.proto"; import "interchain_security/ccv/consumer/v1/genesis.proto"; +import "interchain_security/ccv/provider/v1/provider.proto"; + service Query { // ConsumerGenesis queries the genesis state needed to start a consumer chain // whose proposal has been accepted - rpc ConsumerGenesis(QueryConsumerGenesisRequest) + rpc QueryConsumerGenesis(QueryConsumerGenesisRequest) returns (QueryConsumerGenesisResponse) { option (google.api.http).get = "/interchain_security/ccv/provider/consumer_genesis/{chain_id}"; } + + // ConsumerChains queries active consumer chains supported by the provider + // chain + rpc QueryConsumerChains(QueryConsumerChainsRequest) + returns (QueryConsumerChainsResponse) { + option (google.api.http).get = + "/interchain_security/ccv/provider/consumer_chains"; + } + + // QueryConsumerChainStarts queries consumer chain start proposals. + rpc QueryConsumerChainStarts(QueryConsumerChainStartProposalsRequest) + returns (QueryConsumerChainStartProposalsResponse) { + option (google.api.http).get = + "/interchain_security/ccv/provider/consumer_chain_start_proposals"; + } + + // QueryConsumerChainStops queries consumer chain stop proposals. + rpc QueryConsumerChainStops(QueryConsumerChainStopProposalsRequest) + returns (QueryConsumerChainStopProposalsResponse) { + option (google.api.http).get = + "/interchain_security/ccv/provider/consumer_chain_stop_proposals"; + } } message QueryConsumerGenesisRequest { string chain_id = 1; } @@ -23,3 +47,24 @@ message QueryConsumerGenesisResponse { interchain_security.ccv.consumer.v1.GenesisState genesis_state = 1 [ (gogoproto.nullable) = false ]; } + +message QueryConsumerChainsRequest {} + +message QueryConsumerChainsResponse { repeated Chain chains = 1; } + +message QueryConsumerChainStartProposalsRequest {} + +message QueryConsumerChainStartProposalsResponse { + ConsumerAdditionProposals proposals = 1; +} + +message QueryConsumerChainStopProposalsRequest {} + +message QueryConsumerChainStopProposalsResponse { + ConsumerRemovalProposals proposals = 1; +} + +message Chain { + string chain_id = 1; + string client_id = 2; +} diff --git a/tests/difference/core/driver/setup.go b/tests/difference/core/driver/setup.go index 3228c3e802..4f6240dce1 100644 --- a/tests/difference/core/driver/setup.go +++ b/tests/difference/core/driver/setup.go @@ -476,8 +476,13 @@ func (b *Builder) createConsumerGenesis(tmConfig *ibctesting.TendermintConfig) * 1000, // ignore distribution "", // ignore distribution "", // ignore distribution + ccv.DefaultCCVTimeoutPeriod, + consumertypes.DefaultTransferTimeoutPeriod, + consumertypes.DefaultConsumerRedistributeFrac, + consumertypes.DefaultHistoricalEntries, + consumertypes.DefaultConsumerUnbondingPeriod, ) - return consumertypes.NewInitialGenesisState(providerClient, providerConsState, valUpdates, consumertypes.SlashRequests{}, params) + return consumertypes.NewInitialGenesisState(providerClient, providerConsState, valUpdates, params) } func (b *Builder) createLink() { @@ -512,9 +517,7 @@ func (b *Builder) doIBCHandshake() { // Configure and create the consumer Client tmConfig := b.path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig) - // TODO: This is intentionally set to unbonding period for P (provider) - // TODO: Not sure why it breaks without this. - tmConfig.UnbondingPeriod = b.initState.UnbondingP + tmConfig.UnbondingPeriod = b.initState.UnbondingC tmConfig.TrustingPeriod = b.initState.Trusting tmConfig.MaxClockDrift = b.initState.MaxClockDrift err = b.path.EndpointB.CreateClient() @@ -534,7 +537,7 @@ func (b *Builder) doIBCHandshake() { func (b *Builder) sendEmptyVSCPacketToFinishHandshake() { vscID := b.providerKeeper().GetValidatorSetUpdateId(b.providerChain().GetContext()) - timeout := uint64(types.GetTimeoutTimestamp(b.chain(P).CurrentHeader.Time).UnixNano()) + timeout := uint64(b.chain(P).CurrentHeader.Time.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) pd := types.NewValidatorSetChangePacketData( []abci.ValidatorUpdate{}, @@ -692,12 +695,12 @@ func (b *Builder) build() { // Create a simulated network link link b.createLink() + // Set the unbonding time on the consumer to the model value + b.consumerKeeper().SetUnbondingPeriod(b.ctx(C), b.initState.UnbondingC) + // Establish connection, channel b.doIBCHandshake() - // Set the unbonding time on the consumer to the model value - b.consumerKeeper().SetUnbondingTime(b.ctx(C), b.initState.UnbondingC) - // Send an empty VSC packet from the provider to the consumer to finish // the handshake. This is necessary because the model starts from a // completely initialized state, with a completed handshake. @@ -752,6 +755,10 @@ func (b *Builder) build() { b.updateClient(b.chainID(C)) } +// The state of the data returned is equivalent to the state of two chains +// after a full handshake, but the precise order of steps used to reach the +// state does not necessarily mimic the order of steps that happen in a +// live scenario. func GetZeroState(suite *suite.Suite, initState InitState) ( *ibctesting.Path, []sdk.ValAddress, int64, int64) { b := Builder{initState: initState, suite: suite} diff --git a/tests/e2e/README.md b/tests/e2e/README.md index da07797183..b8ad9d1970 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -1,13 +1,17 @@ -## End To End Testing + +# End To End Testing E2e tests are categorized into files as follows: -- `setup_test.go` - setup for the e2e tests -- `common_test.go` - helper functions -- `channel_init_test.go` - e2e tests for the _Channel Initialization_ sub-protocol -- `valset_update_test.go` - e2e tests for the _Validator Set Update_ sub-protocol -- `unbonding_test.go` - e2e tests for the _Completion of Unbonding Operations_ -- `slashing_test.go` - e2e tests for the _Consumer Initiated Slashing_ sub-protocol -- `distribution_test.go` - e2e tests for the _Reward Distribution_ sub-protocol -- `stop_consumer_test.go` - e2e tests for the _Consumer Chain Removal_ sub-protocol -- `normal_operations_test.go` - e2e tests for _normal operations_ of ICS enabled chains \ No newline at end of file +- `setup.go` - setup for the e2e tests +- `common.go` - helper functions +- `channel_init.go` - e2e tests for the _Channel Initialization_ sub-protocol +- `valset_update.go` - e2e tests for the _Validator Set Update_ sub-protocol +- `unbonding.go` - e2e tests for the _Completion of Unbonding Operations_ +- `slashing.go` - e2e tests for the _Consumer Initiated Slashing_ sub-protocol +- `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 +- `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` diff --git a/tests/e2e/channel_init.go b/tests/e2e/channel_init.go new file mode 100644 index 0000000000..646f16539e --- /dev/null +++ b/tests/e2e/channel_init.go @@ -0,0 +1,192 @@ +package e2e + +import ( + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + + tmtypes "github.com/tendermint/tendermint/types" + + channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + + ccv "github.com/cosmos/interchain-security/x/ccv/types" + + abci "github.com/tendermint/tendermint/abci/types" + + clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" +) + +func (suite *CCVTestSuite) TestConsumerGenesis() { + + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + + genesis := consumerKeeper.ExportGenesis(suite.consumerChain.GetContext()) + + // suite.Require().Equal(suite.providerClient, genesis.ProviderClientState) + // suite.Require().Equal(suite.providerConsState, genesis.ProviderConsensusState) + + suite.Require().NotPanics(func() { + consumerKeeper.InitGenesis(suite.consumerChain.GetContext(), genesis) + // reset suite to reset provider client + suite.SetupTest() + consumerKeeper = suite.consumerApp.GetConsumerKeeper() + }) + + ctx := suite.consumerChain.GetContext() + portId := consumerKeeper.GetPort(ctx) + suite.Require().Equal(ccv.ConsumerPortID, portId) + + clientId, ok := consumerKeeper.GetProviderClientID(ctx) + suite.Require().True(ok) + _, ok = suite.consumerApp.GetIBCKeeper().ClientKeeper.GetClientState(ctx, clientId) + suite.Require().True(ok) + // suite.Require().Equal(genesis.ProviderClientState, clientState, "client state not set correctly after InitGenesis") + + suite.SetupCCVChannel() + + origTime := suite.consumerChain.GetContext().BlockTime() + + pk1, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) + suite.Require().NoError(err) + pk2, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) + suite.Require().NoError(err) + pd := ccv.NewValidatorSetChangePacketData( + []abci.ValidatorUpdate{ + { + PubKey: pk1, + Power: 30, + }, + { + PubKey: pk2, + Power: 20, + }, + }, + 1, + nil, + ) + packet := channeltypes.NewPacket(pd.GetBytes(), 1, + ccv.ProviderPortID, suite.path.EndpointB.ChannelID, + ccv.ConsumerPortID, suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(1, 0), 0) + consumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) + valUpdates := tmtypes.TM2PB.ValidatorUpdates(suite.providerChain.Vals) + + restartGenesis := consumerKeeper.ExportGenesis(suite.consumerChain.GetContext()) + suite.Require().Equal(valUpdates, restartGenesis.InitialValSet) + + // ensure reset genesis is set correctly + providerChannel := suite.path.EndpointA.ChannelID + suite.Require().Equal(providerChannel, restartGenesis.ProviderChannelId) + maturityTime := consumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 1) + unbondingPeriod := consumerKeeper.GetUnbondingPeriod(suite.consumerCtx()) + suite.Require().Equal(uint64(origTime.Add(unbondingPeriod).UnixNano()), maturityTime, "maturity time is not set correctly in genesis") + + suite.Require().NotPanics(func() { + consumerKeeper.InitGenesis(suite.consumerChain.GetContext(), restartGenesis) + }) +} + +// TestProviderClientMatches tests that the provider client managed by the consumer keeper matches the client keeper's client state +func (suite *CCVTestSuite) TestProviderClientMatches() { + providerClientID, ok := suite.consumerApp.GetConsumerKeeper().GetProviderClientID(suite.consumerCtx()) + suite.Require().True(ok) + + clientState, _ := suite.consumerApp.GetIBCKeeper().ClientKeeper.GetClientState(suite.consumerCtx(), providerClientID) + suite.Require().Equal(suite.providerClient, clientState, "stored client state does not match genesis provider client") +} + +// TestInitTimeout tests the init timeout +func (suite *CCVTestSuite) TestInitTimeout() { + testCases := []struct { + name string + handshake func() + removed bool + }{ + { + "init times out before INIT", func() {}, true, + }, + { + "init times out before TRY", func() { + // send ChanOpenInit + err := suite.path.EndpointA.ChanOpenInit() + suite.Require().NoError(err) + }, true, + }, + { + "init times out before ACK", func() { + // send ChanOpenInit + err := suite.path.EndpointA.ChanOpenInit() + suite.Require().NoError(err) + // send ChanOpenTry + err = suite.path.EndpointB.ChanOpenTry() + suite.Require().NoError(err) + }, true, + }, + { + "init times out before CONFIRM", func() { + // send ChanOpenInit + err := suite.path.EndpointA.ChanOpenInit() + suite.Require().NoError(err) + // send ChanOpenTry + err = suite.path.EndpointB.ChanOpenTry() + suite.Require().NoError(err) + // send ChanOpenAck + err = suite.path.EndpointA.ChanOpenAck() + suite.Require().NoError(err) + }, true, + }, + { + "init completes before timeout", func() { + // send ChanOpenInit + err := suite.path.EndpointA.ChanOpenInit() + suite.Require().NoError(err) + // send ChanOpenTry + err = suite.path.EndpointB.ChanOpenTry() + suite.Require().NoError(err) + // send ChanOpenAck + err = suite.path.EndpointA.ChanOpenAck() + suite.Require().NoError(err) + // send ChanOpenConfirm + err = suite.path.EndpointB.ChanOpenConfirm() + suite.Require().NoError(err) + }, false, + }, + } + + for i, tc := range testCases { + providerKeeper := suite.providerApp.GetProviderKeeper() + initTimeout := providerKeeper.GetParams(suite.providerCtx()).InitTimeoutPeriod + chainID := suite.consumerChain.ChainID + + // get init timeout timestamp + ts, found := providerKeeper.GetInitTimeoutTimestamp(suite.providerCtx(), chainID) + suite.Require().True(found, "cannot find init timeout timestamp; test: %s", tc.name) + expectedTs := suite.providerCtx().BlockTime().Add(initTimeout) + suite.Require().Equal(uint64(expectedTs.UnixNano()), ts, "unexpected init timeout timestamp; test: %s", tc.name) + + // create connection + suite.coordinator.CreateConnections(suite.path) + + // channel opening handshake + tc.handshake() + + // call NextBlock + suite.providerChain.NextBlock() + + // increment time + incrementTimeBy(suite, initTimeout) + + // check whether the chain was removed + _, found = providerKeeper.GetConsumerClientId(suite.providerCtx(), chainID) + suite.Require().Equal(!tc.removed, found, "unexpected outcome; test: %s", tc.name) + + if tc.removed { + // check if the chain was properly removed + suite.checkConsumerChainIsRemoved(chainID, false, false) + } + + if i+1 < len(testCases) { + // reset suite to reset provider client + suite.SetupTest() + } + } +} diff --git a/tests/e2e/channel_init_test.go b/tests/e2e/channel_init_test.go deleted file mode 100644 index c319fda16f..0000000000 --- a/tests/e2e/channel_init_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package e2e_test - -import ( - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - - app "github.com/cosmos/interchain-security/app/consumer" - - tmtypes "github.com/tendermint/tendermint/types" - - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - - appConsumer "github.com/cosmos/interchain-security/app/consumer" - ccv "github.com/cosmos/interchain-security/x/ccv/types" - - abci "github.com/tendermint/tendermint/abci/types" - - clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" -) - -func (suite *CCVTestSuite) TestConsumerGenesis() { - genesis := suite.consumerChain.App.(*app.App).ConsumerKeeper.ExportGenesis(suite.consumerChain.GetContext()) - - suite.Require().Equal(suite.providerClient, genesis.ProviderClientState) - suite.Require().Equal(suite.providerConsState, genesis.ProviderConsensusState) - - suite.Require().NotPanics(func() { - suite.consumerChain.App.(*app.App).ConsumerKeeper.InitGenesis(suite.consumerChain.GetContext(), genesis) - // reset suite to reset provider client - suite.SetupTest() - }) - - ctx := suite.consumerChain.GetContext() - portId := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetPort(ctx) - suite.Require().Equal(ccv.ConsumerPortID, portId) - - clientId, ok := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetProviderClientID(ctx) - suite.Require().True(ok) - clientState, ok := suite.consumerChain.App.GetIBCKeeper().ClientKeeper.GetClientState(ctx, clientId) - suite.Require().True(ok) - suite.Require().Equal(genesis.ProviderClientState, clientState, "client state not set correctly after InitGenesis") - - suite.SetupCCVChannel() - - origTime := suite.consumerChain.GetContext().BlockTime() - - pk1, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) - suite.Require().NoError(err) - pk2, err := cryptocodec.ToTmProtoPublicKey(ed25519.GenPrivKey().PubKey()) - suite.Require().NoError(err) - pd := ccv.NewValidatorSetChangePacketData( - []abci.ValidatorUpdate{ - { - PubKey: pk1, - Power: 30, - }, - { - PubKey: pk2, - Power: 20, - }, - }, - 1, - nil, - ) - packet := channeltypes.NewPacket(pd.GetBytes(), 1, - ccv.ProviderPortID, suite.path.EndpointB.ChannelID, - ccv.ConsumerPortID, suite.path.EndpointA.ChannelID, - clienttypes.NewHeight(1, 0), 0) - suite.consumerChain.App.(*app.App).ConsumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) - valUpdates := tmtypes.TM2PB.ValidatorUpdates(suite.providerChain.Vals) - - restartGenesis := suite.consumerChain.App.(*app.App).ConsumerKeeper.ExportGenesis(suite.consumerChain.GetContext()) - suite.Require().Equal(valUpdates, restartGenesis.InitialValSet) - - // ensure reset genesis is set correctly - providerChannel := suite.path.EndpointA.ChannelID - suite.Require().Equal(providerChannel, restartGenesis.ProviderChannelId) - maturityTime := suite.consumerChain.App.(*app.App).ConsumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 1) - unbondingPeriod, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(suite.consumerCtx()) - suite.Require().True(found) - suite.Require().Equal(uint64(origTime.Add(unbondingPeriod).UnixNano()), maturityTime, "maturity time is not set correctly in genesis") - - suite.Require().NotPanics(func() { - suite.consumerChain.App.(*app.App).ConsumerKeeper.InitGenesis(suite.consumerChain.GetContext(), restartGenesis) - }) -} - -// TestProviderClientMatches tests that the provider client managed by the consumer keeper matches the client keeper's client state -func (suite *CCVTestSuite) TestProviderClientMatches() { - providerClientID, ok := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.consumerCtx()) - suite.Require().True(ok) - - clientState, _ := suite.consumerChain.App.GetIBCKeeper().ClientKeeper.GetClientState(suite.consumerCtx(), providerClientID) - suite.Require().Equal(suite.providerClient, clientState, "stored client state does not match genesis provider client") -} diff --git a/tests/e2e/common_test.go b/tests/e2e/common.go similarity index 72% rename from tests/e2e/common_test.go rename to tests/e2e/common.go index 396aa02ee3..9e8bd1f803 100644 --- a/tests/e2e/common_test.go +++ b/tests/e2e/common.go @@ -1,27 +1,24 @@ -package e2e_test +package e2e import ( - "strings" + "fmt" "time" sdk "github.com/cosmos/cosmos-sdk/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" 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/cosmos/interchain-security/x/ccv/utils" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" - "github.com/cosmos/ibc-go/modules/core/exported" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" 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" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" ibctesting "github.com/cosmos/ibc-go/v3/testing" - - appConsumer "github.com/cosmos/interchain-security/app/consumer" - appProvider "github.com/cosmos/interchain-security/app/provider" ) // ChainType defines the type of chain (either provider or consumer) @@ -41,22 +38,25 @@ func (s *CCVTestSuite) consumerCtx() sdk.Context { } func (s *CCVTestSuite) providerBondDenom() string { - return s.providerChain.App.(*appProvider.App).StakingKeeper.BondDenom(s.providerCtx()) + return s.providerApp.GetE2eStakingKeeper().BondDenom(s.providerCtx()) } -func (s *CCVTestSuite) getVal(index int) (validator stakingtypes.Validator, valAddr sdk.ValAddress) { +func (s *CCVTestSuite) getValByIdx(index int) (validator stakingtypes.Validator, valAddr sdk.ValAddress) { // Choose a validator, and get its address and data structure into the correct types tmValidator := s.providerChain.Vals.Validators[index] valAddr, err := sdk.ValAddressFromHex(tmValidator.Address.String()) s.Require().NoError(err) - validator, found := s.providerChain.App.(*appProvider.App).StakingKeeper.GetValidator(s.providerCtx(), valAddr) - s.Require().True(found) + return s.getVal(s.providerCtx(), valAddr), valAddr +} - return validator, valAddr +func (s *CCVTestSuite) getVal(ctx sdk.Context, valAddr sdk.ValAddress) stakingtypes.Validator { + validator, found := s.providerApp.GetE2eStakingKeeper().GetValidator(s.providerCtx(), valAddr) + s.Require().True(found) + return validator } func getBalance(s *CCVTestSuite, providerCtx sdk.Context, delAddr sdk.AccAddress) sdk.Int { - return s.providerChain.App.(*appProvider.App).BankKeeper.GetBalance(providerCtx, delAddr, s.providerBondDenom()).Amount + return s.providerApp.GetE2eBankKeeper().GetBalance(providerCtx, delAddr, s.providerBondDenom()).Amount } // delegateAndUndelegate delegates bondAmt from delAddr to the first validator @@ -85,19 +85,17 @@ func delegateAndUndelegate(s *CCVTestSuite, delAddr sdk.AccAddress, bondAmt sdk. func delegateAndRedelegate(s *CCVTestSuite, delAddr sdk.AccAddress, srcValAddr sdk.ValAddress, dstValAddr sdk.ValAddress, amount sdk.Int) { - stakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper - // Delegate to src validator - srcValTokensBefore := stakingKeeper.Validator(s.providerCtx(), srcValAddr).GetBondedTokens() + srcValTokensBefore := s.getVal(s.providerCtx(), srcValAddr).GetBondedTokens() _, sharesDelegated, _ := delegate(s, delAddr, amount) // Assert expected amount was bonded to src validator - srcValTokensAfter := stakingKeeper.Validator(s.providerCtx(), srcValAddr).GetBondedTokens() + srcValTokensAfter := s.getVal(s.providerCtx(), srcValAddr).GetBondedTokens() s.Require().Equal(srcValTokensAfter.Sub(srcValTokensBefore), amount) s.providerChain.NextBlock() - dstValTokensBefore := stakingKeeper.Validator(s.providerCtx(), dstValAddr).GetBondedTokens() + dstValTokensBefore := s.getVal(s.providerCtx(), dstValAddr).GetBondedTokens() // redelegate shares from src to dst validators redelegate(s, delAddr, @@ -107,20 +105,20 @@ func delegateAndRedelegate(s *CCVTestSuite, delAddr sdk.AccAddress, ) // Assert expected amount was delegated to dst val - dstValTokensAfter := stakingKeeper.Validator(s.providerCtx(), dstValAddr).GetBondedTokens() + dstValTokensAfter := s.getVal(s.providerCtx(), dstValAddr).GetBondedTokens() s.Require().Equal(dstValTokensAfter.Sub(dstValTokensBefore), amount) // Assert delegated tokens amount returned to original value for src validator - s.Require().Equal(srcValTokensBefore, stakingKeeper.Validator(s.providerCtx(), srcValAddr).GetBondedTokens()) + s.Require().Equal(srcValTokensBefore, s.getVal(s.providerCtx(), srcValAddr).GetBondedTokens()) } // delegate delegates bondAmt to the first validator func delegate(s *CCVTestSuite, delAddr sdk.AccAddress, bondAmt sdk.Int) (initBalance sdk.Int, shares sdk.Dec, valAddr sdk.ValAddress) { initBalance = getBalance(s, s.providerCtx(), delAddr) // choose a validator - validator, valAddr := s.getVal(0) + validator, valAddr := s.getValByIdx(0) // delegate bondAmt tokens on provider to change validator powers - shares, err := s.providerChain.App.(*appProvider.App).StakingKeeper.Delegate( + shares, err := s.providerApp.GetE2eStakingKeeper().Delegate( s.providerCtx(), delAddr, bondAmt, @@ -136,11 +134,11 @@ func delegate(s *CCVTestSuite, delAddr sdk.AccAddress, bondAmt sdk.Int) (initBal // undelegate unbonds an amount of delegator shares from a given validator func undelegate(s *CCVTestSuite, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec) (valsetUpdateId uint64) { - _, err := s.providerChain.App.(*appProvider.App).StakingKeeper.Undelegate(s.providerCtx(), delAddr, valAddr, sharesAmount) + _, err := s.providerApp.GetE2eStakingKeeper().Undelegate(s.providerCtx(), delAddr, valAddr, sharesAmount) s.Require().NoError(err) // save the current valset update ID - valsetUpdateID := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetValidatorSetUpdateId(s.providerCtx()) + valsetUpdateID := s.providerApp.GetProviderKeeper().GetValidatorSetUpdateId(s.providerCtx()) return valsetUpdateID } @@ -149,10 +147,12 @@ func undelegate(s *CCVTestSuite, delAddr sdk.AccAddress, valAddr sdk.ValAddress, // on the provider chain using delegated funds from delAddr func redelegate(s *CCVTestSuite, delAddr sdk.AccAddress, valSrcAddr sdk.ValAddress, ValDstAddr sdk.ValAddress, sharesAmount sdk.Dec) { + + stakingKeeper := s.providerApp.GetE2eStakingKeeper() ctx := s.providerCtx() // delegate bondAmt tokens on provider to change validator powers - completionTime, err := s.providerChain.App.(*appProvider.App).StakingKeeper.BeginRedelegation( + completionTime, err := stakingKeeper.BeginRedelegation( ctx, delAddr, valSrcAddr, @@ -161,7 +161,6 @@ func redelegate(s *CCVTestSuite, delAddr sdk.AccAddress, valSrcAddr sdk.ValAddre ) s.Require().NoError(err) - stakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper providerUnbondingPeriod := stakingKeeper.UnbondingTime(ctx) valSrc, found := stakingKeeper.GetValidator(ctx, valSrcAddr) @@ -207,19 +206,18 @@ func relayAllCommittedPackets( } // incrementTimeByUnbondingPeriod increments the overall time by -// - if chainType == Provider, the unbonding period on the provider. -// - otherwise, the unbonding period on the consumer. +// - if chainType == Provider, the unbonding period on the provider. +// - otherwise, the unbonding period on the consumer. // // 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 - providerUnbondingPeriod := s.providerChain.App.GetStakingKeeper().UnbondingTime(s.providerCtx()) - consumerUnbondingPeriod, found := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(s.consumerCtx()) - s.Require().True(found) - expectedUnbondingPeriod := utils.ComputeConsumerUnbondingPeriod(providerUnbondingPeriod) - s.Require().Equal(expectedUnbondingPeriod+24*time.Hour, providerUnbondingPeriod, "unexpected provider unbonding period") - s.Require().Equal(expectedUnbondingPeriod, consumerUnbondingPeriod, "unexpected consumer unbonding period") + 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 @@ -239,19 +237,44 @@ func incrementTimeByUnbondingPeriod(s *CCVTestSuite, chainType ChainType) { } } -func checkStakingUnbondingOps(s *CCVTestSuite, id uint64, found bool, onHold bool) { - stakingUnbondingOp, wasFound := getStakingUnbondingDelegationEntry(s.providerCtx(), s.providerChain.App.(*appProvider.App).StakingKeeper, id) - s.Require().True(found == wasFound) - s.Require().True(onHold == (0 < stakingUnbondingOp.UnbondingOnHoldRefCount)) +func checkStakingUnbondingOps(s *CCVTestSuite, id uint64, found bool, onHold bool, msgAndArgs ...interface{}) { + stakingUnbondingOp, wasFound := getStakingUnbondingDelegationEntry(s.providerCtx(), s.providerApp.GetE2eStakingKeeper(), id) + s.Require().Equal( + found, + wasFound, + fmt.Sprintf("checkStakingUnbondingOps failed - getStakingUnbondingDelegationEntry; %s", msgAndArgs...), + ) + if wasFound { + s.Require().True( + onHold == (0 < stakingUnbondingOp.UnbondingOnHoldRefCount), + fmt.Sprintf("checkStakingUnbondingOps failed - onHold; %s", msgAndArgs...), + ) + } } -func checkCCVUnbondingOp(s *CCVTestSuite, providerCtx sdk.Context, chainID string, valUpdateID uint64, found bool) { - entries, wasFound := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetUnbondingOpsFromIndex(providerCtx, chainID, valUpdateID) - s.Require().True(found == wasFound) +func checkCCVUnbondingOp(s *CCVTestSuite, providerCtx sdk.Context, chainID string, valUpdateID uint64, found bool, msgAndArgs ...interface{}) { + entries, wasFound := s.providerApp.GetProviderKeeper().GetUnbondingOpsFromIndex(providerCtx, chainID, valUpdateID) + s.Require().Equal( + found, + wasFound, + fmt.Sprintf("checkCCVUnbondingOp failed - GetUnbondingOpsFromIndex; %s", msgAndArgs...), + ) if found { - s.Require().True(len(entries) > 0, "No unbonding ops found") - s.Require().True(len(entries[0].UnbondingConsumerChains) > 0, "Unbonding op with no consumer chains") - s.Require().True(strings.Compare(entries[0].UnbondingConsumerChains[0], "testchain2") == 0, "Unbonding op with unexpected consumer chain") + s.Require().Greater( + len(entries), + 0, + fmt.Sprintf("checkCCVUnbondingOp failed - no unbonding ops found; %s", msgAndArgs...), + ) + s.Require().Greater( + len(entries[0].UnbondingConsumerChains), + 0, + fmt.Sprintf("checkCCVUnbondingOp failed - unbonding op with no consumer chains; %s", msgAndArgs...), + ) + s.Require().Equal( + "testchain2", + entries[0].UnbondingConsumerChains[0], + fmt.Sprintf("checkCCVUnbondingOp failed - unbonding op with unexpected consumer chain; %s", msgAndArgs...), + ) } } @@ -260,8 +283,7 @@ func checkCCVUnbondingOp(s *CCVTestSuite, providerCtx sdk.Context, chainID strin func checkRedelegations(s *CCVTestSuite, delAddr sdk.AccAddress, expect uint16) []stakingtypes.Redelegation { - redelegations := s.providerChain.App.(*appProvider.App).StakingKeeper. - GetRedelegations(s.providerCtx(), delAddr, 2) + redelegations := s.providerApp.GetE2eStakingKeeper().GetRedelegations(s.providerCtx(), delAddr, 2) s.Require().Len(redelegations, int(expect)) return redelegations @@ -273,7 +295,7 @@ func checkRedelegationEntryCompletionTime( s.Require().Equal(expectedCompletion, entry.CompletionTime) } -func getStakingUnbondingDelegationEntry(ctx sdk.Context, k stakingkeeper.Keeper, id uint64) (stakingUnbondingOp stakingtypes.UnbondingDelegationEntry, found bool) { +func getStakingUnbondingDelegationEntry(ctx sdk.Context, k e2e.E2eStakingKeeper, id uint64) (stakingUnbondingOp stakingtypes.UnbondingDelegationEntry, found bool) { stakingUbd, found := k.GetUnbondingDelegationByUnbondingId(ctx, id) for _, entry := range stakingUbd.Entries { @@ -290,10 +312,10 @@ func getStakingUnbondingDelegationEntry(ctx sdk.Context, k stakingkeeper.Keeper, // SendEmptyVSCPacket sends a VSC packet without any changes // to ensure that the channel gets established func (suite *CCVTestSuite) SendEmptyVSCPacket() { - providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper + providerKeeper := suite.providerApp.GetProviderKeeper() oldBlockTime := suite.providerChain.GetContext().BlockTime() - timeout := uint64(ccv.GetTimeoutTimestamp(oldBlockTime).UnixNano()) + timeout := uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) valUpdateID := providerKeeper.GetValidatorSetUpdateId(suite.providerChain.GetContext()) @@ -303,7 +325,7 @@ func (suite *CCVTestSuite) SendEmptyVSCPacket() { nil, ) - seq, ok := suite.providerChain.App.(*appProvider.App).GetIBCKeeper().ChannelKeeper.GetNextSequenceSend( + seq, ok := suite.providerApp.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend( suite.providerChain.GetContext(), ccv.ProviderPortID, suite.path.EndpointB.ChannelID) suite.Require().True(ok) @@ -320,7 +342,7 @@ func (suite *CCVTestSuite) SendEmptyVSCPacket() { // Note that it must be called before sending the embedding IBC packet. func (suite *CCVTestSuite) commitSlashPacket(ctx sdk.Context, packetData ccv.SlashPacketData) []byte { oldBlockTime := ctx.BlockTime() - timeout := uint64(ccv.GetTimeoutTimestamp(oldBlockTime).UnixNano()) + timeout := uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) packet := channeltypes.NewPacket(packetData.GetBytes(), 1, ccv.ConsumerPortID, suite.path.EndpointA.ChannelID, ccv.ProviderPortID, suite.path.EndpointB.ChannelID, clienttypes.Height{}, timeout) @@ -331,10 +353,10 @@ func (suite *CCVTestSuite) commitSlashPacket(ctx sdk.Context, packetData ccv.Sla // incrementTimeBy increments the overall time by jumpPeriod func incrementTimeBy(s *CCVTestSuite, jumpPeriod time.Duration) { // Get unboding period from staking keeper - consumerUnbondingPeriod, found := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(s.consumerChain.GetContext()) - s.Require().True(found) + consumerUnbondingPeriod := s.consumerApp.GetConsumerKeeper().GetUnbondingPeriod(s.consumerChain.GetContext()) split := 1 - if jumpPeriod > consumerUnbondingPeriod/utils.TrustingPeriodFraction { + 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 @@ -350,8 +372,6 @@ func incrementTimeBy(s *CCVTestSuite, jumpPeriod time.Duration) { } } -// TODO: The two CreateCustomClient methods below can be consolidated when test suite structures are consolidated - // CreateCustomClient creates an IBC client on the endpoint // using the given unbonding period. // It will update the clientID for the endpoint if the message @@ -365,7 +385,7 @@ func (suite *CCVTestSuite) CreateCustomClient(endpoint *ibctesting.Endpoint, unb tmConfig, ok := endpoint.ClientConfig.(*ibctesting.TendermintConfig) require.True(endpoint.Chain.T, ok) tmConfig.UnbondingPeriod = unbondingPeriod - tmConfig.TrustingPeriod = unbondingPeriod / utils.TrustingPeriodFraction + tmConfig.TrustingPeriod = unbondingPeriod / providertypes.DefaultTrustingPeriodFraction height := endpoint.Counterparty.Chain.LastHeader.GetHeight().(clienttypes.Height) UpgradePath := []string{"upgrade", "upgradedIBCState"} diff --git a/tests/e2e/democracy_test.go b/tests/e2e/democracy.go similarity index 53% rename from tests/e2e/democracy_test.go rename to tests/e2e/democracy.go index 68445c618e..8b4dfda7f9 100644 --- a/tests/e2e/democracy_test.go +++ b/tests/e2e/democracy.go @@ -1,203 +1,63 @@ -package e2e_test +package e2e import ( - "bytes" "fmt" "strconv" "testing" "time" sdk "github.com/cosmos/cosmos-sdk/types" - transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/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" ibctesting "github.com/cosmos/ibc-go/v3/testing" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" "github.com/cosmos/cosmos-sdk/x/params/types/proposal" proposaltypes "github.com/cosmos/cosmos-sdk/x/params/types/proposal" - appConsumer "github.com/cosmos/interchain-security/app/consumer-democracy" - appProvider "github.com/cosmos/interchain-security/app/provider" - "github.com/cosmos/interchain-security/testutil/simapp" - consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" + "github.com/cosmos/interchain-security/testutil/e2e" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" - "github.com/cosmos/interchain-security/x/ccv/types" - "github.com/cosmos/interchain-security/x/ccv/utils" - - tmtypes "github.com/tendermint/tendermint/types" - "github.com/stretchr/testify/suite" ) -var consumerFraction, _ = sdk.NewDecFromStr(consumerkeeper.ConsumerRedistributeFrac) - type ConsumerDemocracyTestSuite struct { suite.Suite - - coordinator *ibctesting.Coordinator - - // testing chains - providerChain *ibctesting.TestChain + coordinator *ibctesting.Coordinator consumerChain *ibctesting.TestChain - - path *ibctesting.Path - transferPath *ibctesting.Path -} - -func (s *ConsumerDemocracyTestSuite) SetupTest() { - s.coordinator, s.providerChain, s.consumerChain = simapp.NewProviderConsumerDemocracyCoordinator(s.T()) - - // valsets must match - providerValUpdates := tmtypes.TM2PB.ValidatorUpdates(s.providerChain.Vals) - consumerValUpdates := tmtypes.TM2PB.ValidatorUpdates(s.consumerChain.Vals) - s.Require().True(len(providerValUpdates) == len(consumerValUpdates), "initial valset not matching") - for i := 0; i < len(providerValUpdates); i++ { - addr1 := utils.GetChangePubKeyAddress(providerValUpdates[i]) - addr2 := utils.GetChangePubKeyAddress(consumerValUpdates[i]) - s.Require().True(bytes.Equal(addr1, addr2), "validator mismatch") - } - - // move both chains to the next block - s.providerChain.NextBlock() - s.consumerChain.NextBlock() - - // create consumer client on provider chain and set as consumer client for consumer chainID in provider keeper. - err := s.providerChain.App.(*appProvider.App).ProviderKeeper.CreateConsumerClient( - s.providerCtx(), - s.consumerChain.ChainID, - s.consumerChain.LastHeader.GetHeight().(clienttypes.Height), - false, - ) - s.Require().NoError(err) - - // move provider to next block to commit the state - s.providerChain.NextBlock() - - // initialize the consumer chain with the genesis state stored on the provider - consumerGenesis, found := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetConsumerGenesis( - s.providerCtx(), - s.consumerChain.ChainID, - ) - s.Require().True(found, "consumer genesis not found") - s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.InitGenesis(s.consumerChain.GetContext(), &consumerGenesis) - - // create path for the CCV channel - s.path = ibctesting.NewPath(s.consumerChain, s.providerChain) - - // update CCV path with correct info - // - set provider endpoint's clientID - consumerClient, found := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetConsumerClientId( - s.providerCtx(), - s.consumerChain.ChainID, - ) - s.Require().True(found, "consumer client not found") - s.path.EndpointB.ClientID = consumerClient - // - set consumer endpoint's clientID - providerClient, found := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(s.consumerChain.GetContext()) - s.Require().True(found, "provider client not found") - s.path.EndpointA.ClientID = providerClient - // - client config - providerUnbondingPeriod := s.providerChain.App.(*appProvider.App).GetStakingKeeper().UnbondingTime(s.providerCtx()) - s.path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = providerUnbondingPeriod - s.path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod = providerUnbondingPeriod / utils.TrustingPeriodFraction - consumerUnbondingPeriod := utils.ComputeConsumerUnbondingPeriod(providerUnbondingPeriod) - s.path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = consumerUnbondingPeriod - s.path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod = consumerUnbondingPeriod / utils.TrustingPeriodFraction - // - channel config - s.path.EndpointA.ChannelConfig.PortID = types.ConsumerPortID - s.path.EndpointB.ChannelConfig.PortID = types.ProviderPortID - s.path.EndpointA.ChannelConfig.Version = types.Version - s.path.EndpointB.ChannelConfig.Version = types.Version - s.path.EndpointA.ChannelConfig.Order = channeltypes.ORDERED - s.path.EndpointB.ChannelConfig.Order = channeltypes.ORDERED - - // set chains sender account number - // TODO: to be fixed in #151 - err = s.path.EndpointB.Chain.SenderAccount.SetAccountNumber(6) - s.Require().NoError(err) - err = s.path.EndpointA.Chain.SenderAccount.SetAccountNumber(0) - s.Require().NoError(err) - - // create path for the transfer channel - s.transferPath = ibctesting.NewPath(s.consumerChain, s.providerChain) - s.transferPath.EndpointA.ChannelConfig.PortID = transfertypes.PortID - s.transferPath.EndpointB.ChannelConfig.PortID = transfertypes.PortID - s.transferPath.EndpointA.ChannelConfig.Version = transfertypes.Version - s.transferPath.EndpointB.ChannelConfig.Version = transfertypes.Version + consumerApp e2e.DemocConsumerApp + setupCallback DemocSetupCallback } -func (s *ConsumerDemocracyTestSuite) SetupCCVChannel() { - s.StartSetupCCVChannel() - s.CompleteSetupCCVChannel() - s.SetupTransferChannel() +// NewCCVTestSuite returns a new instance of ConsumerDemocracyTestSuite, +// ready to be tested against using suite.Run(). +func NewConsumerDemocracyTestSuite(setupCallback DemocSetupCallback) *ConsumerDemocracyTestSuite { + democSuite := new(ConsumerDemocracyTestSuite) + democSuite.setupCallback = setupCallback + return democSuite } -func (s *ConsumerDemocracyTestSuite) StartSetupCCVChannel() { - s.coordinator.CreateConnections(s.path) - - err := s.path.EndpointA.ChanOpenInit() - s.Require().NoError(err) - - err = s.path.EndpointB.ChanOpenTry() - s.Require().NoError(err) -} - -func (s *ConsumerDemocracyTestSuite) CompleteSetupCCVChannel() { - err := s.path.EndpointA.ChanOpenAck() - s.Require().NoError(err) - - err = s.path.EndpointB.ChanOpenConfirm() - s.Require().NoError(err) - - // ensure counterparty is up to date - err = s.path.EndpointA.UpdateClient() - s.Require().NoError(err) -} - -func (s *ConsumerDemocracyTestSuite) SetupTransferChannel() { - // transfer path will use the same connection as ccv path - - s.transferPath.EndpointA.ClientID = s.path.EndpointA.ClientID - s.transferPath.EndpointA.ConnectionID = s.path.EndpointA.ConnectionID - s.transferPath.EndpointB.ClientID = s.path.EndpointB.ClientID - s.transferPath.EndpointB.ConnectionID = s.path.EndpointB.ConnectionID - - // CCV channel handshake will automatically initiate transfer channel handshake on ACK - // so transfer channel will be on stage INIT when CompleteSetupCCVChannel returns. - s.transferPath.EndpointA.ChannelID = s.consumerChain.App.(*appConsumer.App). - ConsumerKeeper.GetDistributionTransmissionChannel(s.consumerChain.GetContext()) - - // Complete TRY, ACK, CONFIRM for transfer path - err := s.transferPath.EndpointB.ChanOpenTry() - s.Require().NoError(err) - - err = s.transferPath.EndpointA.ChanOpenAck() - s.Require().NoError(err) - - err = s.transferPath.EndpointB.ChanOpenConfirm() - s.Require().NoError(err) - - // ensure counterparty is up to date - err = s.transferPath.EndpointA.UpdateClient() - s.Require().NoError(err) -} +// Callback for instantiating a new coordinator, consumer test chain, and consumer app +// before every test defined on the suite. +type DemocSetupCallback func(t *testing.T) ( + coord *ibctesting.Coordinator, + consumerChain *ibctesting.TestChain, + consumerApp e2e.DemocConsumerApp, +) -func TestConsumerDemocracyTestSuite(t *testing.T) { - suite.Run(t, new(ConsumerDemocracyTestSuite)) +// SetupTest sets up in-mem state before every test relevant to ccv with a democracy consumer +func (suite *ConsumerDemocracyTestSuite) SetupTest() { + // Instantiate new test utils using callback + suite.coordinator, suite.consumerChain, + suite.consumerApp = suite.setupCallback(suite.T()) } -func (s *ConsumerDemocracyTestSuite) TestDemocracyRewarsDistribution() { +func (s *ConsumerDemocracyTestSuite) TestDemocracyRewardsDistribution() { s.consumerChain.NextBlock() - stakingKeeper := s.consumerChain.App.(*appConsumer.App).StakingKeeper - authKeeper := s.consumerChain.App.(*appConsumer.App).AccountKeeper - distrKeeper := s.consumerChain.App.(*appConsumer.App).DistrKeeper - bankKeeper := s.consumerChain.App.(*appConsumer.App).BankKeeper + stakingKeeper := s.consumerApp.GetE2eStakingKeeper() + accountKeeper := s.consumerApp.GetE2eAccountKeeper() + distrKeeper := s.consumerApp.GetE2eDistributionKeeper() + bankKeeper := s.consumerApp.GetE2eBankKeeper() bondDenom := stakingKeeper.BondDenom(s.consumerCtx()) currentRepresentativesRewards := map[string]sdk.Dec{} @@ -211,7 +71,7 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyRewarsDistribution() { } distrModuleAccount := distrKeeper.GetDistributionAccount(s.consumerCtx()) - providerRedistributeAccount := authKeeper.GetModuleAccount(s.consumerCtx(), consumertypes.ConsumerToSendToProviderName) + providerRedistributeAccount := accountKeeper.GetModuleAccount(s.consumerCtx(), consumertypes.ConsumerToSendToProviderName) //balance of consumer redistribute address will always be 0 when checked between 2 NextBlock() calls currentDistrModuleAccountBalance := sdk.NewDecFromInt(bankKeeper.GetBalance(s.consumerCtx(), distrModuleAccount.GetAddress(), bondDenom).Amount) @@ -245,14 +105,21 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyRewarsDistribution() { consumerRedistributeDifference = consumerRedistributeDifference.Add(representativeDifference[key]) } + consumerRedistributionFraction := sdk.MustNewDecFromStr(s.consumerApp.GetConsumerKeeper().GetConsumerRedistributionFrac(s.consumerCtx())) + //confirm that the total amount given to the community pool plus all representatives is equal to the total amount taken out of distribution s.Require().Equal(distrModuleDifference, consumerRedistributeDifference) //confirm that the percentage given to the community pool is equal to the configured community tax percentage. - s.Require().Equal(communityPoolDifference.Quo(consumerRedistributeDifference), distrKeeper.GetCommunityTax(s.consumerCtx())) + s.Require().Equal(communityPoolDifference.Quo(consumerRedistributeDifference), + distrKeeper.GetCommunityTax(s.consumerCtx())) //check that the fraction actually kept by the consumer is the correct fraction. using InEpsilon because the math code uses truncations - s.Require().InEpsilon(distrModuleDifference.Quo(providerDifference.Add(distrModuleDifference)).MustFloat64(), consumerFraction.MustFloat64(), float64(0.0001)) + s.Require().InEpsilon(distrModuleDifference.Quo( + providerDifference.Add(distrModuleDifference)).MustFloat64(), + consumerRedistributionFraction.MustFloat64(), float64(0.0001)) //check that the fraction actually kept by the provider is the correct fraction. using InEpsilon because the math code uses truncations - s.Require().InEpsilon(providerDifference.Quo(providerDifference.Add(distrModuleDifference)).MustFloat64(), sdk.NewDec(1).Sub(consumerFraction).MustFloat64(), float64(0.0001)) + s.Require().InEpsilon(providerDifference.Quo( + providerDifference.Add(distrModuleDifference)).MustFloat64(), + sdk.NewDec(1).Sub(consumerRedistributionFraction).MustFloat64(), float64(0.0001)) totalRepresentativePower := stakingKeeper.GetValidatorSet().TotalBondedTokens(s.consumerCtx()) @@ -264,11 +131,11 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyRewarsDistribution() { } func (s *ConsumerDemocracyTestSuite) TestDemocracyGovernanceWhitelisting() { - govKeeper := s.consumerChain.App.(*appConsumer.App).GovKeeper - stakingKeeper := s.consumerChain.App.(*appConsumer.App).StakingKeeper - bankKeeper := s.consumerChain.App.(*appConsumer.App).BankKeeper - authKeeper := s.consumerChain.App.(*appConsumer.App).AccountKeeper - mintKeeper := s.consumerChain.App.(*appConsumer.App).MintKeeper + govKeeper := s.consumerApp.GetE2eGovKeeper() + stakingKeeper := s.consumerApp.GetE2eStakingKeeper() + bankKeeper := s.consumerApp.GetE2eBankKeeper() + accountKeeper := s.consumerApp.GetE2eAccountKeeper() + mintKeeper := s.consumerApp.GetE2eMintKeeper() newAuthParamValue := uint64(128) newMintParamValue := sdk.NewDecWithPrec(1, 1) // "0.100000000000000000" allowedChange := proposal.ParamChange{Subspace: minttypes.ModuleName, Key: "InflationMax", Value: fmt.Sprintf("\"%s\"", newMintParamValue)} @@ -291,11 +158,11 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyGovernanceWhitelisting() { s.consumerChain.CurrentHeader.Time = s.consumerChain.CurrentHeader.Time.Add(votingParams.VotingPeriod) s.consumerChain.NextBlock() //at this moment, proposal is added, but not yet executed. we are saving old param values for comparison - oldAuthParamValue := authKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters + oldAuthParamValue := accountKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters oldMintParamValue := mintKeeper.GetParams(s.consumerCtx()).InflationMax s.consumerChain.NextBlock() //at this moment, proposal is executed or deleted if forbidden - currentAuthParamValue := authKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters + currentAuthParamValue := accountKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters currentMintParamValue := mintKeeper.GetParams(s.consumerCtx()).InflationMax //check that parameters are not changed, since the proposal contained both forbidden and allowed changes s.Assert().Equal(oldAuthParamValue, currentAuthParamValue) @@ -326,9 +193,9 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyGovernanceWhitelisting() { s.Assert().NoError(err) s.consumerChain.CurrentHeader.Time = s.consumerChain.CurrentHeader.Time.Add(votingParams.VotingPeriod) s.consumerChain.NextBlock() - oldAuthParamValue = authKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters + oldAuthParamValue = accountKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters s.consumerChain.NextBlock() - currentAuthParamValue = authKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters + currentAuthParamValue = accountKeeper.GetParams(s.consumerCtx()).MaxMemoCharacters //check that parameters are not changed, since the proposal contained forbidden changes s.Assert().Equal(oldAuthParamValue, currentAuthParamValue) s.Assert().NotEqual(newAuthParamValue, currentAuthParamValue) @@ -336,7 +203,7 @@ func (s *ConsumerDemocracyTestSuite) TestDemocracyGovernanceWhitelisting() { s.Assert().Equal(votersOldBalances, getAccountsBalances(s.consumerCtx(), bankKeeper, bondDenom, votingAccounts)) } -func submitProposalWithDepositAndVote(govKeeper govkeeper.Keeper, ctx sdk.Context, paramChange proposaltypes.ParameterChangeProposal, +func submitProposalWithDepositAndVote(govKeeper e2e.E2eGovKeeper, ctx sdk.Context, paramChange proposaltypes.ParameterChangeProposal, accounts []ibctesting.SenderAccount, depositAmount sdk.Coins) error { proposal, err := govKeeper.SubmitProposal(ctx, ¶mChange) if err != nil { @@ -356,7 +223,7 @@ func submitProposalWithDepositAndVote(govKeeper govkeeper.Keeper, ctx sdk.Contex return nil } -func getAccountsBalances(ctx sdk.Context, bankKeeper bankkeeper.Keeper, bondDenom string, accounts []ibctesting.SenderAccount) map[string]sdk.Int { +func getAccountsBalances(ctx sdk.Context, bankKeeper e2e.E2eBankKeeper, bondDenom string, accounts []ibctesting.SenderAccount) map[string]sdk.Int { accountsBalances := map[string]sdk.Int{} for _, acc := range accounts { accountsBalances[string(acc.SenderAccount.GetAddress())] = @@ -366,10 +233,6 @@ func getAccountsBalances(ctx sdk.Context, bankKeeper bankkeeper.Keeper, bondDeno return accountsBalances } -func (s *ConsumerDemocracyTestSuite) providerCtx() sdk.Context { - return s.providerChain.GetContext() -} - func (s *ConsumerDemocracyTestSuite) consumerCtx() sdk.Context { return s.consumerChain.GetContext() } diff --git a/tests/e2e/distribution_test.go b/tests/e2e/distribution.go similarity index 84% rename from tests/e2e/distribution_test.go rename to tests/e2e/distribution.go index 5eb7b12b77..cffae78e54 100644 --- a/tests/e2e/distribution_test.go +++ b/tests/e2e/distribution.go @@ -1,4 +1,4 @@ -package e2e_test +package e2e import ( "strings" @@ -6,14 +6,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - app "github.com/cosmos/interchain-security/app/consumer" - providerApp "github.com/cosmos/interchain-security/app/provider" - consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" ) -//This test is valid for minimal viable consumer chain +// This test is valid for minimal viable consumer chain func (s *CCVTestSuite) TestRewardsDistribution() { //set up channel and delegate some tokens in order for validator set update to be sent to the consumer chain @@ -28,12 +25,12 @@ func (s *CCVTestSuite) TestRewardsDistribution() { relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 1) //reward for the provider chain will be sent after each 2 blocks - consumerParams := s.consumerChain.App.(*app.App).GetSubspace(consumertypes.ModuleName) + consumerParams := s.consumerApp.GetSubspace(consumertypes.ModuleName) consumerParams.Set(s.consumerCtx(), consumertypes.KeyBlocksPerDistributionTransmission, int64(2)) s.consumerChain.NextBlock() - consumerAccountKeeper := s.consumerChain.App.(*app.App).AccountKeeper - consumerBankKeeper := s.consumerChain.App.(*app.App).BankKeeper + consumerAccountKeeper := s.consumerApp.GetE2eAccountKeeper() + consumerBankKeeper := s.consumerApp.GetE2eBankKeeper() //send coins to the fee pool which is used for reward distribution consumerFeePoolAddr := consumerAccountKeeper.GetModuleAccount(s.consumerCtx(), authtypes.FeeCollectorName).GetAddress() @@ -45,7 +42,7 @@ func (s *CCVTestSuite) TestRewardsDistribution() { s.Require().Equal(sdk.NewInt(100).Add(feePoolTokensOld.AmountOf(sdk.DefaultBondDenom)), feePoolTokens.AmountOf(sdk.DefaultBondDenom)) //calculate the reward for consumer and provider chain. Consumer will receive ConsumerRedistributeFrac, the rest is going to provider - frac, err := sdk.NewDecFromStr(consumerkeeper.ConsumerRedistributeFrac) + frac, err := sdk.NewDecFromStr(s.consumerApp.GetConsumerKeeper().GetConsumerRedistributionFrac(s.consumerCtx())) s.Require().NoError(err) consumerExpectedRewards, _ := sdk.NewDecCoinsFromCoins(feePoolTokens...).MulDec(frac).TruncateDecimal() providerExpectedRewards := feePoolTokens.Sub(consumerExpectedRewards) @@ -68,7 +65,7 @@ func (s *CCVTestSuite) TestRewardsDistribution() { relayAllCommittedPackets(s, s.consumerChain, s.transferPath, transfertypes.PortID, s.transferPath.EndpointA.ChannelID, 1) s.providerChain.NextBlock() - communityCoins := s.providerChain.App.(*providerApp.App).DistrKeeper.GetFeePoolCommunityCoins(s.providerCtx()) + communityCoins := s.providerApp.GetE2eDistributionKeeper().GetFeePoolCommunityCoins(s.providerCtx()) ibcCoinIndex := -1 for i, coin := range communityCoins { if strings.HasPrefix(coin.Denom, "ibc") { diff --git a/tests/e2e/instance_test.go b/tests/e2e/instance_test.go new file mode 100644 index 0000000000..4c6a47c39a --- /dev/null +++ b/tests/e2e/instance_test.go @@ -0,0 +1,59 @@ +package e2e_test + +import ( + "testing" + + ibctesting "github.com/cosmos/ibc-go/v3/testing" + appConsumer "github.com/cosmos/interchain-security/app/consumer" + appConsumerDemocracy "github.com/cosmos/interchain-security/app/consumer-democracy" + appProvider "github.com/cosmos/interchain-security/app/provider" + "github.com/cosmos/interchain-security/tests/e2e" + e2etestutil "github.com/cosmos/interchain-security/testutil/e2e" + "github.com/cosmos/interchain-security/testutil/simapp" + "github.com/stretchr/testify/suite" +) + +// This file can be used as an example e2e testing instance for any provider/consumer applications. +// In the case of this repo, we're testing the dummy provider/consumer applications, +// but to test any arbitrary app, you only need to replicate this file, and pass in the +// appropriate callback to the testing suites. Note that any provider/consumer applications +// must implement the interfaces defined in /testutil/e2e/interfaces.go + +// Executes the standard group of ccv tests against a consumer and provider app.go implementation. +func TestCCVTestSuite(t *testing.T) { + + ccvSuite := e2e.NewCCVTestSuite( + func(t *testing.T) ( + *ibctesting.Coordinator, + *ibctesting.TestChain, + *ibctesting.TestChain, + e2etestutil.ProviderApp, + e2etestutil.ConsumerApp, + ) { + // Here we pass the concrete types that must implement the necessary interfaces + // to be ran with e2e tests. + coord, prov, cons := simapp.NewProviderConsumerCoordinator(t) + return coord, prov, cons, prov.App.(*appProvider.App), cons.App.(*appConsumer.App) + }, + ) + suite.Run(t, ccvSuite) +} + +// TODO: Run the gov enabled consumer against the standard suite of tests: https://github.com/cosmos/interchain-security/issues/397 + +// Executes a specialized group of tests specific to a democracy consumer, against a democracy consumer app.go implementation. +func TestConsumerDemocracyTestSuite(t *testing.T) { + democSuite := e2e.NewConsumerDemocracyTestSuite( + func(t *testing.T) ( + *ibctesting.Coordinator, + *ibctesting.TestChain, + e2etestutil.DemocConsumerApp, + ) { + // Here we pass the concrete types that must implement the necessary interfaces + // to be ran with e2e tests. + coord, _, cons := simapp.NewProviderConsumerDemocracyCoordinator(t) + return coord, cons, cons.App.(*appConsumerDemocracy.App) + }, + ) + suite.Run(t, democSuite) +} diff --git a/tests/e2e/normal_operations_test.go b/tests/e2e/normal_operations.go similarity index 79% rename from tests/e2e/normal_operations_test.go rename to tests/e2e/normal_operations.go index 1c90efaf50..5fc6689467 100644 --- a/tests/e2e/normal_operations_test.go +++ b/tests/e2e/normal_operations.go @@ -1,15 +1,14 @@ -package e2e_test +package e2e import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - appConsumer "github.com/cosmos/interchain-security/app/consumer" - "github.com/cosmos/interchain-security/x/ccv/consumer/types" + consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) // Tests the tracking of historical info in the context of new blocks being committed -func (k CCVTestSuite) TestTrackHistoricalInfo() { - consumerKeeper := k.consumerChain.App.(*appConsumer.App).ConsumerKeeper +func (k CCVTestSuite) TestHistoricalInfo() { + consumerKeeper := k.consumerApp.GetConsumerKeeper() cCtx := k.consumerChain.GetContext // save init consumer valset length @@ -22,7 +21,7 @@ func (k CCVTestSuite) TestTrackHistoricalInfo() { createVal := func(k CCVTestSuite) { // add new validator to consumer states pk := ed25519.GenPrivKey().PubKey() - cVal, err := types.NewCCValidator(pk.Address(), int64(1), pk) + cVal, err := consumertypes.NewCCValidator(pk.Address(), int64(1), pk) k.Require().NoError(err) consumerKeeper.SetCCValidator(k.consumerChain.GetContext(), cVal) @@ -39,13 +38,14 @@ func (k CCVTestSuite) TestTrackHistoricalInfo() { createVal, createVal, func(k CCVTestSuite) { - newHeight := k.consumerChain.GetContext().BlockHeight() + int64(types.HistoricalEntries) + historicalEntries := k.consumerApp.GetConsumerKeeper().GetHistoricalEntries(k.consumerCtx()) + newHeight := k.consumerChain.GetContext().BlockHeight() + historicalEntries header := tmproto.Header{ ChainID: "HelloChain", Height: newHeight, } ctx := k.consumerChain.GetContext().WithBlockHeader(header) - k.consumerChain.App.(*appConsumer.App).ConsumerKeeper.TrackHistoricalInfo(ctx) + consumerKeeper.TrackHistoricalInfo(ctx) }, } @@ -71,7 +71,7 @@ func (k CCVTestSuite) TestTrackHistoricalInfo() { expLen: 0, }, { - height: initHeight + int64(types.HistoricalEntries) + 2, + height: initHeight + int64(consumertypes.DefaultHistoricalEntries) + 2, found: true, expLen: initValsetLen + 2, }, diff --git a/tests/e2e/setup_test.go b/tests/e2e/setup.go similarity index 72% rename from tests/e2e/setup_test.go rename to tests/e2e/setup.go index 3fd0522729..069566253f 100644 --- a/tests/e2e/setup_test.go +++ b/tests/e2e/setup.go @@ -1,11 +1,15 @@ -package e2e_test +package e2e import ( + "time" + ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" "bytes" "testing" + e2e "github.com/cosmos/interchain-security/testutil/e2e" + ccv "github.com/cosmos/interchain-security/x/ccv/types" "github.com/cosmos/interchain-security/x/ccv/utils" @@ -14,32 +18,55 @@ import ( channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" ibctesting "github.com/cosmos/ibc-go/v3/testing" - appConsumer "github.com/cosmos/interchain-security/app/consumer" - appProvider "github.com/cosmos/interchain-security/app/provider" - "github.com/cosmos/interchain-security/testutil/simapp" - tmtypes "github.com/tendermint/tendermint/types" "github.com/stretchr/testify/suite" ) +// CCVTestSuite is an in-mem test suite which implements the standard group of tests validating +// the e2e functionality of ccv enabled chains. +// Any method implemented for this struct will be ran when suite.Run() is called. type CCVTestSuite struct { suite.Suite coordinator *ibctesting.Coordinator providerChain *ibctesting.TestChain consumerChain *ibctesting.TestChain + providerApp e2e.ProviderApp + consumerApp e2e.ConsumerApp providerClient *ibctmtypes.ClientState providerConsState *ibctmtypes.ConsensusState path *ibctesting.Path transferPath *ibctesting.Path + setupCallback SetupCallback } -func TestCCVTestSuite(t *testing.T) { - suite.Run(t, new(CCVTestSuite)) +// NewCCVTestSuite returns a new instance of CCVTestSuite, ready to be tested against using suite.Run(). +func NewCCVTestSuite(setupCallback SetupCallback) *CCVTestSuite { + ccvSuite := new(CCVTestSuite) + ccvSuite.setupCallback = setupCallback + return ccvSuite } +// Callback for instantiating a new coordinator, provider/consumer test chains, and provider/consumer app +// before every test defined on the suite. +type SetupCallback func(t *testing.T) ( + coord *ibctesting.Coordinator, + providerChain *ibctesting.TestChain, + consumerChain *ibctesting.TestChain, + providerApp e2e.ProviderApp, + consumerApp e2e.ConsumerApp, +) + +// SetupTest sets up in-mem state before every test func (suite *CCVTestSuite) SetupTest() { - suite.coordinator, suite.providerChain, suite.consumerChain = simapp.NewProviderConsumerCoordinator(suite.T()) + + // Instantiate new test utils using callback + suite.coordinator, suite.providerChain, + suite.consumerChain, suite.providerApp, + suite.consumerApp = suite.setupCallback(suite.T()) + + providerKeeper := suite.providerApp.GetProviderKeeper() + consumerKeeper := suite.consumerApp.GetConsumerKeeper() // valsets must match providerValUpdates := tmtypes.TM2PB.ValidatorUpdates(suite.providerChain.Vals) @@ -56,7 +83,7 @@ func (suite *CCVTestSuite) SetupTest() { suite.consumerChain.NextBlock() // create consumer client on provider chain and set as consumer client for consumer chainID in provider keeper. - err := suite.providerChain.App.(*appProvider.App).ProviderKeeper.CreateConsumerClient( + err := providerKeeper.CreateConsumerClient( suite.providerCtx(), suite.consumerChain.ChainID, suite.consumerChain.LastHeader.GetHeight().(clienttypes.Height), @@ -67,12 +94,12 @@ func (suite *CCVTestSuite) SetupTest() { suite.providerChain.NextBlock() // initialize the consumer chain with the genesis state stored on the provider - consumerGenesis, found := suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetConsumerGenesis( + consumerGenesis, found := providerKeeper.GetConsumerGenesis( suite.providerCtx(), suite.consumerChain.ChainID, ) suite.Require().True(found, "consumer genesis not found") - suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.InitGenesis(suite.consumerChain.GetContext(), &consumerGenesis) + consumerKeeper.InitGenesis(suite.consumerCtx(), &consumerGenesis) suite.providerClient = consumerGenesis.ProviderClientState suite.providerConsState = consumerGenesis.ProviderConsensusState @@ -81,7 +108,7 @@ func (suite *CCVTestSuite) SetupTest() { // update CCV path with correct info // - set provider endpoint's clientID - consumerClient, found := suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetConsumerClientId( + consumerClient, found := providerKeeper.GetConsumerClientId( suite.providerCtx(), suite.consumerChain.ChainID, ) @@ -89,16 +116,18 @@ func (suite *CCVTestSuite) SetupTest() { suite.Require().True(found, "consumer client not found") suite.path.EndpointB.ClientID = consumerClient // - set consumer endpoint's clientID - providerClient, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderClientID(suite.consumerChain.GetContext()) + providerClient, found := consumerKeeper.GetProviderClientID(suite.consumerChain.GetContext()) suite.Require().True(found, "provider client not found") suite.path.EndpointA.ClientID = providerClient // - client config - providerUnbondingPeriod := suite.providerChain.App.(*appProvider.App).GetStakingKeeper().UnbondingTime(suite.providerCtx()) + + trustingPeriodFraction := suite.providerApp.GetProviderKeeper().GetTrustingPeriodFraction(suite.providerCtx()) + providerUnbondingPeriod := suite.providerApp.GetStakingKeeper().UnbondingTime(suite.providerCtx()) suite.path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = providerUnbondingPeriod - suite.path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod = providerUnbondingPeriod / utils.TrustingPeriodFraction - consumerUnbondingPeriod := utils.ComputeConsumerUnbondingPeriod(providerUnbondingPeriod) + suite.path.EndpointB.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod = providerUnbondingPeriod / time.Duration(trustingPeriodFraction) + consumerUnbondingPeriod := consumerKeeper.GetUnbondingPeriod(suite.consumerCtx()) suite.path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).UnbondingPeriod = consumerUnbondingPeriod - suite.path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod = consumerUnbondingPeriod / utils.TrustingPeriodFraction + suite.path.EndpointA.ClientConfig.(*ibctesting.TendermintConfig).TrustingPeriod = consumerUnbondingPeriod / time.Duration(trustingPeriodFraction) // - channel config suite.path.EndpointA.ChannelConfig.PortID = ccv.ConsumerPortID suite.path.EndpointB.ChannelConfig.PortID = ccv.ProviderPortID @@ -159,8 +188,9 @@ func (suite *CCVTestSuite) SetupTransferChannel() { // CCV channel handshake will automatically initiate transfer channel handshake on ACK // so transfer channel will be on stage INIT when CompleteSetupCCVChannel returns. - suite.transferPath.EndpointA.ChannelID = suite.consumerChain.App.(*appConsumer.App). - ConsumerKeeper.GetDistributionTransmissionChannel(suite.consumerChain.GetContext()) + suite.transferPath.EndpointA.ChannelID = + suite.consumerApp.GetConsumerKeeper().GetDistributionTransmissionChannel( + suite.consumerChain.GetContext()) // Complete TRY, ACK, CONFIRM for transfer path err := suite.transferPath.EndpointB.ChanOpenTry() diff --git a/tests/e2e/slashing_test.go b/tests/e2e/slashing.go similarity index 81% rename from tests/e2e/slashing_test.go rename to tests/e2e/slashing.go index 1e7e5fd6af..f7a6736fae 100644 --- a/tests/e2e/slashing_test.go +++ b/tests/e2e/slashing.go @@ -1,4 +1,4 @@ -package e2e_test +package e2e import ( "fmt" @@ -14,8 +14,6 @@ import ( clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - appConsumer "github.com/cosmos/interchain-security/app/consumer" - appProvider "github.com/cosmos/interchain-security/app/provider" "github.com/cosmos/interchain-security/x/ccv/types" abci "github.com/tendermint/tendermint/abci/types" @@ -28,10 +26,10 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { s.SetupTransferChannel() validatorsPerChain := len(s.consumerChain.Vals.Validators) - providerStakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper - providerSlashingKeeper := s.providerChain.App.(*appProvider.App).SlashingKeeper - - consumerKeeper := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() + providerSlashingKeeper := s.providerApp.GetE2eSlashingKeeper() + consumerKeeper := s.consumerApp.GetConsumerKeeper() + providerKeeper := s.providerApp.GetProviderKeeper() // get a cross-chain validator address, pubkey and balance tmVals := s.consumerChain.Vals.Validators @@ -52,7 +50,8 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { providerSlashingKeeper.SetValidatorSigningInfo(s.providerCtx(), consAddr, valInfo) // get valseUpdateId for current block height - valsetUpdateId := consumerKeeper.GetHeightValsetUpdateID(s.consumerCtx(), uint64(s.consumerCtx().BlockHeight())) + valsetUpdateId := consumerKeeper.GetHeightValsetUpdateID(s.consumerCtx(), + uint64(s.consumerCtx().BlockHeight())) // construct the downtime packet with the validator address and power along // with the slashing and jailing parameters @@ -64,21 +63,22 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { oldBlockTime := s.consumerCtx().BlockTime() slashFraction := int64(100) packetData := types.NewSlashPacketData(validator, valsetUpdateId, stakingtypes.Downtime) - timeout := uint64(types.GetTimeoutTimestamp(oldBlockTime).UnixNano()) - packet := channeltypes.NewPacket(packetData.GetBytes(), 1, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, - ccv.ProviderPortID, s.path.EndpointB.ChannelID, clienttypes.Height{}, timeout) + timeout := uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + packet := channeltypes.NewPacket(packetData.GetBytes(), 1, ccv.ConsumerPortID, + s.path.EndpointA.ChannelID, ccv.ProviderPortID, s.path.EndpointB.ChannelID, + clienttypes.Height{}, timeout) // Send the downtime packet through CCV err = s.path.EndpointA.SendPacket(packet) s.Require().NoError(err) // Set outstanding slashing flag - s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SetOutstandingDowntime(s.consumerCtx(), consAddr) + consumerKeeper.SetOutstandingDowntime(s.consumerCtx(), consAddr) // save next VSC packet info oldBlockTime = s.providerCtx().BlockTime() - timeout = uint64(types.GetTimeoutTimestamp(oldBlockTime).UnixNano()) - valsetUpdateID := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetValidatorSetUpdateId(s.providerCtx()) + timeout = uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + valsetUpdateID := providerKeeper.GetValidatorSetUpdateId(s.providerCtx()) // receive the downtime packet on the provider chain; // RecvPacket() calls the provider endblocker thus sends a VSC packet to the consumer @@ -119,7 +119,7 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { // check that the validator is successfully jailed on provider - validatorJailed, ok := s.providerChain.App.(*appProvider.App).StakingKeeper.GetValidatorByConsAddr(s.providerCtx(), consAddr) + validatorJailed, ok := s.providerApp.GetE2eStakingKeeper().GetValidatorByConsAddr(s.providerCtx(), consAddr) s.Require().True(ok) s.Require().True(validatorJailed.Jailed) s.Require().Equal(validatorJailed.Status, stakingtypes.Unbonding) @@ -135,7 +135,7 @@ func (s *CCVTestSuite) TestSendSlashPacketDowntime() { s.Require().True(valSignInfo.JailedUntil.After(s.providerCtx().BlockHeader().Time)) // check that the outstanding slashing flag is reset on the consumer - pFlag := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OutstandingDowntime(s.consumerCtx(), consAddr) + pFlag := consumerKeeper.OutstandingDowntime(s.consumerCtx(), consAddr) s.Require().False(pFlag) // check that slashing packet gets acknowledged @@ -149,9 +149,10 @@ func (s *CCVTestSuite) TestSendSlashPacketDoubleSign() { s.SetupTransferChannel() validatorsPerChain := len(s.consumerChain.Vals.Validators) - providerStakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper - providerSlashingKeeper := s.providerChain.App.(*appProvider.App).SlashingKeeper - consumerKeeper := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() + providerSlashingKeeper := s.providerApp.GetE2eSlashingKeeper() + providerKeeper := s.providerApp.GetProviderKeeper() + consumerKeeper := s.consumerApp.GetConsumerKeeper() // get a cross-chain validator address, pubkey and balance tmVals := s.consumerChain.Vals.Validators @@ -184,7 +185,7 @@ func (s *CCVTestSuite) TestSendSlashPacketDoubleSign() { oldBlockTime := s.consumerCtx().BlockTime() packetData := types.NewSlashPacketData(validator, valsetUpdateId, stakingtypes.DoubleSign) - timeout := uint64(types.GetTimeoutTimestamp(oldBlockTime).UnixNano()) + timeout := uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) packet := channeltypes.NewPacket(packetData.GetBytes(), 1, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, ccv.ProviderPortID, s.path.EndpointB.ChannelID, clienttypes.Height{}, timeout) @@ -194,8 +195,8 @@ func (s *CCVTestSuite) TestSendSlashPacketDoubleSign() { // save next VSC packet info oldBlockTime = s.providerCtx().BlockTime() - timeout = uint64(types.GetTimeoutTimestamp(oldBlockTime).UnixNano()) - valsetUpdateID := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetValidatorSetUpdateId(s.providerCtx()) + timeout = uint64(oldBlockTime.Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + valsetUpdateID := providerKeeper.GetValidatorSetUpdateId(s.providerCtx()) // receive the downtime packet on the provider chain; // RecvPacket() calls the provider endblocker and thus sends a VSC packet to the consumer @@ -235,7 +236,7 @@ func (s *CCVTestSuite) TestSendSlashPacketDoubleSign() { s.Require().NoError(err) // check that the validator is successfully jailed on provider - validatorJailed, ok := s.providerChain.App.(*appProvider.App).StakingKeeper.GetValidatorByConsAddr(s.providerCtx(), consAddr) + validatorJailed, ok := providerStakingKeeper.GetValidatorByConsAddr(s.providerCtx(), consAddr) s.Require().True(ok) s.Require().True(validatorJailed.Jailed) s.Require().Equal(validatorJailed.Status, stakingtypes.Unbonding) @@ -256,8 +257,8 @@ func (s *CCVTestSuite) TestSendSlashPacketDoubleSign() { } func (s *CCVTestSuite) TestSlashPacketAcknowldgement() { - providerKeeper := s.providerChain.App.(*appProvider.App).ProviderKeeper - consumerKeeper := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper + providerKeeper := s.providerApp.GetProviderKeeper() + consumerKeeper := s.consumerApp.GetConsumerKeeper() s.SetupCCVChannel() s.SetupTransferChannel() @@ -277,9 +278,9 @@ func (s *CCVTestSuite) TestSlashPacketAcknowldgement() { // TestHandleSlashPacketDoubleSigning tests the handling of a double-signing related slash packet, with e2e tests func (suite *CCVTestSuite) TestHandleSlashPacketDoubleSigning() { - providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper - providerSlashingKeeper := suite.providerChain.App.(*appProvider.App).SlashingKeeper - providerStakingKeeper := suite.providerChain.App.(*appProvider.App).StakingKeeper + providerKeeper := suite.providerApp.GetProviderKeeper() + providerSlashingKeeper := suite.providerApp.GetE2eSlashingKeeper() + providerStakingKeeper := suite.providerApp.GetE2eStakingKeeper() tmVal := suite.providerChain.Vals.Validators[0] consAddr := sdk.ConsAddress(tmVal.Address) @@ -308,7 +309,7 @@ func (suite *CCVTestSuite) TestHandleSlashPacketDoubleSigning() { ) suite.NoError(err) - // verify that validator is jailed in the staking and slashing mdodules' states + // verify that validator is jailed in the staking and slashing modules' states suite.Require().True(providerStakingKeeper.IsValidatorJailed(suite.providerCtx(), consAddr)) signingInfo, _ := providerSlashingKeeper.GetValidatorSigningInfo(suite.providerCtx(), consAddr) @@ -318,9 +319,9 @@ func (suite *CCVTestSuite) TestHandleSlashPacketDoubleSigning() { // TestHandleSlashPacketErrors tests errors for the HandleSlashPacket method in an e2e testing setting func (suite *CCVTestSuite) TestHandleSlashPacketErrors() { - providerStakingKeeper := suite.providerChain.App.(*appProvider.App).StakingKeeper - ProviderKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper - providerSlashingKeeper := suite.providerChain.App.(*appProvider.App).SlashingKeeper + providerStakingKeeper := suite.providerApp.GetE2eStakingKeeper() + ProviderKeeper := suite.providerApp.GetProviderKeeper() + providerSlashingKeeper := suite.providerApp.GetE2eSlashingKeeper() consumerChainID := suite.consumerChain.ChainID // sync contexts block height @@ -402,8 +403,9 @@ func (suite *CCVTestSuite) TestHandleSlashPacketErrors() { // by varying the slash packet VSC ID mapping to infraction heights // lesser, equal or greater than the undelegation entry creation height func (suite *CCVTestSuite) TestHandleSlashPacketDistribution() { - providerStakingKeeper := suite.providerChain.App.(*appProvider.App).StakingKeeper - providerKeeper := suite.providerChain.App.(*appProvider.App).ProviderKeeper + providerKeeper := suite.providerApp.GetProviderKeeper() + providerStakingKeeper := suite.providerApp.GetE2eStakingKeeper() + providerSlashingKeeper := suite.providerApp.GetE2eSlashingKeeper() // choose a validator tmValidator := suite.providerChain.Vals.Validators[0] @@ -455,7 +457,7 @@ func (suite *CCVTestSuite) TestHandleSlashPacketDistribution() { } // create validator signing info to test slashing - suite.providerChain.App.(*appProvider.App).SlashingKeeper.SetValidatorSigningInfo( + providerSlashingKeeper.SetValidatorSigningInfo( suite.providerChain.GetContext(), sdk.ConsAddress(tmValidator.Address), slashingtypes.ValidatorSigningInfo{Address: tmValidator.Address.String()}, @@ -473,7 +475,8 @@ func (suite *CCVTestSuite) TestHandleSlashPacketDistribution() { } // save unbonding balance before slashing tests - ubd, found := providerStakingKeeper.GetUnbondingDelegation(suite.providerChain.GetContext(), delAddr, valAddr) + ubd, found := providerStakingKeeper.GetUnbondingDelegation( + suite.providerChain.GetContext(), delAddr, valAddr) suite.Require().True(found) ubdBalance := ubd.Entries[0].Balance @@ -507,36 +510,40 @@ func (suite *CCVTestSuite) TestValidatorDowntime() { suite.SetupCCVChannel() suite.SendEmptyVSCPacket() + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + consumerSlashingKeeper := suite.consumerApp.GetE2eSlashingKeeper() + consumerIBCKeeper := suite.consumerApp.GetIBCKeeper() + // sync suite context after CCV channel is established ctx := suite.consumerCtx() - app := suite.consumerChain.App.(*appConsumer.App) channelID := suite.path.EndpointA.ChannelID // pick a cross-chain validator - vals := app.ConsumerKeeper.GetAllCCValidator(ctx) + vals := consumerKeeper.GetAllCCValidator(ctx) consAddr := sdk.ConsAddress(vals[0].Address) // save next sequence before sending a slash packet - seq, ok := app.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) + seq, ok := consumerIBCKeeper.ChannelKeeper.GetNextSequenceSend( + ctx, ccv.ConsumerPortID, channelID) suite.Require().True(ok) // Sign 100 blocks valPower := int64(1) - height, signedBlocksWindow := int64(0), app.SlashingKeeper.SignedBlocksWindow(ctx) + height, signedBlocksWindow := int64(0), consumerSlashingKeeper.SignedBlocksWindow(ctx) for ; height < signedBlocksWindow; height++ { ctx = ctx.WithBlockHeight(height) - app.SlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, true) + consumerSlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, true) } - missedBlockThreshold := (2 * signedBlocksWindow) - app.SlashingKeeper.MinSignedPerWindow(ctx) + missedBlockThreshold := (2 * signedBlocksWindow) - consumerSlashingKeeper.MinSignedPerWindow(ctx) ctx = suite.consumerCtx() // construct slash packet to be sent and get its commit packetData := ccv.NewSlashPacketData( abci.Validator{Address: vals[0].Address, Power: valPower}, // get the VSC ID mapping the infraction height - app.ConsumerKeeper.GetHeightValsetUpdateID(ctx, uint64(missedBlockThreshold-sdk.ValidatorUpdateDelay-1)), + consumerKeeper.GetHeightValsetUpdateID(ctx, uint64(missedBlockThreshold-sdk.ValidatorUpdateDelay-1)), stakingtypes.Downtime, ) expCommit := suite.commitSlashPacket(ctx, packetData) @@ -544,42 +551,42 @@ func (suite *CCVTestSuite) TestValidatorDowntime() { // Miss 50 blocks and expect a slash packet to be sent for ; height <= missedBlockThreshold; height++ { ctx = ctx.WithBlockHeight(height) - app.SlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, false) + consumerSlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, false) } ctx = suite.consumerCtx() // check validator signing info - res, _ := app.SlashingKeeper.GetValidatorSigningInfo(ctx, consAddr) + res, _ := consumerSlashingKeeper.GetValidatorSigningInfo(ctx, consAddr) // expect increased jail time - suite.Require().True(res.JailedUntil.Equal(ctx.BlockTime().Add(app.SlashingKeeper.DowntimeJailDuration(ctx))), "did not update validator jailed until signing info") + suite.Require().True(res.JailedUntil.Equal(ctx.BlockTime().Add(consumerSlashingKeeper.DowntimeJailDuration(ctx))), "did not update validator jailed until signing info") // expect missed block counters reseted suite.Require().Zero(res.MissedBlocksCounter, "did not reset validator missed block counter") suite.Require().Zero(res.IndexOffset) - app.SlashingKeeper.IterateValidatorMissedBlockBitArray(ctx, consAddr, func(_ int64, missed bool) bool { + consumerSlashingKeeper.IterateValidatorMissedBlockBitArray(ctx, consAddr, func(_ int64, missed bool) bool { suite.Require().True(missed) return false }) // verify that the slash packet was sent - gotCommit := app.IBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) + gotCommit := consumerIBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) suite.Require().NotNil(gotCommit, "did not found slash packet commitment") suite.Require().EqualValues(expCommit, gotCommit, "invalid slash packet commitment") // verify that the slash packet was sent - suite.Require().True(app.ConsumerKeeper.OutstandingDowntime(ctx, consAddr)) + suite.Require().True(consumerKeeper.OutstandingDowntime(ctx, consAddr)) // check that the outstanding slashing flag prevents the jailed validator to keep missing block for ; height < missedBlockThreshold+signedBlocksWindow; height++ { ctx = ctx.WithBlockHeight(height) - app.SlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, false) + consumerSlashingKeeper.HandleValidatorSignature(ctx, vals[0].Address, valPower, false) } - res, _ = app.SlashingKeeper.GetValidatorSigningInfo(ctx, consAddr) + res, _ = consumerSlashingKeeper.GetValidatorSigningInfo(ctx, consAddr) suite.Require().Zero(res.MissedBlocksCounter, "did not reset validator missed block counter") suite.Require().Zero(res.IndexOffset) - app.SlashingKeeper.IterateValidatorMissedBlockBitArray(ctx, consAddr, func(_ int64, missed bool) bool { + consumerSlashingKeeper.IterateValidatorMissedBlockBitArray(ctx, consAddr, func(_ int64, missed bool) bool { suite.Require().True(missed, "did not reset validator missed block bit array") return false }) @@ -595,7 +602,6 @@ func (suite *CCVTestSuite) TestValidatorDoubleSigning() { // sync suite context after CCV channel is established ctx := suite.consumerCtx() - app := suite.consumerChain.App.(*appConsumer.App) channelID := suite.path.EndpointA.ChannelID // create a validator pubkey and address @@ -616,29 +622,29 @@ func (suite *CCVTestSuite) TestValidatorDoubleSigning() { } // add validator signing-info to the store - app.SlashingKeeper.SetValidatorSigningInfo(ctx, consAddr, slashingtypes.ValidatorSigningInfo{ + suite.consumerApp.GetE2eSlashingKeeper().SetValidatorSigningInfo(ctx, consAddr, slashingtypes.ValidatorSigningInfo{ Address: consAddr.String(), Tombstoned: false, }) // save next sequence before sending a slash packet - seq, ok := app.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) + seq, ok := suite.consumerApp.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) suite.Require().True(ok) // construct slash packet data and get the expcted commit hash packetData := ccv.NewSlashPacketData( abci.Validator{Address: consAddr.Bytes(), Power: power}, // get VSC ID mapping to the infraction height with the TM delay substracted - app.ConsumerKeeper.GetHeightValsetUpdateID(ctx, uint64(infractionHeight-sdk.ValidatorUpdateDelay)), + suite.consumerApp.GetConsumerKeeper().GetHeightValsetUpdateID(ctx, uint64(infractionHeight-sdk.ValidatorUpdateDelay)), stakingtypes.DoubleSign, ) expCommit := suite.commitSlashPacket(ctx, packetData) // expect to send slash packet when handling double-sign evidence - app.EvidenceKeeper.HandleEquivocationEvidence(ctx, e) + suite.consumerApp.GetE2eEvidenceKeeper().HandleEquivocationEvidence(ctx, e) // check that slash packet is sent - gotCommit := app.IBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) + gotCommit := suite.consumerApp.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq) suite.NotNil(gotCommit) suite.Require().EqualValues(expCommit, gotCommit) @@ -648,12 +654,14 @@ func (suite *CCVTestSuite) TestValidatorDoubleSigning() { func (suite *CCVTestSuite) TestSendSlashPacket() { suite.SetupCCVChannel() - app := suite.consumerChain.App.(*appConsumer.App) + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + consumerIBCKeeper := suite.consumerApp.GetIBCKeeper() + ctx := suite.consumerChain.GetContext() channelID := suite.path.EndpointA.ChannelID // check that CCV channel isn't established - _, ok := app.ConsumerKeeper.GetProviderChannel(ctx) + _, ok := consumerKeeper.GetProviderChannel(ctx) suite.Require().False(ok) // expect to store 4 slash requests for downtime @@ -670,7 +678,7 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { addr := ed25519.GenPrivKey().PubKey().Address() val := abci.Validator{ Address: addr} - app.ConsumerKeeper.SendSlashPacket(ctx, val, 0, infraction) + consumerKeeper.SendSlashPacket(ctx, val, 0, infraction) slashedVals = append(slashedVals, slashedVal{validator: val, infraction: infraction}) } infraction = stakingtypes.DoubleSign @@ -679,15 +687,15 @@ 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 { - app.ConsumerKeeper.SendSlashPacket(ctx, sv.validator, 0, sv.infraction) + consumerKeeper.SendSlashPacket(ctx, sv.validator, 0, sv.infraction) } // verify that all requests are stored - requests := app.ConsumerKeeper.GetPendingSlashRequests(ctx) + requests := consumerKeeper.GetPendingSlashRequests(ctx) suite.Require().Len(requests.GetRequests(), 16) // save consumer next sequence - seq, _ := app.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) + seq, _ := consumerIBCKeeper.ChannelKeeper.GetNextSequenceSend(ctx, ccv.ConsumerPortID, channelID) // establish ccv channel by sending an empty VSC packet to consumer endpoint suite.SendEmptyVSCPacket() @@ -695,7 +703,7 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { // 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++ { - commit := app.IBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq+uint64(i)) + commit := consumerIBCKeeper.ChannelKeeper.GetPacketCommitment(ctx, ccv.ConsumerPortID, channelID, seq+uint64(i)) if i > 11 { suite.Require().Nil(commit) continue @@ -709,18 +717,18 @@ func (suite *CCVTestSuite) TestSendSlashPacket() { downtime := r.Infraction == stakingtypes.Downtime if downtime { consAddr := sdk.ConsAddress(r.Packet.Validator.Address) - suite.Require().True(app.ConsumerKeeper.OutstandingDowntime(ctx, consAddr)) + suite.Require().True(consumerKeeper.OutstandingDowntime(ctx, consAddr)) } } // check that pending slash requests get cleared after being sent - requests = app.ConsumerKeeper.GetPendingSlashRequests(ctx) + requests = consumerKeeper.GetPendingSlashRequests(ctx) suite.Require().Len(requests.GetRequests(), 0) // check that slash requests aren't stored when channel is established - app.ConsumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.Downtime) - app.ConsumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.DoubleSign) + consumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.Downtime) + consumerKeeper.SendSlashPacket(ctx, abci.Validator{}, 0, stakingtypes.DoubleSign) - requests = app.ConsumerKeeper.GetPendingSlashRequests(ctx) + requests = consumerKeeper.GetPendingSlashRequests(ctx) suite.Require().Len(requests.GetRequests(), 0) } diff --git a/tests/e2e/stop_consumer_test.go b/tests/e2e/stop_consumer.go similarity index 67% rename from tests/e2e/stop_consumer_test.go rename to tests/e2e/stop_consumer.go index 767b8d793d..a14c6e413d 100644 --- a/tests/e2e/stop_consumer_test.go +++ b/tests/e2e/stop_consumer.go @@ -1,11 +1,9 @@ -package e2e_test +package e2e import ( sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - appConsumer "github.com/cosmos/interchain-security/app/consumer" - appProvider "github.com/cosmos/interchain-security/app/provider" ccv "github.com/cosmos/interchain-security/x/ccv/types" abci "github.com/tendermint/tendermint/abci/types" ) @@ -13,6 +11,9 @@ import ( // Tests the functionality of stopping a consumer chain at a higher level than unit tests func (s *CCVTestSuite) TestStopConsumerChain() { + providerKeeper := s.providerApp.GetProviderKeeper() + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() + // default consumer chain ID consumerChainID := s.consumerChain.ChainID @@ -21,7 +22,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() { valAddr, err := sdk.ValAddressFromHex(tmValidator.Address.String()) s.Require().NoError(err) - validator, found := s.providerChain.App.(*appProvider.App).StakingKeeper.GetValidator(s.providerCtx(), valAddr) + validator, found := providerStakingKeeper.GetValidator(s.providerCtx(), valAddr) s.Require().True(found) // get delegator address @@ -54,7 +55,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() { }, { func(suite *CCVTestSuite) error { - testShares, err = s.providerChain.App.(*appProvider.App).StakingKeeper.Delegate(s.providerCtx(), delAddr, bondAmt, stakingtypes.Unbonded, stakingtypes.Validator(validator), true) + testShares, err = providerStakingKeeper.Delegate(s.providerCtx(), delAddr, bondAmt, stakingtypes.Unbonded, stakingtypes.Validator(validator), true) return err }, }, @@ -62,7 +63,7 @@ func (s *CCVTestSuite) TestStopConsumerChain() { func(suite *CCVTestSuite) error { for i := 0; i < ubdOpsNum; i++ { // undelegate one quarter of the shares - _, err := s.providerChain.App.(*appProvider.App).StakingKeeper.Undelegate(s.providerCtx(), delAddr, valAddr, testShares.QuoInt64(int64(ubdOpsNum))) + _, err := providerStakingKeeper.Undelegate(s.providerCtx(), delAddr, valAddr, testShares.QuoInt64(int64(ubdOpsNum))) if err != nil { return err } @@ -74,9 +75,9 @@ func (s *CCVTestSuite) TestStopConsumerChain() { }, { func(suite *CCVTestSuite) error { - s.providerChain.App.(*appProvider.App).ProviderKeeper.SetSlashAcks(s.providerCtx(), consumerChainID, []string{"validator-1", "validator-2", "validator-3"}) - s.providerChain.App.(*appProvider.App).ProviderKeeper.SetLockUnbondingOnTimeout(s.providerCtx(), consumerChainID) - s.providerChain.App.(*appProvider.App).ProviderKeeper.AppendPendingVSC(s.providerCtx(), consumerChainID, ccv.ValidatorSetChangePacketData{ValsetUpdateId: 1}) + 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}) return nil }, }, @@ -88,11 +89,11 @@ func (s *CCVTestSuite) TestStopConsumerChain() { } // stop the consumer chain - err = s.providerChain.App.(*appProvider.App).ProviderKeeper.StopConsumerChain(s.providerCtx(), consumerChainID, false, true) + err = providerKeeper.StopConsumerChain(s.providerCtx(), consumerChainID, false, true) s.Require().NoError(err) // check all states are removed and the unbonding operation released - s.checkConsumerChainIsRemoved(consumerChainID, false) + s.checkConsumerChainIsRemoved(consumerChainID, false, true) } // TODO Simon: implement OnChanCloseConfirm in IBC-GO testing to close the consumer chain's channel end @@ -102,8 +103,10 @@ func (s *CCVTestSuite) TestStopConsumerOnChannelClosed() { s.SetupTransferChannel() s.SendEmptyVSCPacket() + providerKeeper := s.providerApp.GetProviderKeeper() + // stop the consumer chain - err := s.providerChain.App.(*appProvider.App).ProviderKeeper.StopConsumerChain(s.providerCtx(), s.consumerChain.ChainID, true, true) + err := providerKeeper.StopConsumerChain(s.providerCtx(), s.consumerChain.ChainID, true, true) s.Require().NoError(err) err = s.path.EndpointA.UpdateClient() @@ -120,20 +123,23 @@ func (s *CCVTestSuite) TestStopConsumerOnChannelClosed() { //s.consumerChain.NextBlock() // check that the provider's channel is removed - // _, found := s.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderChannel(s.consumerCtx()) + // _, found := s.consumerApp.GetConsumerKeeper().GetProviderChannel(s.consumerCtx()) // s.Require().False(found) } -func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, lockUbd bool) { +func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, lockUbd bool, checkChannel bool) { channelID := s.path.EndpointB.ChannelID - providerKeeper := s.providerChain.App.(*appProvider.App).ProviderKeeper + providerKeeper := s.providerApp.GetProviderKeeper() + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() - // check channel's state is closed - s.Require().Equal(channeltypes.CLOSED, s.path.EndpointB.GetChannel().State) + if checkChannel { + // check channel's state is closed + s.Require().Equal(channeltypes.CLOSED, s.path.EndpointB.GetChannel().State) + } // check UnbondingOps were deleted and undelegation entries aren't onHold if !lockUbd { - s.providerChain.App.(*appProvider.App).ProviderKeeper.IterateOverUnbondingOpIndex( + providerKeeper.IterateOverUnbondingOpIndex( s.providerCtx(), chainID, func(vscID uint64, ubdIndex []uint64) bool { @@ -142,7 +148,7 @@ func (s *CCVTestSuite) checkConsumerChainIsRemoved(chainID string, lockUbd bool) for _, ubdID := range ubdIndex { _, found = providerKeeper.GetUnbondingOp(s.providerCtx(), ubdIndex[ubdID]) s.Require().False(found) - ubd, _ := s.providerChain.App.(*appProvider.App).StakingKeeper.GetUnbondingDelegationByUnbondingId(s.providerCtx(), ubdIndex[ubdID]) + ubd, _ := providerStakingKeeper.GetUnbondingDelegationByUnbondingId(s.providerCtx(), ubdIndex[ubdID]) s.Require().Zero(ubd.Entries[ubdID].UnbondingOnHoldRefCount) } return true @@ -177,13 +183,15 @@ func (suite *CCVTestSuite) TestProviderChannelClosed() { // establish provider channel with a first VSC packet suite.SendEmptyVSCPacket() - channelID, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetProviderChannel(suite.consumerChain.GetContext()) + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + + channelID, found := consumerKeeper.GetProviderChannel(suite.consumerChain.GetContext()) suite.Require().True(found) // close provider channel - err := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.ChanCloseInit(suite.consumerChain.GetContext(), ccv.ConsumerPortID, channelID) + err := consumerKeeper.ChanCloseInit(suite.consumerChain.GetContext(), ccv.ConsumerPortID, channelID) suite.Require().NoError(err) - suite.Require().True(suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.IsChannelClosed(suite.consumerChain.GetContext(), channelID)) + suite.Require().True(consumerKeeper.IsChannelClosed(suite.consumerChain.GetContext(), channelID)) // assert begin blocker did panics defer func() { @@ -192,5 +200,5 @@ func (suite *CCVTestSuite) TestProviderChannelClosed() { } suite.Require().Fail("Begin blocker did not panic with a closed channel") }() - suite.consumerChain.App.(*appConsumer.App).BeginBlocker(suite.consumerChain.GetContext(), abci.RequestBeginBlock{}) + suite.consumerApp.BeginBlocker(suite.consumerChain.GetContext(), abci.RequestBeginBlock{}) } diff --git a/tests/e2e/unbonding.go b/tests/e2e/unbonding.go new file mode 100644 index 0000000000..566a0a130e --- /dev/null +++ b/tests/e2e/unbonding.go @@ -0,0 +1,456 @@ +package e2e + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" + 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 +// VSC packets timing out. +func (s *CCVTestSuite) TestUndelegationNormalOperation() { + unbondConsumer := func(expectedPackets int) { + // relay 1 VSC packet from provider to consumer + relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, expectedPackets) + // increment time so that the unbonding period ends on the consumer + incrementTimeByUnbondingPeriod(s, Consumer) + // relay 1 VSCMatured packet from consumer to provider + relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, expectedPackets) + } + + testCases := []struct { + name string + shareDiv int64 + unbond func(expBalance, balance sdk.Int) + }{ + { + "provider unbonding period elapses first", 2, func(expBalance, balance sdk.Int) { + // increment time so that the unbonding period ends on the provider + incrementTimeByUnbondingPeriod(s, Provider) + + // check that onHold is true + checkStakingUnbondingOps(s, 1, true, true, "unbonding should be on hold") + + // check that the unbonding is not complete + s.Require().Equal(expBalance, balance, "unexpected balance after provider unbonding") + + // undelegation complete on consumer + unbondConsumer(1) + }, + }, + { + "consumer unbonding period elapses first", 2, func(expBalance, balance sdk.Int) { + // undelegation complete on consumer + unbondConsumer(1) + + // check that onHold is false + checkStakingUnbondingOps(s, 1, true, false, "unbonding should be not be on hold") + + // check that the unbonding is not complete + s.Require().Equal(expBalance, balance, "unexpected balance after consumer unbonding") + + // increment time so that the unbonding period ends on the provider + incrementTimeByUnbondingPeriod(s, Provider) + }, + }, + { + "no valset changes", 1, func(expBalance, balance sdk.Int) { + // undelegation complete on consumer + unbondConsumer(1) + + // check that onHold is false + checkStakingUnbondingOps(s, 1, true, false, "unbonding should be not be on hold") + + // check that the unbonding is not complete + s.Require().Equal(expBalance, balance, "unexpected balance after consumer unbonding") + + // increment time so that the unbonding period ends on the provider + incrementTimeByUnbondingPeriod(s, Provider) + }, + }, + } + + for i, tc := range testCases { + providerKeeper := s.providerApp.GetProviderKeeper() + consumerKeeper := s.consumerApp.GetConsumerKeeper() + stakingKeeper := s.providerApp.GetE2eStakingKeeper() + + s.SetupCCVChannel() + + // set VSC timeout period to not trigger the removal of the consumer chain + providerUnbondingPeriod := stakingKeeper.UnbondingTime(s.providerCtx()) + consumerUnbondingPeriod := consumerKeeper.GetUnbondingPeriod(s.consumerCtx()) + providerKeeper.SetVscTimeoutPeriod(s.providerCtx(), providerUnbondingPeriod+consumerUnbondingPeriod+24*time.Hour) + + // delegate bondAmt and undelegate tc.shareDiv of it + bondAmt := sdk.NewInt(10000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, tc.shareDiv) + // - check that staking unbonding op was created and onHold is true + checkStakingUnbondingOps(s, 1, true, true, "test: "+tc.name) + // - check that CCV unbonding op was created + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true, "test: "+tc.name) + + // call NextBlock on the provider (which increments the height) + s.providerChain.NextBlock() + + // unbond both on provider and consumer and check that + // the balance remains unchanged in between + tc.unbond(initBalance.Sub(bondAmt), getBalance(s, s.providerCtx(), delAddr)) + + // check that the unbonding operation completed + // - check that ccv unbonding op has been deleted + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false, "test: "+tc.name) + // - check that staking unbonding op has been deleted + checkStakingUnbondingOps(s, valsetUpdateID, false, false, "test: "+tc.name) + // - check that necessary delegated coins have been returned + unbondAmt := bondAmt.Sub(bondAmt.Quo(sdk.NewInt(tc.shareDiv))) + s.Require().Equal( + initBalance.Sub(unbondAmt), + getBalance(s, s.providerCtx(), delAddr), + "unexpected initial balance after unbonding; test: %s", tc.name, + ) + + if i+1 < len(testCases) { + // reset suite to reset provider client + s.SetupTest() + } + } +} + +// TestUndelegationVscTimeout tests that an undelegation +// completes after vscTimeoutPeriod even if it does not +// reach maturity on the consumer chain. In this case, +// the consumer chain is removed. +func (s *CCVTestSuite) TestUndelegationVscTimeout() { + providerKeeper := s.providerApp.GetProviderKeeper() + + s.SetupCCVChannel() + + // set VSC timeout period to trigger the removal of the consumer chain + vscTimeout := providerKeeper.GetVscTimeoutPeriod(s.providerCtx()) + + // delegate bondAmt and undelegate 1/2 of it + bondAmt := sdk.NewInt(10000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) + // - check that staking unbonding op was created and onHold is true + checkStakingUnbondingOps(s, 1, true, true) + // - check that CCV unbonding op was created + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) + + // call NextBlock on the provider (which increments the height) + s.providerChain.NextBlock() + + // increment time so that the unbonding period ends on the provider + incrementTimeByUnbondingPeriod(s, Provider) + + // check that onHold is true + checkStakingUnbondingOps(s, 1, true, true, "unbonding should be on hold") + + // check that the unbonding is not complete + s.Require().Equal( + initBalance.Sub(bondAmt), + getBalance(s, s.providerCtx(), delAddr), + "unexpected balance after provider unbonding") + + // increment time + incrementTimeBy(s, vscTimeout) + + // check whether the chain was removed + chainID := s.consumerChain.ChainID + _, found := providerKeeper.GetConsumerClientId(s.providerCtx(), chainID) + s.Require().Equal(false, found, "consumer chain was not removed") + + // check if the chain was properly removed + s.checkConsumerChainIsRemoved(chainID, false, true) + + // check that the unbonding operation completed + // - check that ccv unbonding op has been deleted + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) + // - check that staking unbonding op has been deleted + checkStakingUnbondingOps(s, valsetUpdateID, false, false) + // - check that necessary delegated coins have been returned + unbondAmt := bondAmt.Sub(bondAmt.Quo(sdk.NewInt(2))) + s.Require().Equal( + initBalance.Sub(unbondAmt), + getBalance(s, s.providerCtx(), delAddr), + "unexpected initial balance after VSC timeout", + ) +} + +// TestUndelegationDuringInit checks that before the CCV channel is established +// - no undelegations can complete, even if the provider unbonding period elapses +// - all the VSC packets are stored in state as pending +// - if the channel handshake times out, then the undelegation completes +func (s *CCVTestSuite) TestUndelegationDuringInit() { + testCases := []struct { + name string + updateInitTimeoutTimestamp func(*providerkeeper.Keeper, time.Duration) + removed bool + }{ + { + "channel handshake completes after unbonding period", func(pk *providerkeeper.Keeper, pUnbondingPeriod time.Duration) { + // change the init timeout timestamp for this consumer chain + // to make sure the chain is not removed before the unbonding period elapses + ts := s.providerCtx().BlockTime().Add(pUnbondingPeriod + 24*time.Hour) + pk.SetInitTimeoutTimestamp(s.providerCtx(), s.consumerChain.ChainID, uint64(ts.UnixNano())) + }, false, + }, + { + "channel handshake times out before unbonding period", func(pk *providerkeeper.Keeper, pUnbondingPeriod time.Duration) { + // change the init timeout timestamp for this consumer chain + // to make sure the chain is removed before the unbonding period elapses + ts := s.providerCtx().BlockTime().Add(pUnbondingPeriod - 24*time.Hour) + pk.SetInitTimeoutTimestamp(s.providerCtx(), s.consumerChain.ChainID, uint64(ts.UnixNano())) + }, true, + }, + } + + for i, tc := range testCases { + providerKeeper := s.providerApp.GetProviderKeeper() + stakingKeeper := s.providerApp.GetE2eStakingKeeper() + + // delegate bondAmt and undelegate 1/2 of it + bondAmt := sdk.NewInt(10000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) + // - check that staking unbonding op was created and onHold is true + checkStakingUnbondingOps(s, 1, true, true, "test: "+tc.name) + // - check that CCV unbonding op was created + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true, "test: "+tc.name) + + // get provider unbonding period + providerUnbondingPeriod := stakingKeeper.UnbondingTime(s.providerCtx()) + // update init timeout timestamp + tc.updateInitTimeoutTimestamp(&providerKeeper, providerUnbondingPeriod) + + // call NextBlock on the provider (which increments the height) + 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) + + // delegate again to create another VSC packet + delegate(s, delAddr, bondAmt) + + // call NextBlock on the provider (which increments the height) + 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) + + // increment time so that the unbonding period ends on the provider + incrementTimeByUnbondingPeriod(s, Provider) + + // check whether the unbonding op is still there and onHold is true + checkStakingUnbondingOps(s, 1, !tc.removed, true, "test: "+tc.name) + + if !tc.removed { + // check that unbonding has not yet completed, i.e., the initBalance + // is still lower by the bond amount, because it has been taken out of + // the delegator's account + s.Require().Equal( + initBalance.Sub(bondAmt).Sub(bondAmt), + getBalance(s, s.providerCtx(), delAddr), + "unexpected initial balance before unbonding; test: %s", tc.name, + ) + + // complete CCV channel setup + s.SetupCCVChannel() + + // relay VSC packets from provider to consumer + relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 2) + + // increment time so that the unbonding period ends on the consumer + incrementTimeByUnbondingPeriod(s, Consumer) + + // relay VSCMatured packets from consumer to provider + relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 2) + + // check that the unbonding operation completed + // - check that ccv unbonding op has been deleted + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false, "test: "+tc.name) + // - check that staking unbonding op has been deleted + checkStakingUnbondingOps(s, valsetUpdateID, false, false, "test: "+tc.name) + // - check that one quarter the delegated coins have been returned + s.Require().Equal( + initBalance.Sub(bondAmt).Sub(bondAmt.Quo(sdk.NewInt(2))), + getBalance(s, s.providerCtx(), delAddr), + "unexpected initial balance after unbonding; test: %s", tc.name, + ) + } + + if i+1 < len(testCases) { + // reset suite to reset provider client + s.SetupTest() + } + } +} + +// Bond some tokens on provider +// Unbond them to create unbonding op +// Check unbonding ops on both sides +// Advance time so that provider's unbonding op completes +// Check that unbonding has completed in provider staking +func (s *CCVTestSuite) TestUnbondingNoConsumer() { + + providerKeeper := s.providerApp.GetProviderKeeper() + providerStakingKeeper := s.providerApp.GetE2eStakingKeeper() + + // remove the consumer chain, which was already registered during setup + providerKeeper.DeleteConsumerClientId(s.providerCtx(), s.consumerChain.ChainID) + + // delegate bondAmt and undelegate 1/2 of it + bondAmt := sdk.NewInt(10000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) + // - check that staking unbonding op was created and onHold is FALSE + checkStakingUnbondingOps(s, 1, true, false) + // - check that CCV unbonding op was NOT created + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) + + // increment time so that the unbonding period ends on the provider; + // cannot use incrementTimeByUnbondingPeriod() since it tries + // to also update the provider's client on the consumer + providerUnbondingPeriod := providerStakingKeeper.UnbondingTime(s.providerCtx()) + s.coordinator.IncrementTimeBy(providerUnbondingPeriod + time.Hour) + + // call NextBlock on the provider (which increments the height) + s.providerChain.NextBlock() + + // check that the unbonding operation completed + // - check that staking unbonding op has been deleted + checkStakingUnbondingOps(s, valsetUpdateID, false, false) + // - check that half the coins have been returned + s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt.Quo(sdk.NewInt(2))))) +} + +// TestRedelegationNoConsumer tests a redelegate transaction +// submitted on a provider chain with no consumers +func (s *CCVTestSuite) TestRedelegationNoConsumer() { + + providerKeeper := s.providerApp.GetProviderKeeper() + stakingKeeper := s.providerApp.GetE2eStakingKeeper() + + // remove the consumer chain, which was already registered during setup + providerKeeper.DeleteConsumerClientId(s.providerCtx(), s.consumerChain.ChainID) + + // Setup delegator, bond amount, and src/dst validators + bondAmt := sdk.NewInt(10000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + _, srcVal := s.getValByIdx(0) + _, dstVal := s.getValByIdx(1) + + delegateAndRedelegate( + s, + delAddr, + srcVal, + dstVal, + bondAmt, + ) + + // 1 redelegation record should exist for original delegator + redelegations := checkRedelegations(s, delAddr, 1) + + // Check that the only entry has appropriate maturation time, the unbonding period from now + checkRedelegationEntryCompletionTime( + s, + redelegations[0].Entries[0], + s.providerCtx().BlockTime().Add(stakingKeeper.UnbondingTime(s.providerCtx())), + ) + + // Increment time so that the unbonding period passes on the provider + incrementTimeByUnbondingPeriod(s, Provider) + + // Call NextBlock on the provider (which increments the height) + s.providerChain.NextBlock() + + // No redelegation records should exist for original delegator anymore + checkRedelegations(s, delAddr, 0) +} + +// TestRedelegationWithConsumer tests a redelegate transaction submitted on a provider chain +// when the unbonding period elapses first on the provider chain +func (s *CCVTestSuite) TestRedelegationProviderFirst() { + s.SetupCCVChannel() + s.SetupTransferChannel() + + providerKeeper := s.providerApp.GetProviderKeeper() + consumerKeeper := s.consumerApp.GetConsumerKeeper() + stakingKeeper := s.providerApp.GetE2eStakingKeeper() + + // set VSC timeout period to not trigger the removal of the consumer chain + providerUnbondingPeriod := stakingKeeper.UnbondingTime(s.providerCtx()) + consumerUnbondingPeriod := consumerKeeper.GetUnbondingPeriod(s.consumerCtx()) + providerKeeper.SetVscTimeoutPeriod(s.providerCtx(), providerUnbondingPeriod+consumerUnbondingPeriod+24*time.Hour) + + // Setup delegator, bond amount, and src/dst validators + bondAmt := sdk.NewInt(10000000) + delAddr := s.providerChain.SenderAccount.GetAddress() + _, srcVal := s.getValByIdx(0) + _, dstVal := s.getValByIdx(1) + + delegateAndRedelegate( + s, + delAddr, + srcVal, + dstVal, + bondAmt, + ) + + // 1 redelegation record should exist for original delegator + redelegations := checkRedelegations(s, delAddr, 1) + + // Check that the only entry has appropriate maturation time, the unbonding period from now + checkRedelegationEntryCompletionTime( + s, + redelegations[0].Entries[0], + s.providerCtx().BlockTime().Add(stakingKeeper.UnbondingTime(s.providerCtx())), + ) + + // Save the current valset update ID + valsetUpdateID := providerKeeper.GetValidatorSetUpdateId(s.providerCtx()) + + // Check that CCV unbonding op was created from AfterUnbondingInitiated hook + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) + + // Call NextBlock on the provider (which increments the height) + s.providerChain.NextBlock() + + // Relay 2 VSC packets from provider to consumer (original delegation, and redelegation) + relayAllCommittedPackets(s, s.providerChain, s.path, + ccv.ProviderPortID, s.path.EndpointB.ChannelID, 2) + + // Increment time so that the unbonding period ends on the provider + incrementTimeByUnbondingPeriod(s, Provider) + + // 1 redelegation record should still exist for original delegator on provider + checkRedelegations(s, delAddr, 1) + + // CCV unbonding op should also still exist + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) + + // Increment time so that the unbonding period ends on the consumer + incrementTimeByUnbondingPeriod(s, Consumer) + + // Relay 2 VSCMatured packets from consumer to provider (original delegation and redelegation) + relayAllCommittedPackets(s, s.consumerChain, + s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 2) + + // + // Check that the redelegation operation has now completed on provider + // + + // Redelegation record should be deleted for original delegator + checkRedelegations(s, delAddr, 0) + + // Check that ccv unbonding op has been deleted + checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) +} diff --git a/tests/e2e/unbonding_test.go b/tests/e2e/unbonding_test.go deleted file mode 100644 index baeb96eb22..0000000000 --- a/tests/e2e/unbonding_test.go +++ /dev/null @@ -1,351 +0,0 @@ -package e2e_test - -import ( - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - - appProvider "github.com/cosmos/interchain-security/app/provider" - ccv "github.com/cosmos/interchain-security/x/ccv/types" -) - -// TestUndelegationProviderFirst checks that an unbonding operation completes -// when the unbonding period elapses first on the provider chain -func (s *CCVTestSuite) TestUndelegationProviderFirst() { - s.SetupCCVChannel() - s.SetupTransferChannel() - - // delegate bondAmt and undelegate 1/2 of it - bondAmt := sdk.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) - // - check that staking unbonding op was created and onHold is true - checkStakingUnbondingOps(s, 1, true, true) - // - check that CCV unbonding op was created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) - - // call NextBlock on the provider (which increments the height) - 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, Provider) - - // check that onHold is true - checkStakingUnbondingOps(s, 1, true, true) - // check that the unbonding is not complete - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt))) - - // increment time so that the unbonding period ends on the consumer - incrementTimeByUnbondingPeriod(s, Consumer) - - // relay 1 VSCMatured packet from consumer to provider - relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 1) - - // check that the unbonding operation completed - // - check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false) - // - check that half the delegated coins have been returned - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt.Quo(sdk.NewInt(2))))) -} - -// TestUndelegationConsumerFirst checks that an unbonding operation completes -// when the unbonding period elapses first on the consumer chain -func (s *CCVTestSuite) TestUndelegationConsumerFirst() { - s.SetupCCVChannel() - s.SetupTransferChannel() - - // delegate bondAmt and undelegate 1/2 of it - bondAmt := sdk.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) - // - check that staking unbonding op was created and onHold is true - checkStakingUnbondingOps(s, 1, true, true) - // - check that CCV unbonding op was created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) - - // call NextBlock on the provider (which increments the height) - 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 consumer - incrementTimeByUnbondingPeriod(s, Consumer) - - // relay 1 VSCMatured packet from consumer to provider - relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 1) - - // check that the unbonding is not complete - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt))) - - // increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - - // check that the unbonding operation completed - // - check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false) - // - check that half the delegated coins have been returned - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt.Quo(sdk.NewInt(2))))) -} - -// TestUndelegationNoValsetChange checks that an unbonding operation completes -// even when the validator set is not changed -func (s *CCVTestSuite) TestUndelegationNoValsetChange() { - s.SetupCCVChannel() - s.SetupTransferChannel() - - // delegate bondAmt and undelegate all of it - bondAmt := sdk.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 1) - // - check that staking unbonding op was created and onHold is true - checkStakingUnbondingOps(s, 1, true, true) - // - check that CCV unbonding op was created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) - - // call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // relay 1 VSC packet from provider to consumer - relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 1) - - // check that the unbonding is not complete - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt))) - - // increment time so that the unbonding period ends on the consumer - incrementTimeByUnbondingPeriod(s, Consumer) - - // relay 1 VSCMatured packet from consumer to provider - relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 1) - - // increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - - // check that the unbonding operation completed - // - check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false) - // - check that all the delegated coins have been returned - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance)) -} - -// TestUndelegationDuringInit checks that before the CCV channel is established -// - no undelegations can complete, even if the provider unbonding period elapses -// - all the VSC packets are stored in state as pending -func (s *CCVTestSuite) TestUndelegationDuringInit() { - // delegate bondAmt and undelegate 1/2 of it - bondAmt := sdk.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) - // - check that staking unbonding op was created and onHold is true - checkStakingUnbondingOps(s, 1, true, true) - // - check that CCV unbonding op was created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) - - // call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // check that the VSC packet is stored in state as pending - pendingVSCs, _ := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) - s.Require().True(len(pendingVSCs) == 1, "no pending VSC packet found") - - // delegate again to create another VSC packet - delegate(s, delAddr, bondAmt) - - // call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // check that the VSC packet is stored in state as pending - pendingVSCs, _ = s.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingVSCs(s.providerCtx(), s.consumerChain.ChainID) - s.Require().True(len(pendingVSCs) == 2, "only one pending VSC packet found") - - // increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - // - check that the unbonding op is still there and onHold is true - checkStakingUnbondingOps(s, 1, true, true) - // - check that unbonding has not yet completed, i.e., the initBalance - // is still lower by the bond amount, because it has been taken out of - // the delegator's account - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt).Sub(bondAmt))) - - // complete CCV channel setup - s.SetupCCVChannel() - s.SetupTransferChannel() - - // relay VSC packets from provider to consumer - relayAllCommittedPackets(s, s.providerChain, s.path, ccv.ProviderPortID, s.path.EndpointB.ChannelID, 2) - - // increment time so that the unbonding period ends on the consumer - incrementTimeByUnbondingPeriod(s, Consumer) - - // relay VSCMatured packets from consumer to provider - relayAllCommittedPackets(s, s.consumerChain, s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 2) - - // check that the unbonding operation completed - // - check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false) - // - check that one quarter the delegated coins have been returned - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt).Sub(bondAmt.Quo(sdk.NewInt(2))))) -} - -// TODO FIX, the consumer is added during SetupTest() -// Bond some tokens on provider -// Unbond them to create unbonding op -// Check unbonding ops on both sides -// Advance time so that provider's unbonding op completes -// Check that unbonding has completed in provider staking -func (s *CCVTestSuite) TestUnbondingNoConsumer() { - // remove the consumer chain, which was already registered during setup - s.providerChain.App.(*appProvider.App).ProviderKeeper.DeleteConsumerClientId(s.providerCtx(), s.consumerChain.ChainID) - - // delegate bondAmt and undelegate 1/2 of it - bondAmt := sdk.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - initBalance, valsetUpdateID := delegateAndUndelegate(s, delAddr, bondAmt, 2) - // - check that staking unbonding op was created and onHold is FALSE - checkStakingUnbondingOps(s, 1, true, false) - // - check that CCV unbonding op was NOT created - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) - - // increment time so that the unbonding period ends on the provider; - // cannot use incrementTimeByUnbondingPeriod() since it tries - // to also update the provider's client on the consumer - providerUnbondingPeriod := s.providerChain.App.GetStakingKeeper().UnbondingTime(s.providerCtx()) - s.coordinator.IncrementTimeBy(providerUnbondingPeriod + time.Hour) - - // call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // check that the unbonding operation completed - // - check that staking unbonding op has been deleted - checkStakingUnbondingOps(s, valsetUpdateID, false, false) - // - check that half the coins have been returned - s.Require().True(getBalance(s, s.providerCtx(), delAddr).Equal(initBalance.Sub(bondAmt.Quo(sdk.NewInt(2))))) -} - -// TestRedelegationNoConsumer tests a redelegate transaction -// submitted on a provider chain with no consumers -func (s *CCVTestSuite) TestRedelegationNoConsumer() { - - providerKeeper := s.providerChain.App.(*appProvider.App).ProviderKeeper - stakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper - - // remove the consumer chain, which was already registered during setup - providerKeeper.DeleteConsumerClientId(s.providerCtx(), s.consumerChain.ChainID) - - // Setup delegator, bond amount, and src/dst validators - bondAmt := sdk.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - _, srcVal := s.getVal(0) - _, dstVal := s.getVal(1) - - delegateAndRedelegate( - s, - delAddr, - srcVal, - dstVal, - bondAmt, - ) - - // 1 redelegation record should exist for original delegator - redelegations := checkRedelegations(s, delAddr, 1) - - // Check that the only entry has appropriate maturation time, the unbonding period from now - checkRedelegationEntryCompletionTime( - s, - redelegations[0].Entries[0], - s.providerCtx().BlockTime().Add(stakingKeeper.UnbondingTime(s.providerCtx())), - ) - - // Increment time so that the unbonding period passes on the provider - incrementTimeByUnbondingPeriod(s, Provider) - - // Call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // No redelegation records should exist for original delegator anymore - checkRedelegations(s, delAddr, 0) -} - -// TestRedelegationWithConsumer tests a redelegate transaction submitted on a provider chain -// when the unbonding period elapses first on the provider chain -func (s *CCVTestSuite) TestRedelegationProviderFirst() { - s.SetupCCVChannel() - s.SetupTransferChannel() - - stakingKeeper := s.providerChain.App.(*appProvider.App).StakingKeeper - providerKeeper := s.providerChain.App.(*appProvider.App).ProviderKeeper - - // Setup delegator, bond amount, and src/dst validators - bondAmt := sdk.NewInt(10000000) - delAddr := s.providerChain.SenderAccount.GetAddress() - _, srcVal := s.getVal(0) - _, dstVal := s.getVal(1) - - delegateAndRedelegate( - s, - delAddr, - srcVal, - dstVal, - bondAmt, - ) - - // 1 redelegation record should exist for original delegator - redelegations := checkRedelegations(s, delAddr, 1) - - // Check that the only entry has appropriate maturation time, the unbonding period from now - checkRedelegationEntryCompletionTime( - s, - redelegations[0].Entries[0], - s.providerCtx().BlockTime().Add(stakingKeeper.UnbondingTime(s.providerCtx())), - ) - - // Save the current valset update ID - valsetUpdateID := providerKeeper.GetValidatorSetUpdateId(s.providerCtx()) - - // Check that CCV unbonding op was created from AfterUnbondingInitiated hook - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) - - // Call NextBlock on the provider (which increments the height) - s.providerChain.NextBlock() - - // Relay 2 VSC packets from provider to consumer (original delegation, and redelegation) - relayAllCommittedPackets(s, s.providerChain, s.path, - ccv.ProviderPortID, s.path.EndpointB.ChannelID, 2) - - // Increment time so that the unbonding period ends on the provider - incrementTimeByUnbondingPeriod(s, Provider) - - // 1 redelegation record should still exist for original delegator on provider - checkRedelegations(s, delAddr, 1) - - // CCV unbonding op should also still exist - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, true) - - // Increment time so that the unbonding period ends on the consumer - incrementTimeByUnbondingPeriod(s, Consumer) - - // Relay 2 VSCMatured packets from consumer to provider (original delegation and redelegation) - relayAllCommittedPackets(s, s.consumerChain, - s.path, ccv.ConsumerPortID, s.path.EndpointA.ChannelID, 2) - - // - // Check that the redelegation operation has now completed on provider - // - - // Redelegation record should be deleted for original delegator - checkRedelegations(s, delAddr, 0) - - // Check that ccv unbonding op has been deleted - checkCCVUnbondingOp(s, s.providerCtx(), s.consumerChain.ChainID, valsetUpdateID, false) -} diff --git a/tests/e2e/valset_update_test.go b/tests/e2e/valset_update.go similarity index 77% rename from tests/e2e/valset_update_test.go rename to tests/e2e/valset_update.go index faecf9cd1f..22fe4e5cc2 100644 --- a/tests/e2e/valset_update_test.go +++ b/tests/e2e/valset_update.go @@ -1,4 +1,4 @@ -package e2e_test +package e2e import ( "time" @@ -7,7 +7,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/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" - appConsumer "github.com/cosmos/interchain-security/app/consumer" ccv "github.com/cosmos/interchain-security/x/ccv/types" abci "github.com/tendermint/tendermint/abci/types" ) @@ -37,6 +36,9 @@ func (s *CCVTestSuite) TestPacketRoundtrip() { // TestSendVSCMaturedPackets tests the behavior of SendVSCMaturedPackets and related state checks func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { + + consumerKeeper := suite.consumerApp.GetConsumerKeeper() + // setup CCV channel suite.SetupCCVChannel() @@ -68,7 +70,7 @@ func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { // send first packet packet := channeltypes.NewPacket(pd.GetBytes(), 1, ccv.ProviderPortID, suite.path.EndpointB.ChannelID, ccv.ConsumerPortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) - ack := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) + ack := consumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) suite.Require().NotNil(ack, "OnRecvVSCPacket did not return ack") suite.Require().True(ack.Success(), "OnRecvVSCPacket did not return a Success Acknowledgment") @@ -80,7 +82,7 @@ func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { pd.ValsetUpdateId = 2 packet.Data = pd.GetBytes() packet.Sequence = 2 - ack = suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) + ack = consumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) suite.Require().NotNil(ack, "OnRecvVSCPacket did not return ack") suite.Require().True(ack.Success(), "OnRecvVSCPacket did not return a Success Acknowledgment") @@ -92,31 +94,30 @@ func (suite *CCVTestSuite) TestSendVSCMaturedPackets() { pd.ValsetUpdateId = 3 packet.Data = pd.GetBytes() packet.Sequence = 3 - ack = suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) + ack = consumerKeeper.OnRecvVSCPacket(suite.consumerChain.GetContext(), packet, pd) suite.Require().NotNil(ack, "OnRecvVSCPacket did not return ack") suite.Require().True(ack.Success(), "OnRecvVSCPacket did not return a Success Acknowledgment") // increase time such that first two packets are unbonded but third is not. - unbondingPeriod, found := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetUnbondingTime(suite.consumerChain.GetContext()) - suite.Require().True(found) + unbondingPeriod := consumerKeeper.GetUnbondingPeriod(suite.consumerChain.GetContext()) // increase time incrementTimeBy(suite, unbondingPeriod-time.Hour) - err = suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.SendVSCMaturedPackets(suite.consumerChain.GetContext()) + err = consumerKeeper.SendVSCMaturedPackets(suite.consumerChain.GetContext()) suite.Require().NoError(err) // ensure first two packets are unbonded and VSCMatured packets are sent // unbonded time is deleted - time1 := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 1) - time2 := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 2) + 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 := suite.consumerChain.App.(*appConsumer.App).ConsumerKeeper.GetPacketMaturityTime(suite.consumerChain.GetContext(), 3) + 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") // check that the packets are committed in state - commitments := suite.consumerChain.App.GetIBCKeeper().ChannelKeeper.GetAllPacketCommitmentsAtChannel( + commitments := suite.consumerApp.GetIBCKeeper().ChannelKeeper.GetAllPacketCommitmentsAtChannel( suite.consumerChain.GetContext(), ccv.ConsumerPortID, suite.path.EndpointA.ChannelID, diff --git a/tests/integration/actions.go b/tests/integration/actions.go index 6fd087e372..54bca82601 100644 --- a/tests/integration/actions.go +++ b/tests/integration/actions.go @@ -184,7 +184,7 @@ func (tr TestRun) submitTextProposal( } } -type submitConsumerProposalAction struct { +type submitConsumerAdditionProposalAction struct { chain chainID from validatorID deposit uint @@ -194,7 +194,7 @@ type submitConsumerProposalAction struct { } func (tr TestRun) submitConsumerAdditionProposal( - action submitConsumerProposalAction, + action submitConsumerAdditionProposalAction, verbose bool, ) { spawnTime := tr.containerConfig.now.Add(time.Duration(action.spawnTime) * time.Millisecond) @@ -247,6 +247,65 @@ func (tr TestRun) submitConsumerAdditionProposal( } } +type submitConsumerRemovalProposalAction struct { + chain chainID + from validatorID + deposit uint + consumerChain chainID + stopTimeOffset time.Duration // offset from time.Now() +} + +func (tr TestRun) submitConsumerRemovalProposal( + action submitConsumerRemovalProposalAction, + verbose bool, +) { + stopTime := tr.containerConfig.now.Add(action.stopTimeOffset) + prop := client.ConsumerRemovalProposalJSON{ + Title: fmt.Sprintf("Stop the %v chain", action.consumerChain), + Description: "It was a great chain", + ChainId: string(tr.chainConfigs[action.consumerChain].chainId), + StopTime: stopTime, + Deposit: fmt.Sprint(action.deposit) + `stake`, + } + + bz, err := json.Marshal(prop) + if err != nil { + log.Fatal(err) + } + + jsonStr := string(bz) + if strings.Contains(jsonStr, "'") { + log.Fatal("prop json contains single quote") + } + + //#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments. + bz, err = exec.Command("docker", "exec", tr.containerConfig.instanceName, + "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, jsonStr, "/temp-proposal.json")).CombinedOutput() + + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + //#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments. + bz, err = exec.Command("docker", "exec", tr.containerConfig.instanceName, tr.chainConfigs[action.chain].binaryName, + + "tx", "gov", "submit-proposal", "consumer-removal", + "/temp-proposal.json", + + `--from`, `validator`+fmt.Sprint(action.from), + `--chain-id`, string(tr.chainConfigs[action.chain].chainId), + `--home`, tr.getValidatorHome(action.chain, action.from), + `--node`, tr.getValidatorNode(action.chain, action.from), + `--keyring-backend`, `test`, + `-b`, `block`, + `-y`, + ).CombinedOutput() + + if err != nil { + log.Fatal(err, "\n", string(bz)) + } +} + type submitParamChangeProposalAction struct { chain chainID from validatorID @@ -962,3 +1021,35 @@ func (tr TestRun) registerRepresentative( wg.Wait() } + +// Creates an additional node on selected chain +// by copying an existing validator's home folder +// +// Steps needed to double sign: +// - copy existing validator's state and configs +// - use existing priv_validator_key.json +// - use new node_key.json (otherwise node gets rejected) +// - reset priv_validator_state.json to initial values +// - start the new node +// Double sign should be registered within couple blocks. +type doublesignSlashAction struct { + // start another node for this validator + validator validatorID + chain chainID +} + +func (tr TestRun) invokeDoublesignSlash( + action doublesignSlashAction, + verbose bool, +) { + chainConfig := tr.chainConfigs[action.chain] + //#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments. + bz, err := exec.Command("docker", "exec", tr.containerConfig.instanceName, "/bin/bash", + "/testnet-scripts/cause-doublesign.sh", chainConfig.binaryName, string(action.validator), + string(chainConfig.chainId), chainConfig.ipPrefix).CombinedOutput() + + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + tr.waitBlocks("provi", 10, 2*time.Minute) +} diff --git a/tests/integration/config.go b/tests/integration/config.go index e7d6bee54d..c29736b17a 100644 --- a/tests/integration/config.go +++ b/tests/integration/config.go @@ -87,6 +87,46 @@ func getDefaultValidators() map[validatorID]ValidatorConfig { } } +func DoubleSignTestRun() TestRun { + return TestRun{ + name: "double-sign", + containerConfig: ContainerConfig{ + containerName: "interchain-security-ds-container", + instanceName: "interchain-security-ds-instance", + ccvVersion: "1", + now: time.Now(), + }, + validatorConfigs: getDefaultValidators(), + chainConfigs: map[chainID]ChainConfig{ + chainID("provi"): { + chainId: chainID("provi"), + binaryName: "interchain-security-pd", + ipPrefix: "7.7.7", + votingWaitTime: 5, + genesisChanges: ".app_state.gov.voting_params.voting_period = \"5s\" | " + + // Custom slashing parameters for testing validator downtime functionality + // See https://docs.cosmos.network/main/modules/slashing/04_begin_block.html#uptime-tracking + ".app_state.slashing.params.signed_blocks_window = \"2\" | " + + ".app_state.slashing.params.min_signed_per_window = \"0.500000000000000000\" | " + + ".app_state.slashing.params.downtime_jail_duration = \"2s\" | " + + ".app_state.slashing.params.slash_fraction_downtime = \"0.010000000000000000\" | " + + ".app_state.slashing.params.slash_fraction_double_sign = \"0.100000000000000000\"", + }, + chainID("consu"): { + chainId: chainID("consu"), + binaryName: "interchain-security-cd", + ipPrefix: "7.7.8", + votingWaitTime: 10, + genesisChanges: ".app_state.gov.voting_params.voting_period = \"10s\" | " + + ".app_state.slashing.params.signed_blocks_window = \"2\" | " + + ".app_state.slashing.params.min_signed_per_window = \"0.500000000000000000\" | " + + ".app_state.slashing.params.downtime_jail_duration = \"2s\" | " + + ".app_state.slashing.params.slash_fraction_downtime = \"0.010000000000000000\"", + }, + }, + } +} + func DefaultTestRun() TestRun { return TestRun{ name: "default", @@ -196,7 +236,11 @@ func (s *TestRun) ValidateStringLiterals() { panic("ip suffix 253 is reserved for query node") } - if ipSuffix < 1 || ipSuffix > 252 { + if ipSuffix == 252 { + panic("ip suffix 252 is reserved for double signing node") + } + + if ipSuffix < 1 || 251 < ipSuffix { panic("ip suffix out of range, need to change config") } } diff --git a/tests/integration/main.go b/tests/integration/main.go index c90d6a10a6..bedf0d65b1 100644 --- a/tests/integration/main.go +++ b/tests/integration/main.go @@ -37,12 +37,20 @@ func main() { dmc.ValidateStringLiterals() dmc.startDocker() + ds := DoubleSignTestRun() + ds.SetLocalSDKPath(*localSdkPath) + ds.ValidateStringLiterals() + ds.startDocker() + wg.Add(1) go tr.ExecuteSteps(&wg, happyPathSteps) wg.Add(1) go dmc.ExecuteSteps(&wg, democracySteps) + wg.Add(1) + go ds.ExecuteSteps(&wg, doubleSignProviderSteps) + wg.Wait() fmt.Printf("TOTAL TIME ELAPSED: %v\n", time.Since(start)) } @@ -55,8 +63,10 @@ func (tr *TestRun) runStep(step Step, verbose bool) { tr.sendTokens(action, verbose) case submitTextProposalAction: tr.submitTextProposal(action, verbose) - case submitConsumerProposalAction: + case submitConsumerAdditionProposalAction: tr.submitConsumerAdditionProposal(action, verbose) + case submitConsumerRemovalProposalAction: + tr.submitConsumerRemovalProposal(action, verbose) case submitParamChangeProposalAction: tr.submitParamChangeProposal(action, verbose) case voteGovProposalAction: @@ -85,6 +95,8 @@ func (tr *TestRun) runStep(step Step, verbose bool) { tr.invokeDowntimeSlash(action, verbose) case unjailValidatorAction: tr.unjailValidator(action, verbose) + case doublesignSlashAction: + tr.invokeDoublesignSlash(action, verbose) case registerRepresentativeAction: tr.registerRepresentative(action, verbose) default: @@ -96,6 +108,7 @@ func (tr *TestRun) runStep(step Step, verbose bool) { // Check state if !reflect.DeepEqual(actualState, modelState) { + fmt.Println("action", reflect.TypeOf(step.action).Name()) pretty.Print("actual state", actualState) pretty.Print("model state", modelState) log.Fatal(`actual state (-) not equal to model state (+): ` + pretty.Compare(actualState, modelState)) @@ -110,9 +123,8 @@ func (tr *TestRun) ExecuteSteps(wg *sync.WaitGroup, steps []Step) { start := time.Now() for i, step := range steps { // print something the show the test is alive - if i%10 == 0 { - fmt.Printf("running %s: step %d\n", tr.name, i+1) - } + fmt.Printf("running %s: step %d == %s \n", + tr.name, i+1, reflect.TypeOf(step.action).Name()) tr.runStep(step, *verbose) } diff --git a/tests/integration/state.go b/tests/integration/state.go index 3e0785cd78..bfd16ca38e 100644 --- a/tests/integration/state.go +++ b/tests/integration/state.go @@ -22,6 +22,7 @@ type ChainState struct { RepresentativePowers *map[validatorID]uint Params *[]Param Rewards *Rewards + ConsumerChains *map[chainID]bool } type Proposal interface { @@ -36,7 +37,7 @@ type TextProposal struct { func (p TextProposal) isProposal() {} -type ConsumerProposal struct { +type ConsumerAdditionProposal struct { Deposit uint Chain chainID SpawnTime int @@ -44,6 +45,17 @@ type ConsumerProposal struct { Status string } +func (p ConsumerAdditionProposal) isProposal() {} + +type ConsumerRemovalProposal struct { + Deposit uint + Chain chainID + StopTime int + Status string +} + +func (p ConsumerRemovalProposal) isProposal() {} + type Rewards struct { IsRewarded map[validatorID]bool //if true it will calculate if the validator/delegator is rewarded between 2 successive blocks, @@ -54,8 +66,6 @@ type Rewards struct { IsNativeDenom bool } -func (p ConsumerProposal) isProposal() {} - type ParamsProposal struct { Deposit uint Status string @@ -115,6 +125,11 @@ func (tr TestRun) getChainState(chain chainID, modelState ChainState) ChainState chainState.Rewards = &rewards } + if modelState.ConsumerChains != nil { + chains := tr.getConsumerChains(chain) + chainState.ConsumerChains = &chains + } + return chainState } @@ -315,7 +330,7 @@ func (tr TestRun) getProposal(chain chainID, proposal uint) Proposal { } } - return ConsumerProposal{ + return ConsumerAdditionProposal{ Deposit: uint(deposit), Status: status, Chain: chain, @@ -325,6 +340,25 @@ func (tr TestRun) getProposal(chain chainID, proposal uint) Proposal { RevisionHeight: gjson.Get(string(bz), `content.initial_height.revision_height`).Uint(), }, } + case "/interchain_security.ccv.provider.v1.ConsumerRemovalProposal": + chainId := gjson.Get(string(bz), `content.chain_id`).String() + stopTime := gjson.Get(string(bz), `content.stop_time`).Time().Sub(tr.containerConfig.now) + + var chain chainID + for i, conf := range tr.chainConfigs { + if string(conf.chainId) == chainId { + chain = i + break + } + } + + return ConsumerRemovalProposal{ + Deposit: uint(deposit), + Status: status, + Chain: chain, + StopTime: int(stopTime.Milliseconds()), + } + case "/cosmos.params.v1beta1.ParameterChangeProposal": return ParamsProposal{ Deposit: uint(deposit), @@ -439,6 +473,32 @@ func (tr TestRun) getParam(chain chainID, param Param) string { return value.String() } +// getConsumerChains returns a list of consumer chains that're being secured by the provider chain, +// determined by querying the provider chain. +func (tr TestRun) getConsumerChains(chain chainID) map[chainID]bool { + //#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments. + cmd := exec.Command("docker", "exec", tr.containerConfig.instanceName, tr.chainConfigs[chain].binaryName, + + "query", "provider", "list-consumer-chains", + `--node`, tr.getQueryNode(chain), + `-o`, `json`, + ) + + bz, err := cmd.CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + arr := gjson.Get(string(bz), "chains").Array() + chains := make(map[chainID]bool) + for _, c := range arr { + id := c.Get("chain_id").String() + chains[chainID(id)] = true + } + + return chains +} + func (tr TestRun) getValidatorNode(chain chainID, validator validatorID) string { return "tcp://" + tr.getValidatorIP(chain, validator) + ":26658" } diff --git a/tests/integration/steps.go b/tests/integration/steps.go index c9044e5bd8..b1c68ee008 100644 --- a/tests/integration/steps.go +++ b/tests/integration/steps.go @@ -18,6 +18,7 @@ var happyPathSteps = concatSteps( stepsDelegate("consu"), stepsUnbondRedelegate("consu"), stepsDowntime("consu"), + stepsStopChain("consu"), ) var democracySteps = concatSteps( @@ -26,3 +27,8 @@ var democracySteps = concatSteps( stepsDelegate("democ"), stepsDemocracy("democ"), ) + +var doubleSignProviderSteps = concatSteps( + stepsStartChains("consu", false), + stepsDoubleSign("consu", "provi", "carol"), +) diff --git a/tests/integration/steps_double_sign.go b/tests/integration/steps_double_sign.go new file mode 100644 index 0000000000..ae7cc055a2 --- /dev/null +++ b/tests/integration/steps_double_sign.go @@ -0,0 +1,125 @@ +package main + +// simulates double signing on provider and consumer chains +func stepsDoubleSign(consumerName, doubleSignChain, doubleSignValidator string) []Step { + return []Step{ + // provider double sign + { + action: doublesignSlashAction{ + chain: chainID("provi"), + validator: validatorID("carol"), + }, + state: State{ + // slash on provider + chainID("provi"): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 500, + validatorID("carol"): 0, + }, + }, + // not slashed on consumer yet + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 500, + validatorID("carol"): 500, + }, + }, + }, + }, + { + // relay power change to consumer + action: relayPacketsAction{ + chain: chainID("provi"), + port: "provider", + channel: 0, + }, + state: State{ + chainID("provi"): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 500, + validatorID("carol"): 0, + }, + }, + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 500, + validatorID("carol"): 0, + }, + }, + }, + }, + { + action: doublesignSlashAction{ + chain: chainID("consu"), + validator: validatorID("bob"), + }, + state: State{ + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 500, + validatorID("carol"): 0, + }, + }, + chainID("provi"): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 500, + validatorID("carol"): 0, + }, + }, + }, + }, + { + action: relayPacketsAction{ + chain: chainID("provi"), + port: "provider", + channel: 0, + }, + state: State{ + chainID("provi"): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 0, + validatorID("carol"): 0, + }, + }, + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 500, + validatorID("carol"): 0, + }, + }, + }, + }, + { + // relay power change to consumer + action: relayPacketsAction{ + chain: chainID("provi"), + port: "provider", + channel: 0, + }, + state: State{ + chainID("provi"): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 0, + validatorID("carol"): 0, + }, + }, + chainID(consumerName): ChainState{ + ValPowers: &map[validatorID]uint{ + validatorID("alice"): 500, + validatorID("bob"): 0, + validatorID("carol"): 0, + }, + }, + }, + }, + } +} diff --git a/tests/integration/steps_start_chains.go b/tests/integration/steps_start_chains.go index fca51fa254..7356f9fe5c 100644 --- a/tests/integration/steps_start_chains.go +++ b/tests/integration/steps_start_chains.go @@ -46,7 +46,7 @@ func stepsStartChains(consumerName string, setupTransferChan bool) []Step { }, }, { - action: submitConsumerProposalAction{ + action: submitConsumerAdditionProposalAction{ chain: chainID("provi"), from: validatorID("alice"), deposit: 10000001, @@ -61,7 +61,7 @@ func stepsStartChains(consumerName string, setupTransferChan bool) []Step { validatorID("bob"): 9500000002, }, Proposals: &map[uint]Proposal{ - 1: ConsumerProposal{ + 1: ConsumerAdditionProposal{ Deposit: 10000001, Chain: chainID(consumerName), SpawnTime: 0, @@ -82,7 +82,7 @@ func stepsStartChains(consumerName string, setupTransferChan bool) []Step { state: State{ chainID("provi"): ChainState{ Proposals: &map[uint]Proposal{ - 1: ConsumerProposal{ + 1: ConsumerAdditionProposal{ Deposit: 10000001, Chain: chainID(consumerName), SpawnTime: 0, diff --git a/tests/integration/steps_stop_chain.go b/tests/integration/steps_stop_chain.go new file mode 100644 index 0000000000..c35a7f28f1 --- /dev/null +++ b/tests/integration/steps_stop_chain.go @@ -0,0 +1,60 @@ +package main + +import "time" + +// submits a consumer-removal proposal and removes the chain +func stepsStopChain(consumerName string) []Step { + s := []Step{ + { + action: submitConsumerRemovalProposalAction{ + chain: chainID("provi"), + from: validatorID("bob"), + deposit: 10000001, + consumerChain: chainID(consumerName), + stopTimeOffset: 0 * time.Millisecond, + }, + state: State{ + chainID("provi"): ChainState{ + ValBalances: &map[validatorID]uint{ + validatorID("bob"): 9490000001, + }, + Proposals: &map[uint]Proposal{ + 2: ConsumerRemovalProposal{ + Deposit: 10000001, + Chain: chainID(consumerName), + StopTime: 0, + Status: "PROPOSAL_STATUS_VOTING_PERIOD", + }, + }, + ConsumerChains: &map[chainID]bool{"consu": true}, // consumer chain not yet removed + }, + }, + }, + { + action: voteGovProposalAction{ + chain: chainID("provi"), + from: []validatorID{validatorID("alice"), validatorID("bob"), validatorID("carol")}, + vote: []string{"yes", "yes", "yes"}, + propNumber: 2, + }, + state: State{ + chainID("provi"): ChainState{ + Proposals: &map[uint]Proposal{ + 2: ConsumerRemovalProposal{ + Deposit: 10000001, + Chain: chainID(consumerName), + StopTime: 0, + Status: "PROPOSAL_STATUS_PASSED", + }, + }, + ValBalances: &map[validatorID]uint{ + validatorID("bob"): 9500000002, + }, + ConsumerChains: &map[chainID]bool{}, // Consumer chain is now removed + }, + }, + }, + } + + return s +} diff --git a/tests/integration/testnet-scripts/cause-doublesign.sh b/tests/integration/testnet-scripts/cause-doublesign.sh new file mode 100755 index 0000000000..bb42116905 --- /dev/null +++ b/tests/integration/testnet-scripts/cause-doublesign.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -eux + +# The gaiad binary +BIN=$1 + +VAL_ID=$2 + +# The chain ID +CHAIN_ID=$3 + +# chain's IP address prefix; 7.7.7, 7.7.8... +# see chain config for details +CHAIN_PREFIX=$4 + +# create directory for double signing node +mkdir /$CHAIN_ID/validatorsybil +cp -r /$CHAIN_ID/validator$VAL_ID/* /$CHAIN_ID/validatorsybil + +# clear state in validatorsybil +echo '{"height": "0","round": 0,"step": 0,"signature":"","signbytes":""}' > /$CHAIN_ID/validatorsybil/data/priv_validator_state.json + +# add new node key to sybil +# key was generated using gaiad init +# if the node key is not unique, double signing cannot be achieved +# and errors such as this can be seen in the terminal +# 5:54PM ERR found conflicting vote from ourselves; did you unsafe_reset a validator? height=1961 module=consensus round=0 type=2 +# 5:54PM ERR failed to process message err="conflicting votes from validator C888306A908A217B9A943D1DAD8790044D0947A4" +echo '{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"tj55by/yYwruSz4NxsOG9y9k2WrPvKLXKQdz/9jL9Uptmi647OYpcisjwf92TyA+wCUYVDOgW7D53Q+638l9/w=="}}' > /$CHAIN_ID/validatorsybil/config/node_key.json + +# does not use persistent peers; will do a lookup in genesis.json to find peers +ARGS="--address tcp://$CHAIN_PREFIX.252:26655 --rpc.laddr tcp://$CHAIN_PREFIX.252:26658 --grpc.address $CHAIN_PREFIX.252:9091 --log_level trace --p2p.laddr tcp://$CHAIN_PREFIX.252:26656 --grpc-web.enable=false" + +# start double signing node - it should not talk to the node with the same key +ip netns exec $CHAIN_ID-sybil $BIN $ARGS --home /$CHAIN_ID/validatorsybil start &> /$CHAIN_ID/validatorsybil/logs & + diff --git a/tests/integration/testnet-scripts/start-chain.sh b/tests/integration/testnet-scripts/start-chain.sh index aa2a78187f..b7b16ef512 100644 --- a/tests/integration/testnet-scripts/start-chain.sh +++ b/tests/integration/testnet-scripts/start-chain.sh @@ -175,7 +175,7 @@ done # COLLECT GENTXS IF WE ARE STARTING A NEW CHAIN -if [ "$SKIP_GENTX" = "false" ] ; then +if [ "$SKIP_GENTX" = "false" ] ; then # make the final genesis.json $BIN collect-gentxs --home /$CHAIN_ID/validator$FIRST_VAL_ID @@ -230,6 +230,26 @@ do ip netns exec $NET_NAMESPACE_NAME $BIN $ARGS start &> /$CHAIN_ID/validator$VAL_ID/logs & done +## SETUP DOUBLE SIGNING NODE NETWORK NAMESPACE +# double signing node is started using cause-doublesign.sh +# here we just allocate a network namespace so it can be used later +SYBIL_NODE_ID="sybil" +SYBIL_IP_SUFFIX="252" +SYBIL_NET_NAMESPACE_NAME="$CHAIN_ID-$SYBIL_NODE_ID" +SYBIL_IP_ADDR="$CHAIN_IP_PREFIX.$SYBIL_IP_SUFFIX/24" + +ip netns add $SYBIL_NET_NAMESPACE_NAME +ip link add $SYBIL_NET_NAMESPACE_NAME-in type veth peer name $SYBIL_NET_NAMESPACE_NAME-out +ip link set $SYBIL_NET_NAMESPACE_NAME-in netns $SYBIL_NET_NAMESPACE_NAME +ip netns exec $SYBIL_NET_NAMESPACE_NAME ip addr add $SYBIL_IP_ADDR dev $SYBIL_NET_NAMESPACE_NAME-in +ip link set $SYBIL_NET_NAMESPACE_NAME-out master virtual-bridge + +## DOUBLE SIGNING ENABLE DEVICE +ip link set $SYBIL_NET_NAMESPACE_NAME-out up +ip netns exec $SYBIL_NET_NAMESPACE_NAME ip link set dev $SYBIL_NET_NAMESPACE_NAME-in up +ip netns exec $SYBIL_NET_NAMESPACE_NAME ip link set dev lo up +## DONE DOUBLE SIGNING NODE ENABLE DEVICE + ## SETUP QUERY NODE NETWORK NAMESPACE QUERY_NODE_ID="query" QUERY_IP_SUFFIX="253" diff --git a/testutil/e2e/interfaces.go b/testutil/e2e/interfaces.go new file mode 100644 index 0000000000..0e34aacbe6 --- /dev/null +++ b/testutil/e2e/interfaces.go @@ -0,0 +1,148 @@ +package e2e + +import ( + "time" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + 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" + 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" + ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +// The interface that any provider app must implement to be compatible with ccv e2e tests. +// This is a wrapper around the ibc testing app interface with additional constraints. +type ProviderApp interface { + ibctesting.TestingApp + + // + // Keeper getters + // + + GetProviderKeeper() providerkeeper.Keeper + // Returns a staking keeper interface with more capabilities than the expected_keepers interface + GetE2eStakingKeeper() E2eStakingKeeper + // Returns a bank keeper interface with more capabilities than the expected_keepers interface + GetE2eBankKeeper() E2eBankKeeper + // Returns a slashing keeper interface with more capabilities than the expected_keepers interface + GetE2eSlashingKeeper() E2eSlashingKeeper + // Returns a distribution keeper interface with more capabilities than the expected_keepers interface + GetE2eDistributionKeeper() E2eDistributionKeeper +} + +// The interface that any consumer app must implement to be compatible with e2e tests +// This is a wrapper around the ibc testing app interface with additional constraints. +type ConsumerApp interface { + ibctesting.TestingApp + + BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock + GetConsumerKeeper() consumerkeeper.Keeper + GetSubspace(moduleName string) paramstypes.Subspace + + // + // Keeper getters + // + + // Returns a bank keeper interface with more capabilities than the expected_keepers interface + GetE2eBankKeeper() E2eBankKeeper + // Returns an account keeper interface with more capabilities than the expected_keepers interface + GetE2eAccountKeeper() E2eAccountKeeper + // Returns a slashing keeper interface with more capabilities than the expected_keepers interface + GetE2eSlashingKeeper() E2eSlashingKeeper + // Returns an evidence keeper interface with more capabilities than the expected_keepers interface + GetE2eEvidenceKeeper() E2eEvidenceKeeper +} + +type DemocConsumerApp interface { + ConsumerApp + // Returns a distribution keeper interface with more capabilities than the expected_keepers interface + GetE2eDistributionKeeper() E2eDistributionKeeper + // Returns a staking keeper interface with more capabilities than the expected_keepers interface + GetE2eStakingKeeper() E2eStakingKeeper + // Returns a mint keeper interface with more capabilities than the expected_keepers interface + GetE2eMintKeeper() E2eMintKeeper + // Returns a gov keeper interface with more capabilities than the expected_keepers interface + GetE2eGovKeeper() E2eGovKeeper +} + +// +// The following keeper interfaces are wrappers around the expected keepers for ccv modules, +// since e2e tests require extra functionality from external keepers. +// + +type E2eStakingKeeper interface { + ccvtypes.StakingKeeper + Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Int, tokenSrc types.BondStatus, + validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err error) + Undelegate(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec, + ) (time.Time, error) + BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, + sharesAmount sdk.Dec) (completionTime time.Time, err error) + GetUnbondingDelegationByUnbondingId(ctx sdk.Context, id uint64, + ) (ubd types.UnbondingDelegation, found bool) + GetRedelegations(ctx sdk.Context, delegator sdk.AccAddress, + maxRetrieve uint16) (redelegations []types.Redelegation) + BondDenom(ctx sdk.Context) (res string) + IsValidatorJailed(ctx sdk.Context, addr sdk.ConsAddress) bool + GetUnbondingDelegation(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, + ) (ubd types.UnbondingDelegation, found bool) + GetAllValidators(ctx sdk.Context) (validators []types.Validator) + GetValidatorSet() types.ValidatorSet +} + +type E2eBankKeeper interface { + ccvtypes.BankKeeper + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, + recipientModule string, amt sdk.Coins) error +} + +type E2eAccountKeeper interface { + ccvtypes.AccountKeeper + GetParams(sdk.Context) authtypes.Params +} + +type E2eSlashingKeeper interface { + ccvtypes.SlashingKeeper + SetValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress, + info slashingtypes.ValidatorSigningInfo) + SignedBlocksWindow(ctx sdk.Context) (res int64) + HandleValidatorSignature(ctx sdk.Context, addr cryptotypes.Address, power int64, signed bool) + MinSignedPerWindow(ctx sdk.Context) int64 + IterateValidatorMissedBlockBitArray(ctx sdk.Context, + address sdk.ConsAddress, handler func(index int64, missed bool) (stop bool)) +} + +type E2eEvidenceKeeper interface { + HandleEquivocationEvidence(ctx sdk.Context, evidence *evidencetypes.Equivocation) +} + +type E2eDistributionKeeper interface { + GetFeePoolCommunityCoins(ctx sdk.Context) sdk.DecCoins + GetDistributionAccount(ctx sdk.Context) authtypes.ModuleAccountI + GetValidatorOutstandingRewards(ctx sdk.Context, + val sdk.ValAddress) (rewards distributiontypes.ValidatorOutstandingRewards) + GetCommunityTax(ctx sdk.Context) (percent sdk.Dec) +} + +type E2eMintKeeper interface { + GetParams(ctx sdk.Context) (params minttypes.Params) +} + +type E2eGovKeeper interface { + GetDepositParams(ctx sdk.Context) govtypes.DepositParams + GetVotingParams(ctx sdk.Context) govtypes.VotingParams + SetVotingParams(ctx sdk.Context, votingParams govtypes.VotingParams) + SubmitProposal(ctx sdk.Context, content govtypes.Content) (govtypes.Proposal, error) + AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (bool, error) + AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, options govtypes.WeightedVoteOptions) error +} diff --git a/testutil/keeper/expectations.go b/testutil/keeper/expectations.go index bbbb7ac12d..acffcc416e 100644 --- a/testutil/keeper/expectations.go +++ b/testutil/keeper/expectations.go @@ -28,9 +28,6 @@ func GetMocksForCreateConsumerClient(ctx sdk.Context, mocks *MockedKeepers, expectedChainID string, expectedLatestHeight clienttypes.Height) []*gomock.Call { expectations := []*gomock.Call{ - mocks.MockStakingKeeper.EXPECT().UnbondingTime(ctx).Return(time.Hour).Times( - 1, // called once in CreateConsumerClient - ), mocks.MockClientKeeper.EXPECT().CreateClient( ctx, diff --git a/testutil/keeper/unit_test_helpers.go b/testutil/keeper/unit_test_helpers.go index fef396eb72..3365683d0b 100644 --- a/testutil/keeper/unit_test_helpers.go +++ b/testutil/keeper/unit_test_helpers.go @@ -2,7 +2,6 @@ package keeper import ( "testing" - time "time" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -25,9 +24,6 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" - commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types" - ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" - providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" ) // Parameters needed to instantiate an in-memory keeper @@ -164,27 +160,6 @@ func GetConsumerKeeperAndCtx(t *testing.T, params InMemKeeperParams) ( return NewInMemConsumerKeeper(params, mocks), params.Ctx, ctrl, mocks } -// Sets a template client state for a params subspace so that the provider's -// GetTemplateClient method will be satisfied. -func (params *InMemKeeperParams) SetTemplateClientState(customState *ibctmtypes.ClientState) { - - keyTable := paramstypes.NewKeyTable(paramstypes.NewParamSetPair( - providertypes.KeyTemplateClient, &ibctmtypes.ClientState{}, - func(value interface{}) error { return nil })) - - newSubspace := params.ParamsSubspace.WithKeyTable(keyTable) - params.ParamsSubspace = &newSubspace - - // Default template client state if none provided - if customState == nil { - customState = ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, - time.Second*10, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), - []string{"upgrade", "upgradedIBCState"}, true, true) - } - - params.ParamsSubspace.Set(params.Ctx, providertypes.KeyTemplateClient, customState) -} - // Registers proto interfaces for params.Cdc // // For now, we explicitly force certain unit tests to register sdk crypto interfaces. diff --git a/x/ccv/consumer/client/cli/query.go b/x/ccv/consumer/client/cli/query.go new file mode 100644 index 0000000000..27910ef76b --- /dev/null +++ b/x/ccv/consumer/client/cli/query.go @@ -0,0 +1,51 @@ +package cli + +import ( + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/interchain-security/x/ccv/consumer/types" +) + +// NewQueryCmd returns a root CLI command handler for all x/ccv/provider query commands. +func NewQueryCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the ccv consumer module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand(CmdNextFeeDistribution()) + + return cmd +} + +func CmdNextFeeDistribution() *cobra.Command { + cmd := &cobra.Command{ + Use: "next-fee-distribution", + Short: "Query next fee distribution data", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + req := &types.QueryNextFeeDistributionEstimateRequest{} + res, err := queryClient.QueryNextFeeDistribution(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/ccv/consumer/keeper/distribution.go b/x/ccv/consumer/keeper/distribution.go index 1e17ed178d..377adadbda 100644 --- a/x/ccv/consumer/keeper/distribution.go +++ b/x/ccv/consumer/keeper/distribution.go @@ -1,8 +1,6 @@ package keeper import ( - "time" - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -14,13 +12,6 @@ import ( ccv "github.com/cosmos/interchain-security/x/ccv/types" ) -const TransferTimeDelay = 1 * 7 * 24 * time.Hour // 1 weeks - -// The fraction of tokens allocated to the consumer redistribution address -// during distribution events. The fraction is a string representing a -// decimal number. For example "0.75" would represent 75%. -const ConsumerRedistributeFrac = "0.75" - // Simple model, send tokens to the fee pool of the provider validator set // reference: cosmos/ibc-go/v3/modules/apps/transfer/keeper/msg_server.go func (k Keeper) DistributeToProviderValidatorSet(ctx sdk.Context) error { @@ -34,7 +25,7 @@ func (k Keeper) DistributeToProviderValidatorSet(ctx sdk.Context) error { fpTokens := k.bankKeeper.GetAllBalances(ctx, consumerFeePoolAddr) // split the fee pool, send the consumer's fraction to the consumer redistribution address - frac, err := sdk.NewDecFromStr(ConsumerRedistributeFrac) + frac, err := sdk.NewDecFromStr(k.GetConsumerRedistributionFrac(ctx)) if err != nil { return err } @@ -76,7 +67,8 @@ func (k Keeper) DistributeToProviderValidatorSet(ctx sdk.Context) error { tstProviderTokens := k.bankKeeper.GetAllBalances(ctx, tstProviderAddr) providerAddr := k.GetProviderFeePoolAddrStr(ctx) timeoutHeight := clienttypes.ZeroHeight() - timeoutTimestamp := uint64(ctx.BlockTime().Add(TransferTimeDelay).UnixNano()) + transferTimeoutPeriod := k.GetTransferTimeoutPeriod(ctx) + timeoutTimestamp := uint64(ctx.BlockTime().Add(transferTimeoutPeriod).UnixNano()) for _, token := range tstProviderTokens { err := k.ibcTransferKeeper.SendTransfer(ctx, transfertypes.PortID, @@ -140,3 +132,38 @@ func (k Keeper) GetConnectionHops(ctx sdk.Context, srcPort, srcChan string) ([]s } return ch.ConnectionHops, nil } + +// GetEstimatedNextFeeDistribution returns data about next fee distribution. Data represents an estimation of +// accumulated fees at the current block height. +func (k Keeper) GetEstimatedNextFeeDistribution(ctx sdk.Context) (types.NextFeeDistributionEstimate, error) { + lastH, err := k.GetLastTransmissionBlockHeight(ctx) + if err != nil { + return types.NextFeeDistributionEstimate{}, err + } + + nextH := lastH.GetHeight() + k.GetBlocksPerDistributionTransmission(ctx) + + consumerFeePoolAddr := k.authKeeper.GetModuleAccount(ctx, k.feeCollectorName).GetAddress() + total := k.bankKeeper.GetAllBalances(ctx, consumerFeePoolAddr) + + fracParam := k.GetConsumerRedistributionFrac(ctx) + frac, err := sdk.NewDecFromStr(fracParam) + if err != nil { + return types.NextFeeDistributionEstimate{}, err + } + + totalTokens := sdk.NewDecCoinsFromCoins(total...) + // truncated decimals are implicitly added to provider + consumerTokens, _ := totalTokens.MulDec(frac).TruncateDecimal() + providerTokens := total.Sub(consumerTokens) + + return types.NextFeeDistributionEstimate{ + CurrentHeight: ctx.BlockHeight(), + LastHeight: lastH.GetHeight(), + NextHeight: nextH, + DistributionFraction: fracParam, + Total: totalTokens.String(), + ToProvider: sdk.NewDecCoinsFromCoins(providerTokens...).String(), + ToConsumer: sdk.NewDecCoinsFromCoins(consumerTokens...).String(), + }, nil +} diff --git a/x/ccv/consumer/keeper/distribution_test.go b/x/ccv/consumer/keeper/distribution_test.go new file mode 100644 index 0000000000..6c11a9b63b --- /dev/null +++ b/x/ccv/consumer/keeper/distribution_test.go @@ -0,0 +1,68 @@ +package keeper_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + authTypes "github.com/cosmos/cosmos-sdk/x/auth/types" + testkeeper "github.com/cosmos/interchain-security/testutil/keeper" + "github.com/cosmos/interchain-security/x/ccv/consumer/types" + "github.com/golang/mock/gomock" +) + +// TestGetEstimatedNextFeeDistribution tests next fee distribution parameters. +func TestGetEstimatedNextFeeDistribution(t *testing.T) { + keeperParams := testkeeper.NewInMemKeeperParams(t) + ctx := keeperParams.Ctx + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mocks := testkeeper.NewMockedKeepers(ctrl) + mockAccountKeeper := mocks.MockAccountKeeper + mockBankKeeper := mocks.MockBankKeeper + consumerKeeper := testkeeper.NewInMemConsumerKeeper(keeperParams, mocks) + consumerKeeper.SetParams(ctx, types.DefaultParams()) + + // Setup mock account balance + fracParam := consumerKeeper.GetConsumerRedistributionFrac(ctx) + fracDec, err := sdk.NewDecFromStr(fracParam) + require.NoError(t, err) + feeAmount := sdk.Coin{ + Denom: "MOCK", + Amount: sdk.NewInt(100), + } + feeAmountCoins := sdk.Coins([]sdk.Coin{feeAmount}) + feeAmountDec := sdk.NewDecCoinsFromCoins(feeAmountCoins...) + consumerTokens, _ := feeAmountDec.MulDec(fracDec).TruncateDecimal() + providerTokens := feeAmountCoins.Sub(consumerTokens) + mAcc := authTypes.NewModuleAccount(&authTypes.BaseAccount{}, "", "auth") + + // Setup mock calls + gomock.InOrder( + mockAccountKeeper.EXPECT().GetModuleAccount(ctx, ""). + Return(mAcc). + Times(1), + mockBankKeeper.EXPECT().GetAllBalances(ctx, mAcc.GetAddress()). + Return(feeAmountCoins). + Times(1), + ) + + // set next height to be 10 blocks from current + consumerKeeper.SetBlocksPerDistributionTransmission(ctx, 10) + expect := types.NextFeeDistributionEstimate{ + NextHeight: 10, + LastHeight: 0, + CurrentHeight: 0, + DistributionFraction: fracParam, + Total: feeAmountDec.String(), + ToProvider: sdk.NewDecCoinsFromCoins(providerTokens...).String(), + ToConsumer: sdk.NewDecCoinsFromCoins(consumerTokens...).String(), + } + + res, err := consumerKeeper.GetEstimatedNextFeeDistribution(ctx) + require.NoError(t, err) + require.NotEmpty(t, res) + require.EqualValues(t, expect, res, "fee distribution data does not match") +} diff --git a/x/ccv/consumer/keeper/genesis.go b/x/ccv/consumer/keeper/genesis.go index 945bde75f8..0bbf654969 100644 --- a/x/ccv/consumer/keeper/genesis.go +++ b/x/ccv/consumer/keeper/genesis.go @@ -9,13 +9,17 @@ import ( "github.com/cosmos/interchain-security/x/ccv/consumer/types" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" - utils "github.com/cosmos/interchain-security/x/ccv/utils" abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" ) // InitGenesis initializes the CCV consumer state and binds to PortID. +// The three states in which a consumer chain can start/restart: +// +// 1. A client to the provider was never created, i.e. a consumer chain is started for the first time. +// 2. A consumer chain restarts after a client to the provider was created, but the CCV channel handshake is still in progress +// 3. A consumer chain restarts after the CCV channel handshake was completed. func (k Keeper) InitGenesis(ctx sdk.Context, state *consumertypes.GenesisState) []abci.ValidatorUpdate { k.SetParams(ctx, state.Params) // TODO: Remove enabled flag and find a better way to setup e2e tests @@ -38,57 +42,47 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state *consumertypes.GenesisState) } // initialValSet is checked in NewChain case by ValidateGenesis + // chain first start without client or CCV channel established (1) if state.NewChain { - // Create the provider client in InitGenesis for new consumer chain. CCV Handshake must be established with this client id. + // create the provider client in InitGenesis for new consumer chain. CCV Handshake must be established with this client id. clientID, err := k.clientKeeper.CreateClient(ctx, state.ProviderClientState, state.ProviderConsensusState) if err != nil { panic(err) } - - // Set the unbonding period: use the unbonding period on the provider to - // compute the unbonding period on the consumer - unbondingTime := utils.ComputeConsumerUnbondingPeriod(state.ProviderClientState.UnbondingPeriod) - k.SetUnbondingTime(ctx, unbondingTime) - // Set default value for valset update ID + // set default value for valset update ID k.SetHeightValsetUpdateID(ctx, uint64(ctx.BlockHeight()), uint64(0)) + // set provider client id. k.SetProviderClientID(ctx, clientID) } else { - // verify that latest consensus state on provider client matches the initial validator set of restarted chain - // thus, IBC genesis MUST run before CCV consumer genesis - consState, ok := k.clientKeeper.GetLatestClientConsensusState(ctx, state.ProviderClientId) - if !ok { - panic("consensus state for provider client not found. MUST run IBC genesis before CCV consumer genesis") - } - tmConsState, ok := consState.(*ibctmtypes.ConsensusState) - if !ok { - panic(fmt.Sprintf("consensus state has wrong type. expected: %T, got: %T", &ibctmtypes.ConsensusState{}, consState)) - } - - // ensure that initial validator set is same as initial consensus state on provider client. - // this will be verified by provider module on channel handshake. - vals, err := tmtypes.PB2TM.ValidatorUpdates(state.InitialValSet) - if err != nil { + // verify genesis initial valset against the latest consensus state + // IBC genesis MUST run before CCV consumer genesis + if err := k.verifyGenesisInitValset(ctx, state); err != nil { panic(err) } - valSet := tmtypes.NewValidatorSet(vals) - - if !bytes.Equal(tmConsState.NextValidatorsHash, valSet.Hash()) { - panic("initial validator set does not match last consensus state of the provider client") - } - - // Set the unbonding period: use the unbonding period on the provider to - // compute the unbonding period on the consumer - clientState, ok := k.clientKeeper.GetClientState(ctx, state.ProviderClientId) - if !ok { - panic("client state for provider client not found. MUST run IBC genesis before CCV consumer genesis") - } - tmClientState, ok := clientState.(*ibctmtypes.ClientState) - if !ok { - panic(fmt.Sprintf("client state has wrong type. expected: %T, got: %T", &ibctmtypes.ClientState{}, clientState)) + // chain restarts without a CCV channel established (2) + if state.ProviderChannelId == "" { + k.SetPendingSlashRequests(ctx, state.PendingSlashRequests) + + // chain restarts with a CCV channel established (3) + } else { + // set provider channel ID + k.SetProviderChannel(ctx, state.ProviderChannelId) + // set all unbonding sequences + for _, mp := range state.MaturingPackets { + k.SetPacketMaturityTime(ctx, mp.VscId, mp.MaturityTime) + } + // set outstanding downtime slashing requests + for _, od := range state.OutstandingDowntimeSlashing { + consAddr, err := sdk.ConsAddressFromBech32(od.ValidatorConsensusAddress) + if err != nil { + panic(err) + } + k.SetOutstandingDowntime(ctx, consAddr) + } + // set last transmission block height + k.SetLastTransmissionBlockHeight(ctx, state.LastTransmissionBlockHeight) } - unbondingTime := utils.ComputeConsumerUnbondingPeriod(tmClientState.UnbondingPeriod) - k.SetUnbondingTime(ctx, unbondingTime) // set height to valset update id mapping for _, h2v := range state.HeightToValsetUpdateId { @@ -97,12 +91,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state *consumertypes.GenesisState) // set provider client id k.SetProviderClientID(ctx, state.ProviderClientId) - // set provider channel id. - k.SetProviderChannel(ctx, state.ProviderChannelId) - // set all unbonding sequences - for _, mp := range state.MaturingPackets { - k.SetPacketMaturityTime(ctx, mp.VscId, mp.MaturityTime) - } + } // populate cross chain validators states with initial valset @@ -120,7 +109,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt } // export the current validator set - valset, err := k.GetCurrentValidatorsAsABCIpdates(ctx) + valset, err := k.GetCurrentValidatorsAsABCIUpdates(ctx) if err != nil { panic(fmt.Sprintf("fail to retrieve the validator set: %s", err)) } @@ -142,16 +131,6 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt return false }) - heightToVCIDs := []types.HeightToValsetUpdateID{} - k.IterateHeightToValsetUpdateID(ctx, func(height, vscID uint64) bool { - hv := types.HeightToValsetUpdateID{ - Height: height, - ValsetUpdateId: vscID, - } - heightToVCIDs = append(heightToVCIDs, hv) - return true - }) - outstandingDowntimes := []types.OutstandingDowntime{} k.IterateOutstandingDowntime(ctx, func(addr string) bool { od := types.OutstandingDowntime{ @@ -166,36 +145,60 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt channelID, maturingPackets, valset, - heightToVCIDs, + k.GetHeightToValsetUpdateIDs(ctx), + consumertypes.SlashRequests{}, outstandingDowntimes, + consumertypes.LastTransmissionBlockHeight{}, params, ) } else { clientID, ok := k.GetProviderClientID(ctx) - // if provider clientID and channelID don't exist on the consumer chain, then CCV protocol is disabled for this chain - // return a disabled genesis state + // if provider clientID and channelID don't exist on the consumer chain, + // then CCV protocol is disabled for this chain return a default genesis state if !ok { return consumertypes.DefaultGenesisState() } - cs, ok := k.clientKeeper.GetClientState(ctx, clientID) - if !ok { - panic("provider client not set on already running consumer chain") - } - tmCs, ok := cs.(*ibctmtypes.ClientState) - if !ok { - panic("provider client consensus state is not tendermint client state") - } - consState, ok := k.clientKeeper.GetLatestClientConsensusState(ctx, clientID) - if !ok { - panic("provider consensus state not set on already running consumer chain") - } - tmConsState, ok := consState.(*ibctmtypes.ConsensusState) - if !ok { - 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.NewRestartGenesisState( + clientID, + "", + nil, + valset, + k.GetHeightToValsetUpdateIDs(ctx), + k.GetPendingSlashRequests(ctx), + nil, + consumertypes.LastTransmissionBlockHeight{}, + params, + ) } return } + +// VerifyGenesisInitValset verifies the latest consensus state on provider client matches +// the initial validator set of restarted chain thus +func (k Keeper) verifyGenesisInitValset(ctx sdk.Context, genState *consumertypes.GenesisState) error { + + consState, ok := k.clientKeeper.GetLatestClientConsensusState(ctx, genState.ProviderClientId) + if !ok { + return fmt.Errorf("consensus state for provider client not found. MUST run IBC genesis before CCV consumer genesis") + } + tmConsState, ok := consState.(*ibctmtypes.ConsensusState) + if !ok { + return fmt.Errorf(fmt.Sprintf("consensus state has wrong type. expected: %T, got: %T", &ibctmtypes.ConsensusState{}, consState)) + } + + // ensure that initial validator set is same as initial consensus state on provider client. + // this will be verified by provider module on channel handshake. + vals, err := tmtypes.PB2TM.ValidatorUpdates(genState.InitialValSet) + if err != nil { + return err + } + valSet := tmtypes.NewValidatorSet(vals) + + if !bytes.Equal(tmConsState.NextValidatorsHash, valSet.Hash()) { + return fmt.Errorf("initial validator set does not match last consensus state of the provider client") + } + return nil +} diff --git a/x/ccv/consumer/keeper/genesis_test.go b/x/ccv/consumer/keeper/genesis_test.go index 0e8c3c0f55..6e08fc54bb 100644 --- a/x/ccv/consumer/keeper/genesis_test.go +++ b/x/ccv/consumer/keeper/genesis_test.go @@ -13,7 +13,6 @@ import ( consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" "github.com/cosmos/interchain-security/x/ccv/consumer/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" - utils "github.com/cosmos/interchain-security/x/ccv/utils" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" @@ -27,26 +26,29 @@ import ( ) // TestInitGenesis tests that a consumer chain is correctly initialised from genesis. -// It covers the cases where a chain is new or restarted which means that -// its CCV channel is already established. +// It covers the cases where a chain is new or restarted func TestInitGenesis(t *testing.T) { // create states to initialise a consumer chain from genesis - // create provider channel and client ids - provChannelID := "ChannelID" + // mock the consumer genesis state values provClientID := "tendermint-07" - // generate validator public key + provChannelID := "ChannelID" + + vscID := uint64(0) + blockHeight := uint64(0) + + // create validator set pubKey, err := testutil.GenPubKey() require.NoError(t, err) - // create validator set with single validator validator := tmtypes.NewValidator(pubKey, 1) - // create a provider consensus state using a single validator + valset := []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)} + + // create ibc client and last consensus states provConsState := ibctmtypes.NewConsensusState( time.Time{}, commitmenttypes.NewMerkleRoot([]byte("apphash")), tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}).Hash()[:], ) - // create a provider client state provClientState := ibctmtypes.NewClientState( "provider", ibctmtypes.DefaultTrustLevel, @@ -62,16 +64,26 @@ func TestInitGenesis(t *testing.T) { slashRequests := consumertypes.SlashRequests{ Requests: []consumertypes.SlashRequest{{Infraction: stakingtypes.Downtime}}, } - matPacket := consumertypes.MaturingVSCPacket{ - VscId: uint64(1), - MaturityTime: uint64(time.Now().UnixNano()), + matPackets := []consumertypes.MaturingVSCPacket{ + { + VscId: uint64(1), + MaturityTime: uint64(time.Now().UnixNano()), + }, + } + // mock height to valset update ID values + defaultHeightValsetUpdateIDs := []consumertypes.HeightToValsetUpdateID{ + {ValsetUpdateId: vscID, Height: blockHeight}, } + updatedHeightValsetUpdateIDs := append(defaultHeightValsetUpdateIDs, + consumertypes.HeightToValsetUpdateID{ValsetUpdateId: vscID + 1, Height: blockHeight + 1}, + ) - // create paramameters for a new chain - params := types.NewParams(true, types.DefaultBlocksPerDistributionTransmission, "", "") + // create default parameters for a new chain + params := types.DefaultParams() + params.Enabled = true // define two test cases which respectively create a genesis struct, use it to call InitGenesis - // and finally check that the genesis states are imported in the consumer keeper stores + // and finally check that the genesis states are successfully imported in the consumer keeper stores testCases := []struct { name string malleate func(sdk.Context, testutil.MockedKeepers) @@ -79,80 +91,101 @@ func TestInitGenesis(t *testing.T) { assertStates func(sdk.Context, consumerkeeper.Keeper, *consumertypes.GenesisState) }{ { - name: "restart a new chain", - malleate: func(ctx sdk.Context, mocks testutil.MockedKeepers) { + "start a new chain", + func(ctx sdk.Context, mocks testutil.MockedKeepers) { gomock.InOrder( testkeeper.ExpectGetCapabilityMock(ctx, mocks), testkeeper.ExpectCreateClientMock(ctx, mocks, provClientID, provClientState, provConsState), + testkeeper.ExpectGetCapabilityMock(ctx, mocks), ) }, - // create a genesis for a new chain - genesis: consumertypes.NewInitialGenesisState( + consumertypes.NewInitialGenesisState( provClientState, provConsState, - []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, - slashRequests, + valset, params, ), + func(ctx sdk.Context, ck consumerkeeper.Keeper, gs *consumertypes.GenesisState) { + assertPortIsSetAndBonded(t, ctx, &ck) - assertStates: func(ctx sdk.Context, ck consumerkeeper.Keeper, gs *consumertypes.GenesisState) { - require.Equal(t, gs.Params, ck.GetParams(ctx)) - require.Equal(t, ccv.ConsumerPortID, ck.GetPort(ctx)) - - // compute the consumer unbonding period as done in InitGenesis (x/ccv/consumer/keeper/genesis.go) - expectedUbdPeriod := utils.ComputeConsumerUnbondingPeriod(gs.ProviderClientState.UnbondingPeriod) - gotUbdPeriod, found := ck.GetUnbondingTime(ctx) - - require.True(t, found) - require.Equal(t, expectedUbdPeriod, gotUbdPeriod) + assertProviderClientID(t, ctx, &ck, provClientID) + assertHeightValsetUpdateID(t, ctx, &ck, defaultHeightValsetUpdateIDs) - require.Zero(t, ck.GetHeightValsetUpdateID(ctx, uint64(ctx.BlockHeight()))) - - cid, ok := ck.GetProviderClientID(ctx) - require.True(t, ok) - require.Equal(t, provClientID, cid) + require.Equal(t, validator.Address.Bytes(), ck.GetAllCCValidator(ctx)[0].Address) + require.Equal(t, gs.Params, ck.GetParams(ctx)) + }, + }, { + "restart a chain with a client on provider without an established CCV channel", + func(ctx sdk.Context, mocks testutil.MockedKeepers) { + gomock.InOrder( + testkeeper.ExpectGetCapabilityMock(ctx, mocks), + testkeeper.ExpectLatestConsensusStateMock(ctx, mocks, provClientID, provConsState), + testkeeper.ExpectGetCapabilityMock(ctx, mocks), + ) + }, + consumertypes.NewRestartGenesisState( + provClientID, + "", + matPackets, + valset, + defaultHeightValsetUpdateIDs, + slashRequests, + nil, + consumertypes.LastTransmissionBlockHeight{}, + params, + ), + func(ctx sdk.Context, ck consumerkeeper.Keeper, gs *consumertypes.GenesisState) { + assertPortIsSetAndBonded(t, ctx, &ck) + require.Equal(t, slashRequests, ck.GetPendingSlashRequests(ctx)) + assertHeightValsetUpdateID(t, ctx, &ck, defaultHeightValsetUpdateIDs) + assertProviderClientID(t, ctx, &ck, provClientID) + require.Equal(t, validator.Address.Bytes(), ck.GetAllCCValidator(ctx)[0].Address) + require.Equal(t, gs.Params, ck.GetParams(ctx)) }, }, { - name: "restart a chain with an already established channel", - malleate: func(ctx sdk.Context, mocks testutil.MockedKeepers) { + "restart a chain with an established CCV channel", + func(ctx sdk.Context, mocks testutil.MockedKeepers) { + // simulate a CCV channel handshake completition + params.DistributionTransmissionChannel = "distribution-channel" + params.ProviderFeePoolAddrStr = "provider-fee-pool-address" gomock.InOrder( testkeeper.ExpectGetCapabilityMock(ctx, mocks), testkeeper.ExpectLatestConsensusStateMock(ctx, mocks, provClientID, provConsState), - testkeeper.ExpectGetClientStateMock(ctx, mocks, provClientID, provClientState), + testkeeper.ExpectGetCapabilityMock(ctx, mocks), ) }, // create a genesis for a restarted chain - genesis: &consumertypes.GenesisState{ - ProviderClientId: provClientID, - ProviderChannelId: provChannelID, - Params: params, - NewChain: false, - ProviderClientState: provClientState, - ProviderConsensusState: provConsState, - InitialValSet: []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, - OutstandingDowntimeSlashing: []consumertypes.OutstandingDowntime{ + consumertypes.NewRestartGenesisState( + provClientID, + provChannelID, + matPackets, + valset, + updatedHeightValsetUpdateIDs, + consumertypes.SlashRequests{}, + []consumertypes.OutstandingDowntime{ {ValidatorConsensusAddress: sdk.ConsAddress(validator.Bytes()).String()}, }, - HeightToValsetUpdateId: []consumertypes.HeightToValsetUpdateID{ - {ValsetUpdateId: matPacket.VscId, Height: uint64(0)}, - }, - MaturingPackets: []consumertypes.MaturingVSCPacket{matPacket}, - }, - assertStates: func(ctx sdk.Context, ck consumerkeeper.Keeper, gs *consumertypes.GenesisState) { - require.Equal(t, gs.Params, ck.GetParams(ctx)) - require.Equal(t, ccv.ConsumerPortID, ck.GetPort(ctx)) + consumertypes.LastTransmissionBlockHeight{Height: int64(blockHeight)}, + params, + ), + func(ctx sdk.Context, ck consumerkeeper.Keeper, gs *consumertypes.GenesisState) { + assertPortIsSetAndBonded(t, ctx, &ck) - // compute the consumer unbonding period as done in InitGenesis (x/ccv/consumer/keeper/genesis.go) - expectedUbdPeriod := utils.ComputeConsumerUnbondingPeriod(gs.ProviderClientState.UnbondingPeriod) - gotUbdPeriod, found := ck.GetUnbondingTime(ctx) + gotChannelID, ok := ck.GetProviderChannel(ctx) + require.True(t, ok) + require.Equal(t, provChannelID, gotChannelID) - require.True(t, found) - require.Equal(t, expectedUbdPeriod, gotUbdPeriod) + require.Equal(t, vscID, ck.GetPacketMaturityTime(ctx, vscID)) - // export states to genesis - require.Equal(t, matPacket.VscId, ck.GetHeightValsetUpdateID(ctx, uint64(0))) + require.Equal(t, gs.OutstandingDowntimeSlashing, ck.GetOutstandingDowntimes(ctx)) + + ltbh, err := ck.GetLastTransmissionBlockHeight(ctx) + require.NoError(t, err) + require.Equal(t, gs.LastTransmissionBlockHeight, *ltbh) + + assertHeightValsetUpdateID(t, ctx, &ck, updatedHeightValsetUpdateIDs) + assertProviderClientID(t, ctx, &ck, provClientID) - require.Equal(t, matPacket.MaturityTime, ck.GetPacketMaturityTime(ctx, matPacket.VscId)) require.Equal(t, gs.Params, ck.GetParams(ctx)) }, }, @@ -160,7 +193,6 @@ func TestInitGenesis(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - keeperParams := testkeeper.NewInMemKeeperParams(t) // Explicitly register codec with public key interface keeperParams.RegisterSdkCryptoCodecInterfaces() @@ -187,93 +219,112 @@ func TestExportGenesis(t *testing.T) { // create provider channel and client ids provClientID := "tendermint-07" provChannelID := "provChannelID" + + vscID := uint64(0) + blockHeight := uint64(0) + slashRequests := consumertypes.SlashRequests{ Requests: []consumertypes.SlashRequest{{Infraction: stakingtypes.Downtime}}, } - restartHeight := uint64(0) - matPacket := consumertypes.MaturingVSCPacket{ - VscId: uint64(1), - MaturityTime: uint64(time.Now().UnixNano()), + matPackets := []consumertypes.MaturingVSCPacket{ + { + VscId: uint64(1), + MaturityTime: uint64(time.Now().UnixNano()), + }, } - // create a single validator + // mock a validator set pubKey := ed25519.GenPrivKey().PubKey() tmPK, err := cryptocodec.ToTmPubKeyInterface(pubKey) require.NoError(t, err) validator := tmtypes.NewValidator(tmPK, 1) - // create a provider consensus state using a single validator - provConsState := ibctmtypes.NewConsensusState( - time.Time{}, - commitmenttypes.NewMerkleRoot([]byte("apphash")), - tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}).Hash()[:], + valset := []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)} + + // mock height to valset update ID values + defaultHeightValsetUpdateIDs := []consumertypes.HeightToValsetUpdateID{ + {ValsetUpdateId: vscID, Height: blockHeight}, + } + updatedHeightValsetUpdateIDs := append(defaultHeightValsetUpdateIDs, + consumertypes.HeightToValsetUpdateID{ValsetUpdateId: vscID + 1, Height: blockHeight + 1}, ) - // create a provider client state - provClientState := ibctmtypes.NewClientState( - "provider", - ibctmtypes.DefaultTrustLevel, - 0, - stakingtypes.DefaultUnbondingTime, - time.Second*10, - clienttypes.Height{}, - commitmenttypes.GetSDKSpecs(), - []string{"upgrade", "upgradedIBCState"}, - true, + lbth := consumertypes.LastTransmissionBlockHeight{Height: int64(blockHeight)} + // create paramameters for an enabled consumer chain + params := types.NewParams( true, + types.DefaultBlocksPerDistributionTransmission, + "", + "", + ccv.DefaultCCVTimeoutPeriod, + consumertypes.DefaultTransferTimeoutPeriod, + consumertypes.DefaultConsumerRedistributeFrac, + consumertypes.DefaultHistoricalEntries, + consumertypes.DefaultConsumerUnbondingPeriod, ) - // create paramameters for an enabled consumer chain - params := types.NewParams(true, types.DefaultBlocksPerDistributionTransmission, "", "") // define two test cases which respectively populate the consumer chain store // using the states declared above then call ExportGenesis to finally check - // that the resulting genesis struct stores this same states + // that the resulting genesis struct contains the same states testCases := []struct { name string malleate func(sdk.Context, consumerkeeper.Keeper, testutil.MockedKeepers) expGenesis *consumertypes.GenesisState }{ { - name: "export a new chain", - malleate: func(ctx sdk.Context, ck consumerkeeper.Keeper, mocks testutil.MockedKeepers) { - // populate the states used by a new consumer chain + "export a chain without an established CCV channel", + func(ctx sdk.Context, ck consumerkeeper.Keeper, mocks testutil.MockedKeepers) { + // populate the states allowed before a CCV channel is established + ck.SetProviderClientID(ctx, provClientID) cVal, err := consumertypes.NewCCValidator(validator.Address.Bytes(), 1, pubKey) require.NoError(t, err) ck.SetCCValidator(ctx, cVal) - ck.SetProviderClientID(ctx, provClientID) - ck.SetPendingSlashRequests( - ctx, - slashRequests, - ) + ck.SetParams(ctx, params) - // set the mock calls executed during the export - gomock.InOrder( - testkeeper.ExpectGetClientStateMock(ctx, mocks, provClientID, provClientState), - testkeeper.ExpectLatestConsensusStateMock(ctx, mocks, provClientID, provConsState), - ) - }, + ck.SetPendingSlashRequests(ctx, slashRequests) + ck.SetHeightValsetUpdateID(ctx, defaultHeightValsetUpdateIDs[0].Height, defaultHeightValsetUpdateIDs[0].ValsetUpdateId) - expGenesis: consumertypes.NewInitialGenesisState(provClientState, provConsState, - []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, slashRequests, params), + }, + consumertypes.NewRestartGenesisState( + provClientID, + "", + nil, + valset, + defaultHeightValsetUpdateIDs, + slashRequests, + nil, + consumertypes.LastTransmissionBlockHeight{}, + params, + ), }, { - name: "export a chain that has an established CCV channel", - malleate: func(ctx sdk.Context, ck consumerkeeper.Keeper, mocks testutil.MockedKeepers) { - // populate the states used by a restarted chain + "export a chain with an established CCV channel", + func(ctx sdk.Context, ck consumerkeeper.Keeper, mocks testutil.MockedKeepers) { + ck.SetProviderClientID(ctx, provClientID) + ck.SetProviderChannel(ctx, provChannelID) + cVal, err := consumertypes.NewCCValidator(validator.Address.Bytes(), 1, pubKey) require.NoError(t, err) ck.SetCCValidator(ctx, cVal) - ck.SetOutstandingDowntime(ctx, sdk.ConsAddress(validator.Address.Bytes())) + + ck.SetParams(ctx, params) + + ck.SetHeightValsetUpdateID(ctx, updatedHeightValsetUpdateIDs[0].Height, updatedHeightValsetUpdateIDs[0].ValsetUpdateId) + ck.SetHeightValsetUpdateID(ctx, updatedHeightValsetUpdateIDs[1].Height, updatedHeightValsetUpdateIDs[1].ValsetUpdateId) + // populate the required states for an established CCV channel - ck.SetProviderClientID(ctx, provClientID) - ck.SetProviderChannel(ctx, provChannelID) - ck.SetHeightValsetUpdateID(ctx, restartHeight, matPacket.VscId) - ck.SetPacketMaturityTime(ctx, matPacket.VscId, matPacket.MaturityTime) + ck.SetPacketMaturityTime(ctx, matPackets[0].VscId, matPackets[0].MaturityTime) + ck.SetOutstandingDowntime(ctx, sdk.ConsAddress(validator.Address.Bytes())) + ck.SetLastTransmissionBlockHeight(ctx, lbth) }, - expGenesis: consumertypes.NewRestartGenesisState( + consumertypes.NewRestartGenesisState( provClientID, provChannelID, - []consumertypes.MaturingVSCPacket{matPacket}, - []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, - []types.HeightToValsetUpdateID{{Height: restartHeight, ValsetUpdateId: matPacket.VscId}}, - []consumertypes.OutstandingDowntime{{ValidatorConsensusAddress: sdk.ConsAddress(validator.Address.Bytes()).String()}}, + matPackets, + valset, + updatedHeightValsetUpdateIDs, + types.SlashRequests{}, + []consumertypes.OutstandingDowntime{ + {ValidatorConsensusAddress: sdk.ConsAddress(validator.Address.Bytes()).String()}, + }, + lbth, params, ), }, @@ -300,3 +351,21 @@ func TestExportGenesis(t *testing.T) { }) } } +func assertPortIsSetAndBonded(t *testing.T, ctx sdk.Context, ck *consumerkeeper.Keeper) { + require.Equal(t, ck.GetPort(ctx), string(ccv.ConsumerPortID)) + require.True(t, ck.IsBound(ctx, ccv.ConsumerPortID)) +} +func assertHeightValsetUpdateID(t *testing.T, ctx sdk.Context, ck *consumerkeeper.Keeper, heighValsetUpdateIDs []consumertypes.HeightToValsetUpdateID) { + ctr := 0 + ck.IterateHeightToValsetUpdateID(ctx, func(height uint64, vscID uint64) bool { + require.Equal(t, heighValsetUpdateIDs[ctr].Height, height) + require.Equal(t, heighValsetUpdateIDs[ctr].ValsetUpdateId, vscID) + ctr++ + return true + }) +} +func assertProviderClientID(t *testing.T, ctx sdk.Context, ck *consumerkeeper.Keeper, clientID string) { + cid, ok := ck.GetProviderClientID(ctx) + require.True(t, ok) + require.Equal(t, clientID, cid) +} diff --git a/x/ccv/consumer/keeper/grpc_query.go b/x/ccv/consumer/keeper/grpc_query.go new file mode 100644 index 0000000000..0e7d10f814 --- /dev/null +++ b/x/ccv/consumer/keeper/grpc_query.go @@ -0,0 +1,29 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/interchain-security/x/ccv/consumer/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var _ types.QueryServer = Keeper{} + +func (k Keeper) QueryNextFeeDistribution(c context.Context, + req *types.QueryNextFeeDistributionEstimateRequest) (*types.QueryNextFeeDistributionEstimateResponse, error) { + + ctx := sdk.UnwrapSDKContext(c) + + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + nextDist, err := k.GetEstimatedNextFeeDistribution(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + + return &types.QueryNextFeeDistributionEstimateResponse{Data: &nextDist}, nil +} diff --git a/x/ccv/consumer/keeper/keeper.go b/x/ccv/consumer/keeper/keeper.go index c7433ffaf0..248671262d 100644 --- a/x/ccv/consumer/keeper/keeper.go +++ b/x/ccv/consumer/keeper/keeper.go @@ -3,7 +3,6 @@ package keeper import ( "encoding/binary" "fmt" - "time" "github.com/cosmos/cosmos-sdk/codec" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -17,6 +16,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/interchain-security/x/ccv/consumer/types" + consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" "github.com/tendermint/tendermint/libs/log" ) @@ -136,30 +136,6 @@ func (k Keeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability return k.scopedKeeper.ClaimCapability(ctx, cap, name) } -// SetUnbondingTime sets the unbonding period of the consumer chain -func (k Keeper) SetUnbondingTime(ctx sdk.Context, unbondingTime time.Duration) { - store := ctx.KVStore(k.storeKey) - timeBytes := make([]byte, 8) - binary.BigEndian.PutUint64(timeBytes, uint64(unbondingTime.Nanoseconds())) - store.Set(types.UnbondingTimeKey(), timeBytes) -} - -// GetUnbondingTime gets the unbonding period of the consumer chain -func (k Keeper) GetUnbondingTime(ctx sdk.Context) (time.Duration, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.UnbondingTimeKey()) - if bz == nil { - return 0, false - } - return time.Duration(binary.BigEndian.Uint64(bz)), true -} - -// DeleteUnbondingTime deletes the unbonding period of the consumer chain -func (k Keeper) DeleteUnbondingTime(ctx sdk.Context) { - store := ctx.KVStore(k.storeKey) - store.Delete(types.UnbondingTimeKey()) -} - // SetProviderClientID sets the clientID for the client to the provider. // Set in InitGenesis func (k Keeper) SetProviderClientID(ctx sdk.Context, clientID string) { @@ -458,3 +434,31 @@ func (k Keeper) AppendPendingSlashRequests(ctx sdk.Context, req types.SlashReque srArray = append(srArray, req) k.SetPendingSlashRequests(ctx, types.SlashRequests{Requests: srArray}) } + +// GetHeightToValsetUpdateIDs returns all height to valset update id pairs into a list +func (k Keeper) GetHeightToValsetUpdateIDs(ctx sdk.Context) []types.HeightToValsetUpdateID { + heightToVCIDs := []types.HeightToValsetUpdateID{} + k.IterateHeightToValsetUpdateID(ctx, func(height, vscID uint64) bool { + hv := types.HeightToValsetUpdateID{ + Height: height, + ValsetUpdateId: vscID, + } + heightToVCIDs = append(heightToVCIDs, hv) + return true + }) + + return heightToVCIDs +} + +// GetOutstandingDowntimes returns all outstanding downtimes in store +func (k Keeper) GetOutstandingDowntimes(ctx sdk.Context) []consumertypes.OutstandingDowntime { + outstandingDowntimes := []types.OutstandingDowntime{} + k.IterateOutstandingDowntime(ctx, func(addr string) bool { + od := types.OutstandingDowntime{ + ValidatorConsensusAddress: addr, + } + outstandingDowntimes = append(outstandingDowntimes, od) + return false + }) + return outstandingDowntimes +} diff --git a/x/ccv/consumer/keeper/keeper_test.go b/x/ccv/consumer/keeper/keeper_test.go index 67a5db53ca..431f0b6dd5 100644 --- a/x/ccv/consumer/keeper/keeper_test.go +++ b/x/ccv/consumer/keeper/keeper_test.go @@ -2,7 +2,6 @@ package keeper_test import ( "testing" - "time" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" @@ -17,21 +16,6 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" ) -// TestUnbondingTime tests getter and setter functionality for the unbonding period of a consumer chain -func TestUnbondingTime(t *testing.T) { - - consumerKeeper, ctx, ctrl, _ := testkeeper.GetConsumerKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) - defer ctrl.Finish() - - _, ok := consumerKeeper.GetUnbondingTime(ctx) - require.False(t, ok) - unbondingPeriod := time.Hour * 24 * 7 * 3 - consumerKeeper.SetUnbondingTime(ctx, unbondingPeriod) - storedUnbondingPeriod, ok := consumerKeeper.GetUnbondingTime(ctx) - require.True(t, ok) - require.Equal(t, storedUnbondingPeriod, unbondingPeriod) -} - // TestProviderClientID tests getter and setter functionality for the client ID stored on consumer keeper func TestProviderClientID(t *testing.T) { diff --git a/x/ccv/consumer/keeper/params.go b/x/ccv/consumer/keeper/params.go index e69a66d92b..8fd20ad2f8 100644 --- a/x/ccv/consumer/keeper/params.go +++ b/x/ccv/consumer/keeper/params.go @@ -1,18 +1,26 @@ package keeper import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/interchain-security/x/ccv/consumer/types" + ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" ) -// GetParams returns the paramset for the consumer module +// GetParams returns the params for the consumer ccv module func (k Keeper) GetParams(ctx sdk.Context) types.Params { return types.NewParams( k.GetEnabled(ctx), k.GetBlocksPerDistributionTransmission(ctx), k.GetDistributionTransmissionChannel(ctx), k.GetProviderFeePoolAddrStr(ctx), + k.GetCCVTimeoutPeriod(ctx), + k.GetTransferTimeoutPeriod(ctx), + k.GetConsumerRedistributionFrac(ctx), + k.GetHistoricalEntries(ctx), + k.GetUnbondingPeriod(ctx), ) } @@ -57,3 +65,44 @@ func (k Keeper) GetProviderFeePoolAddrStr(ctx sdk.Context) string { func (k Keeper) SetProviderFeePoolAddrStr(ctx sdk.Context, addr string) { k.paramStore.Set(ctx, types.KeyProviderFeePoolAddrStr, addr) } + +// GetCCVTimeoutPeriod returns the timeout period for sent ccv related ibc packets +func (k Keeper) GetCCVTimeoutPeriod(ctx sdk.Context) time.Duration { + var p time.Duration + k.paramStore.Get(ctx, ccvtypes.KeyCCVTimeoutPeriod, &p) + return p +} + +// GetTransferTimeoutPeriod returns the timeout period for sent transfer related ibc packets +func (k Keeper) GetTransferTimeoutPeriod(ctx sdk.Context) time.Duration { + var p time.Duration + k.paramStore.Get(ctx, types.KeyTransferTimeoutPeriod, &p) + return p +} + +// GetConsumerRedistributionFrac returns the fraction of tokens allocated to the consumer redistribution +// address during distribution events. The fraction is a string representing a +// decimal number. For example "0.75" would represent 75%. +func (k Keeper) GetConsumerRedistributionFrac(ctx sdk.Context) string { + var str string + k.paramStore.Get(ctx, types.KeyConsumerRedistributionFrac, &str) + return str +} + +// GetHistoricalEntries returns the number of historical info entries to persist in store +func (k Keeper) GetHistoricalEntries(ctx sdk.Context) int64 { + var n int64 + k.paramStore.Get(ctx, types.KeyHistoricalEntries, &n) + return n +} + +// Only used to set an unbonding period in diff tests +func (k Keeper) SetUnbondingPeriod(ctx sdk.Context, period time.Duration) { + k.paramStore.Set(ctx, types.KeyConsumerUnbondingPeriod, period) +} + +func (k Keeper) GetUnbondingPeriod(ctx sdk.Context) time.Duration { + var period time.Duration + k.paramStore.Get(ctx, types.KeyConsumerUnbondingPeriod, &period) + return period +} diff --git a/x/ccv/consumer/keeper/params_test.go b/x/ccv/consumer/keeper/params_test.go index 0bc043d984..2d2061e2a1 100644 --- a/x/ccv/consumer/keeper/params_test.go +++ b/x/ccv/consumer/keeper/params_test.go @@ -2,24 +2,39 @@ package keeper_test import ( "testing" + "time" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/x/ccv/consumer/types" + consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" + ccv "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" ) -// TestParams tests the default params set for a consumer chain, and related getters/setters +// TestParams tests getters/setters for consumer params func TestParams(t *testing.T) { consumerKeeper, ctx, ctrl, _ := testkeeper.GetConsumerKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) defer ctrl.Finish() consumerKeeper.SetParams(ctx, types.DefaultParams()) - expParams := types.NewParams(false, 1000, "", "") // these are the default params, IBC suite independently sets enabled=true + expParams := types.NewParams( + false, + 1000, + "", + "", + ccv.DefaultCCVTimeoutPeriod, + consumertypes.DefaultTransferTimeoutPeriod, + consumertypes.DefaultConsumerRedistributeFrac, + consumertypes.DefaultHistoricalEntries, + consumertypes.DefaultConsumerUnbondingPeriod, + ) // these are the default params, IBC suite independently sets enabled=true params := consumerKeeper.GetParams(ctx) require.Equal(t, expParams, params) - newParams := types.NewParams(false, 1000, "abc", "def") + newParams := types.NewParams(false, 1000, + "channel-2", "cosmos19pe9pg5dv9k5fzgzmsrgnw9rl9asf7ddwhu7lm", + 7*24*time.Hour, 25*time.Hour, "0.5", 500, 24*21*time.Hour) consumerKeeper.SetParams(ctx, newParams) params = consumerKeeper.GetParams(ctx) require.Equal(t, newParams, params) @@ -28,12 +43,16 @@ func TestParams(t *testing.T) { gotBPDT := consumerKeeper.GetBlocksPerDistributionTransmission(ctx) require.Equal(t, gotBPDT, int64(10)) - consumerKeeper.SetDistributionTransmissionChannel(ctx, "foobarbaz") + consumerKeeper.SetDistributionTransmissionChannel(ctx, "channel-7") gotChan := consumerKeeper.GetDistributionTransmissionChannel(ctx) - require.Equal(t, gotChan, "foobarbaz") + require.Equal(t, gotChan, "channel-7") - consumerKeeper.SetProviderFeePoolAddrStr(ctx, "foobar") + consumerKeeper.SetProviderFeePoolAddrStr(ctx, "cosmos1dkas8mu4kyhl5jrh4nzvm65qz588hy9qcz08la") gotAddr := consumerKeeper. GetProviderFeePoolAddrStr(ctx) - require.Equal(t, gotAddr, "foobar") + require.Equal(t, gotAddr, "cosmos1dkas8mu4kyhl5jrh4nzvm65qz588hy9qcz08la") + + consumerKeeper.SetUnbondingPeriod(ctx, time.Hour*24*10) + storedUnbondingPeriod := consumerKeeper.GetUnbondingPeriod(ctx) + require.Equal(t, time.Hour*24*10, storedUnbondingPeriod) } diff --git a/x/ccv/consumer/keeper/relay.go b/x/ccv/consumer/keeper/relay.go index b32ee25d8b..a149eca8eb 100644 --- a/x/ccv/consumer/keeper/relay.go +++ b/x/ccv/consumer/keeper/relay.go @@ -54,11 +54,7 @@ func (k Keeper) OnRecvVSCPacket(ctx sdk.Context, packet channeltypes.Packet, new } // Save maturity time and packet - unbondingPeriod, found := k.GetUnbondingTime(ctx) - if !found { - panic("the unbonding period is not set on the consumer chain") - } - maturityTime := ctx.BlockTime().Add(unbondingPeriod) + maturityTime := ctx.BlockTime().Add(k.GetUnbondingPeriod(ctx)) k.SetPacketMaturityTime(ctx, newChanges.ValsetUpdateId, uint64(maturityTime.UnixNano())) // set height to VSC id mapping @@ -108,6 +104,7 @@ func (k Keeper) SendVSCMaturedPackets(ctx sdk.Context) error { channelID, // source channel id ccv.ConsumerPortID, // source port id packetData.GetBytes(), + k.GetCCVTimeoutPeriod(ctx), ) if err != nil { return err @@ -153,6 +150,7 @@ func (k Keeper) SendSlashPacket(ctx sdk.Context, validator abci.Validator, valse channelID, // source channel id ccv.ConsumerPortID, // source port id packetData.GetBytes(), + k.GetCCVTimeoutPeriod(ctx), ) if err != nil { panic(err) @@ -179,7 +177,7 @@ func (k Keeper) SendPendingSlashRequests(ctx sdk.Context) { // send the emebdded slash packet to the CCV channel // if the outstanding downtime flag is false for the validator - downtime := slashReq.Infraction == stakingtypes.Downtime + downtime := slashReq.Packet.Infraction == stakingtypes.Downtime if !downtime || !k.OutstandingDowntime(ctx, sdk.ConsAddress(slashReq.Packet.Validator.Address)) { // send packet over IBC err := utils.SendIBCPacket( @@ -189,6 +187,7 @@ func (k Keeper) SendPendingSlashRequests(ctx sdk.Context) { channelID, // source channel id ccv.ConsumerPortID, // source port id slashReq.Packet.GetBytes(), + k.GetCCVTimeoutPeriod(ctx), ) if err != nil { panic(err) diff --git a/x/ccv/consumer/keeper/relay_test.go b/x/ccv/consumer/keeper/relay_test.go index 028675793c..218d8c4d6a 100644 --- a/x/ccv/consumer/keeper/relay_test.go +++ b/x/ccv/consumer/keeper/relay_test.go @@ -13,6 +13,7 @@ import ( channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" host "github.com/cosmos/ibc-go/v3/modules/core/24-host" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" + consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" "github.com/cosmos/interchain-security/x/ccv/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" "github.com/golang/mock/gomock" @@ -114,7 +115,11 @@ func TestOnRecvVSCPacket(t *testing.T) { // Set channel to provider, still in context of consumer chain consumerKeeper.SetProviderChannel(ctx, consumerCCVChannelID) - consumerKeeper.SetUnbondingTime(ctx, 100*time.Hour) + + // Set module params with custom unbonding period + moduleParams := consumertypes.DefaultParams() + moduleParams.UnbondingPeriod = 100 * time.Hour + consumerKeeper.SetParams(ctx, moduleParams) for _, tc := range testCases { ack := consumerKeeper.OnRecvVSCPacket(ctx, tc.packet, tc.newChanges) @@ -138,9 +143,7 @@ func TestOnRecvVSCPacket(t *testing.T) { }) require.Equal(t, tc.expectedPendingChanges, *actualPendingChanges, "pending changes not equal to expected changes after successful packet receive. case: %s", tc.name) - unbondingPeriod, found := consumerKeeper.GetUnbondingTime(ctx) - require.True(t, found) - expectedTime := uint64(ctx.BlockTime().Add(unbondingPeriod).UnixNano()) + expectedTime := uint64(ctx.BlockTime().Add(consumerKeeper.GetUnbondingPeriod(ctx)).UnixNano()) maturityTime := consumerKeeper.GetPacketMaturityTime(ctx, tc.newChanges.ValsetUpdateId) require.Equal(t, expectedTime, maturityTime, "packet maturity time has unexpected value for case: %s", tc.name) } diff --git a/x/ccv/consumer/keeper/validators.go b/x/ccv/consumer/keeper/validators.go index 541631c27f..0f164e5dd8 100644 --- a/x/ccv/consumer/keeper/validators.go +++ b/x/ccv/consumer/keeper/validators.go @@ -111,13 +111,9 @@ func (k Keeper) MaxValidators(sdk.Context) uint32 { panic("unimplemented on CCV keeper") } -// UnbondingTime returns consumer unbonding time +// UnbondingTime returns consumer unbonding period, satisfying the staking keeper interface func (k Keeper) UnbondingTime(ctx sdk.Context) time.Duration { - unbondingTime, found := k.GetUnbondingTime(ctx) - if !found { - panic("the consumer unbonding period is not set") - } - return unbondingTime + return k.GetUnbondingPeriod(ctx) } // GetHistoricalInfo gets the historical info at a given height @@ -154,7 +150,7 @@ func (k Keeper) DeleteHistoricalInfo(ctx sdk.Context, height int64) { // heights that are below pruning height func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) { - entryNum := types.HistoricalEntries + numHistoricalEntries := k.GetHistoricalEntries(ctx) // Prune store to ensure we only have parameter-defined historical entries. // In most cases, this will involve removing a single historical entry. @@ -163,7 +159,7 @@ func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) { // Since the entries to be deleted are always in a continuous range, we can iterate // over the historical entries starting from the most recent version to be pruned // and then return at the first empty entry. - for i := ctx.BlockHeight() - int64(entryNum); i >= 0; i-- { + for i := ctx.BlockHeight() - int64(numHistoricalEntries); i >= 0; i-- { _, found := k.GetHistoricalInfo(ctx, i) if found { k.DeleteHistoricalInfo(ctx, i) @@ -173,7 +169,7 @@ func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) { } // if there is no need to persist historicalInfo, return - if entryNum == 0 { + if numHistoricalEntries == 0 { return } @@ -203,8 +199,8 @@ func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) { k.SetHistoricalInfo(ctx, ctx.BlockHeight(), &historicalEntry) } -// GetCurrentValidatorsAsABCIpdates gets all cross-chain validators converted to the ABCI validator update type -func (k Keeper) GetCurrentValidatorsAsABCIpdates(ctx sdk.Context) ([]abci.ValidatorUpdate, error) { +// GetCurrentValidatorsAsABCIUpdates gets all cross-chain validators converted to the ABCI validator update type +func (k Keeper) GetCurrentValidatorsAsABCIUpdates(ctx sdk.Context) ([]abci.ValidatorUpdate, error) { vals := k.GetAllCCValidator(ctx) valUpdates := make([]abci.ValidatorUpdate, 0, len(vals)) for _, v := range vals { diff --git a/x/ccv/consumer/module.go b/x/ccv/consumer/module.go index 3c8080d5c1..ae6f6bfda8 100644 --- a/x/ccv/consumer/module.go +++ b/x/ccv/consumer/module.go @@ -1,6 +1,7 @@ package consumer import ( + "context" "encoding/json" "fmt" "math/rand" @@ -19,7 +20,9 @@ import ( porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" + "github.com/cosmos/interchain-security/x/ccv/consumer/client/cli" "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" + consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" ) @@ -71,6 +74,10 @@ func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Rout // RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the ibc-consumer module. // TODO func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + err := consumertypes.RegisterQueryHandlerClient(context.Background(), mux, consumertypes.NewQueryClient(clientCtx)) + if err != nil { + panic(err) + } } // GetTxCmd implements AppModuleBasic interface @@ -82,7 +89,7 @@ func (AppModuleBasic) GetTxCmd() *cobra.Command { // GetQueryCmd implements AppModuleBasic interface // TODO func (AppModuleBasic) GetQueryCmd() *cobra.Command { - return nil + return cli.NewQueryCmd() } // AppModule represents the AppModule for this module @@ -121,6 +128,7 @@ func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { // RegisterServices registers module services. // TODO func (am AppModule) RegisterServices(cfg module.Configurator) { + consumertypes.RegisterQueryServer(cfg.QueryServer(), am.keeper) } // InitGenesis performs genesis initialization for the consumer module. It returns diff --git a/x/ccv/consumer/types/consumer.pb.go b/x/ccv/consumer/types/consumer.pb.go index f6a55d06c0..8def5aad90 100644 --- a/x/ccv/consumer/types/consumer.pb.go +++ b/x/ccv/consumer/types/consumer.pb.go @@ -10,16 +10,20 @@ import ( types1 "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" _ "github.com/regen-network/cosmos-proto" + _ "google.golang.org/protobuf/types/known/durationpb" io "io" math "math" math_bits "math/bits" + time "time" ) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +var _ = time.Kitchen // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. @@ -29,8 +33,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Params defines the parameters for CCV consumer module type Params struct { - // TODO: Remove enabled flag and find a better way to setup e2e tests - // See: https://github.com/cosmos/interchain-security/issues/339 + // TODO: Remove enabled flag and find a better way to setup e2e tests + // See: https://github.com/cosmos/interchain-security/issues/339 Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` /////////////////////// // Distribution Params @@ -44,6 +48,21 @@ type Params struct { // provider handshake procedure. DistributionTransmissionChannel string `protobuf:"bytes,3,opt,name=distribution_transmission_channel,json=distributionTransmissionChannel,proto3" json:"distribution_transmission_channel,omitempty"` ProviderFeePoolAddrStr string `protobuf:"bytes,4,opt,name=provider_fee_pool_addr_str,json=providerFeePoolAddrStr,proto3" json:"provider_fee_pool_addr_str,omitempty"` + // Sent CCV related IBC packets will timeout after this duration + CcvTimeoutPeriod time.Duration `protobuf:"bytes,5,opt,name=ccv_timeout_period,json=ccvTimeoutPeriod,proto3,stdduration" json:"ccv_timeout_period"` + // Sent transfer related IBC packets will timeout after this duration + TransferTimeoutPeriod time.Duration `protobuf:"bytes,6,opt,name=transfer_timeout_period,json=transferTimeoutPeriod,proto3,stdduration" json:"transfer_timeout_period"` + // The fraction of tokens allocated to the consumer redistribution address + // during distribution events. The fraction is a string representing a + // decimal number. For example "0.75" would represent 75%. + ConsumerRedistributionFraction string `protobuf:"bytes,7,opt,name=consumer_redistribution_fraction,json=consumerRedistributionFraction,proto3" json:"consumer_redistribution_fraction,omitempty"` + // The number of historical info entries to persist in store. + // This param is a part of the cosmos sdk staking module. In the case of + // a ccv enabled consumer chain, the ccv module acts as the staking module. + HistoricalEntries int64 `protobuf:"varint,8,opt,name=historical_entries,json=historicalEntries,proto3" json:"historical_entries,omitempty"` + // Unbonding period for the consumer, + // which should be smaller than that of the provider in general. + UnbondingPeriod time.Duration `protobuf:"bytes,9,opt,name=unbonding_period,json=unbondingPeriod,proto3,stdduration" json:"unbonding_period"` } func (m *Params) Reset() { *m = Params{} } @@ -107,6 +126,41 @@ func (m *Params) GetProviderFeePoolAddrStr() string { return "" } +func (m *Params) GetCcvTimeoutPeriod() time.Duration { + if m != nil { + return m.CcvTimeoutPeriod + } + return 0 +} + +func (m *Params) GetTransferTimeoutPeriod() time.Duration { + if m != nil { + return m.TransferTimeoutPeriod + } + return 0 +} + +func (m *Params) GetConsumerRedistributionFraction() string { + if m != nil { + return m.ConsumerRedistributionFraction + } + return "" +} + +func (m *Params) GetHistoricalEntries() int64 { + if m != nil { + return m.HistoricalEntries + } + return 0 +} + +func (m *Params) GetUnbondingPeriod() time.Duration { + if m != nil { + return m.UnbondingPeriod + } + return 0 +} + // LastTransmissionBlockHeight is the last time validator holding // pools were transmitted to the provider chain type LastTransmissionBlockHeight struct { @@ -326,46 +380,55 @@ func init() { } var fileDescriptor_5b27a82b276e7f93 = []byte{ - // 614 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcd, 0x6e, 0xd3, 0x4c, - 0x14, 0x8d, 0xbf, 0xf4, 0x0b, 0x65, 0x5a, 0x58, 0x98, 0xa8, 0x84, 0x22, 0xa5, 0xa9, 0xa9, 0x50, - 0x24, 0xd4, 0xb1, 0x92, 0x8a, 0x4d, 0x77, 0x4d, 0xaa, 0x8a, 0x3f, 0x89, 0xc8, 0xad, 0x58, 0xb0, - 0xb1, 0xc6, 0xe3, 0x5b, 0x67, 0x14, 0x7b, 0xc6, 0xcc, 0x8c, 0x0d, 0x7e, 0x0b, 0xf6, 0xbc, 0x00, - 0x0f, 0xc0, 0x43, 0x54, 0xac, 0xba, 0x64, 0x55, 0xa1, 0xf6, 0x0d, 0xd8, 0xb2, 0x41, 0xfe, 0x0b, - 0x46, 0x22, 0x12, 0xbb, 0x7b, 0x34, 0xe7, 0x1c, 0xcf, 0xdc, 0x73, 0xaf, 0xd1, 0x98, 0x71, 0x0d, - 0x92, 0xce, 0x09, 0xe3, 0xae, 0x02, 0x9a, 0x48, 0xa6, 0x33, 0x9b, 0xd2, 0xd4, 0xa6, 0x82, 0xab, - 0x24, 0x02, 0x69, 0xa7, 0xa3, 0x65, 0x8d, 0x63, 0x29, 0xb4, 0x30, 0x1f, 0xfd, 0x45, 0x83, 0x29, - 0x4d, 0xf1, 0x92, 0x97, 0x8e, 0xb6, 0xf7, 0x56, 0x19, 0xe7, 0x7e, 0x34, 0x2d, 0xad, 0xb6, 0x1f, - 0x04, 0x42, 0x04, 0x21, 0xd8, 0x05, 0xf2, 0x92, 0x73, 0x9b, 0xf0, 0xac, 0x3a, 0xda, 0xa3, 0x42, - 0x45, 0x42, 0xd9, 0x4a, 0x93, 0x05, 0xe3, 0x81, 0x9d, 0x8e, 0x3c, 0xd0, 0x64, 0x54, 0xe3, 0x8a, - 0xd5, 0x0d, 0x44, 0x20, 0x8a, 0xd2, 0xce, 0xab, 0xda, 0xb6, 0xd4, 0xba, 0xe5, 0x41, 0x09, 0xca, - 0x23, 0xeb, 0xa7, 0x81, 0x3a, 0x33, 0x22, 0x49, 0xa4, 0xcc, 0x1e, 0xba, 0x05, 0x9c, 0x78, 0x21, - 0xf8, 0x3d, 0x63, 0x60, 0x0c, 0xd7, 0x9d, 0x1a, 0x9a, 0xaf, 0xd1, 0x9e, 0x17, 0x0a, 0xba, 0x50, - 0x6e, 0x0c, 0xd2, 0xf5, 0x99, 0xd2, 0x92, 0x79, 0x89, 0x66, 0x82, 0xbb, 0x5a, 0x12, 0xae, 0x22, - 0xa6, 0x14, 0x13, 0xbc, 0xf7, 0xdf, 0xc0, 0x18, 0xb6, 0x9d, 0xdd, 0x92, 0x3b, 0x03, 0x79, 0xdc, - 0x60, 0x9e, 0x35, 0x88, 0xe6, 0x0b, 0xb4, 0xbb, 0xd2, 0xc5, 0xa5, 0x73, 0xc2, 0x39, 0x84, 0xbd, - 0xf6, 0xc0, 0x18, 0xde, 0x76, 0x76, 0xfc, 0x15, 0x26, 0xd3, 0x92, 0x66, 0x1e, 0xa2, 0xed, 0x58, - 0x8a, 0x94, 0xf9, 0x20, 0xdd, 0x73, 0x00, 0x37, 0x16, 0x22, 0x74, 0x89, 0xef, 0x4b, 0x57, 0x69, - 0xd9, 0x5b, 0x2b, 0x4c, 0xb6, 0x6a, 0xc6, 0x09, 0xc0, 0x4c, 0x88, 0xf0, 0xc8, 0xf7, 0xe5, 0xa9, - 0x96, 0xd6, 0x53, 0xf4, 0xf0, 0x15, 0x51, 0xba, 0x69, 0x3b, 0xc9, 0x2f, 0xff, 0x0c, 0x58, 0x30, - 0xd7, 0xe6, 0x16, 0xea, 0xcc, 0x8b, 0xaa, 0x68, 0x48, 0xdb, 0xa9, 0x90, 0xf5, 0xd9, 0x40, 0xf7, - 0xa6, 0x52, 0x28, 0x35, 0xcd, 0xf3, 0x7c, 0x43, 0x42, 0xe6, 0x13, 0x2d, 0x64, 0xde, 0xc1, 0xfc, - 0xc3, 0xa0, 0x54, 0x21, 0xd8, 0x74, 0x6a, 0x68, 0x76, 0xd1, 0xff, 0xb1, 0x78, 0x0f, 0xb2, 0x6a, - 0x51, 0x09, 0x4c, 0x82, 0x3a, 0x71, 0xe2, 0x2d, 0x20, 0x2b, 0xde, 0xba, 0x31, 0xee, 0xe2, 0x32, - 0x7f, 0x5c, 0xe7, 0x8f, 0x8f, 0x78, 0x36, 0x39, 0xf8, 0x71, 0xb5, 0x73, 0x3f, 0x23, 0x51, 0x78, - 0x68, 0xe5, 0x13, 0x05, 0x5c, 0x25, 0xca, 0x2d, 0x75, 0xd6, 0xd7, 0x2f, 0xfb, 0xdd, 0x2a, 0x4f, - 0x2a, 0xb3, 0x58, 0x0b, 0x3c, 0x4b, 0xbc, 0x97, 0x90, 0x39, 0x95, 0xb1, 0xf5, 0xc9, 0x40, 0x9b, - 0xa7, 0x21, 0x51, 0x73, 0x07, 0xde, 0x25, 0xa0, 0xb4, 0x39, 0x45, 0x9d, 0x98, 0xd0, 0x05, 0x94, - 0x6f, 0xda, 0x18, 0x3f, 0xc1, 0xab, 0xc6, 0x37, 0x1d, 0xe1, 0x42, 0x39, 0x2b, 0xe8, 0xc7, 0x44, - 0x13, 0xa7, 0x92, 0x9a, 0x27, 0x08, 0x31, 0x7e, 0x2e, 0x09, 0xd5, 0x75, 0xec, 0x77, 0xc7, 0x8f, - 0x71, 0x75, 0x91, 0x7a, 0x22, 0xab, 0x09, 0xc5, 0xcf, 0x97, 0xcc, 0xb3, 0x2c, 0x06, 0xa7, 0xa1, - 0xb4, 0x7c, 0x74, 0xa7, 0x79, 0x39, 0x65, 0x9e, 0xa2, 0x75, 0x59, 0xd5, 0x3d, 0x63, 0xd0, 0x1e, - 0x6e, 0x8c, 0x47, 0xf8, 0x1f, 0xd6, 0x0b, 0x37, 0x5d, 0x26, 0x6b, 0x17, 0x57, 0x3b, 0x2d, 0x67, - 0x69, 0x34, 0x39, 0xbb, 0xb8, 0xee, 0x1b, 0x97, 0xd7, 0x7d, 0xe3, 0xfb, 0x75, 0xdf, 0xf8, 0x78, - 0xd3, 0x6f, 0x5d, 0xde, 0xf4, 0x5b, 0xdf, 0x6e, 0xfa, 0xad, 0xb7, 0x87, 0x01, 0xd3, 0xf3, 0xc4, - 0xc3, 0x54, 0x44, 0xd5, 0x5a, 0xd8, 0xbf, 0xbf, 0xb6, 0xbf, 0xdc, 0xd3, 0x0f, 0x7f, 0xfe, 0x02, - 0x74, 0x16, 0x83, 0xf2, 0x3a, 0x45, 0x48, 0x07, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x91, 0xef, - 0xc0, 0x3c, 0x33, 0x04, 0x00, 0x00, + // 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, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -388,6 +451,42 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + n1, err1 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.UnbondingPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.UnbondingPeriod):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintConsumer(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x4a + if m.HistoricalEntries != 0 { + i = encodeVarintConsumer(dAtA, i, uint64(m.HistoricalEntries)) + i-- + dAtA[i] = 0x40 + } + if len(m.ConsumerRedistributionFraction) > 0 { + i -= len(m.ConsumerRedistributionFraction) + copy(dAtA[i:], m.ConsumerRedistributionFraction) + i = encodeVarintConsumer(dAtA, i, uint64(len(m.ConsumerRedistributionFraction))) + i-- + dAtA[i] = 0x3a + } + n2, err2 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.TransferTimeoutPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.TransferTimeoutPeriod):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintConsumer(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x32 + n3, err3 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.CcvTimeoutPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.CcvTimeoutPeriod):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintConsumer(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0x2a if len(m.ProviderFeePoolAddrStr) > 0 { i -= len(m.ProviderFeePoolAddrStr) copy(dAtA[i:], m.ProviderFeePoolAddrStr) @@ -603,6 +702,19 @@ func (m *Params) Size() (n int) { if l > 0 { n += 1 + l + sovConsumer(uint64(l)) } + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.CcvTimeoutPeriod) + n += 1 + l + sovConsumer(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.TransferTimeoutPeriod) + n += 1 + l + sovConsumer(uint64(l)) + l = len(m.ConsumerRedistributionFraction) + if l > 0 { + n += 1 + l + sovConsumer(uint64(l)) + } + if m.HistoricalEntries != 0 { + n += 1 + sovConsumer(uint64(m.HistoricalEntries)) + } + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.UnbondingPeriod) + n += 1 + l + sovConsumer(uint64(l)) return n } @@ -807,6 +919,156 @@ func (m *Params) Unmarshal(dAtA []byte) error { } m.ProviderFeePoolAddrStr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CcvTimeoutPeriod", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConsumer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(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 err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.CcvTimeoutPeriod, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TransferTimeoutPeriod", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConsumer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(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 err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.TransferTimeoutPeriod, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsumerRedistributionFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConsumer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthConsumer + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthConsumer + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConsumerRedistributionFraction = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HistoricalEntries", wireType) + } + m.HistoricalEntries = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConsumer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HistoricalEntries |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UnbondingPeriod", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowConsumer + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(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 err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.UnbondingPeriod, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipConsumer(dAtA[iNdEx:]) diff --git a/x/ccv/consumer/types/genesis.go b/x/ccv/consumer/types/genesis.go index 0e2a0b2557..95dbebad48 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,7 +21,6 @@ func NewInitialGenesisState(cs *ibctmtypes.ClientState, consState *ibctmtypes.Co ProviderClientState: cs, ProviderConsensusState: consState, InitialValSet: initValSet, - PendingSlashRequests: slashRequests, } } @@ -30,7 +29,9 @@ func NewRestartGenesisState(clientID, channelID string, maturingPackets []MaturingVSCPacket, initValSet []abci.ValidatorUpdate, heightToValsetUpdateIDs []HeightToValsetUpdateID, + pendingSlashRequests SlashRequests, outstandingDowntimes []OutstandingDowntime, + lastTransBlockHeight LastTransmissionBlockHeight, params Params, ) *GenesisState { @@ -42,7 +43,9 @@ func NewRestartGenesisState(clientID, channelID string, NewChain: false, InitialValSet: initValSet, HeightToValsetUpdateId: heightToValsetUpdateIDs, + PendingSlashRequests: pendingSlashRequests, OutstandingDowntimeSlashing: outstandingDowntimes, + LastTransmissionBlockHeight: lastTransBlockHeight, } } @@ -62,6 +65,9 @@ func (gs GenesisState) Validate() error { if len(gs.InitialValSet) == 0 { return sdkerrors.Wrap(ccv.ErrInvalidGenesis, "initial validator set is empty") } + if err := gs.Params.Validate(); err != nil { + return err + } if gs.NewChain { if gs.ProviderClientState == nil { @@ -85,6 +91,9 @@ func (gs GenesisState) Validate() error { if len(gs.MaturingPackets) != 0 { return sdkerrors.Wrap(ccv.ErrInvalidGenesis, "maturing packets must be empty for new chain") } + if gs.LastTransmissionBlockHeight.Height != 0 { + return sdkerrors.Wrap(ccv.ErrInvalidGenesis, "last transmission block height must be empty for new chain") + } // ensure that initial validator set is same as initial consensus state on provider client. // this will be verified by provider module on channel handshake. @@ -101,9 +110,7 @@ func (gs GenesisState) Validate() error { if gs.ProviderClientId == "" { return sdkerrors.Wrap(ccv.ErrInvalidGenesis, "provider client id must be set for a restarting consumer genesis state") } - if gs.ProviderChannelId == "" { - return sdkerrors.Wrap(ccv.ErrInvalidGenesis, "provider channel id must be set for a restarting consumer genesis state") - } + if gs.ProviderClientState != nil || gs.ProviderConsensusState != nil { return sdkerrors.Wrap(ccv.ErrInvalidGenesis, "provider client state and consensus states must be nil for a restarting genesis state") } diff --git a/x/ccv/consumer/types/genesis.pb.go b/x/ccv/consumer/types/genesis.pb.go index aa66509507..7a45a91d03 100644 --- a/x/ccv/consumer/types/genesis.pb.go +++ b/x/ccv/consumer/types/genesis.pb.go @@ -38,7 +38,7 @@ type GenesisState struct { ProviderConsensusState *types.ConsensusState `protobuf:"bytes,6,opt,name=provider_consensus_state,json=providerConsensusState,proto3" json:"provider_consensus_state,omitempty"` // MaturingPackets nil on new chain, filled on restart. MaturingPackets []MaturingVSCPacket `protobuf:"bytes,7,rep,name=maturing_packets,json=maturingPackets,proto3" json:"maturing_packets"` - // InitialValset filled in on new chain, manually filled in on restart. + // InitialValset filled in on new chain and on restart. InitialValSet []types1.ValidatorUpdate `protobuf:"bytes,8,rep,name=initial_val_set,json=initialValSet,proto3" json:"initial_val_set"` // HeightToValsetUpdateId nil on new chain, filled on restart. HeightToValsetUpdateId []HeightToValsetUpdateID `protobuf:"bytes,9,rep,name=height_to_valset_update_id,json=heightToValsetUpdateId,proto3" json:"height_to_valset_update_id"` @@ -46,6 +46,8 @@ type GenesisState struct { 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"` + // LastTransmissionBlockHeight nil on new chain, filled on restart. + LastTransmissionBlockHeight LastTransmissionBlockHeight `protobuf:"bytes,12,opt,name=last_transmission_block_height,json=lastTransmissionBlockHeight,proto3" json:"last_transmission_block_height"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -158,8 +160,15 @@ func (m *GenesisState) GetPendingSlashRequests() SlashRequests { return SlashRequests{} } -// UnbondingSequence defines the genesis information for each unbonding packet -// sequence. +func (m *GenesisState) GetLastTransmissionBlockHeight() LastTransmissionBlockHeight { + if m != nil { + return m.LastTransmissionBlockHeight + } + return LastTransmissionBlockHeight{} +} + +// MaturingVSCPacket defines the genesis information for the +// unbonding VSC packet type MaturingVSCPacket struct { VscId uint64 `protobuf:"varint,1,opt,name=vscId,proto3" json:"vscId,omitempty"` MaturityTime uint64 `protobuf:"varint,2,opt,name=maturity_time,json=maturityTime,proto3" json:"maturity_time,omitempty"` @@ -324,53 +333,56 @@ 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, + // 774 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x4d, 0x6f, 0x2b, 0x35, + 0x14, 0xcd, 0xf0, 0xf2, 0x42, 0xe2, 0xf6, 0xf1, 0xfa, 0xdc, 0x12, 0x0d, 0x8d, 0x08, 0x21, 0xdd, + 0x44, 0x02, 0x66, 0x94, 0x20, 0x21, 0x04, 0x12, 0x82, 0xb6, 0x12, 0x44, 0x82, 0x52, 0x4d, 0xd2, + 0x2c, 0xba, 0xb1, 0x1c, 0x8f, 0x35, 0x63, 0x75, 0xc6, 0x0e, 0x63, 0xcf, 0x94, 0x2e, 0xd8, 0xb0, + 0x65, 0xc3, 0xcf, 0xea, 0xb2, 0x4b, 0xc4, 0x02, 0xa1, 0xf6, 0x8f, 0xa0, 0xb1, 0x3d, 0xf9, 0xa0, + 0x41, 0x64, 0x67, 0xfb, 0xde, 0x73, 0xce, 0xfd, 0xf2, 0x05, 0x43, 0xc6, 0x15, 0xcd, 0x48, 0x8c, + 0x19, 0x47, 0x92, 0x92, 0x3c, 0x63, 0xea, 0xce, 0x27, 0xa4, 0xf0, 0x89, 0xe0, 0x32, 0x4f, 0x69, + 0xe6, 0x17, 0x43, 0x3f, 0xa2, 0x9c, 0x4a, 0x26, 0xbd, 0x45, 0x26, 0x94, 0x80, 0x27, 0x5b, 0x20, + 0x1e, 0x21, 0x85, 0x57, 0x41, 0xbc, 0x62, 0x78, 0xec, 0xb3, 0x39, 0xf1, 0x13, 0x16, 0xc5, 0x8a, + 0x24, 0x8c, 0x72, 0x25, 0x7d, 0x45, 0x79, 0x48, 0xb3, 0x94, 0x71, 0x55, 0x52, 0xae, 0x6e, 0x86, + 0xf5, 0xf8, 0xc3, 0x12, 0x40, 0x44, 0x46, 0x7d, 0x12, 0x63, 0xce, 0x69, 0x52, 0x7a, 0xd9, 0xa3, + 0x75, 0x39, 0x8a, 0x44, 0x24, 0xf4, 0xd1, 0x2f, 0x4f, 0xf6, 0x75, 0xb4, 0x4b, 0x06, 0xcb, 0xd0, + 0x0c, 0xa6, 0xb3, 0x16, 0x0c, 0x9e, 0x13, 0xe6, 0xab, 0xbb, 0x05, 0xb5, 0xf9, 0xf5, 0xff, 0x6c, + 0x82, 0xfd, 0x6f, 0x4d, 0xc6, 0x13, 0x85, 0x15, 0x85, 0x63, 0xd0, 0x58, 0xe0, 0x0c, 0xa7, 0xd2, + 0x75, 0x7a, 0xce, 0x60, 0x6f, 0xf4, 0x91, 0xb7, 0x43, 0x05, 0xbc, 0x4b, 0x0d, 0x39, 0xad, 0xdf, + 0xff, 0xf5, 0x41, 0x2d, 0xb0, 0x04, 0xf0, 0x63, 0x00, 0x17, 0x99, 0x28, 0x58, 0x48, 0x33, 0x64, + 0x0a, 0x83, 0x58, 0xe8, 0xbe, 0xd5, 0x73, 0x06, 0xad, 0xe0, 0xa0, 0xb2, 0x9c, 0x69, 0xc3, 0x38, + 0x84, 0x1e, 0x38, 0x5c, 0x79, 0x9b, 0x52, 0x94, 0xee, 0x2f, 0xb4, 0xfb, 0x9b, 0xa5, 0xbb, 0xb1, + 0x8c, 0x43, 0xd8, 0x01, 0x2d, 0x4e, 0x6f, 0x91, 0x0e, 0xcc, 0xad, 0xf7, 0x9c, 0x41, 0x33, 0x68, + 0x72, 0x7a, 0x7b, 0x56, 0xde, 0x21, 0x02, 0xef, 0xfe, 0x5b, 0x5a, 0x96, 0xe9, 0xb9, 0x2f, 0xab, + 0xa4, 0xe6, 0xc4, 0x5b, 0xef, 0x98, 0xb7, 0xd6, 0xa3, 0x62, 0xe8, 0x99, 0xa8, 0x74, 0x45, 0x82, + 0xc3, 0xcd, 0x50, 0x4d, 0x99, 0x62, 0xe0, 0xae, 0x04, 0x04, 0x97, 0x94, 0xcb, 0x5c, 0x5a, 0x8d, + 0x86, 0xd6, 0xf0, 0xfe, 0x57, 0xa3, 0x82, 0x19, 0x99, 0xf6, 0x52, 0x66, 0xe3, 0x1d, 0x46, 0xe0, + 0x20, 0xc5, 0x2a, 0xcf, 0x18, 0x8f, 0xd0, 0x02, 0x93, 0x1b, 0xaa, 0xa4, 0xfb, 0x76, 0xef, 0xc5, + 0x60, 0x6f, 0xf4, 0xd9, 0x4e, 0xad, 0xf9, 0xc1, 0x82, 0x67, 0x93, 0xb3, 0x4b, 0x0d, 0xb7, 0x5d, + 0x7a, 0x5d, 0xb1, 0x9a, 0x57, 0x09, 0x2f, 0xc0, 0x6b, 0xc6, 0x99, 0x62, 0x38, 0x41, 0x05, 0x4e, + 0x90, 0xa4, 0xca, 0x6d, 0x6a, 0x9d, 0xde, 0x7a, 0xe0, 0xe5, 0x04, 0x79, 0x33, 0x9c, 0xb0, 0x10, + 0x2b, 0x91, 0x5d, 0x2d, 0x42, 0xac, 0xa8, 0x65, 0x7c, 0x65, 0xe1, 0x33, 0x9c, 0x4c, 0xa8, 0x82, + 0xbf, 0x80, 0xe3, 0x98, 0x96, 0xe9, 0x23, 0x25, 0x4a, 0x46, 0x49, 0x15, 0xca, 0xb5, 0x7f, 0xd9, + 0xd7, 0x96, 0xa6, 0xfe, 0x72, 0xa7, 0x14, 0xbe, 0xd3, 0x34, 0x53, 0x31, 0xd3, 0x24, 0x46, 0x73, + 0x7c, 0x6e, 0x55, 0xdb, 0xf1, 0x36, 0x6b, 0x08, 0x7f, 0x75, 0xc0, 0xfb, 0x22, 0x57, 0x52, 0x61, + 0x1e, 0x96, 0xb5, 0x0b, 0xc5, 0x2d, 0x57, 0x2c, 0xa5, 0x48, 0x26, 0x58, 0xc6, 0x8c, 0x47, 0x2e, + 0xd0, 0x21, 0x7c, 0xbe, 0x53, 0x08, 0x3f, 0xae, 0x98, 0xce, 0x2d, 0x91, 0xd5, 0xef, 0x88, 0xe7, + 0xa6, 0x89, 0x95, 0x80, 0x1c, 0xb4, 0x17, 0xd4, 0xe8, 0x6b, 0x59, 0x94, 0xd1, 0x9f, 0x72, 0x2a, + 0x95, 0x74, 0xf7, 0xf4, 0x90, 0x8c, 0x76, 0x12, 0xd7, 0x74, 0x81, 0x45, 0x5a, 0xd9, 0x23, 0xcb, + 0xbb, 0x61, 0x83, 0xbf, 0x39, 0xa0, 0x9b, 0x60, 0xa9, 0x90, 0xca, 0x30, 0x97, 0x29, 0x93, 0x92, + 0x09, 0x8e, 0xe6, 0x89, 0x20, 0x37, 0xc8, 0xd4, 0xc9, 0xdd, 0xd7, 0xc2, 0x5f, 0xef, 0x24, 0xfc, + 0x3d, 0x96, 0x6a, 0xba, 0xc6, 0x74, 0x5a, 0x12, 0x99, 0x6e, 0x54, 0xd9, 0x27, 0xff, 0xed, 0xd2, + 0xbf, 0x00, 0x6f, 0x9e, 0x4d, 0x1f, 0x3c, 0x02, 0x2f, 0x0b, 0x49, 0xc6, 0xa1, 0xde, 0x2f, 0xf5, + 0xc0, 0x5c, 0xe0, 0x09, 0x78, 0x65, 0xe6, 0x51, 0xdd, 0xa1, 0xb2, 0x82, 0x7a, 0x4d, 0xd4, 0x83, + 0xfd, 0xea, 0x71, 0xca, 0x52, 0xda, 0xbf, 0x06, 0xed, 0xed, 0xa3, 0x00, 0xdb, 0xa0, 0x61, 0xd3, + 0x33, 0xac, 0xf6, 0x06, 0x07, 0xe0, 0xe0, 0xd9, 0xe4, 0x19, 0xe6, 0x77, 0x8a, 0x8d, 0x71, 0xe9, + 0x5f, 0x81, 0xc3, 0x2d, 0x3d, 0x86, 0x5f, 0x81, 0x4e, 0x51, 0x0d, 0xfb, 0xda, 0x47, 0xc7, 0x61, + 0x98, 0x51, 0x69, 0x76, 0x64, 0x2b, 0x78, 0x6f, 0xe9, 0xb2, 0xfc, 0xbb, 0xdf, 0x18, 0x87, 0xd3, + 0xe9, 0xfd, 0x63, 0xd7, 0x79, 0x78, 0xec, 0x3a, 0x7f, 0x3f, 0x76, 0x9d, 0xdf, 0x9f, 0xba, 0xb5, + 0x87, 0xa7, 0x6e, 0xed, 0x8f, 0xa7, 0x6e, 0xed, 0xfa, 0x8b, 0x88, 0xa9, 0x38, 0x9f, 0x7b, 0x44, + 0xa4, 0x3e, 0x11, 0x32, 0x15, 0xd2, 0x5f, 0xb5, 0xe4, 0x93, 0xe5, 0x72, 0xff, 0x79, 0x73, 0xbd, + 0xeb, 0xdd, 0x3d, 0x6f, 0xe8, 0xe5, 0xfd, 0xe9, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xd1, 0x51, + 0x43, 0x8f, 0xd1, 0x06, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -393,6 +405,16 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.LastTransmissionBlockHeight.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 { size, err := m.PendingSlashRequests.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -680,6 +702,8 @@ func (m *GenesisState) Size() (n int) { } l = m.PendingSlashRequests.Size() n += 1 + l + sovGenesis(uint64(l)) + l = m.LastTransmissionBlockHeight.Size() + n += 1 + l + sovGenesis(uint64(l)) return n } @@ -1119,6 +1143,39 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastTransmissionBlockHeight", 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.LastTransmissionBlockHeight.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 3408c81ccb..3dc3508c78 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, }, { @@ -94,6 +94,7 @@ func TestValidateInitialGenesisState(t *testing.T) { nil, nil, types.SlashRequests{}, + types.LastTransmissionBlockHeight{}, }, true, }, @@ -111,6 +112,7 @@ func TestValidateInitialGenesisState(t *testing.T) { nil, nil, types.SlashRequests{}, + types.LastTransmissionBlockHeight{}, }, true, }, @@ -128,12 +130,31 @@ func TestValidateInitialGenesisState(t *testing.T) { nil, nil, types.SlashRequests{}, + types.LastTransmissionBlockHeight{}, + }, + true, + }, + { + "invalid new consumer genesis state: non-empty last transmission packet", + &types.GenesisState{ + params, + "", + "", + true, + cs, + consensusState, + nil, + valUpdates, + nil, + nil, + types.SlashRequests{}, + types.LastTransmissionBlockHeight{Height: 1}, }, 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,7 +162,23 @@ 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.NewParams( + true, + types.DefaultBlocksPerDistributionTransmission, + "", + "", + 0, // CCV timeout period cannot be 0 + types.DefaultTransferTimeoutPeriod, + types.DefaultConsumerRedistributeFrac, + types.DefaultHistoricalEntries, + types.DefaultConsumerUnbondingPeriod, + )), true, }, } @@ -182,7 +219,7 @@ func TestValidateRestartGenesisState(t *testing.T) { }{ { "valid restart consumer genesis state: empty maturing packets", - types.NewRestartGenesisState("ccvclient", "ccvchannel", nil, valUpdates, nil, nil, params), + types.NewRestartGenesisState("ccvclient", "ccvchannel", nil, valUpdates, nil, types.SlashRequests{}, nil, types.LastTransmissionBlockHeight{}, params), false, }, { @@ -191,31 +228,26 @@ func TestValidateRestartGenesisState(t *testing.T) { {1, uint64(time.Now().UnixNano())}, {3, uint64(time.Now().UnixNano())}, {5, uint64(time.Now().UnixNano())}, - }, valUpdates, nil, nil, params), + }, valUpdates, nil, types.SlashRequests{}, nil, types.LastTransmissionBlockHeight{}, params), false, }, { "invalid restart consumer genesis state: channel id is empty", - types.NewRestartGenesisState("", "ccvchannel", nil, valUpdates, nil, nil, params), - true, - }, - { - "invalid restart consumer genesis state: channel id is empty", - types.NewRestartGenesisState("ccvclient", "", nil, valUpdates, nil, nil, params), + types.NewRestartGenesisState("", "ccvchannel", nil, valUpdates, nil, types.SlashRequests{}, nil, types.LastTransmissionBlockHeight{}, params), true, }, { "invalid restart consumer genesis state: maturing packet vscId is invalid", types.NewRestartGenesisState("ccvclient", "ccvchannel", []types.MaturingVSCPacket{ {0, uint64(time.Now().UnixNano())}, - }, valUpdates, nil, nil, params), + }, valUpdates, nil, types.SlashRequests{}, nil, types.LastTransmissionBlockHeight{}, params), true, }, { "invalid restart consumer genesis state: maturing packet time is invalid", types.NewRestartGenesisState("ccvclient", "ccvchannel", []types.MaturingVSCPacket{ {1, 0}, - }, valUpdates, nil, nil, params), + }, valUpdates, nil, types.SlashRequests{}, nil, types.LastTransmissionBlockHeight{}, params), true, }, { @@ -232,6 +264,7 @@ func TestValidateRestartGenesisState(t *testing.T) { nil, nil, types.SlashRequests{}, + types.LastTransmissionBlockHeight{}, }, true, }, @@ -249,12 +282,29 @@ func TestValidateRestartGenesisState(t *testing.T) { nil, nil, types.SlashRequests{}, + types.LastTransmissionBlockHeight{}, }, true, }, { "invalid restart consumer genesis state: nil initial validator set", - types.NewRestartGenesisState("ccvclient", "ccvchannel", nil, nil, nil, nil, params), + types.NewRestartGenesisState("ccvclient", "ccvchannel", nil, nil, nil, types.SlashRequests{}, nil, types.LastTransmissionBlockHeight{}, params), + true, + }, + { + "invalid restart consumer genesis state: invalid params", + types.NewRestartGenesisState("ccvclient", "ccvchannel", nil, valUpdates, nil, types.SlashRequests{}, nil, types.LastTransmissionBlockHeight{}, + types.NewParams( + true, + types.DefaultBlocksPerDistributionTransmission, + "", + "", + 0, // CCV timeout period cannot be 0 + types.DefaultTransferTimeoutPeriod, + types.DefaultConsumerRedistributeFrac, + types.DefaultHistoricalEntries, + types.DefaultConsumerUnbondingPeriod, + )), true, }, } diff --git a/x/ccv/consumer/types/keys.go b/x/ccv/consumer/types/keys.go index a94006840a..422cbd1528 100644 --- a/x/ccv/consumer/types/keys.go +++ b/x/ccv/consumer/types/keys.go @@ -19,9 +19,6 @@ const ( // QuerierRoute is the querier route for IBC consumer QuerierRoute = ModuleName - // HistoricalEntries is set to 10000 like the staking module parameter DefaultHistoricalEntries - HistoricalEntries uint32 = 10000 - // ConsumerRedistributeName the root string for the consumer-redistribution account address ConsumerRedistributeName = "cons_redistribute" diff --git a/x/ccv/consumer/types/params.go b/x/ccv/consumer/types/params.go index 2b6e11ea00..68d586f3c6 100644 --- a/x/ccv/consumer/types/params.go +++ b/x/ccv/consumer/types/params.go @@ -1,19 +1,54 @@ package types import ( - "fmt" + fmt "fmt" + time "time" + sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" ) -// about 2 hr at 7.6 seconds per blocks -const DefaultBlocksPerDistributionTransmission = 1000 +const ( + // about 2 hr at 7.6 seconds per blocks + DefaultBlocksPerDistributionTransmission = 1000 + // Default transfer timeout period is 1 hour, less than the default blocks + // per dist transmission * average block time. + // Since IBC token transfers do not have to be in order, it could be easier + // to reason about the distribution protocol if the previous reward times out + // before sending the next one. Note that on timeout, the transferred funds are + // added back to the pool, so the next transfer will include them as well. + DefaultTransferTimeoutPeriod = time.Hour + + // The default fraction of tokens allocated to the consumer redistribution address + // during distribution events. The fraction is a string representing a + // decimal number. For example "0.75" would represent 75%. + DefaultConsumerRedistributeFrac = "0.75" + + // Default number of historical info entries to persist in store. + // We use the same default as the staking module, but use a signed integer + // so that negative values can be caught during parameter validation in a readable way, + // (and for consistency with other protobuf schemas defined for ccv). + DefaultHistoricalEntries = int64(stakingtypes.DefaultHistoricalEntries) + + // In general, the default unbonding period on the consumer is one day less + // than the default unbonding period on the provider, where the provider uses + // the staking module default. + DefaultConsumerUnbondingPeriod = stakingtypes.DefaultUnbondingTime - 24*time.Hour +) + +// Reflection based keys for params subspace var ( KeyEnabled = []byte("Enabled") KeyBlocksPerDistributionTransmission = []byte("BlocksPerDistributionTransmission") KeyDistributionTransmissionChannel = []byte("DistributionTransmissionChannel") KeyProviderFeePoolAddrStr = []byte("ProviderFeePoolAddrStr") + KeyTransferTimeoutPeriod = []byte("TransferTimeoutPeriod") + KeyConsumerRedistributionFrac = []byte("ConsumerRedistributionFraction") + KeyHistoricalEntries = []byte("HistoricalEntries") + KeyConsumerUnbondingPeriod = []byte("UnbondingPeriod") ) // ParamKeyTable type declaration for parameters @@ -23,12 +58,20 @@ func ParamKeyTable() paramtypes.KeyTable { // NewParams creates new consumer parameters with provided arguments func NewParams(enabled bool, blocksPerDistributionTransmission int64, - distributionTransmissionChannel, providerFeePoolAddrStr string) Params { + distributionTransmissionChannel, providerFeePoolAddrStr string, + ccvTimeoutPeriod time.Duration, transferTimeoutPeriod time.Duration, + consumerRedistributionFraction string, historicalEntries int64, + consumerUnbondingPeriod time.Duration) Params { return Params{ Enabled: enabled, BlocksPerDistributionTransmission: blocksPerDistributionTransmission, DistributionTransmissionChannel: distributionTransmissionChannel, ProviderFeePoolAddrStr: providerFeePoolAddrStr, + CcvTimeoutPeriod: ccvTimeoutPeriod, + TransferTimeoutPeriod: transferTimeoutPeriod, + ConsumerRedistributionFraction: consumerRedistributionFraction, + HistoricalEntries: historicalEntries, + UnbondingPeriod: consumerUnbondingPeriod, } } @@ -39,44 +82,101 @@ func DefaultParams() Params { DefaultBlocksPerDistributionTransmission, "", "", + ccvtypes.DefaultCCVTimeoutPeriod, + DefaultTransferTimeoutPeriod, + DefaultConsumerRedistributeFrac, + DefaultHistoricalEntries, + DefaultConsumerUnbondingPeriod, ) } // Validate all ccv-consumer module parameters func (p Params) Validate() error { + if err := ccvtypes.ValidateBool(p.Enabled); err != nil { + return err + } + if err := ccvtypes.ValidatePositiveInt64(p.BlocksPerDistributionTransmission); err != nil { + return err + } + if err := validateDistributionTransmissionChannel(p.DistributionTransmissionChannel); err != nil { + return err + } + if err := validateProviderFeePoolAddrStr(p.ProviderFeePoolAddrStr); err != nil { + return err + } + if err := ccvtypes.ValidateDuration(p.CcvTimeoutPeriod); err != nil { + return err + } + if err := ccvtypes.ValidateDuration(p.TransferTimeoutPeriod); err != nil { + return err + } + if err := validateConsumerRedistributionFraction(p.ConsumerRedistributionFraction); err != nil { + return err + } + if err := ccvtypes.ValidatePositiveInt64(p.HistoricalEntries); err != nil { + return err + } + if err := ccvtypes.ValidateDuration(p.UnbondingPeriod); err != nil { + return err + } return nil } // ParamSetPairs implements params.ParamSet func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ - paramtypes.NewParamSetPair(KeyEnabled, p.Enabled, validateBool), + paramtypes.NewParamSetPair(KeyEnabled, p.Enabled, ccvtypes.ValidateBool), paramtypes.NewParamSetPair(KeyBlocksPerDistributionTransmission, - p.BlocksPerDistributionTransmission, validateInt64), + p.BlocksPerDistributionTransmission, ccvtypes.ValidatePositiveInt64), paramtypes.NewParamSetPair(KeyDistributionTransmissionChannel, - p.DistributionTransmissionChannel, validateString), + p.DistributionTransmissionChannel, validateDistributionTransmissionChannel), paramtypes.NewParamSetPair(KeyProviderFeePoolAddrStr, - p.ProviderFeePoolAddrStr, validateString), + p.ProviderFeePoolAddrStr, validateProviderFeePoolAddrStr), + paramtypes.NewParamSetPair(ccvtypes.KeyCCVTimeoutPeriod, + p.CcvTimeoutPeriod, ccvtypes.ValidateDuration), + paramtypes.NewParamSetPair(KeyTransferTimeoutPeriod, + p.TransferTimeoutPeriod, ccvtypes.ValidateDuration), + paramtypes.NewParamSetPair(KeyConsumerRedistributionFrac, + p.ConsumerRedistributionFraction, validateConsumerRedistributionFraction), + paramtypes.NewParamSetPair(KeyHistoricalEntries, + p.HistoricalEntries, ccvtypes.ValidatePositiveInt64), + paramtypes.NewParamSetPair(KeyConsumerUnbondingPeriod, + p.UnbondingPeriod, ccvtypes.ValidateDuration), } } -func validateBool(i interface{}) error { - if _, ok := i.(bool); !ok { - return fmt.Errorf("invalid parameter type: %T", i) +func validateDistributionTransmissionChannel(i interface{}) error { + // Accept empty string as valid, since this will be the default value on genesis + if i == "" { + return nil } - return nil + // Otherwise validate as usual for a channelID + return ccvtypes.ValidateChannelIdentifier(i) } -func validateInt64(i interface{}) error { - if _, ok := i.(int64); !ok { - return fmt.Errorf("invalid parameter type: %T", i) +func validateProviderFeePoolAddrStr(i interface{}) error { + // Accept empty string as valid, since this will be the default value on genesis + if i == "" { + return nil } - return nil + // Otherwise validate as usual for a bech32 address + return ccvtypes.ValidateBech32(i) } -func validateString(i interface{}) error { - if _, ok := i.(string); !ok { +func validateConsumerRedistributionFraction(i interface{}) error { + str, ok := i.(string) + if !ok { return fmt.Errorf("invalid parameter type: %T", i) } + dec, err := sdk.NewDecFromStr(str) + if err != nil { + return err + } + if dec.IsNegative() { + return fmt.Errorf("consumer redistribution fraction is negative") + } + if dec.Sub(sdk.NewDec(1)).IsPositive() { + return fmt.Errorf("consumer redistribution fraction cannot be above 1.0") + } return nil } diff --git a/x/ccv/consumer/types/params_test.go b/x/ccv/consumer/types/params_test.go new file mode 100644 index 0000000000..0fd7f87eb2 --- /dev/null +++ b/x/ccv/consumer/types/params_test.go @@ -0,0 +1,53 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" +) + +// Tests the validation of consumer params that happens at genesis +func TestValidateParams(t *testing.T) { + + testCases := []struct { + name string + params consumertypes.Params + expPass bool + }{ + {"default params", consumertypes.DefaultParams(), true}, + {"custom valid params", + consumertypes.NewParams(true, 5, "", "", 1004, 1005, "0.5", 1000, 24*21*time.Hour), true}, + {"custom invalid params, block per dist transmission", + consumertypes.NewParams(true, -5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour), false}, + {"custom invalid params, dist transmission channel", + consumertypes.NewParams(true, 5, "badchannel/", "", 5, 1005, "0.5", 1000, 24*21*time.Hour), false}, + {"custom invalid params, provider fee pool addr string", + consumertypes.NewParams(true, 5, "", "imabadaddress", 5, 1005, "0.5", 1000, 24*21*time.Hour), false}, + {"custom invalid params, ccv timeout", + consumertypes.NewParams(true, 5, "", "", -5, 1005, "0.5", 1000, 24*21*time.Hour), false}, + {"custom invalid params, transfer timeout", + consumertypes.NewParams(true, 5, "", "", 1004, -7, "0.5", 1000, 24*21*time.Hour), false}, + {"custom invalid params, consumer redist fraction is negative", + consumertypes.NewParams(true, 5, "", "", 5, 1005, "-0.5", 1000, 24*21*time.Hour), false}, + {"custom invalid params, consumer redist fraction is over 1", + consumertypes.NewParams(true, 5, "", "", 5, 1005, "1.2", 1000, 24*21*time.Hour), false}, + {"custom invalid params, bad consumer redist fraction ", + consumertypes.NewParams(true, 5, "", "", 5, 1005, "notFrac", 1000, 24*21*time.Hour), false}, + {"custom invalid params, negative num historical entries", + consumertypes.NewParams(true, 5, "", "", 5, 1005, "0.5", -100, 24*21*time.Hour), false}, + {"custom invalid params, negative unbonding period", + consumertypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, -24*21*time.Hour), false}, + } + + for _, tc := range testCases { + err := tc.params.Validate() + if tc.expPass { + require.Nil(t, err, "expected error to be nil for test case: %s", tc.name) + } else { + require.NotNil(t, err, "expected error but got nil for test case: %s", tc.name) + } + } +} diff --git a/x/ccv/consumer/types/query.pb.go b/x/ccv/consumer/types/query.pb.go new file mode 100644 index 0000000000..2ac0f06d06 --- /dev/null +++ b/x/ccv/consumer/types/query.pb.go @@ -0,0 +1,991 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: interchain_security/ccv/consumer/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// NextFeeDistributionEstimate holds information about next fee distribution +type NextFeeDistributionEstimate struct { + // current block height at the time of querying + CurrentHeight int64 `protobuf:"varint,1,opt,name=currentHeight,proto3" json:"currentHeight,omitempty"` + // block height at which last distribution took place + LastHeight int64 `protobuf:"varint,2,opt,name=lastHeight,proto3" json:"lastHeight,omitempty"` + // block height at which next distribution will take place + NextHeight int64 `protobuf:"varint,3,opt,name=nextHeight,proto3" json:"nextHeight,omitempty"` + // ratio between consumer and provider fee distribution + DistributionFraction string `protobuf:"bytes,4,opt,name=distribution_fraction,json=distributionFraction,proto3" json:"distribution_fraction,omitempty"` + // total accruead fees at the time of querying + Total string `protobuf:"bytes,5,opt,name=total,proto3" json:"total,omitempty"` + // amount distibuted to provider chain + ToProvider string `protobuf:"bytes,6,opt,name=toProvider,proto3" json:"toProvider,omitempty"` + // amount distributed (kept) by consumer chain + ToConsumer string `protobuf:"bytes,7,opt,name=toConsumer,proto3" json:"toConsumer,omitempty"` +} + +func (m *NextFeeDistributionEstimate) Reset() { *m = NextFeeDistributionEstimate{} } +func (m *NextFeeDistributionEstimate) String() string { return proto.CompactTextString(m) } +func (*NextFeeDistributionEstimate) ProtoMessage() {} +func (*NextFeeDistributionEstimate) Descriptor() ([]byte, []int) { + return fileDescriptor_f627751d3cc10225, []int{0} +} +func (m *NextFeeDistributionEstimate) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NextFeeDistributionEstimate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NextFeeDistributionEstimate.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NextFeeDistributionEstimate) XXX_Merge(src proto.Message) { + xxx_messageInfo_NextFeeDistributionEstimate.Merge(m, src) +} +func (m *NextFeeDistributionEstimate) XXX_Size() int { + return m.Size() +} +func (m *NextFeeDistributionEstimate) XXX_DiscardUnknown() { + xxx_messageInfo_NextFeeDistributionEstimate.DiscardUnknown(m) +} + +var xxx_messageInfo_NextFeeDistributionEstimate proto.InternalMessageInfo + +func (m *NextFeeDistributionEstimate) GetCurrentHeight() int64 { + if m != nil { + return m.CurrentHeight + } + return 0 +} + +func (m *NextFeeDistributionEstimate) GetLastHeight() int64 { + if m != nil { + return m.LastHeight + } + return 0 +} + +func (m *NextFeeDistributionEstimate) GetNextHeight() int64 { + if m != nil { + return m.NextHeight + } + return 0 +} + +func (m *NextFeeDistributionEstimate) GetDistributionFraction() string { + if m != nil { + return m.DistributionFraction + } + return "" +} + +func (m *NextFeeDistributionEstimate) GetTotal() string { + if m != nil { + return m.Total + } + return "" +} + +func (m *NextFeeDistributionEstimate) GetToProvider() string { + if m != nil { + return m.ToProvider + } + return "" +} + +func (m *NextFeeDistributionEstimate) GetToConsumer() string { + if m != nil { + return m.ToConsumer + } + return "" +} + +type QueryNextFeeDistributionEstimateRequest struct { +} + +func (m *QueryNextFeeDistributionEstimateRequest) Reset() { + *m = QueryNextFeeDistributionEstimateRequest{} +} +func (m *QueryNextFeeDistributionEstimateRequest) String() string { return proto.CompactTextString(m) } +func (*QueryNextFeeDistributionEstimateRequest) ProtoMessage() {} +func (*QueryNextFeeDistributionEstimateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f627751d3cc10225, []int{1} +} +func (m *QueryNextFeeDistributionEstimateRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryNextFeeDistributionEstimateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryNextFeeDistributionEstimateRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryNextFeeDistributionEstimateRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryNextFeeDistributionEstimateRequest.Merge(m, src) +} +func (m *QueryNextFeeDistributionEstimateRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryNextFeeDistributionEstimateRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryNextFeeDistributionEstimateRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryNextFeeDistributionEstimateRequest proto.InternalMessageInfo + +type QueryNextFeeDistributionEstimateResponse struct { + Data *NextFeeDistributionEstimate `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` +} + +func (m *QueryNextFeeDistributionEstimateResponse) Reset() { + *m = QueryNextFeeDistributionEstimateResponse{} +} +func (m *QueryNextFeeDistributionEstimateResponse) String() string { return proto.CompactTextString(m) } +func (*QueryNextFeeDistributionEstimateResponse) ProtoMessage() {} +func (*QueryNextFeeDistributionEstimateResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f627751d3cc10225, []int{2} +} +func (m *QueryNextFeeDistributionEstimateResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryNextFeeDistributionEstimateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryNextFeeDistributionEstimateResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryNextFeeDistributionEstimateResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryNextFeeDistributionEstimateResponse.Merge(m, src) +} +func (m *QueryNextFeeDistributionEstimateResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryNextFeeDistributionEstimateResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryNextFeeDistributionEstimateResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryNextFeeDistributionEstimateResponse proto.InternalMessageInfo + +func (m *QueryNextFeeDistributionEstimateResponse) GetData() *NextFeeDistributionEstimate { + if m != nil { + return m.Data + } + return nil +} + +func init() { + proto.RegisterType((*NextFeeDistributionEstimate)(nil), "interchain_security.ccv.consumer.v1.NextFeeDistributionEstimate") + proto.RegisterType((*QueryNextFeeDistributionEstimateRequest)(nil), "interchain_security.ccv.consumer.v1.QueryNextFeeDistributionEstimateRequest") + proto.RegisterType((*QueryNextFeeDistributionEstimateResponse)(nil), "interchain_security.ccv.consumer.v1.QueryNextFeeDistributionEstimateResponse") +} + +func init() { + proto.RegisterFile("interchain_security/ccv/consumer/v1/query.proto", fileDescriptor_f627751d3cc10225) +} + +var fileDescriptor_f627751d3cc10225 = []byte{ + // 428 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0xcf, 0x8b, 0xd3, 0x40, + 0x14, 0xc7, 0x3b, 0xd9, 0xed, 0x8a, 0x23, 0x5e, 0x86, 0x15, 0xc2, 0x2a, 0x61, 0x89, 0x82, 0xf5, + 0xd0, 0x0c, 0xbb, 0x7b, 0x10, 0xbd, 0x28, 0xfe, 0x58, 0x3c, 0xa8, 0x68, 0xd9, 0x93, 0x97, 0x65, + 0x3a, 0x7d, 0x9b, 0x0e, 0x34, 0x33, 0xd9, 0x99, 0x97, 0xd0, 0xde, 0xa4, 0x7f, 0x80, 0x08, 0xfe, + 0x53, 0x1e, 0x0b, 0x5e, 0x3c, 0x4a, 0xeb, 0x1f, 0xe1, 0x51, 0x92, 0x34, 0x9a, 0x82, 0xb6, 0x3d, + 0xec, 0x2d, 0xf9, 0x7e, 0xde, 0xbc, 0xef, 0xcb, 0x37, 0x6f, 0x28, 0x57, 0x1a, 0xc1, 0xca, 0xa1, + 0x50, 0xfa, 0xdc, 0x81, 0xcc, 0xac, 0xc2, 0x09, 0x97, 0x32, 0xe7, 0xd2, 0x68, 0x97, 0x25, 0x60, + 0x79, 0x7e, 0xc4, 0x2f, 0x33, 0xb0, 0x93, 0x28, 0xb5, 0x06, 0x0d, 0xbb, 0xfb, 0x8f, 0x03, 0x91, + 0x94, 0x79, 0x54, 0x1f, 0x88, 0xf2, 0xa3, 0x83, 0x3b, 0xb1, 0x31, 0xf1, 0x08, 0xb8, 0x48, 0x15, + 0x17, 0x5a, 0x1b, 0x14, 0xa8, 0x8c, 0x76, 0x55, 0x8b, 0xf0, 0x93, 0x47, 0x6f, 0xbf, 0x85, 0x31, + 0x9e, 0x02, 0xbc, 0x50, 0x0e, 0xad, 0xea, 0x67, 0x05, 0x7e, 0xe9, 0x50, 0x25, 0x02, 0x81, 0xdd, + 0xa3, 0x37, 0x65, 0x66, 0x2d, 0x68, 0x7c, 0x05, 0x2a, 0x1e, 0xa2, 0x4f, 0x0e, 0x49, 0x67, 0xa7, + 0xb7, 0x2a, 0xb2, 0x80, 0xd2, 0x91, 0x70, 0x75, 0x89, 0x57, 0x96, 0x34, 0x94, 0x82, 0x6b, 0x18, + 0xd7, 0x7c, 0xa7, 0xe2, 0x7f, 0x15, 0x76, 0x42, 0x6f, 0x0d, 0x1a, 0xee, 0xe7, 0x17, 0x56, 0xc8, + 0xe2, 0xc1, 0xdf, 0x3d, 0x24, 0x9d, 0xeb, 0xbd, 0xfd, 0x26, 0x3c, 0x5d, 0x32, 0xb6, 0x4f, 0xdb, + 0x68, 0x50, 0x8c, 0xfc, 0x76, 0x59, 0x54, 0xbd, 0x14, 0x56, 0x68, 0xde, 0x59, 0x93, 0xab, 0x01, + 0x58, 0x7f, 0xaf, 0x44, 0x0d, 0xa5, 0xe2, 0xcf, 0x97, 0xf9, 0xf8, 0xd7, 0x6a, 0x5e, 0x2b, 0xe1, + 0x03, 0x7a, 0xff, 0x7d, 0x11, 0xf1, 0x9a, 0x50, 0x7a, 0x70, 0x99, 0x81, 0xc3, 0xf0, 0x23, 0xa1, + 0x9d, 0xcd, 0xb5, 0x2e, 0x35, 0xda, 0x01, 0x3b, 0xa3, 0xbb, 0x03, 0x81, 0xa2, 0xcc, 0xef, 0xc6, + 0xf1, 0xd3, 0x68, 0x8b, 0x5f, 0x17, 0xad, 0xeb, 0x5b, 0x76, 0x3b, 0x9e, 0x7a, 0xb4, 0x5d, 0x8e, + 0xc0, 0x7e, 0x11, 0xea, 0xff, 0x6f, 0x18, 0xf6, 0x7a, 0x2b, 0xbb, 0x2d, 0xbf, 0xfb, 0xe0, 0xcd, + 0x15, 0x75, 0xab, 0x92, 0x09, 0x9f, 0x4c, 0xbf, 0xfd, 0xfc, 0xe2, 0x3d, 0x62, 0x0f, 0x37, 0xef, + 0x7f, 0xb1, 0x32, 0xdd, 0x0b, 0x80, 0x6e, 0x73, 0x21, 0x9e, 0x9d, 0x7d, 0x9d, 0x07, 0x64, 0x36, + 0x0f, 0xc8, 0x8f, 0x79, 0x40, 0x3e, 0x2f, 0x82, 0xd6, 0x6c, 0x11, 0xb4, 0xbe, 0x2f, 0x82, 0xd6, + 0x87, 0xc7, 0xb1, 0xc2, 0x61, 0xd6, 0x8f, 0xa4, 0x49, 0xb8, 0x34, 0x2e, 0x31, 0xae, 0xe1, 0xd1, + 0xfd, 0xe3, 0x31, 0x5e, 0x75, 0xc1, 0x49, 0x0a, 0xae, 0xbf, 0x57, 0x5e, 0x90, 0x93, 0xdf, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x1e, 0x6c, 0xbe, 0x84, 0x96, 0x03, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // ConsumerGenesis queries the genesis state needed to start a consumer chain + // whose proposal has been accepted + QueryNextFeeDistribution(ctx context.Context, in *QueryNextFeeDistributionEstimateRequest, opts ...grpc.CallOption) (*QueryNextFeeDistributionEstimateResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) QueryNextFeeDistribution(ctx context.Context, in *QueryNextFeeDistributionEstimateRequest, opts ...grpc.CallOption) (*QueryNextFeeDistributionEstimateResponse, error) { + out := new(QueryNextFeeDistributionEstimateResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.consumer.v1.Query/QueryNextFeeDistribution", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // ConsumerGenesis queries the genesis state needed to start a consumer chain + // whose proposal has been accepted + QueryNextFeeDistribution(context.Context, *QueryNextFeeDistributionEstimateRequest) (*QueryNextFeeDistributionEstimateResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) QueryNextFeeDistribution(ctx context.Context, req *QueryNextFeeDistributionEstimateRequest) (*QueryNextFeeDistributionEstimateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryNextFeeDistribution not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_QueryNextFeeDistribution_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryNextFeeDistributionEstimateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).QueryNextFeeDistribution(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/interchain_security.ccv.consumer.v1.Query/QueryNextFeeDistribution", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).QueryNextFeeDistribution(ctx, req.(*QueryNextFeeDistributionEstimateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "interchain_security.ccv.consumer.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "QueryNextFeeDistribution", + Handler: _Query_QueryNextFeeDistribution_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "interchain_security/ccv/consumer/v1/query.proto", +} + +func (m *NextFeeDistributionEstimate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NextFeeDistributionEstimate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NextFeeDistributionEstimate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ToConsumer) > 0 { + i -= len(m.ToConsumer) + copy(dAtA[i:], m.ToConsumer) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ToConsumer))) + i-- + dAtA[i] = 0x3a + } + if len(m.ToProvider) > 0 { + i -= len(m.ToProvider) + copy(dAtA[i:], m.ToProvider) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ToProvider))) + i-- + dAtA[i] = 0x32 + } + if len(m.Total) > 0 { + i -= len(m.Total) + copy(dAtA[i:], m.Total) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Total))) + i-- + dAtA[i] = 0x2a + } + if len(m.DistributionFraction) > 0 { + i -= len(m.DistributionFraction) + copy(dAtA[i:], m.DistributionFraction) + i = encodeVarintQuery(dAtA, i, uint64(len(m.DistributionFraction))) + i-- + dAtA[i] = 0x22 + } + if m.NextHeight != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.NextHeight)) + i-- + dAtA[i] = 0x18 + } + if m.LastHeight != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.LastHeight)) + i-- + dAtA[i] = 0x10 + } + if m.CurrentHeight != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CurrentHeight)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryNextFeeDistributionEstimateRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryNextFeeDistributionEstimateRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryNextFeeDistributionEstimateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryNextFeeDistributionEstimateResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryNextFeeDistributionEstimateResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryNextFeeDistributionEstimateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Data != nil { + { + size, err := m.Data.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *NextFeeDistributionEstimate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CurrentHeight != 0 { + n += 1 + sovQuery(uint64(m.CurrentHeight)) + } + if m.LastHeight != 0 { + n += 1 + sovQuery(uint64(m.LastHeight)) + } + if m.NextHeight != 0 { + n += 1 + sovQuery(uint64(m.NextHeight)) + } + l = len(m.DistributionFraction) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Total) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.ToProvider) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.ToConsumer) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryNextFeeDistributionEstimateRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryNextFeeDistributionEstimateResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Data != nil { + l = m.Data.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *NextFeeDistributionEstimate) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NextFeeDistributionEstimate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NextFeeDistributionEstimate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentHeight", wireType) + } + m.CurrentHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CurrentHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeight", wireType) + } + m.LastHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NextHeight", wireType) + } + m.NextHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.NextHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DistributionFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DistributionFraction = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Total", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Total = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ToProvider", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ToProvider = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ToConsumer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ToConsumer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryNextFeeDistributionEstimateRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryNextFeeDistributionEstimateRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryNextFeeDistributionEstimateRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryNextFeeDistributionEstimateResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryNextFeeDistributionEstimateResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryNextFeeDistributionEstimateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Data == nil { + m.Data = &NextFeeDistributionEstimate{} + } + if err := m.Data.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/ccv/consumer/types/query.pb.gw.go b/x/ccv/consumer/types/query.pb.gw.go new file mode 100644 index 0000000000..2435a0ae14 --- /dev/null +++ b/x/ccv/consumer/types/query.pb.gw.go @@ -0,0 +1,153 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: interchain_security/ccv/consumer/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_QueryNextFeeDistribution_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryNextFeeDistributionEstimateRequest + var metadata runtime.ServerMetadata + + msg, err := client.QueryNextFeeDistribution(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_QueryNextFeeDistribution_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryNextFeeDistributionEstimateRequest + var metadata runtime.ServerMetadata + + msg, err := server.QueryNextFeeDistribution(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_QueryNextFeeDistribution_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_QueryNextFeeDistribution_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryNextFeeDistribution_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_QueryNextFeeDistribution_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_QueryNextFeeDistribution_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryNextFeeDistribution_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_QueryNextFeeDistribution_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"interchain_security", "ccv", "consumer", "next-fee-distribution"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_QueryNextFeeDistribution_0 = runtime.ForwardResponseMessage +) diff --git a/x/ccv/provider/client/cli/query.go b/x/ccv/provider/client/cli/query.go index fed13c4042..de6269d981 100644 --- a/x/ccv/provider/client/cli/query.go +++ b/x/ccv/provider/client/cli/query.go @@ -18,14 +18,17 @@ func NewQueryCmd() *cobra.Command { RunE: client.ValidateCmd, } - cmd.AddCommand(NewQueryConsumerGenesisCmd()) + cmd.AddCommand(CmdConsumerGenesis()) + cmd.AddCommand(CmdConsumerChains()) + cmd.AddCommand(CmdConsumerStartProposals()) + cmd.AddCommand(CmdConsumerStopProposals()) return cmd } // NewQuerySubspaceParamsCmd returns a CLI command handler for querying subspace // parameters managed by the x/params module. -func NewQueryConsumerGenesisCmd() *cobra.Command { +func CmdConsumerGenesis() *cobra.Command { cmd := &cobra.Command{ Use: "consumer-genesis [chainid]", Short: "Query for consumer chain genesis state by chain id", @@ -38,7 +41,7 @@ func NewQueryConsumerGenesisCmd() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) req := types.QueryConsumerGenesisRequest{ChainId: args[0]} - res, err := queryClient.ConsumerGenesis(cmd.Context(), &req) + res, err := queryClient.QueryConsumerGenesis(cmd.Context(), &req) if err != nil { return err } @@ -51,3 +54,92 @@ func NewQueryConsumerGenesisCmd() *cobra.Command { return cmd } + +func CmdConsumerChains() *cobra.Command { + cmd := &cobra.Command{ + Use: "list-consumer-chains", + Short: "Query active consumer chains for provider chain.", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + req := &types.QueryConsumerChainsRequest{} + res, err := queryClient.QueryConsumerChains(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +func CmdConsumerStartProposals() *cobra.Command { + cmd := &cobra.Command{ + Use: "list-start-proposals", + Short: "Query consumer chains start proposals on provider chain.", + Long: `Query mature and pending consumer chains start proposals on provider chain. + Matured proposals will be executed on the next block - their spawn_time has passed + Pending proposals are waiting for their spawn_time to pass. + `, + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + req := &types.QueryConsumerChainStartProposalsRequest{} + res, err := queryClient.QueryConsumerChainStarts(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +func CmdConsumerStopProposals() *cobra.Command { + cmd := &cobra.Command{ + Use: "list-stop-proposals", + Short: "Query consumer chains stop proposals on provider chain.", + Long: `Query mature and pending consumer chains stop proposals on provider chain. + Matured proposals will be executed on the next block - their stop_time has passed + Pending proposals are waiting for their stop_time to pass. + `, + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + req := &types.QueryConsumerChainStopProposalsRequest{} + res, err := queryClient.QueryConsumerChainStops(cmd.Context(), req) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/ccv/provider/client/proposal_handler.go b/x/ccv/provider/client/proposal_handler.go index 345001c64a..66c20ef233 100644 --- a/x/ccv/provider/client/proposal_handler.go +++ b/x/ccv/provider/client/proposal_handler.go @@ -20,8 +20,10 @@ import ( "github.com/spf13/cobra" ) -// ProposalHandler is the param change proposal handler. -var ProposalHandler = govclient.NewProposalHandler(SubmitConsumerAdditionPropTxCmd, ProposalRESTHandler) +var ( + ConsumerAdditionProposalHandler = govclient.NewProposalHandler(SubmitConsumerAdditionPropTxCmd, ConsumerAdditionProposalRESTHandler) + ConsumerRemovalProposalHandler = govclient.NewProposalHandler(SubmitConsumerRemovalProposalTxCmd, ConsumerRemovalProposalRESTHandler) +) // SubmitConsumerAdditionPropTxCmd returns a CLI command handler for submitting // a consumer addition proposal via a transaction. @@ -35,7 +37,7 @@ Submit a consumer addition proposal along with an initial deposit. The proposal details must be supplied via a JSON file. Example: -$ %s tx gov submit-proposal consumer-addition --from= +$ tx gov submit-proposal consumer-addition --from= Where proposal.json contains: @@ -85,6 +87,59 @@ Where proposal.json contains: } } +// SubmitConsumerRemovalPropTxCmd returns a CLI command handler for submitting +// a consumer addition proposal via a transaction. +func SubmitConsumerRemovalProposalTxCmd() *cobra.Command { + return &cobra.Command{ + Use: "consumer-removal [proposal-file]", + Args: cobra.ExactArgs(1), + Short: "Submit a consumer chain removal proposal", + Long: ` +Submit a consumer chain removal proposal along with an initial deposit. +The proposal details must be supplied via a JSON file. + +Example: +$ tx gov submit-proposal consumer-removal --from= + +Where proposal.json contains: +{ + "title": "Stop the FooChain", + "description": "It was a great chain", + "chain_id": "foochain", + "stop_time": "2022-01-27T15:59:50.121607-08:00", + "deposit": "10000stake" +} + `, RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + proposal, err := ParseConsumerRemovalProposalJSON(args[0]) + if err != nil { + return err + } + + content := types.NewConsumerRemovalProposal( + proposal.Title, proposal.Description, proposal.ChainId, proposal.StopTime) + + from := clientCtx.GetFromAddress() + + deposit, err := sdk.ParseCoinsNormalized(proposal.Deposit) + if err != nil { + return err + } + + msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } +} + type ConsumerAdditionProposalJSON struct { Title string `json:"title"` Description string `json:"description"` @@ -125,16 +180,58 @@ func ParseConsumerAdditionProposalJSON(proposalFile string) (ConsumerAdditionPro return proposal, nil } -// ProposalRESTHandler returns a ProposalRESTHandler that exposes the param -// change REST handler with a given sub-route. -func ProposalRESTHandler(clientCtx client.Context) govrest.ProposalRESTHandler { +type ConsumerRemovalProposalJSON struct { + Title string `json:"title"` + Description string `json:"description"` + ChainId string `json:"chain_id"` + StopTime time.Time `json:"stop_time"` + Deposit string `json:"deposit"` +} + +type ConsumerRemovalProposalReq struct { + BaseReq rest.BaseReq `json:"base_req"` + Proposer sdk.AccAddress `json:"proposer"` + + Title string `json:"title"` + Description string `json:"description"` + ChainId string `json:"chainId"` + + StopTime time.Time `json:"stopTime"` + Deposit sdk.Coins `json:"deposit"` +} + +func ParseConsumerRemovalProposalJSON(proposalFile string) (ConsumerRemovalProposalJSON, error) { + proposal := ConsumerRemovalProposalJSON{} + + contents, err := ioutil.ReadFile(filepath.Clean(proposalFile)) + if err != nil { + return proposal, err + } + + if err := json.Unmarshal(contents, &proposal); err != nil { + return proposal, err + } + + return proposal, nil +} + +// ConsumerAdditionProposalRESTHandler returns a ProposalRESTHandler that exposes the consumer addition rest handler. +func ConsumerAdditionProposalRESTHandler(clientCtx client.Context) govrest.ProposalRESTHandler { return govrest.ProposalRESTHandler{ - SubRoute: "propose_consumer_addition", - Handler: postProposalHandlerFn(clientCtx), + SubRoute: "consumer_addition", + Handler: postConsumerAdditionProposalHandlerFn(clientCtx), } } -func postProposalHandlerFn(clientCtx client.Context) http.HandlerFunc { +// ConsumerRemovalProposalRESTHandler returns a ProposalRESTHandler that exposes the consumer removal rest handler. +func ConsumerRemovalProposalRESTHandler(clientCtx client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: "consumer_removal", + Handler: postConsumerRemovalProposalHandlerFn(clientCtx), + } +} + +func postConsumerAdditionProposalHandlerFn(clientCtx client.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req ConsumerAdditionProposalReq if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { @@ -162,3 +259,32 @@ func postProposalHandlerFn(clientCtx client.Context) http.HandlerFunc { tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) } } + +func postConsumerRemovalProposalHandlerFn(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req ConsumerRemovalProposalReq + if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + content := types.NewConsumerRemovalProposal( + req.Title, req.Description, req.ChainId, req.StopTime, + ) + + msg, err := govtypes.NewMsgSubmitProposal(content, req.Deposit, req.Proposer) + if rest.CheckBadRequestError(w, err) { + return + } + + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) + } +} diff --git a/x/ccv/provider/ibc_module.go b/x/ccv/provider/ibc_module.go index 8792236d14..911cc66272 100644 --- a/x/ccv/provider/ibc_module.go +++ b/x/ccv/provider/ibc_module.go @@ -34,7 +34,6 @@ func (am AppModule) OnChanOpenInit( // OnChanOpenTry implements the IBCModule interface // -// // See: https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/methods.md#ccv-pcf-cotry1 // Spec tag: [CCV-PCF-COTRY.1] func (am AppModule) OnChanOpenTry( diff --git a/x/ccv/provider/keeper/genesis.go b/x/ccv/provider/keeper/genesis.go index 81ce35e7c3..cb5ec457cf 100644 --- a/x/ccv/provider/keeper/genesis.go +++ b/x/ccv/provider/keeper/genesis.go @@ -31,6 +31,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { for _, prop := range genState.ConsumerAdditionProposals { // prevent implicit memory aliasing prop := prop + // TODO: change SetPendingConsumerAdditionProp to not return an error if err := k.SetPendingConsumerAdditionProp(ctx, &prop); err != nil { panic(fmt.Errorf("pending create consumer chain proposal could not be persisted: %w", err)) } @@ -44,6 +45,8 @@ func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { } } + // MatureUnbondings is emptied every EndBlock but it will + // change with sovereign to consumer chain transition so we keep it. if genState.MatureUnbondingOps != nil { if err := k.AppendMaturedUnbondingOps(ctx, genState.MatureUnbondingOps.Ids); err != nil { panic(err) diff --git a/x/ccv/provider/keeper/grpc_query.go b/x/ccv/provider/keeper/grpc_query.go index bd5bdb0693..4f67959c39 100644 --- a/x/ccv/provider/keeper/grpc_query.go +++ b/x/ccv/provider/keeper/grpc_query.go @@ -12,7 +12,7 @@ import ( var _ types.QueryServer = Keeper{} -func (k Keeper) ConsumerGenesis(c context.Context, req *types.QueryConsumerGenesisRequest) (*types.QueryConsumerGenesisResponse, error) { +func (k Keeper) QueryConsumerGenesis(c context.Context, req *types.QueryConsumerGenesisRequest) (*types.QueryConsumerGenesisResponse, error) { ctx := sdk.UnwrapSDKContext(c) if req == nil { @@ -30,3 +30,44 @@ func (k Keeper) ConsumerGenesis(c context.Context, req *types.QueryConsumerGenes return &types.QueryConsumerGenesisResponse{GenesisState: gen}, nil } + +func (k Keeper) QueryConsumerChains(goCtx context.Context, req *types.QueryConsumerChainsRequest) (*types.QueryConsumerChainsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + chains := []*types.Chain{} + cb := func(ctx sdk.Context, chainID, clientID string) bool { + chains = append(chains, &types.Chain{ + ChainId: chainID, + ClientId: clientID, + }) + return false + } + k.IterateConsumerChains(ctx, cb) + + return &types.QueryConsumerChainsResponse{Chains: chains}, nil +} + +func (k Keeper) QueryConsumerChainStarts(goCtx context.Context, req *types.QueryConsumerChainStartProposalsRequest) (*types.QueryConsumerChainStartProposalsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + props := k.GetAllConsumerAdditionProps(ctx) + + return &types.QueryConsumerChainStartProposalsResponse{Proposals: &props}, nil +} + +func (k Keeper) QueryConsumerChainStops(goCtx context.Context, req *types.QueryConsumerChainStopProposalsRequest) (*types.QueryConsumerChainStopProposalsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + props := k.GetAllConsumerRemovalProps(ctx) + + return &types.QueryConsumerChainStopProposalsResponse{Proposals: &props}, nil +} diff --git a/x/ccv/provider/keeper/hooks.go b/x/ccv/provider/keeper/hooks.go new file mode 100644 index 0000000000..2d772caa8d --- /dev/null +++ b/x/ccv/provider/keeper/hooks.go @@ -0,0 +1,80 @@ +package keeper + +import ( + "fmt" + + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + ccv "github.com/cosmos/interchain-security/x/ccv/types" +) + +// Wrapper struct +type Hooks struct { + k *Keeper +} + +var _ stakingtypes.StakingHooks = Hooks{} + +// Returns new provider hooks +func (k *Keeper) Hooks() Hooks { + return Hooks{k} +} + +// This stores a record of each unbonding op from staking, allowing us to track which consumer chains have unbonded +func (h Hooks) AfterUnbondingInitiated(ctx sdk.Context, ID uint64) { + var consumerChainIDS []string + + h.k.IterateConsumerChains(ctx, func(ctx sdk.Context, chainID, clientID string) (stop bool) { + consumerChainIDS = append(consumerChainIDS, chainID) + return false + }) + if len(consumerChainIDS) == 0 { + // Do not put the unbonding op on hold if there are no consumer chains + return + } + valsetUpdateID := h.k.GetValidatorSetUpdateId(ctx) + unbondingOp := ccv.UnbondingOp{ + Id: ID, + UnbondingConsumerChains: consumerChainIDS, + } + + // Add to indexes + for _, consumerChainID := range consumerChainIDS { + index, _ := h.k.GetUnbondingOpIndex(ctx, consumerChainID, valsetUpdateID) + index = append(index, ID) + h.k.SetUnbondingOpIndex(ctx, consumerChainID, valsetUpdateID, index) + } + + // Set unbondingOp + if err := h.k.SetUnbondingOp(ctx, unbondingOp); err != nil { + panic(fmt.Errorf("unbonding op could not be persisted: %w", err)) + } + + // Call back into staking to tell it to stop this op from unbonding when the unbonding period is complete + if err := h.k.stakingKeeper.PutUnbondingOnHold(ctx, ID); err != nil { + panic(fmt.Errorf("unbonding could not be put on hold: %w", err)) + } +} + +// Define unimplemented methods to satisfy the StakingHooks contract +func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) { +} +func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, _ sdk.ConsAddress, valAddr sdk.ValAddress) { +} +func (h Hooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { +} +func (h Hooks) BeforeDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) { +} +func (h Hooks) AfterDelegationModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) { +} +func (h Hooks) BeforeValidatorSlashed(_ sdk.Context, _ sdk.ValAddress, _ sdk.Dec) { +} +func (h Hooks) BeforeValidatorModified(_ sdk.Context, _ sdk.ValAddress) { +} +func (h Hooks) AfterValidatorBonded(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) { +} +func (h Hooks) AfterValidatorBeginUnbonding(_ sdk.Context, _ sdk.ConsAddress, _ sdk.ValAddress) { +} +func (h Hooks) BeforeDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) { +} diff --git a/x/ccv/provider/keeper/keeper.go b/x/ccv/provider/keeper/keeper.go index 2a0f392b91..b68e1ab697 100644 --- a/x/ccv/provider/keeper/keeper.go +++ b/x/ccv/provider/keeper/keeper.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "encoding/json" "fmt" + "time" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,7 +13,6 @@ import ( capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" conntypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" @@ -259,9 +259,13 @@ func (k Keeper) VerifyConsumerChain(ctx sdk.Context, channelID string, connectio return nil } -// SetConsumerChain ensures that the consumer chain has not already been set by a different channel, and then sets the consumer chain mappings in keeper, -// and set the channel status to validating. -// If there is already a ccv channel between the provider and consumer chain then close the channel, so that another channel can be made. +// SetConsumerChain ensures that the consumer chain has not already been +// set by a different channel, and then sets the consumer chain mappings +// in keeper, and set the channel status to validating. +// If there is already a CCV channel between the provider and consumer +// chain then close the channel, so that another channel can be made. +// +// SetConsumerChain is called by OnChanOpenConfirm. func (k Keeper) SetConsumerChain(ctx sdk.Context, channelID string) error { channel, ok := k.channelKeeper.GetChannel(ctx, ccv.ProviderPortID, channelID) if !ok { @@ -283,10 +287,12 @@ func (k Keeper) SetConsumerChain(ctx sdk.Context, channelID string) error { // the CCV channel is established: // - set channel mappings - k.SetChainToChannel(ctx, tmClient.ChainId, channelID) - k.SetChannelToChain(ctx, channelID, tmClient.ChainId) + k.SetChainToChannel(ctx, chainID, channelID) + k.SetChannelToChain(ctx, channelID, chainID) // - set current block height for the consumer chain initialization - k.SetInitChainHeight(ctx, tmClient.ChainId, uint64(ctx.BlockHeight())) + k.SetInitChainHeight(ctx, chainID, uint64(ctx.BlockHeight())) + // - remove init timeout timestamp + k.DeleteInitTimeoutTimestamp(ctx, chainID) return nil } @@ -354,18 +360,15 @@ func (k Keeper) SetUnbondingOpIndex(ctx sdk.Context, chainID string, valsetUpdat // IterateOverUnbondingOpIndex iterates over the unbonding indexes for a given chain id. func (k Keeper) IterateOverUnbondingOpIndex(ctx sdk.Context, chainID string, cb func(vscID uint64, ubdIndex []uint64) bool) { store := ctx.KVStore(k.storeKey) - iterationPrefix := append([]byte{types.UnbondingOpIndexBytePrefix}, types.HashString(chainID)...) - iterator := sdk.KVStorePrefixIterator(store, iterationPrefix) - + iterator := sdk.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.UnbondingOpIndexBytePrefix, chainID)) defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { // parse key to get the current VSC ID - var vscID uint64 - vscBytes, err := types.ParseUnbondingOpIndexKey(iterator.Key()) + _, vscID, err := types.ParseUnbondingOpIndexKey(iterator.Key()) if err != nil { - panic(err) + panic(fmt.Errorf("failed to parse UnbondingOpIndexKey: %w", err)) } - vscID = binary.BigEndian.Uint64(vscBytes) var index ccv.UnbondingOpsIndex if err = index.Unmarshal(iterator.Value()); err != nil { @@ -539,54 +542,6 @@ func (k Keeper) GetValidatorSetUpdateId(ctx sdk.Context) (validatorSetUpdateId u return validatorSetUpdateId } -type StakingHooks struct { - stakingtypes.StakingHooksTemplate - k *Keeper -} - -var _ stakingtypes.StakingHooks = StakingHooks{} - -// Return the wrapper struct -func (k *Keeper) Hooks() StakingHooks { - return StakingHooks{stakingtypes.StakingHooksTemplate{}, k} -} - -// This stores a record of each unbonding op from staking, allowing us to track which consumer chains have unbonded -func (h StakingHooks) AfterUnbondingInitiated(ctx sdk.Context, ID uint64) { - var consumerChainIDS []string - - h.k.IterateConsumerChains(ctx, func(ctx sdk.Context, chainID, clientID string) (stop bool) { - consumerChainIDS = append(consumerChainIDS, chainID) - return false - }) - if len(consumerChainIDS) == 0 { - // Do not put the unbonding op on hold if there are no consumer chains - return - } - valsetUpdateID := h.k.GetValidatorSetUpdateId(ctx) - unbondingOp := ccv.UnbondingOp{ - Id: ID, - UnbondingConsumerChains: consumerChainIDS, - } - - // Add to indexes - for _, consumerChainID := range consumerChainIDS { - index, _ := h.k.GetUnbondingOpIndex(ctx, consumerChainID, valsetUpdateID) - index = append(index, ID) - h.k.SetUnbondingOpIndex(ctx, consumerChainID, valsetUpdateID, index) - } - - // Set unbondingOp - if err := h.k.SetUnbondingOp(ctx, unbondingOp); err != nil { - panic(fmt.Errorf("unbonding op could not be persisted: %w", err)) - } - - // Call back into staking to tell it to stop this op from unbonding when the unbonding period is complete - if err := h.k.stakingKeeper.PutUnbondingOnHold(ctx, ID); err != nil { - panic(fmt.Errorf("unbonding could not be put on hold: %w", err)) - } -} - // SetValsetUpdateBlockHeight sets the block height for a given valset update id func (k Keeper) SetValsetUpdateBlockHeight(ctx sdk.Context, valsetUpdateId, blockHeight uint64) { store := ctx.KVStore(k.storeKey) @@ -605,7 +560,7 @@ func (k Keeper) GetValsetUpdateBlockHeight(ctx sdk.Context, valsetUpdateId uint6 return binary.BigEndian.Uint64(bz), true } -// IterateSlashAcks iterates through the slash acks set in the store +// IterateValsetUpdateBlockHeight iterates over the valset update id to a block height mappings func (k Keeper) IterateValsetUpdateBlockHeight(ctx sdk.Context, cb func(valsetUpdateId, height uint64) bool) { store := ctx.KVStore(k.storeKey) iterator := sdk.KVStorePrefixIterator(store, []byte{types.ValsetUpdateBlockHeightBytePrefix}) @@ -826,3 +781,93 @@ func (k Keeper) DeleteConsumerClientId(ctx sdk.Context, chainID string) { store := ctx.KVStore(k.storeKey) store.Delete(types.ChainToClientKey(chainID)) } + +// SetInitTimeoutTimestamp sets the init timeout timestamp for the given chain ID +func (k Keeper) SetInitTimeoutTimestamp(ctx sdk.Context, chainID string, ts uint64) { + store := ctx.KVStore(k.storeKey) + tsBytes := make([]byte, 8) + binary.BigEndian.PutUint64(tsBytes, ts) + store.Set(types.InitTimeoutTimestampKey(chainID), tsBytes) +} + +// GetInitTimeoutTimestamp returns the init timeout timestamp for the given chain ID. +// This method is used only in testing. +func (k Keeper) GetInitTimeoutTimestamp(ctx sdk.Context, chainID string) (uint64, bool) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.InitTimeoutTimestampKey(chainID)) + if bz == nil { + return 0, false + } + return binary.BigEndian.Uint64(bz), true +} + +// DeleteInitTimeoutTimestamp removes from the store the init timeout timestamp for the given chainID. +func (k Keeper) DeleteInitTimeoutTimestamp(ctx sdk.Context, chainID string) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.InitTimeoutTimestampKey(chainID)) +} + +// IterateInitTimeoutTimestamp iterates through the init timeout timestamps in the store +func (k Keeper) IterateInitTimeoutTimestamp(ctx sdk.Context, cb func(chainID string, ts uint64) bool) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte{types.InitTimeoutTimestampBytePrefix}) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + chainID := string(iterator.Key()[1:]) + ts := binary.BigEndian.Uint64(iterator.Value()) + if !cb(chainID, ts) { + return + } + } +} + +// SetVscSendTimestamp sets the VSC send timestamp +// for a VSCPacket with ID vscID sent to a chain with ID chainID +func (k Keeper) SetVscSendTimestamp( + ctx sdk.Context, + chainID string, + vscID uint64, + timestamp time.Time, +) { + store := ctx.KVStore(k.storeKey) + + // Convert timestamp into bytes for storage + timeBz := sdk.FormatTimeBytes(timestamp) + + store.Set(types.VscSendingTimestampKey(chainID, vscID), timeBz) +} + +// DeleteVscSendTimestamp removes from the store a specific VSC send timestamp +// for the given chainID and vscID. +func (k Keeper) DeleteVscSendTimestamp(ctx sdk.Context, chainID string, vscID uint64) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.VscSendingTimestampKey(chainID, vscID)) +} + +// IterateVscSendTimestamps iterates in order (lowest first) +// over the vsc send timestamps of the given chainID. +func (k Keeper) IterateVscSendTimestamps( + ctx sdk.Context, + chainID string, + cb func(vscID uint64, ts time.Time) bool, +) { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, types.ChainIdWithLenKey(types.VscSendTimestampBytePrefix, chainID)) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + key := iterator.Key() + _, vscID, err := types.ParseVscSendingTimestampKey(key) + if err != nil { + panic(fmt.Errorf("failed to parse VscSendTimestampKey: %w", err)) + } + ts, err := sdk.ParseTimeBytes(iterator.Value()) + if err != nil { + panic(fmt.Errorf("failed to parse timestamp value: %w", err)) + } + if !cb(vscID, ts) { + return + } + } +} diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index a0630016ea..df91c5a4c4 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -2,6 +2,7 @@ package keeper_test import ( "testing" + "time" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" "github.com/golang/mock/gomock" @@ -296,3 +297,100 @@ func TestMaturedUnbondingOps(t *testing.T) { require.Equal(t, unbondingOpIds[i], ids[i]) } } + +func TestInitTimeoutTimestamp(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + tc := []struct { + chainID string + expected uint64 + }{ + {expected: 5, chainID: "chain"}, + {expected: 10, chainID: "chain1"}, + {expected: 12, chainID: "chain2"}, + } + + _, found := providerKeeper.GetInitTimeoutTimestamp(ctx, tc[0].chainID) + require.False(t, found) + + providerKeeper.SetInitTimeoutTimestamp(ctx, tc[0].chainID, tc[0].expected) + providerKeeper.SetInitTimeoutTimestamp(ctx, tc[1].chainID, tc[1].expected) + providerKeeper.SetInitTimeoutTimestamp(ctx, tc[2].chainID, tc[2].expected) + + i := 0 + providerKeeper.IterateInitTimeoutTimestamp(ctx, func(chainID string, ts uint64) bool { + require.Equal(t, chainID, tc[i].chainID) + require.Equal(t, ts, tc[i].expected) + i++ + return true + }) + require.Equal(t, len(tc), i) + + for _, tc := range tc { + ts, found := providerKeeper.GetInitTimeoutTimestamp(ctx, tc.chainID) + require.True(t, found) + require.Equal(t, tc.expected, ts) + } + + providerKeeper.DeleteInitTimeoutTimestamp(ctx, tc[1].chainID) + _, found = providerKeeper.GetInitTimeoutTimestamp(ctx, tc[1].chainID) + require.False(t, found) +} + +// TestVscSendTimestamp tests the set, deletion, and iteration methods for VSC timeout timestamps +func TestVscSendTimestamp(t *testing.T) { + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + now := ctx.BlockTime() + + testCases := []struct { + chainID string + ts time.Time + vscID uint64 + }{ + {chainID: "chain", ts: now.Add(time.Hour), vscID: 1}, + {chainID: "chain", ts: now.Add(2 * time.Hour), vscID: 2}, + {chainID: "chain1", ts: now.Add(time.Hour), vscID: 1}, + {chainID: "chain2", ts: now.Add(time.Hour), vscID: 1}, + } + + i := 0 + chainID := "chain" + providerKeeper.IterateVscSendTimestamps(ctx, chainID, func(_ uint64, _ time.Time) bool { + i++ + return true + }) + require.Equal(t, 0, i) + + for _, tc := range testCases { + providerKeeper.SetVscSendTimestamp(ctx, tc.chainID, tc.vscID, tc.ts) + } + + i = 0 + providerKeeper.IterateVscSendTimestamps(ctx, testCases[0].chainID, func(vscID uint64, ts time.Time) bool { + require.Equal(t, vscID, testCases[i].vscID) + require.Equal(t, ts, testCases[i].ts) + i++ + return true + }) + require.Equal(t, 2, i) + + // delete VSC send timestamps + var ids []uint64 + providerKeeper.IterateVscSendTimestamps(ctx, testCases[0].chainID, func(vscID uint64, _ time.Time) bool { + ids = append(ids, vscID) + return true + }) + for _, vscID := range ids { + providerKeeper.DeleteVscSendTimestamp(ctx, testCases[0].chainID, vscID) + } + + i = 0 + providerKeeper.IterateVscSendTimestamps(ctx, testCases[0].chainID, func(_ uint64, _ time.Time) bool { + i++ + return true + }) + require.Equal(t, 0, i) +} diff --git a/x/ccv/provider/keeper/params.go b/x/ccv/provider/keeper/params.go index 3fdf4f895f..9ce00d2f81 100644 --- a/x/ccv/provider/keeper/params.go +++ b/x/ccv/provider/keeper/params.go @@ -1,11 +1,14 @@ package keeper import ( + "time" + sdk "github.com/cosmos/cosmos-sdk/types" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" "github.com/cosmos/interchain-security/x/ccv/provider/types" + ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" ) // GetTemplateClient returns the template client for provider proposals @@ -15,12 +18,52 @@ func (k Keeper) GetTemplateClient(ctx sdk.Context) *ibctmtypes.ClientState { return &cs } +// GetTrustingPeriodFraction returns a TrustingPeriodFraction +// used to compute the provider IBC client's TrustingPeriod as UnbondingPeriod / TrustingPeriodFraction +func (k Keeper) GetTrustingPeriodFraction(ctx sdk.Context) int64 { + var i int64 + k.paramSpace.Get(ctx, types.KeyTrustingPeriodFraction, &i) + return i +} + +// GetCCVTimeoutPeriod returns the timeout period for sent ibc packets +func (k Keeper) GetCCVTimeoutPeriod(ctx sdk.Context) time.Duration { + var p time.Duration + k.paramSpace.Get(ctx, ccvtypes.KeyCCVTimeoutPeriod, &p) + return p +} + +// GetInitTimeoutPeriod returns the init timeout period +func (k Keeper) GetInitTimeoutPeriod(ctx sdk.Context) time.Duration { + var p time.Duration + k.paramSpace.Get(ctx, types.KeyInitTimeoutPeriod, &p) + return p +} + +// GetVscTimeoutPeriod returns the vsc timeout period +func (k Keeper) GetVscTimeoutPeriod(ctx sdk.Context) time.Duration { + var p time.Duration + k.paramSpace.Get(ctx, types.KeyVscTimeoutPeriod, &p) + return p +} + +// SetVscTimeoutPeriod sets the vsc timeout period +func (k Keeper) SetVscTimeoutPeriod(ctx sdk.Context, period time.Duration) { + k.paramSpace.Set(ctx, types.KeyVscTimeoutPeriod, period) +} + // GetParams returns the paramset for the provider module func (k Keeper) GetParams(ctx sdk.Context) types.Params { - return types.NewParams(k.GetTemplateClient(ctx)) + return types.NewParams( + k.GetTemplateClient(ctx), + k.GetTrustingPeriodFraction(ctx), + k.GetCCVTimeoutPeriod(ctx), + k.GetInitTimeoutPeriod(ctx), + k.GetVscTimeoutPeriod(ctx), + ) } -// SetParams sets the paramset for the provider module +// SetParams sets the params for the provider module func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { k.paramSpace.SetParamSet(ctx, ¶ms) } diff --git a/x/ccv/provider/keeper/params_test.go b/x/ccv/provider/keeper/params_test.go index 6a8298ad6f..02da2aa9de 100644 --- a/x/ccv/provider/keeper/params_test.go +++ b/x/ccv/provider/keeper/params_test.go @@ -9,24 +9,26 @@ import ( ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/x/ccv/provider/types" + ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" ) -// TestParams tests the default params of the keeper, and getting/setting new params. +// TestParams tests the getting/setting of provider ccv module params. func TestParams(t *testing.T) { - defaultParams := types.DefaultParams() - // Construct an in-mem keeper with a populated template client state + // Construct an in-mem keeper with registered key table keeperParams := testkeeper.NewInMemKeeperParams(t) - keeperParams.SetTemplateClientState(nil) providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) defer ctrl.Finish() + defaultParams := types.DefaultParams() + providerKeeper.SetParams(ctx, defaultParams) params := providerKeeper.GetParams(ctx) require.Equal(t, defaultParams, params) newParams := types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, - time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false)) + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + types.DefaultTrustingPeriodFraction, ccvtypes.DefaultCCVTimeoutPeriod, types.DefaultInitTimeoutPeriod, types.DefaultVscTimeoutPeriod) providerKeeper.SetParams(ctx, newParams) params = providerKeeper.GetParams(ctx) require.Equal(t, newParams, params) diff --git a/x/ccv/provider/keeper/proposal.go b/x/ccv/provider/keeper/proposal.go index d9b346e968..7cb9998b8c 100644 --- a/x/ccv/provider/keeper/proposal.go +++ b/x/ccv/provider/keeper/proposal.go @@ -14,7 +14,6 @@ import ( ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" "github.com/cosmos/interchain-security/x/ccv/provider/types" ccv "github.com/cosmos/interchain-security/x/ccv/types" - utils "github.com/cosmos/interchain-security/x/ccv/utils" abci "github.com/tendermint/tendermint/abci/types" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" @@ -46,22 +45,24 @@ func (k Keeper) HandleConsumerAdditionProposal(ctx sdk.Context, p *types.Consume // // See: https://github.com/cosmos/ibc/blob/main/spec/app/ics-028-cross-chain-validation/methods.md#ccv-pcf-crclient1 // Spec tag: [CCV-PCF-CRCLIENT.1] -func (k Keeper) CreateConsumerClient(ctx sdk.Context, chainID string, initialHeight clienttypes.Height, lockUbdOnTimeout bool) error { +func (k Keeper) CreateConsumerClient(ctx sdk.Context, chainID string, + initialHeight clienttypes.Height, lockUbdOnTimeout bool) error { + // check that a client for this chain does not exist if _, found := k.GetConsumerClientId(ctx, chainID); found { // drop the proposal return nil } - // Use the unbonding period on the provider to compute the unbonding period on the consumer - unbondingPeriod := utils.ComputeConsumerUnbondingPeriod(k.stakingKeeper.UnbondingTime(ctx)) + // Consumers always start out with the default unbonding period + consumerUnbondingPeriod := consumertypes.DefaultConsumerUnbondingPeriod // Create client state by getting template client from parameters and filling in zeroed fields from proposal. clientState := k.GetTemplateClient(ctx) clientState.ChainId = chainID clientState.LatestHeight = initialHeight - clientState.TrustingPeriod = unbondingPeriod / utils.TrustingPeriodFraction - clientState.UnbondingPeriod = unbondingPeriod + clientState.TrustingPeriod = consumerUnbondingPeriod / time.Duration(k.GetTrustingPeriodFraction(ctx)) + clientState.UnbondingPeriod = consumerUnbondingPeriod // TODO: Allow for current validators to set different keys consensusState := ibctmtypes.NewConsensusState( @@ -85,6 +86,10 @@ func (k Keeper) CreateConsumerClient(ctx sdk.Context, chainID string, initialHei return err } + // add the init timeout timestamp for this consumer chain + ts := ctx.BlockTime().Add(k.GetParams(ctx).InitTimeoutPeriod) + k.SetInitTimeoutTimestamp(ctx, chainID, uint64(ts.UnixNano())) + // store LockUnbondingOnTimeout flag if lockUbdOnTimeout { k.SetLockUnbondingOnTimeout(ctx, chainID) @@ -125,6 +130,7 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, lockUbd, clos k.DeleteConsumerClientId(ctx, chainID) k.DeleteConsumerGenesis(ctx, chainID) k.DeleteLockUnbondingOnTimeout(ctx, chainID) + k.DeleteInitTimeoutTimestamp(ctx, chainID) // close channel and delete the mappings between chain ID and channel ID if channelID, found := k.GetChainToChannel(ctx, chainID); found { @@ -133,6 +139,16 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, lockUbd, clos } k.DeleteChainToChannel(ctx, chainID) k.DeleteChannelToChain(ctx, channelID) + + // delete VSC send timestamps + var ids []uint64 + k.IterateVscSendTimestamps(ctx, chainID, func(vscID uint64, ts time.Time) bool { + ids = append(ids, vscID) + return true + }) + for _, vscID := range ids { + k.DeleteVscSendTimestamp(ctx, chainID, vscID) + } } k.DeleteInitChainHeight(ctx, chainID) @@ -190,14 +206,14 @@ func (k Keeper) StopConsumerChain(ctx sdk.Context, chainID string, lockUbd, clos // MakeConsumerGenesis constructs a consumer genesis state. func (k Keeper) MakeConsumerGenesis(ctx sdk.Context) (gen consumertypes.GenesisState, err error) { - unbondingTime := k.stakingKeeper.UnbondingTime(ctx) + providerUnbondingPeriod := k.stakingKeeper.UnbondingTime(ctx) height := clienttypes.GetSelfHeight(ctx) clientState := k.GetTemplateClient(ctx) clientState.ChainId = ctx.ChainID() clientState.LatestHeight = height //(+-1???) - clientState.TrustingPeriod = unbondingTime / utils.TrustingPeriodFraction - clientState.UnbondingPeriod = unbondingTime + clientState.TrustingPeriod = providerUnbondingPeriod / time.Duration(k.GetTrustingPeriodFraction(ctx)) + clientState.UnbondingPeriod = providerUnbondingPeriod consState, err := k.clientKeeper.GetSelfConsensusState(ctx, height) if err != nil { @@ -307,14 +323,12 @@ func (k Keeper) ConsumerAdditionPropsToExecute(ctx sdk.Context) []types.Consumer // store the (to be) executed proposals in order propsToExecute := []types.ConsumerAdditionProposal{} - iterator := k.PendingConsumerAdditionPropIterator(ctx) - defer iterator.Close() - k.IteratePendingConsumerAdditionProps(ctx, func(spawnTime time.Time, prop types.ConsumerAdditionProposal) bool { if !ctx.BlockTime().Before(spawnTime) { propsToExecute = append(propsToExecute, prop) return true } + // No more proposals to check, since they're stored/ordered by timestamp. return false }) @@ -341,8 +355,24 @@ func (k Keeper) IteratePendingConsumerAdditionProps(ctx sdk.Context, cb func(spa } } -// DeletePendingConsumerAdditionProps deletes the given consumer addition proposals. -// This method should be called once the proposal has been acted upon. +// GetAllConsumerAdditionProps returns all consumer addition proposals separated into matured and pending. +func (k Keeper) GetAllConsumerAdditionProps(ctx sdk.Context) types.ConsumerAdditionProposals { + props := types.ConsumerAdditionProposals{} + + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte{types.PendingCAPBytePrefix}) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var prop types.ConsumerAdditionProposal + k.cdc.MustUnmarshal(iterator.Value(), &prop) + + props.Pending = append(props.Pending, &prop) + } + return props +} + +// DeletePendingConsumerAdditionProps deletes the given consumer addition proposals func (k Keeper) DeletePendingConsumerAdditionProps(ctx sdk.Context, proposals ...types.ConsumerAdditionProposal) { store := ctx.KVStore(k.storeKey) @@ -416,10 +446,9 @@ func (k Keeper) ConsumerRemovalPropsToExecute(ctx sdk.Context) []types.ConsumerR if !ctx.BlockTime().Before(stopTime) { propsToExecute = append(propsToExecute, prop) return true - } else { - // No more proposals to check, since they're stored/ordered by timestamp. - return false } + // No more proposals to check, since they're stored/ordered by timestamp. + return false }) return propsToExecute @@ -443,6 +472,28 @@ func (k Keeper) IteratePendingConsumerRemovalProps(ctx sdk.Context, cb func(stop } } +// GetAllConsumerRemovalProps returns all consumer removal proposals separated into matured and pending. +func (k Keeper) GetAllConsumerRemovalProps(ctx sdk.Context) types.ConsumerRemovalProposals { + props := types.ConsumerRemovalProposals{} + + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte{types.PendingCRPBytePrefix}) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + key := iterator.Key() + stopTime, chainID, err := types.ParsePendingCRPKey(key) + if err != nil { + panic(fmt.Errorf("failed to parse pending consumer removal proposal key: %w", err)) + } + + props.Pending = append(props.Pending, + &types.ConsumerRemovalProposal{ChainId: chainID, StopTime: stopTime}) + } + + return props +} + // CloseChannel closes the channel for the given channel ID on the condition // that the channel exists and isn't already in the CLOSED state func (k Keeper) CloseChannel(ctx sdk.Context, channelID string) { diff --git a/x/ccv/provider/keeper/proposal_test.go b/x/ccv/provider/keeper/proposal_test.go index 1e309e737b..7f6ad1058e 100644 --- a/x/ccv/provider/keeper/proposal_test.go +++ b/x/ccv/provider/keeper/proposal_test.go @@ -19,6 +19,7 @@ import ( providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" "github.com/cosmos/interchain-security/x/ccv/provider/types" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" + ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" ) // @@ -78,8 +79,8 @@ func TestHandleConsumerAdditionProposal(t *testing.T) { for _, tc := range tests { // Common setup keeperParams := testkeeper.NewInMemKeeperParams(t) - keeperParams.SetTemplateClientState(nil) providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + providerKeeper.SetParams(ctx, providertypes.DefaultParams()) ctx = ctx.WithBlockTime(tc.blockTime) if tc.expCreatedClient { @@ -154,8 +155,8 @@ func TestCreateConsumerClient(t *testing.T) { for _, tc := range tests { // Common setup keeperParams := testkeeper.NewInMemKeeperParams(t) - keeperParams.SetTemplateClientState(nil) providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + providerKeeper.SetParams(ctx, providertypes.DefaultParams()) // Test specific setup tc.setup(&providerKeeper, ctx, &mocks) @@ -355,8 +356,8 @@ func TestHandleConsumerRemovalProposal(t *testing.T) { // Common setup keeperParams := testkeeper.NewInMemKeeperParams(t) - keeperParams.SetTemplateClientState(nil) providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + providerKeeper.SetParams(ctx, providertypes.DefaultParams()) ctx = ctx.WithBlockTime(tc.blockTime) // Mock expectations and setup for stopping the consumer chain, if applicable @@ -374,7 +375,7 @@ func TestHandleConsumerRemovalProposal(t *testing.T) { found := providerKeeper.GetPendingConsumerRemovalProp(ctx, tc.prop.ChainId, tc.prop.StopTime) require.False(t, found) - testConsumerStateIsCleaned(t, ctx, providerKeeper, tc.prop.ChainId, "channelID") + testProviderStateIsCleaned(t, ctx, providerKeeper, tc.prop.ChainId, "channelID") } else { // Proposal should be stored as pending found := providerKeeper.GetPendingConsumerRemovalProp(ctx, tc.prop.ChainId, tc.prop.StopTime) @@ -431,8 +432,8 @@ func TestStopConsumerChain(t *testing.T) { // Common setup keeperParams := testkeeper.NewInMemKeeperParams(t) - keeperParams.SetTemplateClientState(nil) providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + providerKeeper.SetParams(ctx, providertypes.DefaultParams()) // Setup specific to test case tc.setup(ctx, &providerKeeper, mocks) @@ -445,14 +446,14 @@ func TestStopConsumerChain(t *testing.T) { require.NoError(t, err) } - testConsumerStateIsCleaned(t, ctx, providerKeeper, "chainID", "channelID") + testProviderStateIsCleaned(t, ctx, providerKeeper, "chainID", "channelID") ctrl.Finish() } } -// testConsumerStateIsCleaned executes test assertions for a stopped consumer chain's state being cleaned. -func testConsumerStateIsCleaned(t *testing.T, ctx sdk.Context, providerKeeper providerkeeper.Keeper, +// testProviderStateIsCleaned executes test assertions for the proposer's state being cleaned after a stopped consumer chain. +func testProviderStateIsCleaned(t *testing.T, ctx sdk.Context, providerKeeper providerkeeper.Keeper, expectedChainID string, expectedChannelID string) { _, found := providerKeeper.GetConsumerClientId(ctx, expectedChainID) @@ -467,6 +468,14 @@ func testConsumerStateIsCleaned(t *testing.T, ctx sdk.Context, providerKeeper pr require.False(t, found) acks := providerKeeper.GetSlashAcks(ctx, expectedChainID) require.Empty(t, acks) + _, found = providerKeeper.GetInitTimeoutTimestamp(ctx, expectedChainID) + require.False(t, found) + found = false + providerKeeper.IterateVscSendTimestamps(ctx, expectedChainID, func(_ uint64, _ time.Time) bool { + found = true + return false + }) + require.False(t, found) } // TestPendingConsumerRemovalPropDeletion tests the getting/setting @@ -570,14 +579,15 @@ func TestPendingConsumerRemovalPropOrder(t *testing.T) { } } -// TestMakeConsumerGenesis tests the MakeConsumerGenesis keeper method -// -// Note: the initial intention of this test wasn't very clear, it was migrated with best effort +// TestMakeConsumerGenesis tests the MakeConsumerGenesis keeper method. +// An expected genesis state is hardcoded in json, unmarshaled, and compared +// against an actual consumer genesis state constructed by a provider keeper. func TestMakeConsumerGenesis(t *testing.T) { keeperParams := testkeeper.NewInMemKeeperParams(t) - keeperParams.SetTemplateClientState( - &ibctmtypes.ClientState{ + providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + moduleParams := providertypes.Params{ + TemplateClient: &ibctmtypes.ClientState{ TrustLevel: ibctmtypes.DefaultTrustLevel, MaxClockDrift: 10000000000, ProofSpecs: []*_go.ProofSpec{ @@ -621,8 +631,14 @@ func TestMakeConsumerGenesis(t *testing.T) { AllowUpdateAfterExpiry: true, AllowUpdateAfterMisbehaviour: true, }, - ) - providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + // Note these are unused provider parameters for this test, and not actually asserted against + // They must be populated with reasonable values to satisfy SetParams though. + TrustingPeriodFraction: providertypes.DefaultTrustingPeriodFraction, + CcvTimeoutPeriod: ccvtypes.DefaultCCVTimeoutPeriod, + InitTimeoutPeriod: types.DefaultInitTimeoutPeriod, + VscTimeoutPeriod: types.DefaultVscTimeoutPeriod, + } + providerKeeper.SetParams(ctx, moduleParams) defer ctrl.Finish() // @@ -635,7 +651,7 @@ func TestMakeConsumerGenesis(t *testing.T) { actualGenesis, err := providerKeeper.MakeConsumerGenesis(ctx) require.NoError(t, err) - jsonString := `{"params":{"enabled":true, "blocks_per_distribution_transmission":1000, "lock_unbonding_on_timeout": false},"new_chain":true,"provider_client_state":{"chain_id":"testchain1","trust_level":{"numerator":1,"denominator":3},"trusting_period":907200000000000,"unbonding_period":1814400000000000,"max_clock_drift":10000000000,"frozen_height":{},"latest_height":{"revision_height":5},"proof_specs":[{"leaf_spec":{"hash":1,"prehash_value":1,"length":1,"prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":33,"min_prefix_length":4,"max_prefix_length":12,"hash":1}},{"leaf_spec":{"hash":1,"prehash_value":1,"length":1,"prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":32,"min_prefix_length":1,"max_prefix_length":1,"hash":1}}],"upgrade_path":["upgrade","upgradedIBCState"],"allow_update_after_expiry":true,"allow_update_after_misbehaviour":true},"provider_consensus_state":{"timestamp":"2020-01-02T00:00:10Z","root":{"hash":"LpGpeyQVLUo9HpdsgJr12NP2eCICspcULiWa5u9udOA="},"next_validators_hash":"E30CE736441FB9101FADDAF7E578ABBE6DFDB67207112350A9A904D554E1F5BE"},"unbonding_sequences":null,"initial_val_set":[{"pub_key":{"type":"tendermint/PubKeyEd25519","value":"dcASx5/LIKZqagJWN0frOlFtcvz91frYmj/zmoZRWro="},"power":1}]}` + jsonString := `{"params":{"enabled":true, "blocks_per_distribution_transmission":1000, "ccv_timeout_period":2419200000000000, "transfer_timeout_period": 3600000000000, "consumer_redistribution_fraction":"0.75", "historical_entries":10000, "unbonding_period": 1728000000000000},"new_chain":true,"provider_client_state":{"chain_id":"testchain1","trust_level":{"numerator":1,"denominator":3},"trusting_period":907200000000000,"unbonding_period":1814400000000000,"max_clock_drift":10000000000,"frozen_height":{},"latest_height":{"revision_height":5},"proof_specs":[{"leaf_spec":{"hash":1,"prehash_value":1,"length":1,"prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":33,"min_prefix_length":4,"max_prefix_length":12,"hash":1}},{"leaf_spec":{"hash":1,"prehash_value":1,"length":1,"prefix":"AA=="},"inner_spec":{"child_order":[0,1],"child_size":32,"min_prefix_length":1,"max_prefix_length":1,"hash":1}}],"upgrade_path":["upgrade","upgradedIBCState"],"allow_update_after_expiry":true,"allow_update_after_misbehaviour":true},"provider_consensus_state":{"timestamp":"2020-01-02T00:00:10Z","root":{"hash":"LpGpeyQVLUo9HpdsgJr12NP2eCICspcULiWa5u9udOA="},"next_validators_hash":"E30CE736441FB9101FADDAF7E578ABBE6DFDB67207112350A9A904D554E1F5BE"},"unbonding_sequences":null,"initial_val_set":[{"pub_key":{"type":"tendermint/PubKeyEd25519","value":"dcASx5/LIKZqagJWN0frOlFtcvz91frYmj/zmoZRWro="},"power":1}]}` var expectedGenesis consumertypes.GenesisState err = json.Unmarshal([]byte(jsonString), &expectedGenesis) @@ -647,7 +663,7 @@ func TestMakeConsumerGenesis(t *testing.T) { actualGenesis.ProviderConsensusState = &ibctmtypes.ConsensusState{} expectedGenesis.ProviderConsensusState = &ibctmtypes.ConsensusState{} - require.Equal(t, actualGenesis, expectedGenesis, "consumer chain genesis created incorrectly") + require.Equal(t, expectedGenesis, actualGenesis, "consumer chain genesis created incorrectly") } // TestBeginBlockInit directly tests BeginBlockInit against the spec using helpers defined above. @@ -659,8 +675,8 @@ func TestBeginBlockInit(t *testing.T) { now := time.Now().UTC() keeperParams := testkeeper.NewInMemKeeperParams(t) - keeperParams.SetTemplateClientState(nil) providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + providerKeeper.SetParams(ctx, providertypes.DefaultParams()) defer ctrl.Finish() ctx = ctx.WithBlockTime(now) @@ -709,8 +725,8 @@ func TestBeginBlockCCR(t *testing.T) { now := time.Now().UTC() keeperParams := testkeeper.NewInMemKeeperParams(t) - keeperParams.SetTemplateClientState(nil) providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + providerKeeper.SetParams(ctx, providertypes.DefaultParams()) defer ctrl.Finish() ctx = ctx.WithBlockTime(now) @@ -772,3 +788,59 @@ func TestBeginBlockCCR(t *testing.T) { ctx, pendingProps[2].ChainId, pendingProps[2].StopTime) require.True(t, found) } + +// Test getting both matured and pending comnsumer addition proposals +func TestGetAllConsumerAdditionProps(t *testing.T) { + now := time.Now().UTC() + + props := []types.ConsumerAdditionProposal{ + {ChainId: "1", SpawnTime: now.Add(1 * time.Hour)}, + {ChainId: "2", SpawnTime: now.Add(2 * time.Hour)}, + {ChainId: "3", SpawnTime: now.Add(3 * time.Hour)}, + {ChainId: "4", SpawnTime: now.Add(4 * time.Hour)}, + } + + keeperParams := testkeeper.NewInMemKeeperParams(t) + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + defer ctrl.Finish() + + for _, prop := range props { + cpProp := prop // bring into loop scope - avoids using iterator pointer instead of value pointer + err := providerKeeper.SetPendingConsumerAdditionProp(ctx, &cpProp) + require.NoError(t, err) + } + + // advance the clock to be 1 minute after first proposal + ctx = ctx.WithBlockTime(now.Add(time.Minute)) + res := providerKeeper.GetAllConsumerAdditionProps(ctx) + require.NotEmpty(t, res, "GetAllConsumerAdditionProps returned empty result") + require.Len(t, res.Pending, 4, "wrong len for pending addition props") + require.Equal(t, props[0].ChainId, res.Pending[0].ChainId, "wrong chain ID for pending addition prop") +} + +// Test getting both matured and pending consumer removal proposals +func TestGetAllConsumerRemovalProps(t *testing.T) { + now := time.Now().UTC() + + props := []types.ConsumerRemovalProposal{ + {ChainId: "1", StopTime: now.Add(1 * time.Hour)}, + {ChainId: "2", StopTime: now.Add(2 * time.Hour)}, + {ChainId: "3", StopTime: now.Add(3 * time.Hour)}, + {ChainId: "4", StopTime: now.Add(4 * time.Hour)}, + } + + keeperParams := testkeeper.NewInMemKeeperParams(t) + providerKeeper, ctx, ctrl, _ := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + defer ctrl.Finish() + + for _, prop := range props { + providerKeeper.SetPendingConsumerRemovalProp(ctx, prop.ChainId, prop.StopTime) + } + + // advance the clock to be 1 minute after first proposal + ctx = ctx.WithBlockTime(now.Add(time.Minute)) + res := providerKeeper.GetAllConsumerRemovalProps(ctx) + require.NotEmpty(t, res, "GetAllConsumerRemovalProps returned empty result") + require.Len(t, res.Pending, 4, "wrong len for pending removal props") + require.Equal(t, props[0].ChainId, res.Pending[0].ChainId, "wrong chain ID for pending removal prop") +} diff --git a/x/ccv/provider/keeper/relay.go b/x/ccv/provider/keeper/relay.go index b154f9ed13..9c6bd12398 100644 --- a/x/ccv/provider/keeper/relay.go +++ b/x/ccv/provider/keeper/relay.go @@ -66,12 +66,15 @@ func (k Keeper) OnRecvVSCMaturedPacket( // clean up index k.DeleteUnbondingOpIndex(ctx, chainID, data.ValsetUpdateId) + // remove the VSC timeout timestamp for this chainID and vscID + k.DeleteVscSendTimestamp(ctx, chainID, data.ValsetUpdateId) + ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) return ack } // CompleteMaturedUnbondingOps attempts to complete all matured unbonding operations -func (k Keeper) CompleteMaturedUnbondingOps(ctx sdk.Context) { +func (k Keeper) completeMaturedUnbondingOps(ctx sdk.Context) { ids, err := k.ConsumeMaturedUnbondingOps(ctx) if err != nil { panic(fmt.Sprintf("could not get the list of matured unbonding ops: %s", err.Error())) @@ -116,8 +119,18 @@ func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet) err return k.StopConsumerChain(ctx, chainID, k.GetLockUnbondingOnTimeout(ctx, chainID), false) } +// EndBlockVSU contains the EndBlock logic needed for +// the Validator Set Update sub-protocol +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) +} + // SendValidatorUpdates sends latest validator updates to every registered consumer chain -func (k Keeper) SendValidatorUpdates(ctx sdk.Context) { +func (k Keeper) sendValidatorUpdates(ctx sdk.Context) { // get current ValidatorSetUpdateId valUpdateID := k.GetValidatorSetUpdateId(ctx) // get the validator updates from the staking module @@ -147,10 +160,13 @@ func (k Keeper) SendValidatorUpdates(ctx sdk.Context) { 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) @@ -158,7 +174,6 @@ func (k Keeper) SendValidatorUpdates(ctx sdk.Context) { } return false // do not stop the iteration }) - k.SetValsetUpdateBlockHeight(ctx, valUpdateID, uint64(ctx.BlockHeight()+1)) k.IncrementValidatorSetUpdateId(ctx) } @@ -174,13 +189,27 @@ 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, ) if err != nil { panic(fmt.Errorf("packet could not be sent over IBC: %w", err)) } + // set the VSC send timestamp for this packet; + // note that the VSC send timestamp are set when the packets + // are actually sent over IBC + k.SetVscSendTimestamp(ctx, chainID, data.ValsetUpdateId, ctx.BlockTime()) } } +// EndBlockCIS contains the EndBlock logic needed for +// the Consumer Initiated Slashing sub-protocol +func (k Keeper) EndBlockCIS(ctx sdk.Context) { + // get current ValidatorSetUpdateId + valUpdateID := k.GetValidatorSetUpdateId(ctx) + // set the ValsetUpdateBlockHeight + k.SetValsetUpdateBlockHeight(ctx, valUpdateID, uint64(ctx.BlockHeight()+1)) +} + // OnRecvSlashPacket slashes and jails the given validator in the packet data func (k Keeper) OnRecvSlashPacket(ctx sdk.Context, packet channeltypes.Packet, data ccv.SlashPacketData) exported.Acknowledgement { // check that the channel is established @@ -276,3 +305,69 @@ func (k Keeper) HandleSlashPacket(ctx sdk.Context, chainID string, data ccv.Slas return true, nil } + +// EndBlockCIS contains the EndBlock logic needed for +// the Consumer Chain Removal sub-protocol +func (k Keeper) EndBlockCCR(ctx sdk.Context) { + currentTime := ctx.BlockTime() + currentTimeUint64 := uint64(currentTime.UnixNano()) + + // iterate over initTimeoutTimestamps + var chainIdsToRemove []string + k.IterateInitTimeoutTimestamp(ctx, func(chainID string, ts uint64) bool { + if currentTimeUint64 > ts { + // initTimeout expired + chainIdsToRemove = append(chainIdsToRemove, chainID) + // continue to iterate through all timed out consumers + return true + } + // break iteration since the timeout timestamps are in order + return false + }) + // remove consumers that timed out + for _, chainID := range chainIdsToRemove { + // stop the consumer chain and unlock the unbonding. + // Note that the CCV channel was not established, + // thus closeChan is irrelevant + err := k.StopConsumerChain(ctx, chainID, false, false) + if err != nil { + panic(fmt.Errorf("consumer chain failed to stop: %w", err)) + } + } + + // empty slice + chainIdsToRemove = nil + + // Iterate over all consumers with established CCV channels and + // check if the first vscSendTimestamp in iterator + VscTimeoutPeriod + // exceed the current block time. + // Checking the first send timestamp for each chain is sufficient since + // timestamps are ordered by vsc ID. + k.IterateChannelToChain(ctx, func(ctx sdk.Context, _, chainID string) bool { + k.IterateVscSendTimestamps(ctx, chainID, func(_ uint64, ts time.Time) bool { + timeoutTimestamp := ts.Add(k.GetParams(ctx).VscTimeoutPeriod) + if currentTime.After(timeoutTimestamp) { + // vscTimeout expired + chainIdsToRemove = append(chainIdsToRemove, chainID) + } + // break iteration since the send timestamps are in order + return false + }) + // continue to iterate through all consumers + return true + }) + // remove consumers that timed out + for _, chainID := range chainIdsToRemove { + // stop the consumer chain and use lockUnbondingOnTimeout + // to decide whether to lock the unbonding + err := k.StopConsumerChain( + ctx, + chainID, + k.GetLockUnbondingOnTimeout(ctx, chainID), + true, + ) + if err != nil { + panic(fmt.Errorf("consumer chain failed to stop: %w", err)) + } + } +} diff --git a/x/ccv/provider/module.go b/x/ccv/provider/module.go index 8b6721f3d4..c3914f4f5d 100644 --- a/x/ccv/provider/module.go +++ b/x/ccv/provider/module.go @@ -163,11 +163,14 @@ func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { // EndBlock implements the AppModule interface func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { - // notify the staking module to complete all matured unbonding ops - am.keeper.CompleteMaturedUnbondingOps(ctx) + // EndBlock logic needed for the Consumer Initiated Slashing sub-protocol. + // Important: EndBlockCIS must be called before EndBlockVSU + am.keeper.EndBlockCIS(ctx) + // EndBlock logic needed for the Consumer Chain Removal sub-protocol + am.keeper.EndBlockCCR(ctx) + // EndBlock logic needed for the Validator Set Update sub-protocol + am.keeper.EndBlockVSU(ctx) - // send validator updates to consumer chains - am.keeper.SendValidatorUpdates(ctx) return []abci.ValidatorUpdate{} } diff --git a/x/ccv/provider/proposal_handler_test.go b/x/ccv/provider/proposal_handler_test.go index 92c806a1ed..c5cd78760f 100644 --- a/x/ccv/provider/proposal_handler_test.go +++ b/x/ccv/provider/proposal_handler_test.go @@ -15,6 +15,7 @@ import ( testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/x/ccv/provider" "github.com/cosmos/interchain-security/x/ccv/provider/types" + providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" ) // TestConsumerChainProposalHandler tests the highest level handler for proposals concerning both @@ -64,8 +65,8 @@ func TestConsumerChainProposalHandler(t *testing.T) { // Setup keeperParams := testkeeper.NewInMemKeeperParams(t) - keeperParams.SetTemplateClientState(nil) providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, keeperParams) + providerKeeper.SetParams(ctx, providertypes.DefaultParams()) ctx = ctx.WithBlockTime(tc.blockTime) // Mock expectations depending on expected outcome diff --git a/x/ccv/provider/types/codec.go b/x/ccv/provider/types/codec.go index 25250f68c1..bb55872f19 100644 --- a/x/ccv/provider/types/codec.go +++ b/x/ccv/provider/types/codec.go @@ -11,13 +11,16 @@ import ( func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { } -// RegisterInterfaces register the ibc transfer module interfaces to protobuf -// Any. +// RegisterInterfaces registers the provider proposal structs to the interface registry func RegisterInterfaces(registry codectypes.InterfaceRegistry) { registry.RegisterImplementations( (*govtypes.Content)(nil), &ConsumerAdditionProposal{}, ) + registry.RegisterImplementations( + (*govtypes.Content)(nil), + &ConsumerRemovalProposal{}, + ) } var ( diff --git a/x/ccv/provider/types/genesis.pb.go b/x/ccv/provider/types/genesis.pb.go index 9283d01754..ae96c161a0 100644 --- a/x/ccv/provider/types/genesis.pb.go +++ b/x/ccv/provider/types/genesis.pb.go @@ -27,20 +27,19 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the CCV provider chain genesis state type GenesisState struct { - // empty for a completely new chain + // empty for a new chain ValsetUpdateId uint64 `protobuf:"varint,1,opt,name=valset_update_id,json=valsetUpdateId,proto3" json:"valset_update_id,omitempty"` - // empty for a completely new chain + // empty for a new chain ConsumerStates []ConsumerState `protobuf:"bytes,2,rep,name=consumer_states,json=consumerStates,proto3" json:"consumer_states" yaml:"consumer_states"` - // UnbondingOps defines the consumer chains that are still unbonding - // empty for a completely new chain + // empty for a new chain UnbondingOps []types.UnbondingOp `protobuf:"bytes,3,rep,name=unbonding_ops,json=unbondingOps,proto3" json:"unbonding_ops"` - // empty for a completely new chain + // empty for a new chain MatureUnbondingOps *types.MaturedUnbondingOps `protobuf:"bytes,4,opt,name=mature_unbonding_ops,json=matureUnbondingOps,proto3" json:"mature_unbonding_ops,omitempty"` - // empty for a completely new chain + // empty for a new chain ValsetUpdateIdToHeight []ValsetUpdateIdToHeight `protobuf:"bytes,5,rep,name=valset_update_id_to_height,json=valsetUpdateIdToHeight,proto3" json:"valset_update_id_to_height"` - // empty for a completely new chain + // empty for a new chain ConsumerAdditionProposals []ConsumerAdditionProposal `protobuf:"bytes,6,rep,name=consumer_addition_proposals,json=consumerAdditionProposals,proto3" json:"consumer_addition_proposals"` - // empty for a completely new chain + // empty for a new chain ConsumerRemovalProposals []ConsumerRemovalProposal `protobuf:"bytes,7,rep,name=consumer_removal_proposals,json=consumerRemovalProposals,proto3" json:"consumer_removal_proposals"` Params Params `protobuf:"bytes,8,opt,name=params,proto3" json:"params"` } @@ -136,12 +135,13 @@ func (m *GenesisState) GetParams() Params { // consumer chain type ConsumerState struct { - // The provider's identifier for this consumer chain. - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - // The provider's channel identifier to this consumer chain. + // ChainlID defines the chain ID for the consumer chain + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // ChannelID defines the IBC channel ID for the consumer chain ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` // ClientID defines the IBC client ID for the consumer chain - ClientId string `protobuf:"bytes,3,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + ClientId string `protobuf:"bytes,3,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + // InitalHeight defines the initial block height for the consumer chain InitialHeight uint64 `protobuf:"varint,4,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` // LockUnbondingOnTimeout defines whether the unbonding funds should be released for this // chain in case of a IBC channel timeout diff --git a/x/ccv/provider/types/genesis_test.go b/x/ccv/provider/types/genesis_test.go index e1a7556bdc..87aa1f8ff5 100644 --- a/x/ccv/provider/types/genesis_test.go +++ b/x/ccv/provider/types/genesis_test.go @@ -8,6 +8,7 @@ import ( commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" "github.com/cosmos/interchain-security/x/ccv/provider/types" + ccv "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" ) @@ -77,7 +78,8 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, - time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false)), + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + 3, time.Hour, time.Hour, time.Hour), ), true, }, @@ -92,7 +94,84 @@ func TestValidateGenesisState(t *testing.T) { nil, nil, types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, - 0, clienttypes.Height{}, nil, []string{"ibc", "upgradedIBCState"}, true, false)), + 0, clienttypes.Height{}, nil, []string{"ibc", "upgradedIBCState"}, true, false), + types.DefaultTrustingPeriodFraction, ccv.DefaultCCVTimeoutPeriod, types.DefaultInitTimeoutPeriod, types.DefaultVscTimeoutPeriod), + ), + false, + }, + { + "invalid params, zero trusting period fraction", + types.NewGenesisState( + 0, + nil, + []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid"}}, + nil, + nil, + nil, + nil, + types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + 0, // 0 trusting period fraction here + ccv.DefaultCCVTimeoutPeriod, + types.DefaultInitTimeoutPeriod, + types.DefaultVscTimeoutPeriod), + ), + false, + }, + { + "invalid params, zero ccv timeout", + types.NewGenesisState( + 0, + nil, + []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid"}}, + nil, + nil, + nil, + nil, + types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + types.DefaultTrustingPeriodFraction, + 0, // 0 ccv timeout here + types.DefaultInitTimeoutPeriod, + types.DefaultVscTimeoutPeriod), + ), + false, + }, + { + "invalid params, zero init timeout", + types.NewGenesisState( + 0, + nil, + []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid"}}, + nil, + nil, + nil, + nil, + types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + types.DefaultTrustingPeriodFraction, + ccv.DefaultCCVTimeoutPeriod, + 0, // 0 init timeout here + types.DefaultVscTimeoutPeriod), + ), + false, + }, + { + "invalid params, zero vsc timeout", + types.NewGenesisState( + 0, + nil, + []types.ConsumerState{{ChainId: "chainid-1", ChannelId: "channelid"}}, + nil, + nil, + nil, + nil, + types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + types.DefaultTrustingPeriodFraction, + ccv.DefaultCCVTimeoutPeriod, + types.DefaultInitTimeoutPeriod, + 0), // 0 vsc timeout here ), false, }, diff --git a/x/ccv/provider/types/keys.go b/x/ccv/provider/types/keys.go index 338921f33c..3fbf69ac64 100644 --- a/x/ccv/provider/types/keys.go +++ b/x/ccv/provider/types/keys.go @@ -2,13 +2,11 @@ package types import ( "bytes" - "crypto/sha256" "encoding/binary" "fmt" "time" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) type Status int @@ -49,9 +47,13 @@ const ( // from the CCV channel ID to the consumer chain ID. ChannelToChainBytePrefix - // ChainToClientBytePrefix is the byte prefix for storing the consumer chainID for a given consumer clientid. + // ChainToClientBytePrefix is the byte prefix for storing the client ID for a given consumer chainID. ChainToClientBytePrefix + // InitTimeoutTimestampBytePrefix is the byte prefix for storing + // the init timeout timestamp for a given consumer chainID. + InitTimeoutTimestampBytePrefix + // PendingCAPBytePrefix is the byte prefix for storing pending consumer addition proposals before the spawn time occurs. // The key includes the BigEndian timestamp to allow for efficient chronological iteration PendingCAPBytePrefix @@ -84,15 +86,14 @@ const ( // PendingVSCsBytePrefix is the byte prefix that will store pending ValidatorSetChangePacket data PendingVSCsBytePrefix + // VscSendTimestampBytePrefix is the byte prefix for storing + // the list of VSC sending timestamps for a given consumer chainID. + VscSendTimestampBytePrefix + // LockUnbondingOnTimeoutBytePrefix is the byte prefix that will store the consumer chain id which unbonding operations are locked on CCV channel timeout LockUnbondingOnTimeoutBytePrefix ) -const ( - // UnbondingOpIndexKey should be of set length: prefix + hashed chain ID + uint64 - UnbondingOpIndexKeySize = 1 + 32 + 8 -) - // PortKey returns the key to the port ID in the store func PortKey() []byte { return []byte{PortByteKey} @@ -123,97 +124,43 @@ func ChainToClientKey(chainID string) []byte { return append([]byte{ChainToClientBytePrefix}, []byte(chainID)...) } +// InitTimeoutTimestampKey returns the key under which the init timeout timestamp for the given chainID is stored. +func InitTimeoutTimestampKey(chainID string) []byte { + return append([]byte{InitTimeoutTimestampBytePrefix}, []byte(chainID)...) +} + // PendingCAPKey returns the key under which a pending consumer addition proposal is stored func PendingCAPKey(timestamp time.Time, chainID string) []byte { - timeBz := sdk.FormatTimeBytes(timestamp) - timeBzL := len(timeBz) - prefixL := len([]byte{PendingCAPBytePrefix}) - - bz := make([]byte, prefixL+8+timeBzL+len(chainID)) - // copy the prefix - copy(bz[:prefixL], []byte{PendingCAPBytePrefix}) - // copy the time length - copy(bz[prefixL:prefixL+8], sdk.Uint64ToBigEndian(uint64(timeBzL))) - // copy the time bytes - copy(bz[prefixL+8:prefixL+8+timeBzL], timeBz) - // copy the chainId - copy(bz[prefixL+8+timeBzL:], chainID) - return bz + return tsAndChainIdKey(PendingCAPBytePrefix, timestamp, chainID) } // ParsePendingCAPKey returns the time and chain ID for a pending consumer addition proposal key // or an error if unparsable func ParsePendingCAPKey(bz []byte) (time.Time, string, error) { - expectedPrefix := []byte{PendingCAPBytePrefix} - prefixL := len(expectedPrefix) - if prefix := bz[:prefixL]; !bytes.Equal(prefix, expectedPrefix) { - return time.Time{}, "", fmt.Errorf("invalid prefix; expected: %X, got: %X", expectedPrefix, prefix) - } - - timeBzL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8]) - timestamp, err := sdk.ParseTimeBytes(bz[prefixL+8 : prefixL+8+int(timeBzL)]) - if err != nil { - return time.Time{}, "", err - } - - chainID := string(bz[prefixL+8+int(timeBzL):]) - return timestamp, chainID, nil + return parseTsAndChainIdKey(PendingCAPBytePrefix, bz) } // PendingCRPKey returns the key under which pending consumer removal proposals are stored func PendingCRPKey(timestamp time.Time, chainID string) []byte { - timeBz := sdk.FormatTimeBytes(timestamp) - timeBzL := len(timeBz) - prefixL := len([]byte{PendingCRPBytePrefix}) - - bz := make([]byte, prefixL+8+timeBzL+len(chainID)) - // copy the prefix - copy(bz[:prefixL], []byte{PendingCRPBytePrefix}) - // copy the time length - copy(bz[prefixL:prefixL+8], sdk.Uint64ToBigEndian(uint64(timeBzL))) - // copy the time bytes - copy(bz[prefixL+8:prefixL+8+timeBzL], timeBz) - // copy the chainId - copy(bz[prefixL+8+timeBzL:], chainID) - return bz + return tsAndChainIdKey(PendingCRPBytePrefix, timestamp, chainID) } // ParsePendingCRPKey returns the time and chain ID for a pending consumer removal proposal key or an error if unparseable func ParsePendingCRPKey(bz []byte) (time.Time, string, error) { - expectedPrefix := []byte{PendingCRPBytePrefix} - prefixL := len(expectedPrefix) - if prefix := bz[:prefixL]; !bytes.Equal(prefix, expectedPrefix) { - return time.Time{}, "", fmt.Errorf("invalid prefix; expected: %X, got: %X", expectedPrefix, prefix) - } - - timeBzL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8]) - timestamp, err := sdk.ParseTimeBytes(bz[prefixL+8 : prefixL+8+int(timeBzL)]) - if err != nil { - return time.Time{}, "", err - } - - chainID := string(bz[prefixL+8+int(timeBzL):]) - return timestamp, chainID, nil + return parseTsAndChainIdKey(PendingCRPBytePrefix, bz) } // UnbondingOpIndexKey returns an unbonding op index key // Note: chainId is hashed to a fixed length sequence of bytes here to prevent // injection attack between chainIDs. -func UnbondingOpIndexKey(chainID string, valsetUpdateID uint64) []byte { - return AppendMany([]byte{UnbondingOpIndexBytePrefix}, HashString(chainID), - sdk.Uint64ToBigEndian(valsetUpdateID)) +func UnbondingOpIndexKey(chainID string, vscID uint64) []byte { + return chainIdAndVscIdKey(UnbondingOpIndexBytePrefix, chainID, vscID) } // ParseUnbondingOpIndexKey parses an unbonding op index key for VSC ID // Removes the prefix + chainID from index key and returns only the key part. -func ParseUnbondingOpIndexKey(key []byte) (vscID []byte, err error) { - if len(key) != UnbondingOpIndexKeySize { - return nil, sdkerrors.Wrapf( - sdkerrors.ErrLogic, "key provided is incorrect: the key has incorrect length, expected %d, got %d", - UnbondingOpIndexKeySize, len(key), - ) - } - return key[1+32:], nil +func ParseUnbondingOpIndexKey(key []byte) (string, uint64, error) { + return parseChainIdAndVscIdKey(UnbondingOpIndexBytePrefix, key) } // UnbondingOpKey returns the key that stores a record of all the ids of consumer chains that @@ -253,6 +200,18 @@ func PendingVSCsKey(chainID string) []byte { return append([]byte{PendingVSCsBytePrefix}, []byte(chainID)...) } +// VscSendingTimestampKey returns the key under which the +// sending timestamp of the VSCPacket with vsc ID is stored +func VscSendingTimestampKey(chainID string, vscID uint64) []byte { + return chainIdAndVscIdKey(VscSendTimestampBytePrefix, chainID, vscID) +} + +// ParseVscTimeoutTimestampKey returns chain ID and vsc ID +// for a VscSendingTimestampKey or an error if unparsable +func ParseVscSendingTimestampKey(bz []byte) (string, uint64, error) { + return parseChainIdAndVscIdKey(VscSendTimestampBytePrefix, bz) +} + // LockUnbondingOnTimeoutKey returns the key that will store the consumer chain id which unbonding operations are locked // on CCV channel timeout func LockUnbondingOnTimeoutKey(chainID string) []byte { @@ -267,8 +226,106 @@ func AppendMany(byteses ...[]byte) (out []byte) { return out } -// HashString outputs a fixed length 32 byte hash for any string -func HashString(x string) []byte { - hash := sha256.Sum256([]byte(x)) - return hash[:] +// tsAndChainIdKey returns the key with the following format: +// bytePrefix | len(timestamp) | timestamp | chainID +func tsAndChainIdKey(prefix byte, timestamp time.Time, chainID string) []byte { + timeBz := sdk.FormatTimeBytes(timestamp) + timeBzL := len(timeBz) + + return AppendMany( + // Append the prefix + []byte{prefix}, + // Append the time length + sdk.Uint64ToBigEndian(uint64(timeBzL)), + // Append the time bytes + timeBz, + // Append the chainId + []byte(chainID), + ) +} + +// parseTsAndChainIdKey returns the time and chain ID for a TsAndChainId key +func parseTsAndChainIdKey(prefix byte, bz []byte) (time.Time, string, error) { + expectedPrefix := []byte{prefix} + prefixL := len(expectedPrefix) + if prefix := bz[:prefixL]; !bytes.Equal(prefix, expectedPrefix) { + return time.Time{}, "", fmt.Errorf("invalid prefix; expected: %X, got: %X", expectedPrefix, prefix) + } + + timeBzL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8]) + timestamp, err := sdk.ParseTimeBytes(bz[prefixL+8 : prefixL+8+int(timeBzL)]) + if err != nil { + return time.Time{}, "", err + } + + chainID := string(bz[prefixL+8+int(timeBzL):]) + return timestamp, chainID, nil +} + +// chainIdAndTsKey returns the key with the following format: +// bytePrefix | len(chainID) | chainID | timestamp +func chainIdAndTsKey(prefix byte, chainID string, timestamp time.Time) []byte { + partialKey := ChainIdWithLenKey(prefix, chainID) + timeBz := sdk.FormatTimeBytes(timestamp) + return AppendMany( + // Append the partialKey + partialKey, + // Append the time bytes + timeBz, + ) +} + +// chainIdWithLenKey returns the key with the following format: +// bytePrefix | len(chainID) | chainID +func ChainIdWithLenKey(prefix byte, chainID string) []byte { + chainIdL := len(chainID) + return AppendMany( + // Append the prefix + []byte{prefix}, + // Append the chainID length + sdk.Uint64ToBigEndian(uint64(chainIdL)), + // Append the chainID + []byte(chainID), + ) +} + +// parseChainIdAndTsKey returns the chain ID and time for a ChainIdAndTs key +func parseChainIdAndTsKey(prefix byte, bz []byte) (string, time.Time, error) { + expectedPrefix := []byte{prefix} + prefixL := len(expectedPrefix) + if prefix := bz[:prefixL]; !bytes.Equal(prefix, expectedPrefix) { + return "", time.Time{}, fmt.Errorf("invalid prefix; expected: %X, got: %X", expectedPrefix, prefix) + } + chainIdL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8]) + chainID := string(bz[prefixL+8 : prefixL+8+int(chainIdL)]) + timestamp, err := sdk.ParseTimeBytes(bz[prefixL+8+int(chainIdL):]) + if err != nil { + return "", time.Time{}, err + } + return chainID, timestamp, nil +} + +// chainIdAndVscIdKey returns the key with the following format: +// bytePrefix | len(chainID) | chainID | vscID +func chainIdAndVscIdKey(prefix byte, chainID string, vscID uint64) []byte { + partialKey := ChainIdWithLenKey(prefix, chainID) + return AppendMany( + // Append the partialKey + partialKey, + // Append the vscID bytes + sdk.Uint64ToBigEndian(vscID), + ) +} + +// parseChainIdAndVscIdKey returns the chain ID and vsc ID for a ChainIdAndVscId key +func parseChainIdAndVscIdKey(prefix byte, bz []byte) (string, uint64, error) { + expectedPrefix := []byte{prefix} + prefixL := len(expectedPrefix) + if prefix := bz[:prefixL]; !bytes.Equal(prefix, expectedPrefix) { + return "", 0, fmt.Errorf("invalid prefix; expected: %X, got: %X", expectedPrefix, prefix) + } + chainIdL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8]) + chainID := string(bz[prefixL+8 : prefixL+8+int(chainIdL)]) + vscID := sdk.BigEndianToUint64(bz[prefixL+8+int(chainIdL):]) + return chainID, vscID, nil } diff --git a/x/ccv/provider/types/keys_test.go b/x/ccv/provider/types/keys_test.go index 9faca25676..8152ecf01a 100644 --- a/x/ccv/provider/types/keys_test.go +++ b/x/ccv/provider/types/keys_test.go @@ -34,7 +34,7 @@ func TestNoDuplicates(t *testing.T) { // any of which should be a single, unique byte. func getSingleByteKeys() [][]byte { - keys := make([][]byte, 16) + keys := make([][]byte, 32) i := 0 keys[i], i = PortKey(), i+1 @@ -43,6 +43,7 @@ func getSingleByteKeys() [][]byte { keys[i], i = []byte{ChainToChannelBytePrefix}, i+1 keys[i], i = []byte{ChannelToChainBytePrefix}, i+1 keys[i], i = []byte{ChainToClientBytePrefix}, i+1 + keys[i], i = []byte{InitTimeoutTimestampBytePrefix}, i+1 keys[i], i = []byte{PendingCAPBytePrefix}, i+1 keys[i], i = []byte{PendingCRPBytePrefix}, i+1 keys[i], i = []byte{UnbondingOpBytePrefix}, i+1 @@ -52,81 +53,85 @@ func getSingleByteKeys() [][]byte { keys[i], i = []byte{SlashAcksBytePrefix}, i+1 keys[i], i = []byte{InitChainHeightBytePrefix}, i+1 keys[i], i = []byte{PendingVSCsBytePrefix}, i+1 - keys[i] = []byte{LockUnbondingOnTimeoutBytePrefix} + keys[i], i = []byte{VscSendTimestampBytePrefix}, i+1 + keys[i], i = []byte{LockUnbondingOnTimeoutBytePrefix}, i+1 - return keys + return keys[:i] } -// Tests the construction and parsing of keys for storing pending consumer addition proposals -func TestPendingCAPKeyAndParse(t *testing.T) { +// Tests the construction and parsing of TsAndChainId keys +func TestTsAndChainIdKeyAndParse(t *testing.T) { tests := []struct { + prefix byte timestamp time.Time chainID string }{ - {timestamp: time.Now(), chainID: "1"}, - {timestamp: time.Date( + {prefix: 0x01, timestamp: time.Now(), chainID: "1"}, + {prefix: 0x02, timestamp: time.Date( 2003, 11, 17, 20, 34, 58, 651387237, time.UTC), chainID: "some other ID"}, - {timestamp: time.Now().Add(5000 * time.Hour), chainID: "some other other chain ID"}, + {prefix: 0x03, timestamp: time.Now().Add(5000 * time.Hour), chainID: "some other other chain ID"}, } for _, test := range tests { - key := PendingCAPKey(test.timestamp, test.chainID) + key := tsAndChainIdKey(test.prefix, test.timestamp, test.chainID) require.NotEmpty(t, key) // Expected bytes = prefix + time length + time bytes + length of chainID - expectedBytes := 1 + 8 + len(sdk.FormatTimeBytes(time.Time{})) + len(test.chainID) - require.Equal(t, expectedBytes, len(key)) - parsedTime, parsedID, err := ParsePendingCAPKey(key) + expectedLen := 1 + 8 + len(sdk.FormatTimeBytes(time.Time{})) + len(test.chainID) + require.Equal(t, expectedLen, len(key)) + parsedTime, parsedID, err := parseTsAndChainIdKey(test.prefix, key) require.Equal(t, test.timestamp.UTC(), parsedTime.UTC()) require.Equal(t, test.chainID, parsedID) require.NoError(t, err) } } -// Tests the construction and parsing of keys for storing pending consumer removal proposals -func TestPendingCRPKeyAndParse(t *testing.T) { +// Tests the construction and parsing of ChainIdAndTs keys +func TestChainIdAndTsKeyAndParse(t *testing.T) { tests := []struct { - timestamp time.Time + prefix byte chainID string + timestamp time.Time }{ - {timestamp: time.Now(), chainID: "5"}, - {timestamp: time.Date( - 2003, 11, 17, 20, 34, 58, 651387237, time.UTC), chainID: "some other ID"}, - {timestamp: time.Now().Add(5000 * time.Hour), chainID: "some other other chain ID"}, + {prefix: 0x01, chainID: "1", timestamp: time.Now()}, + {prefix: 0x02, chainID: "some other ID", timestamp: time.Date( + 2003, 11, 17, 20, 34, 58, 651387237, time.UTC)}, + {prefix: 0x03, chainID: "some other other chain ID", timestamp: time.Now().Add(5000 * time.Hour)}, } for _, test := range tests { - key := PendingCRPKey(test.timestamp, test.chainID) + key := chainIdAndTsKey(test.prefix, test.chainID, test.timestamp) require.NotEmpty(t, key) - // Expected bytes = prefix + time length + time bytes + length of chainID - expectedBytes := 1 + 8 + len(sdk.FormatTimeBytes(time.Time{})) + len(test.chainID) - require.Equal(t, expectedBytes, len(key)) - parsedTime, parsedID, err := ParsePendingCRPKey(key) - require.Equal(t, test.timestamp.UTC(), parsedTime.UTC()) + // Expected bytes = prefix + chainID length + chainID + time bytes + expectedLen := 1 + 8 + len(test.chainID) + len(sdk.FormatTimeBytes(time.Time{})) + require.Equal(t, expectedLen, len(key)) + parsedID, parsedTime, err := parseChainIdAndTsKey(test.prefix, key) require.Equal(t, test.chainID, parsedID) + require.Equal(t, test.timestamp.UTC(), parsedTime.UTC()) require.NoError(t, err) } } -func TestUnbondingOpIndexKeyAndParse(t *testing.T) { +// Tests the construction and parsing of ChainIdAndVscId keys +func TestChainIdAndVscIdAndParse(t *testing.T) { tests := []struct { - chainID string - valsetUpdateID uint64 + prefix byte + chainID string + vscID uint64 }{ - {chainID: " some chain id", valsetUpdateID: 45}, - {chainID: " some chain id that is longer", valsetUpdateID: 54038}, - {chainID: " some chain id that is longer-er ", valsetUpdateID: 9999999999999999999}, - {chainID: "2", valsetUpdateID: 0}, + {prefix: 0x01, chainID: "1", vscID: 1}, + {prefix: 0x02, chainID: "some other ID", vscID: 2}, + {prefix: 0x03, chainID: "some other other chain ID", vscID: 3}, } for _, test := range tests { - key := UnbondingOpIndexKey(test.chainID, test.valsetUpdateID) + key := chainIdAndVscIdKey(test.prefix, test.chainID, test.vscID) require.NotEmpty(t, key) - // This key should be of set length: prefix + hashed chain ID + uint64 - require.Equal(t, 1+32+8, len(key)) - parsedVSCID, err := ParseUnbondingOpIndexKey(key) - require.NotEmpty(t, parsedVSCID) - asUint64 := sdk.BigEndianToUint64(parsedVSCID) - require.Equal(t, test.valsetUpdateID, asUint64) + // Expected bytes = prefix + chainID length + chainID + vscId bytes + expectedLen := 1 + 8 + len(test.chainID) + 8 + require.Equal(t, expectedLen, len(key)) + parsedID, parsedVscID, err := parseChainIdAndVscIdKey(test.prefix, key) + require.Equal(t, test.chainID, parsedID) + require.Equal(t, test.vscID, parsedVscID) require.NoError(t, err) } } @@ -138,6 +143,7 @@ func TestKeysWithPrefixAndId(t *testing.T) { ChainToChannelKey, ChannelToChainKey, ChainToClientKey, + InitTimeoutTimestampKey, ConsumerGenesisKey, SlashAcksKey, InitChainHeightKey, @@ -149,6 +155,7 @@ func TestKeysWithPrefixAndId(t *testing.T) { ChainToChannelBytePrefix, ChannelToChainBytePrefix, ChainToClientBytePrefix, + InitTimeoutTimestampBytePrefix, ConsumerGenesisBytePrefix, SlashAcksBytePrefix, InitChainHeightBytePrefix, diff --git a/x/ccv/provider/types/params.go b/x/ccv/provider/types/params.go index b121a718a9..be3281ee06 100644 --- a/x/ccv/provider/types/params.go +++ b/x/ccv/provider/types/params.go @@ -8,33 +8,53 @@ import ( clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types" ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types" + consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" + ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" ) const ( - // DefaultTrustingPeriod is duration of the period since - // the LastestTimestamp during which the submitted headers are valid for upgrade - DefaultTrustingPeriod = 3 * 7 * 24 * time.Hour - - // DefaultUnbondingPeriod of the staking unbonding period - DefaultUnbondingPeriod = 4 * 7 * 24 * time.Hour - // DefaultMaxClockDrift defines how much new (untrusted) header's Time can drift into the future. + // This default is only used in the default template client param. DefaultMaxClockDrift = 10 * time.Second + + // DefaultTrustingPeriodFraction is the default fraction used to compute TrustingPeriod + // as UnbondingPeriod / TrustingPeriodFraction + DefaultTrustingPeriodFraction = 2 + + // DefaultInitTimeoutPeriod defines the init timeout period + DefaultInitTimeoutPeriod = 7 * 24 * time.Hour + + // DefaultVscTimeoutPeriod defines the VSC timeout period + DefaultVscTimeoutPeriod = 5 * 7 * 24 * time.Hour ) +// Reflection based keys for params subspace var ( - KeyTemplateClient = []byte("TemplateClient") + KeyTemplateClient = []byte("TemplateClient") + KeyTrustingPeriodFraction = []byte("TrustingPeriodFraction") + KeyInitTimeoutPeriod = []byte("InitTimeoutPeriod") + KeyVscTimeoutPeriod = []byte("VscTimeoutPeriod") ) -// ParamKeyTable type declaration for parameters +// ParamKeyTable returns a key table with the necessary registered provider params func ParamKeyTable() paramtypes.KeyTable { return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) } // NewParams creates new provider parameters with provided arguments -func NewParams(cs *ibctmtypes.ClientState) Params { +func NewParams( + cs *ibctmtypes.ClientState, + trustingPeriodFraction int64, + ccvTimeoutPeriod time.Duration, + initTimeoutPeriod time.Duration, + vscTimeoutPeriod time.Duration, +) Params { return Params{ - TemplateClient: cs, + TemplateClient: cs, + TrustingPeriodFraction: trustingPeriodFraction, + CcvTimeoutPeriod: ccvTimeoutPeriod, + InitTimeoutPeriod: initTimeoutPeriod, + VscTimeoutPeriod: vscTimeoutPeriod, } } @@ -43,30 +63,63 @@ func DefaultParams() Params { // create default client state with chainID, trusting period, unbonding period, and inital height zeroed out. // these fields will be populated during proposal handler. return NewParams( - ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, - DefaultMaxClockDrift, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"upgrade", "upgradedIBCState"}, true, true), + ibctmtypes.NewClientState( + "", // chainID + ibctmtypes.DefaultTrustLevel, + 0, // trusting period + 0, // unbonding period + DefaultMaxClockDrift, + clienttypes.Height{}, // latest(initial) height + commitmenttypes.GetSDKSpecs(), + []string{"upgrade", "upgradedIBCState"}, + true, + true, + ), + DefaultTrustingPeriodFraction, + ccvtypes.DefaultCCVTimeoutPeriod, + DefaultInitTimeoutPeriod, + DefaultVscTimeoutPeriod, ) } // Validate all ccv-provider module parameters func (p Params) Validate() error { if p.TemplateClient == nil { - return fmt.Errorf("Template client is nil") + return fmt.Errorf("template client is nil") + } + if err := validateTemplateClient(*p.TemplateClient); err != nil { + return err + } + if err := ccvtypes.ValidatePositiveInt64(p.TrustingPeriodFraction); err != nil { + return fmt.Errorf("trusting period fraction is invalid: %s", err) + } + if err := ccvtypes.ValidateDuration(p.CcvTimeoutPeriod); err != nil { + return fmt.Errorf("ccv timeout period is invalid: %s", err) } - return validateTemplateClient(*p.TemplateClient) + if err := ccvtypes.ValidateDuration(p.InitTimeoutPeriod); err != nil { + return fmt.Errorf("init timeout period is invalid: %s", err) + } + if err := ccvtypes.ValidateDuration(p.VscTimeoutPeriod); err != nil { + return fmt.Errorf("vsc timeout period is invalid: %s", err) + } + return nil } // ParamSetPairs implements params.ParamSet func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ paramtypes.NewParamSetPair(KeyTemplateClient, p.TemplateClient, validateTemplateClient), + paramtypes.NewParamSetPair(KeyTrustingPeriodFraction, p.TrustingPeriodFraction, ccvtypes.ValidatePositiveInt64), + paramtypes.NewParamSetPair(ccvtypes.KeyCCVTimeoutPeriod, p.CcvTimeoutPeriod, ccvtypes.ValidateDuration), + paramtypes.NewParamSetPair(KeyInitTimeoutPeriod, p.InitTimeoutPeriod, ccvtypes.ValidateDuration), + paramtypes.NewParamSetPair(KeyVscTimeoutPeriod, p.VscTimeoutPeriod, ccvtypes.ValidateDuration), } } func validateTemplateClient(i interface{}) error { cs, ok := i.(ibctmtypes.ClientState) if !ok { - return fmt.Errorf("invalid parameter type: %T", i) + return fmt.Errorf("invalid parameter type: %T, expected: %T", i, ibctmtypes.ClientState{}) } // copy clientstate to prevent changing original pointer @@ -74,8 +127,8 @@ func validateTemplateClient(i interface{}) error { // populate zeroed fields with valid fields copiedClient.ChainId = "chainid" - copiedClient.TrustingPeriod = DefaultTrustingPeriod - copiedClient.UnbondingPeriod = DefaultUnbondingPeriod + copiedClient.TrustingPeriod = consumertypes.DefaultConsumerUnbondingPeriod / DefaultTrustingPeriodFraction + copiedClient.UnbondingPeriod = consumertypes.DefaultConsumerUnbondingPeriod copiedClient.LatestHeight = clienttypes.NewHeight(0, 1) if err := copiedClient.Validate(); err != nil { diff --git a/x/ccv/provider/types/params_test.go b/x/ccv/provider/types/params_test.go index f5252327b1..f4a13a7bd3 100644 --- a/x/ccv/provider/types/params_test.go +++ b/x/ccv/provider/types/params_test.go @@ -13,6 +13,7 @@ import ( ) func TestValidateParams(t *testing.T) { + testCases := []struct { name string params types.Params @@ -20,11 +21,26 @@ func TestValidateParams(t *testing.T) { }{ {"default params", types.DefaultParams(), true}, {"custom valid params", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, - time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false)), true}, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + 3, time.Hour, time.Hour, time.Hour), true}, {"custom invalid params", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, - 0, clienttypes.Height{}, nil, []string{"ibc", "upgradedIBCState"}, true, false)), false}, - {"blank client", types.NewParams(&ibctmtypes.ClientState{}), false}, - {"nil client", types.NewParams(nil), false}, + 0, clienttypes.Height{}, nil, []string{"ibc", "upgradedIBCState"}, true, false), + 3, time.Hour, time.Hour, time.Hour), false}, + {"blank client", types.NewParams(&ibctmtypes.ClientState{}, + 3, time.Hour, time.Hour, time.Hour), false}, + {"nil client", types.NewParams(nil, 3, time.Hour, time.Hour, time.Hour), false}, + {"0 trusting period fraction (denominator)", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + 0, time.Hour, time.Hour, time.Hour), false}, + {"0 ccv timeout period", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + 3, 0, time.Hour, time.Hour), false}, + {"0 init timeout period", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + 3, time.Hour, 0, time.Hour), false}, + {"0 vsc timeout period", types.NewParams(ibctmtypes.NewClientState("", ibctmtypes.DefaultTrustLevel, 0, 0, + time.Second*40, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), []string{"ibc", "upgradedIBCState"}, true, false), + 3, time.Hour, time.Hour, 0), false}, } for _, tc := range testCases { diff --git a/x/ccv/provider/types/proposal.go b/x/ccv/provider/types/proposal.go index 7462115b9a..45d32495a7 100644 --- a/x/ccv/provider/types/proposal.go +++ b/x/ccv/provider/types/proposal.go @@ -17,10 +17,12 @@ const ( var ( _ govtypes.Content = &ConsumerAdditionProposal{} + _ govtypes.Content = &ConsumerRemovalProposal{} ) func init() { govtypes.RegisterProposalType(ProposalTypeConsumerAddition) + govtypes.RegisterProposalType(ProposalTypeConsumerRemoval) } // NewConsumerAdditionProposal creates a new consumer addition proposal. diff --git a/x/ccv/provider/types/provider.pb.go b/x/ccv/provider/types/provider.pb.go index df9f5228ab..b928cb9751 100644 --- a/x/ccv/provider/types/provider.pb.go +++ b/x/ccv/provider/types/provider.pb.go @@ -10,6 +10,7 @@ import ( _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "google.golang.org/protobuf/types/known/durationpb" _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" @@ -166,6 +167,17 @@ func (m *ConsumerRemovalProposal) GetStopTime() time.Time { // Params defines the parameters for CCV Provider module type Params struct { TemplateClient *types1.ClientState `protobuf:"bytes,1,opt,name=template_client,json=templateClient,proto3" json:"template_client,omitempty"` + // TrustingPeriodFraction is used to compute the consumer and provider IBC client's TrustingPeriod from the chain defined UnbondingPeriod + TrustingPeriodFraction int64 `protobuf:"varint,2,opt,name=trusting_period_fraction,json=trustingPeriodFraction,proto3" json:"trusting_period_fraction,omitempty"` + // Sent IBC packets will timeout after this duration + CcvTimeoutPeriod time.Duration `protobuf:"bytes,3,opt,name=ccv_timeout_period,json=ccvTimeoutPeriod,proto3,stdduration" json:"ccv_timeout_period"` + // The channel initialization (IBC channel opening handshake) will timeout after this duration + InitTimeoutPeriod time.Duration `protobuf:"bytes,4,opt,name=init_timeout_period,json=initTimeoutPeriod,proto3,stdduration" json:"init_timeout_period"` + // The VSC packets sent by the provider will timeout after this duration. + // Note that unlike ccv_timeout_period which is an IBC param, + // the vsc_timeout_period is a provider-side param that enables the provider + // to timeout VSC packets even when a consumer chain is not live. + VscTimeoutPeriod time.Duration `protobuf:"bytes,5,opt,name=vsc_timeout_period,json=vscTimeoutPeriod,proto3,stdduration" json:"vsc_timeout_period"` } func (m *Params) Reset() { *m = Params{} } @@ -208,6 +220,34 @@ func (m *Params) GetTemplateClient() *types1.ClientState { return nil } +func (m *Params) GetTrustingPeriodFraction() int64 { + if m != nil { + return m.TrustingPeriodFraction + } + return 0 +} + +func (m *Params) GetCcvTimeoutPeriod() time.Duration { + if m != nil { + return m.CcvTimeoutPeriod + } + return 0 +} + +func (m *Params) GetInitTimeoutPeriod() time.Duration { + if m != nil { + return m.InitTimeoutPeriod + } + return 0 +} + +func (m *Params) GetVscTimeoutPeriod() time.Duration { + if m != nil { + return m.VscTimeoutPeriod + } + return 0 +} + type HandshakeMetadata struct { ProviderFeePoolAddr string `protobuf:"bytes,1,opt,name=provider_fee_pool_addr,json=providerFeePoolAddr,proto3" json:"provider_fee_pool_addr,omitempty"` Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` @@ -306,12 +346,106 @@ func (m *SlashAcks) GetAddresses() []string { return nil } +// ConsumerAdditionProposals holds pending governance proposals on the provider chain to spawn a new chain. +type ConsumerAdditionProposals struct { + // proposals waiting for spawn_time to pass + Pending []*ConsumerAdditionProposal `protobuf:"bytes,1,rep,name=pending,proto3" json:"pending,omitempty"` +} + +func (m *ConsumerAdditionProposals) Reset() { *m = ConsumerAdditionProposals{} } +func (m *ConsumerAdditionProposals) String() string { return proto.CompactTextString(m) } +func (*ConsumerAdditionProposals) ProtoMessage() {} +func (*ConsumerAdditionProposals) Descriptor() ([]byte, []int) { + return fileDescriptor_f22ec409a72b7b72, []int{5} +} +func (m *ConsumerAdditionProposals) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsumerAdditionProposals) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsumerAdditionProposals.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ConsumerAdditionProposals) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsumerAdditionProposals.Merge(m, src) +} +func (m *ConsumerAdditionProposals) XXX_Size() int { + return m.Size() +} +func (m *ConsumerAdditionProposals) XXX_DiscardUnknown() { + xxx_messageInfo_ConsumerAdditionProposals.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsumerAdditionProposals proto.InternalMessageInfo + +func (m *ConsumerAdditionProposals) GetPending() []*ConsumerAdditionProposal { + if m != nil { + return m.Pending + } + return nil +} + +// ConsumerRemovalProposals holds pending governance proposals on the provider chain to remove (and stop) a consumer chain. +type ConsumerRemovalProposals struct { + // proposals waiting for stop_time to pass + Pending []*ConsumerRemovalProposal `protobuf:"bytes,1,rep,name=pending,proto3" json:"pending,omitempty"` +} + +func (m *ConsumerRemovalProposals) Reset() { *m = ConsumerRemovalProposals{} } +func (m *ConsumerRemovalProposals) String() string { return proto.CompactTextString(m) } +func (*ConsumerRemovalProposals) ProtoMessage() {} +func (*ConsumerRemovalProposals) Descriptor() ([]byte, []int) { + return fileDescriptor_f22ec409a72b7b72, []int{6} +} +func (m *ConsumerRemovalProposals) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsumerRemovalProposals) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsumerRemovalProposals.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ConsumerRemovalProposals) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsumerRemovalProposals.Merge(m, src) +} +func (m *ConsumerRemovalProposals) XXX_Size() int { + return m.Size() +} +func (m *ConsumerRemovalProposals) XXX_DiscardUnknown() { + xxx_messageInfo_ConsumerRemovalProposals.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsumerRemovalProposals proto.InternalMessageInfo + +func (m *ConsumerRemovalProposals) GetPending() []*ConsumerRemovalProposal { + if m != nil { + return m.Pending + } + return nil +} + func init() { proto.RegisterType((*ConsumerAdditionProposal)(nil), "interchain_security.ccv.provider.v1.ConsumerAdditionProposal") proto.RegisterType((*ConsumerRemovalProposal)(nil), "interchain_security.ccv.provider.v1.ConsumerRemovalProposal") proto.RegisterType((*Params)(nil), "interchain_security.ccv.provider.v1.Params") proto.RegisterType((*HandshakeMetadata)(nil), "interchain_security.ccv.provider.v1.HandshakeMetadata") proto.RegisterType((*SlashAcks)(nil), "interchain_security.ccv.provider.v1.SlashAcks") + proto.RegisterType((*ConsumerAdditionProposals)(nil), "interchain_security.ccv.provider.v1.ConsumerAdditionProposals") + proto.RegisterType((*ConsumerRemovalProposals)(nil), "interchain_security.ccv.provider.v1.ConsumerRemovalProposals") } func init() { @@ -319,47 +453,57 @@ func init() { } var fileDescriptor_f22ec409a72b7b72 = []byte{ - // 638 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xbf, 0x6f, 0xd4, 0x30, - 0x14, 0xbe, 0xd0, 0x5f, 0x77, 0xbe, 0x52, 0x44, 0xa8, 0x4a, 0x5a, 0xa1, 0xbb, 0xe3, 0x58, 0x0e, - 0x21, 0x12, 0x5d, 0x3b, 0xd1, 0xed, 0x5a, 0x09, 0xca, 0x80, 0xa8, 0xd2, 0xb2, 0x30, 0x10, 0x39, - 0xf6, 0x6b, 0x62, 0x35, 0xb1, 0x23, 0xdb, 0x09, 0x74, 0x67, 0x60, 0xec, 0xc8, 0xd8, 0xff, 0x80, - 0x7f, 0xa3, 0x63, 0x47, 0x26, 0x40, 0xed, 0x3f, 0x82, 0x62, 0x5f, 0x7a, 0x87, 0xc4, 0xc2, 0xc0, - 0xe6, 0xf7, 0xbd, 0xef, 0x73, 0xde, 0x7b, 0x9f, 0xf3, 0xd0, 0x36, 0xe3, 0x1a, 0x24, 0x49, 0x31, - 0xe3, 0x91, 0x02, 0x52, 0x4a, 0xa6, 0xcf, 0x02, 0x42, 0xaa, 0xa0, 0x90, 0xa2, 0x62, 0x14, 0x64, - 0x50, 0x8d, 0x6f, 0xcf, 0x7e, 0x21, 0x85, 0x16, 0xee, 0x93, 0xbf, 0x68, 0x7c, 0x42, 0x2a, 0xff, - 0x96, 0x57, 0x8d, 0xb7, 0xd6, 0x13, 0x91, 0x08, 0xc3, 0x0f, 0xea, 0x93, 0x95, 0x6e, 0xf5, 0x13, - 0x21, 0x92, 0x0c, 0x02, 0x13, 0xc5, 0xe5, 0x49, 0xa0, 0x59, 0x0e, 0x4a, 0xe3, 0xbc, 0x68, 0x08, - 0x2c, 0x26, 0x01, 0x11, 0x12, 0x02, 0x92, 0x31, 0xe0, 0xba, 0xfe, 0xbc, 0x3d, 0x4d, 0x09, 0x41, - 0x4d, 0xc8, 0x58, 0x92, 0x6a, 0x0b, 0xab, 0x40, 0x03, 0xa7, 0x20, 0x73, 0x66, 0xc9, 0xb3, 0xc8, - 0x0a, 0x86, 0x9f, 0x17, 0x90, 0xb7, 0x2f, 0xb8, 0x2a, 0x73, 0x90, 0x13, 0x4a, 0x99, 0x66, 0x82, - 0x1f, 0x4a, 0x51, 0x08, 0x85, 0x33, 0x77, 0x1d, 0x2d, 0x69, 0xa6, 0x33, 0xf0, 0x9c, 0x81, 0x33, - 0xea, 0x84, 0x36, 0x70, 0x07, 0xa8, 0x4b, 0x41, 0x11, 0xc9, 0x8a, 0x9a, 0xec, 0xdd, 0x31, 0xb9, - 0x79, 0xc8, 0xdd, 0x44, 0x6d, 0xdb, 0x3f, 0xa3, 0xde, 0x82, 0x49, 0xaf, 0x98, 0xf8, 0x35, 0x75, - 0x5f, 0xa1, 0x35, 0xc6, 0x99, 0x66, 0x38, 0x8b, 0x52, 0xa8, 0xeb, 0xf4, 0x16, 0x07, 0xce, 0xa8, - 0xbb, 0xbd, 0xe5, 0xb3, 0x98, 0xf8, 0x75, 0x6b, 0xfe, 0xb4, 0xa1, 0x6a, 0xec, 0x1f, 0x18, 0xc6, - 0xde, 0xe2, 0xe5, 0x8f, 0x7e, 0x2b, 0xbc, 0x3b, 0xd5, 0x59, 0xd0, 0x7d, 0x8c, 0x56, 0x13, 0xe0, - 0xa0, 0x98, 0x8a, 0x52, 0xac, 0x52, 0x6f, 0x69, 0xe0, 0x8c, 0x56, 0xc3, 0xee, 0x14, 0x3b, 0xc0, - 0x2a, 0x75, 0xfb, 0xa8, 0x1b, 0x33, 0x8e, 0xe5, 0x99, 0x65, 0x2c, 0x1b, 0x06, 0xb2, 0x90, 0x21, - 0xec, 0x23, 0xa4, 0x0a, 0xfc, 0x91, 0x47, 0xf5, 0x9c, 0xbd, 0x95, 0x69, 0x21, 0xd6, 0x04, 0xbf, - 0x31, 0xc1, 0x3f, 0x6e, 0x4c, 0xd8, 0x6b, 0xd7, 0x85, 0x9c, 0xff, 0xec, 0x3b, 0x61, 0xc7, 0xe8, - 0xea, 0x8c, 0xfb, 0x02, 0x6d, 0x66, 0x82, 0x9c, 0x46, 0x25, 0x8f, 0x05, 0xa7, 0x8c, 0x27, 0x91, - 0xb0, 0x17, 0x8a, 0x52, 0x7b, 0xed, 0x81, 0x33, 0x6a, 0x87, 0x1b, 0x35, 0xe1, 0x5d, 0x93, 0x7f, - 0x6b, 0x74, 0xa2, 0xd4, 0xbb, 0xed, 0x2f, 0x17, 0xfd, 0xd6, 0xd7, 0x8b, 0x7e, 0x6b, 0xf8, 0xcd, - 0x41, 0x0f, 0x1b, 0x1b, 0x42, 0xc8, 0x45, 0x85, 0xb3, 0xff, 0xe9, 0xc2, 0x04, 0x75, 0x94, 0x16, - 0x85, 0xed, 0x7b, 0xf1, 0x1f, 0xfa, 0x6e, 0xd7, 0xb2, 0x3a, 0x31, 0xfc, 0x80, 0x96, 0x0f, 0xb1, - 0xc4, 0xb9, 0x72, 0x8f, 0xd1, 0x3d, 0x0d, 0x79, 0x91, 0x61, 0x0d, 0x91, 0xf5, 0xce, 0x54, 0xda, - 0xdd, 0x7e, 0x66, 0x3c, 0x9d, 0x7f, 0x8d, 0xfe, 0xdc, 0xfb, 0xab, 0xc6, 0xfe, 0xbe, 0x41, 0x8f, - 0x34, 0xd6, 0x10, 0xae, 0x35, 0x77, 0x58, 0x70, 0x18, 0xa3, 0xfb, 0x07, 0x98, 0x53, 0x95, 0xe2, - 0x53, 0x78, 0x03, 0x1a, 0x53, 0xac, 0xb1, 0xbb, 0x83, 0x36, 0x9a, 0xbf, 0x28, 0x3a, 0x01, 0x88, - 0x0a, 0x21, 0xb2, 0x08, 0x53, 0x2a, 0xa7, 0xb3, 0x79, 0xd0, 0x64, 0x5f, 0x02, 0x1c, 0x0a, 0x91, - 0x4d, 0x28, 0x95, 0xae, 0x87, 0x56, 0x2a, 0x90, 0x6a, 0x36, 0xa5, 0x26, 0x1c, 0x3e, 0x45, 0x9d, - 0xa3, 0x0c, 0xab, 0x74, 0x42, 0x4e, 0x95, 0xfb, 0x08, 0x75, 0xea, 0x9b, 0x40, 0x29, 0x50, 0x9e, - 0x33, 0x58, 0x18, 0x75, 0xc2, 0x19, 0xb0, 0x77, 0x7c, 0x79, 0xdd, 0x73, 0xae, 0xae, 0x7b, 0xce, - 0xaf, 0xeb, 0x9e, 0x73, 0x7e, 0xd3, 0x6b, 0x5d, 0xdd, 0xf4, 0x5a, 0xdf, 0x6f, 0x7a, 0xad, 0xf7, - 0xbb, 0x09, 0xd3, 0x69, 0x19, 0xfb, 0x44, 0xe4, 0x01, 0x11, 0x2a, 0x17, 0x2a, 0x98, 0x6d, 0x80, - 0xe7, 0xb7, 0x5b, 0xe3, 0xd3, 0x9f, 0x7b, 0x43, 0x9f, 0x15, 0xa0, 0xe2, 0x65, 0x33, 0xec, 0x9d, - 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xad, 0x37, 0xb8, 0x76, 0x68, 0x04, 0x00, 0x00, + // 797 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x41, 0x6f, 0xe3, 0x44, + 0x14, 0x8e, 0x49, 0xda, 0x24, 0x93, 0x65, 0x61, 0x67, 0x57, 0xc5, 0xa9, 0x50, 0x12, 0xc2, 0x25, + 0x08, 0x61, 0x2b, 0xd9, 0x0b, 0xac, 0xe0, 0x90, 0x16, 0x2d, 0xe5, 0x80, 0xc8, 0xba, 0x05, 0x24, + 0x2e, 0xd6, 0x78, 0x66, 0x6a, 0x8f, 0x6a, 0x7b, 0xac, 0x99, 0xb1, 0xa1, 0x77, 0x0e, 0x1c, 0x57, + 0xe2, 0xb2, 0xc7, 0xfd, 0x07, 0xfc, 0x8d, 0x3d, 0xf6, 0xc8, 0x09, 0x50, 0xfb, 0x47, 0xd0, 0xcc, + 0xd8, 0x49, 0x1b, 0xa8, 0xd4, 0x1e, 0xb8, 0x79, 0xde, 0xfb, 0xbe, 0x6f, 0xde, 0x9b, 0xef, 0xcd, + 0x18, 0x2c, 0x58, 0xae, 0xa8, 0xc0, 0x09, 0x62, 0x79, 0x28, 0x29, 0x2e, 0x05, 0x53, 0xe7, 0x3e, + 0xc6, 0x95, 0x5f, 0x08, 0x5e, 0x31, 0x42, 0x85, 0x5f, 0xcd, 0xd7, 0xdf, 0x5e, 0x21, 0xb8, 0xe2, + 0xf0, 0xc3, 0xff, 0xe0, 0x78, 0x18, 0x57, 0xde, 0x1a, 0x57, 0xcd, 0xf7, 0x9f, 0xc4, 0x3c, 0xe6, + 0x06, 0xef, 0xeb, 0x2f, 0x4b, 0xdd, 0x1f, 0xc7, 0x9c, 0xc7, 0x29, 0xf5, 0xcd, 0x2a, 0x2a, 0x4f, + 0x7d, 0xc5, 0x32, 0x2a, 0x15, 0xca, 0x8a, 0x1a, 0x30, 0xda, 0x06, 0x90, 0x52, 0x20, 0xc5, 0x78, + 0xde, 0x08, 0xb0, 0x08, 0xfb, 0x98, 0x0b, 0xea, 0xe3, 0x94, 0xd1, 0x5c, 0xe9, 0xf2, 0xec, 0x57, + 0x0d, 0xf0, 0x35, 0x20, 0x65, 0x71, 0xa2, 0x6c, 0x58, 0xfa, 0x8a, 0xe6, 0x84, 0x8a, 0x8c, 0x59, + 0xf0, 0x66, 0x65, 0x09, 0xd3, 0x5f, 0xda, 0xc0, 0x3d, 0xe4, 0xb9, 0x2c, 0x33, 0x2a, 0x96, 0x84, + 0x30, 0xbd, 0xd9, 0x4a, 0xf0, 0x82, 0x4b, 0x94, 0xc2, 0x27, 0x60, 0x47, 0x31, 0x95, 0x52, 0xd7, + 0x99, 0x38, 0xb3, 0x7e, 0x60, 0x17, 0x70, 0x02, 0x06, 0x84, 0x4a, 0x2c, 0x58, 0xa1, 0xc1, 0xee, + 0x5b, 0x26, 0x77, 0x3d, 0x04, 0x87, 0xa0, 0x67, 0xcf, 0x87, 0x11, 0xb7, 0x6d, 0xd2, 0x5d, 0xb3, + 0xfe, 0x9a, 0xc0, 0xaf, 0xc0, 0x43, 0x96, 0x33, 0xc5, 0x50, 0x1a, 0x26, 0x54, 0xd7, 0xe9, 0x76, + 0x26, 0xce, 0x6c, 0xb0, 0xd8, 0xf7, 0x58, 0x84, 0x3d, 0xdd, 0x9a, 0x57, 0x37, 0x54, 0xcd, 0xbd, + 0x23, 0x83, 0x38, 0xe8, 0xbc, 0xf9, 0x73, 0xdc, 0x0a, 0xde, 0xae, 0x79, 0x36, 0x08, 0x3f, 0x00, + 0x0f, 0x62, 0x9a, 0x53, 0xc9, 0x64, 0x98, 0x20, 0x99, 0xb8, 0x3b, 0x13, 0x67, 0xf6, 0x20, 0x18, + 0xd4, 0xb1, 0x23, 0x24, 0x13, 0x38, 0x06, 0x83, 0x88, 0xe5, 0x48, 0x9c, 0x5b, 0xc4, 0xae, 0x41, + 0x00, 0x1b, 0x32, 0x80, 0x43, 0x00, 0x64, 0x81, 0x7e, 0xca, 0x43, 0xed, 0x83, 0xdb, 0xad, 0x0b, + 0xb1, 0x1e, 0x78, 0x8d, 0x07, 0xde, 0x49, 0x63, 0xd2, 0x41, 0x4f, 0x17, 0xf2, 0xf2, 0xaf, 0xb1, + 0x13, 0xf4, 0x0d, 0x4f, 0x67, 0xe0, 0x67, 0x60, 0x98, 0x72, 0x7c, 0x16, 0x96, 0x79, 0xc4, 0x73, + 0xc2, 0xf2, 0x38, 0xe4, 0x56, 0x90, 0x97, 0xca, 0xed, 0x4d, 0x9c, 0x59, 0x2f, 0xd8, 0xd3, 0x80, + 0xef, 0x9a, 0xfc, 0xb7, 0x86, 0xc7, 0x4b, 0xf5, 0xac, 0xf7, 0xeb, 0xeb, 0x71, 0xeb, 0xd5, 0xeb, + 0x71, 0x6b, 0xfa, 0xbb, 0x03, 0xde, 0x6b, 0x6c, 0x08, 0x68, 0xc6, 0x2b, 0x94, 0xfe, 0x9f, 0x2e, + 0x2c, 0x41, 0x5f, 0x2a, 0x5e, 0xd8, 0xbe, 0x3b, 0xf7, 0xe8, 0xbb, 0xa7, 0x69, 0x3a, 0x31, 0xfd, + 0xad, 0x0d, 0x76, 0x57, 0x48, 0xa0, 0x4c, 0xc2, 0x13, 0xf0, 0x8e, 0xa2, 0x59, 0x91, 0x22, 0x45, + 0x43, 0x6b, 0x9e, 0x29, 0x75, 0xb0, 0xf8, 0xd8, 0x98, 0x7a, 0x7d, 0x1c, 0xbd, 0x6b, 0x03, 0x58, + 0xcd, 0xbd, 0x43, 0x13, 0x3d, 0x56, 0x48, 0xd1, 0xe0, 0x61, 0xa3, 0x61, 0x83, 0xf0, 0x53, 0xe0, + 0x2a, 0x51, 0x4a, 0xa5, 0x4f, 0xb4, 0xa0, 0x82, 0x71, 0x12, 0x9e, 0x0a, 0x84, 0xd7, 0xdd, 0xb6, + 0x83, 0xbd, 0x26, 0xbf, 0x32, 0xe9, 0xe7, 0x75, 0x16, 0xbe, 0x00, 0x10, 0xe3, 0xaa, 0xf1, 0xa0, + 0x26, 0x9b, 0x23, 0x18, 0x2c, 0x86, 0xff, 0x6a, 0xf3, 0xcb, 0xfa, 0x8a, 0xd9, 0x2e, 0x5f, 0xe9, + 0x2e, 0xdf, 0xc5, 0xb8, 0xaa, 0x3d, 0xb2, 0xd2, 0xf0, 0x18, 0x3c, 0xd6, 0xe3, 0xb7, 0xad, 0xd9, + 0xb9, 0xbb, 0xe6, 0x23, 0xcd, 0xbf, 0x29, 0xfa, 0x02, 0xc0, 0x4a, 0xe2, 0x6d, 0xcd, 0x9d, 0x7b, + 0xd4, 0x59, 0x49, 0x7c, 0x43, 0x72, 0x1a, 0x81, 0x47, 0x47, 0x28, 0x27, 0x32, 0x41, 0x67, 0xf4, + 0x1b, 0xaa, 0x10, 0x41, 0x0a, 0xc1, 0xa7, 0x60, 0xaf, 0x79, 0x9b, 0xc2, 0x53, 0x4a, 0xc3, 0x82, + 0xf3, 0x34, 0x44, 0x84, 0x88, 0x7a, 0xa2, 0x1e, 0x37, 0xd9, 0xe7, 0x94, 0xae, 0x38, 0x4f, 0x97, + 0x84, 0x08, 0xe8, 0x82, 0x6e, 0x45, 0x85, 0xdc, 0xcc, 0x56, 0xb3, 0x9c, 0x7e, 0x04, 0xfa, 0xc7, + 0x29, 0x92, 0xc9, 0x12, 0x9f, 0x49, 0xf8, 0x3e, 0xe8, 0x6b, 0x25, 0x2a, 0x25, 0x95, 0xae, 0x33, + 0x69, 0xcf, 0xfa, 0xc1, 0x26, 0x30, 0x55, 0x60, 0x78, 0xdb, 0xe3, 0x22, 0xe1, 0x0f, 0xa0, 0x5b, + 0x50, 0x73, 0x23, 0x0c, 0x71, 0xb0, 0xf8, 0xc2, 0xbb, 0xc3, 0xd3, 0xea, 0xdd, 0x26, 0x18, 0x34, + 0x6a, 0x53, 0xb1, 0x79, 0xd2, 0xb6, 0xee, 0x92, 0x84, 0xdf, 0x6f, 0x6f, 0xfa, 0xf9, 0xbd, 0x36, + 0xdd, 0xd2, 0x5b, 0xef, 0x79, 0x70, 0xf2, 0xe6, 0x72, 0xe4, 0x5c, 0x5c, 0x8e, 0x9c, 0xbf, 0x2f, + 0x47, 0xce, 0xcb, 0xab, 0x51, 0xeb, 0xe2, 0x6a, 0xd4, 0xfa, 0xe3, 0x6a, 0xd4, 0xfa, 0xf1, 0x59, + 0xcc, 0x54, 0x52, 0x46, 0x1e, 0xe6, 0x99, 0x8f, 0xb9, 0xcc, 0xb8, 0xf4, 0x37, 0x3b, 0x7e, 0xb2, + 0xfe, 0xeb, 0xfc, 0x7c, 0xf3, 0xbf, 0xa3, 0xce, 0x0b, 0x2a, 0xa3, 0x5d, 0xe3, 0xfe, 0xd3, 0x7f, + 0x02, 0x00, 0x00, 0xff, 0xff, 0x97, 0x79, 0x3f, 0x95, 0xa8, 0x06, 0x00, 0x00, } func (m *ConsumerAdditionProposal) Marshal() (dAtA []byte, err error) { @@ -520,6 +664,35 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + n4, err4 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.VscTimeoutPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.VscTimeoutPeriod):]) + if err4 != nil { + return 0, err4 + } + i -= n4 + i = encodeVarintProvider(dAtA, i, uint64(n4)) + i-- + dAtA[i] = 0x2a + n5, err5 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.InitTimeoutPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.InitTimeoutPeriod):]) + if err5 != nil { + return 0, err5 + } + i -= n5 + i = encodeVarintProvider(dAtA, i, uint64(n5)) + i-- + dAtA[i] = 0x22 + n6, err6 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.CcvTimeoutPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.CcvTimeoutPeriod):]) + if err6 != nil { + return 0, err6 + } + i -= n6 + i = encodeVarintProvider(dAtA, i, uint64(n6)) + i-- + dAtA[i] = 0x1a + if m.TrustingPeriodFraction != 0 { + i = encodeVarintProvider(dAtA, i, uint64(m.TrustingPeriodFraction)) + i-- + dAtA[i] = 0x10 + } if m.TemplateClient != nil { { size, err := m.TemplateClient.MarshalToSizedBuffer(dAtA[:i]) @@ -604,6 +777,80 @@ func (m *SlashAcks) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ConsumerAdditionProposals) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsumerAdditionProposals) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsumerAdditionProposals) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Pending) > 0 { + for iNdEx := len(m.Pending) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Pending[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintProvider(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ConsumerRemovalProposals) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsumerRemovalProposals) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsumerRemovalProposals) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Pending) > 0 { + for iNdEx := len(m.Pending) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Pending[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintProvider(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintProvider(dAtA []byte, offset int, v uint64) int { offset -= sovProvider(v) base := offset @@ -684,6 +931,15 @@ func (m *Params) Size() (n int) { l = m.TemplateClient.Size() n += 1 + l + sovProvider(uint64(l)) } + if m.TrustingPeriodFraction != 0 { + n += 1 + sovProvider(uint64(m.TrustingPeriodFraction)) + } + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.CcvTimeoutPeriod) + n += 1 + l + sovProvider(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.InitTimeoutPeriod) + n += 1 + l + sovProvider(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.VscTimeoutPeriod) + n += 1 + l + sovProvider(uint64(l)) return n } @@ -719,6 +975,36 @@ func (m *SlashAcks) Size() (n int) { return n } +func (m *ConsumerAdditionProposals) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Pending) > 0 { + for _, e := range m.Pending { + l = e.Size() + n += 1 + l + sovProvider(uint64(l)) + } + } + return n +} + +func (m *ConsumerRemovalProposals) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Pending) > 0 { + for _, e := range m.Pending { + l = e.Size() + n += 1 + l + sovProvider(uint64(l)) + } + } + return n +} + func sovProvider(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1269,6 +1555,124 @@ func (m *Params) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TrustingPeriodFraction", wireType) + } + m.TrustingPeriodFraction = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TrustingPeriodFraction |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CcvTimeoutPeriod", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthProvider + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthProvider + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.CcvTimeoutPeriod, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitTimeoutPeriod", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthProvider + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthProvider + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.InitTimeoutPeriod, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VscTimeoutPeriod", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthProvider + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthProvider + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.VscTimeoutPeriod, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipProvider(dAtA[iNdEx:]) @@ -1486,6 +1890,174 @@ func (m *SlashAcks) Unmarshal(dAtA []byte) error { } return nil } +func (m *ConsumerAdditionProposals) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsumerAdditionProposals: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsumerAdditionProposals: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pending", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthProvider + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthProvider + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pending = append(m.Pending, &ConsumerAdditionProposal{}) + if err := m.Pending[len(m.Pending)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipProvider(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthProvider + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ConsumerRemovalProposals) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsumerRemovalProposals: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsumerRemovalProposals: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pending", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowProvider + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthProvider + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthProvider + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Pending = append(m.Pending, &ConsumerRemovalProposal{}) + if err := m.Pending[len(m.Pending)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipProvider(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthProvider + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipProvider(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/ccv/provider/types/query.pb.go b/x/ccv/provider/types/query.pb.go index 0bf62a2b99..93a054de8c 100644 --- a/x/ccv/provider/types/query.pb.go +++ b/x/ccv/provider/types/query.pb.go @@ -118,9 +118,316 @@ func (m *QueryConsumerGenesisResponse) GetGenesisState() types.GenesisState { return types.GenesisState{} } +type QueryConsumerChainsRequest struct { +} + +func (m *QueryConsumerChainsRequest) Reset() { *m = QueryConsumerChainsRequest{} } +func (m *QueryConsumerChainsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryConsumerChainsRequest) ProtoMessage() {} +func (*QueryConsumerChainsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_422512d7b7586cd7, []int{2} +} +func (m *QueryConsumerChainsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryConsumerChainsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryConsumerChainsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryConsumerChainsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryConsumerChainsRequest.Merge(m, src) +} +func (m *QueryConsumerChainsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryConsumerChainsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryConsumerChainsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryConsumerChainsRequest proto.InternalMessageInfo + +type QueryConsumerChainsResponse struct { + Chains []*Chain `protobuf:"bytes,1,rep,name=chains,proto3" json:"chains,omitempty"` +} + +func (m *QueryConsumerChainsResponse) Reset() { *m = QueryConsumerChainsResponse{} } +func (m *QueryConsumerChainsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryConsumerChainsResponse) ProtoMessage() {} +func (*QueryConsumerChainsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_422512d7b7586cd7, []int{3} +} +func (m *QueryConsumerChainsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryConsumerChainsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryConsumerChainsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryConsumerChainsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryConsumerChainsResponse.Merge(m, src) +} +func (m *QueryConsumerChainsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryConsumerChainsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryConsumerChainsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryConsumerChainsResponse proto.InternalMessageInfo + +func (m *QueryConsumerChainsResponse) GetChains() []*Chain { + if m != nil { + return m.Chains + } + return nil +} + +type QueryConsumerChainStartProposalsRequest struct { +} + +func (m *QueryConsumerChainStartProposalsRequest) Reset() { + *m = QueryConsumerChainStartProposalsRequest{} +} +func (m *QueryConsumerChainStartProposalsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryConsumerChainStartProposalsRequest) ProtoMessage() {} +func (*QueryConsumerChainStartProposalsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_422512d7b7586cd7, []int{4} +} +func (m *QueryConsumerChainStartProposalsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryConsumerChainStartProposalsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryConsumerChainStartProposalsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryConsumerChainStartProposalsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryConsumerChainStartProposalsRequest.Merge(m, src) +} +func (m *QueryConsumerChainStartProposalsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryConsumerChainStartProposalsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryConsumerChainStartProposalsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryConsumerChainStartProposalsRequest proto.InternalMessageInfo + +type QueryConsumerChainStartProposalsResponse struct { + Proposals *ConsumerAdditionProposals `protobuf:"bytes,1,opt,name=proposals,proto3" json:"proposals,omitempty"` +} + +func (m *QueryConsumerChainStartProposalsResponse) Reset() { + *m = QueryConsumerChainStartProposalsResponse{} +} +func (m *QueryConsumerChainStartProposalsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryConsumerChainStartProposalsResponse) ProtoMessage() {} +func (*QueryConsumerChainStartProposalsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_422512d7b7586cd7, []int{5} +} +func (m *QueryConsumerChainStartProposalsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryConsumerChainStartProposalsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryConsumerChainStartProposalsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryConsumerChainStartProposalsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryConsumerChainStartProposalsResponse.Merge(m, src) +} +func (m *QueryConsumerChainStartProposalsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryConsumerChainStartProposalsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryConsumerChainStartProposalsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryConsumerChainStartProposalsResponse proto.InternalMessageInfo + +func (m *QueryConsumerChainStartProposalsResponse) GetProposals() *ConsumerAdditionProposals { + if m != nil { + return m.Proposals + } + return nil +} + +type QueryConsumerChainStopProposalsRequest struct { +} + +func (m *QueryConsumerChainStopProposalsRequest) Reset() { + *m = QueryConsumerChainStopProposalsRequest{} +} +func (m *QueryConsumerChainStopProposalsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryConsumerChainStopProposalsRequest) ProtoMessage() {} +func (*QueryConsumerChainStopProposalsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_422512d7b7586cd7, []int{6} +} +func (m *QueryConsumerChainStopProposalsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryConsumerChainStopProposalsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryConsumerChainStopProposalsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryConsumerChainStopProposalsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryConsumerChainStopProposalsRequest.Merge(m, src) +} +func (m *QueryConsumerChainStopProposalsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryConsumerChainStopProposalsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryConsumerChainStopProposalsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryConsumerChainStopProposalsRequest proto.InternalMessageInfo + +type QueryConsumerChainStopProposalsResponse struct { + Proposals *ConsumerRemovalProposals `protobuf:"bytes,1,opt,name=proposals,proto3" json:"proposals,omitempty"` +} + +func (m *QueryConsumerChainStopProposalsResponse) Reset() { + *m = QueryConsumerChainStopProposalsResponse{} +} +func (m *QueryConsumerChainStopProposalsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryConsumerChainStopProposalsResponse) ProtoMessage() {} +func (*QueryConsumerChainStopProposalsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_422512d7b7586cd7, []int{7} +} +func (m *QueryConsumerChainStopProposalsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryConsumerChainStopProposalsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryConsumerChainStopProposalsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryConsumerChainStopProposalsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryConsumerChainStopProposalsResponse.Merge(m, src) +} +func (m *QueryConsumerChainStopProposalsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryConsumerChainStopProposalsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryConsumerChainStopProposalsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryConsumerChainStopProposalsResponse proto.InternalMessageInfo + +func (m *QueryConsumerChainStopProposalsResponse) GetProposals() *ConsumerRemovalProposals { + if m != nil { + return m.Proposals + } + return nil +} + +type Chain struct { + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` +} + +func (m *Chain) Reset() { *m = Chain{} } +func (m *Chain) String() string { return proto.CompactTextString(m) } +func (*Chain) ProtoMessage() {} +func (*Chain) Descriptor() ([]byte, []int) { + return fileDescriptor_422512d7b7586cd7, []int{8} +} +func (m *Chain) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Chain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Chain.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Chain) XXX_Merge(src proto.Message) { + xxx_messageInfo_Chain.Merge(m, src) +} +func (m *Chain) XXX_Size() int { + return m.Size() +} +func (m *Chain) XXX_DiscardUnknown() { + xxx_messageInfo_Chain.DiscardUnknown(m) +} + +var xxx_messageInfo_Chain proto.InternalMessageInfo + +func (m *Chain) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +func (m *Chain) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + func init() { proto.RegisterType((*QueryConsumerGenesisRequest)(nil), "interchain_security.ccv.provider.v1.QueryConsumerGenesisRequest") proto.RegisterType((*QueryConsumerGenesisResponse)(nil), "interchain_security.ccv.provider.v1.QueryConsumerGenesisResponse") + proto.RegisterType((*QueryConsumerChainsRequest)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainsRequest") + proto.RegisterType((*QueryConsumerChainsResponse)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainsResponse") + proto.RegisterType((*QueryConsumerChainStartProposalsRequest)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainStartProposalsRequest") + proto.RegisterType((*QueryConsumerChainStartProposalsResponse)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainStartProposalsResponse") + proto.RegisterType((*QueryConsumerChainStopProposalsRequest)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainStopProposalsRequest") + proto.RegisterType((*QueryConsumerChainStopProposalsResponse)(nil), "interchain_security.ccv.provider.v1.QueryConsumerChainStopProposalsResponse") + proto.RegisterType((*Chain)(nil), "interchain_security.ccv.provider.v1.Chain") } func init() { @@ -128,30 +435,46 @@ func init() { } var fileDescriptor_422512d7b7586cd7 = []byte{ - // 359 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x52, 0x4d, 0x4b, 0xfb, 0x30, - 0x18, 0x6f, 0xfe, 0xfc, 0x7d, 0x8b, 0x8a, 0x50, 0x3c, 0xe8, 0x1c, 0x55, 0xe6, 0xc5, 0x8b, 0x09, - 0x9d, 0x17, 0x11, 0x44, 0x9d, 0x88, 0x78, 0x74, 0x7a, 0x12, 0x61, 0x74, 0x59, 0xc8, 0x02, 0x2e, - 0x4f, 0xd7, 0xa4, 0xc5, 0xa1, 0x5e, 0xfc, 0x04, 0x82, 0x5f, 0x6a, 0xc7, 0x81, 0x17, 0x2f, 0x8a, - 0x6c, 0x82, 0x5f, 0x43, 0xd6, 0x17, 0x99, 0xb2, 0xa9, 0xe0, 0xed, 0xe9, 0xd3, 0xfc, 0x5e, 0x13, - 0x4c, 0xa5, 0x32, 0x3c, 0x60, 0x75, 0x4f, 0xaa, 0x8a, 0xe6, 0x2c, 0x0c, 0xa4, 0x69, 0x51, 0xc6, - 0x22, 0xea, 0x07, 0x10, 0xc9, 0x1a, 0x0f, 0x68, 0xe4, 0xd2, 0x66, 0xc8, 0x83, 0x16, 0xf1, 0x03, - 0x30, 0x60, 0xaf, 0x0e, 0x01, 0x10, 0xc6, 0x22, 0x92, 0x01, 0x48, 0xe4, 0xe6, 0xf2, 0x02, 0x40, - 0x5c, 0x70, 0xea, 0xf9, 0x92, 0x7a, 0x4a, 0x81, 0xf1, 0x8c, 0x04, 0xa5, 0x13, 0x8a, 0xdc, 0xbc, - 0x00, 0x01, 0xf1, 0x48, 0xfb, 0x53, 0xba, 0x75, 0x47, 0x39, 0x61, 0xa0, 0x74, 0xd8, 0x48, 0x9c, - 0x08, 0xae, 0xb8, 0x96, 0x29, 0x51, 0x61, 0x13, 0x2f, 0x1d, 0xf7, 0xad, 0xed, 0xa7, 0x27, 0x0e, - 0x93, 0xbf, 0x65, 0xde, 0x0c, 0xb9, 0x36, 0xf6, 0x22, 0x9e, 0x4c, 0xe8, 0x64, 0x6d, 0x01, 0xad, - 0xa0, 0xb5, 0xa9, 0xf2, 0x44, 0xfc, 0x7d, 0x54, 0x2b, 0x5c, 0xe3, 0xfc, 0x70, 0xa4, 0xf6, 0x41, - 0x69, 0x6e, 0x9f, 0xe3, 0xd9, 0x54, 0xaa, 0xa2, 0x8d, 0x67, 0x78, 0x8c, 0x9f, 0x2e, 0xba, 0x64, - 0x54, 0xfa, 0xcc, 0x24, 0x89, 0x5c, 0x92, 0x92, 0x9d, 0xf4, 0x81, 0xa5, 0xff, 0xed, 0xe7, 0x65, - 0xab, 0x3c, 0x23, 0x06, 0x76, 0xc5, 0x37, 0x84, 0xc7, 0x62, 0x79, 0xfb, 0x09, 0xe1, 0xb9, 0x2f, - 0x1e, 0xec, 0x5d, 0xf2, 0x8b, 0x8a, 0xc9, 0x37, 0xc1, 0x73, 0x7b, 0x7f, 0x60, 0x48, 0x0a, 0x28, - 0x1c, 0xdc, 0x3e, 0xbc, 0xde, 0xff, 0xdb, 0xb1, 0xb7, 0x7f, 0x7e, 0x20, 0x59, 0xf4, 0x4a, 0x9a, - 0x91, 0x5e, 0x65, 0xad, 0xdf, 0x94, 0x4e, 0xdb, 0x5d, 0x07, 0x75, 0xba, 0x0e, 0x7a, 0xe9, 0x3a, - 0xe8, 0xae, 0xe7, 0x58, 0x9d, 0x9e, 0x63, 0x3d, 0xf6, 0x1c, 0xeb, 0x6c, 0x4b, 0x48, 0x53, 0x0f, - 0xab, 0x84, 0x41, 0x83, 0x32, 0xd0, 0x0d, 0xd0, 0x03, 0x4a, 0xeb, 0x1f, 0x4a, 0x97, 0x9f, 0xb5, - 0x4c, 0xcb, 0xe7, 0xba, 0x3a, 0x1e, 0x5f, 0xff, 0xc6, 0x7b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5d, - 0x70, 0x08, 0x17, 0xbd, 0x02, 0x00, 0x00, + // 620 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xcf, 0x6f, 0xd3, 0x3e, + 0x18, 0xc6, 0xeb, 0x7e, 0xbf, 0xfb, 0x51, 0x0f, 0x2e, 0x66, 0x12, 0x25, 0xab, 0xc2, 0x14, 0x24, + 0x28, 0x48, 0x24, 0x4a, 0x77, 0x01, 0xa4, 0xd1, 0x1f, 0x13, 0x1a, 0x13, 0x43, 0x82, 0x8e, 0x13, + 0x20, 0x55, 0x59, 0x62, 0x65, 0x96, 0xda, 0x38, 0x8b, 0xdd, 0x88, 0x0a, 0x38, 0xc0, 0x01, 0x71, + 0x44, 0xe2, 0x7f, 0x42, 0x3b, 0x4e, 0xda, 0x85, 0x13, 0x42, 0x2d, 0xff, 0x06, 0x12, 0x8a, 0xe3, + 0xa4, 0x2b, 0x4d, 0xb7, 0xb6, 0xec, 0x96, 0xda, 0x79, 0x9f, 0xf7, 0xf3, 0xbc, 0xf5, 0xe3, 0x40, + 0x83, 0x78, 0x1c, 0x07, 0xf6, 0x81, 0x45, 0xbc, 0x16, 0xc3, 0x76, 0x37, 0x20, 0xbc, 0x67, 0xd8, + 0x76, 0x68, 0xf8, 0x01, 0x0d, 0x89, 0x83, 0x03, 0x23, 0x34, 0x8d, 0xc3, 0x2e, 0x0e, 0x7a, 0xba, + 0x1f, 0x50, 0x4e, 0xd1, 0x8d, 0x8c, 0x02, 0xdd, 0xb6, 0x43, 0x3d, 0x29, 0xd0, 0x43, 0x53, 0x29, + 0xb9, 0x94, 0xba, 0x6d, 0x6c, 0x58, 0x3e, 0x31, 0x2c, 0xcf, 0xa3, 0xdc, 0xe2, 0x84, 0x7a, 0x2c, + 0x96, 0x50, 0x56, 0x5d, 0xea, 0x52, 0xf1, 0x68, 0x44, 0x4f, 0x72, 0xd5, 0x9c, 0x44, 0x62, 0x53, + 0x8f, 0x75, 0x3b, 0x31, 0x89, 0x8b, 0x3d, 0xcc, 0x48, 0x22, 0x54, 0x99, 0x06, 0x3e, 0xe5, 0x12, + 0x35, 0xda, 0x3d, 0xb8, 0xf6, 0x3c, 0xb2, 0xb3, 0x25, 0x55, 0xb7, 0x63, 0xc5, 0x26, 0x3e, 0xec, + 0x62, 0xc6, 0xd1, 0x35, 0xb8, 0x1c, 0xeb, 0x11, 0xa7, 0x08, 0xd6, 0x41, 0xb9, 0xd0, 0x5c, 0x12, + 0xbf, 0x77, 0x1c, 0xed, 0x1d, 0x2c, 0x65, 0x57, 0x32, 0x9f, 0x7a, 0x0c, 0xa3, 0xd7, 0xf0, 0xb2, + 0xc4, 0x6b, 0x31, 0x6e, 0x71, 0x2c, 0xea, 0x57, 0x2a, 0xa6, 0x3e, 0x69, 0x62, 0x89, 0x31, 0x3d, + 0x34, 0x75, 0x29, 0xb6, 0x17, 0x15, 0x36, 0xfe, 0x3f, 0xfa, 0x71, 0x3d, 0xd7, 0xbc, 0xe4, 0x9e, + 0x5a, 0xd3, 0x4a, 0x50, 0x19, 0xe9, 0xbe, 0x15, 0xe9, 0x25, 0xd8, 0x9a, 0xf5, 0x97, 0xab, 0x64, + 0x57, 0xa2, 0x35, 0xe0, 0xa2, 0xe8, 0xcf, 0x8a, 0x60, 0xfd, 0xbf, 0xf2, 0x4a, 0xe5, 0x8e, 0x3e, + 0xc5, 0xbf, 0xa8, 0x0b, 0x91, 0xa6, 0xac, 0xd4, 0x6e, 0xc3, 0x5b, 0xe3, 0x2d, 0xf6, 0xb8, 0x15, + 0xf0, 0x67, 0x01, 0xf5, 0x29, 0xb3, 0xda, 0x29, 0xcd, 0x67, 0x00, 0xcb, 0xe7, 0xbf, 0x9b, 0x8e, + 0xad, 0xe0, 0x27, 0x8b, 0x72, 0x64, 0x0f, 0xa7, 0xc3, 0x93, 0xe2, 0x75, 0xc7, 0x21, 0xd1, 0xf1, + 0x1a, 0x4a, 0x0f, 0x05, 0xb5, 0x32, 0xbc, 0x99, 0x45, 0x42, 0xfd, 0x31, 0xe8, 0x4f, 0x20, 0xdb, + 0xe0, 0xc8, 0xab, 0x92, 0xf9, 0xd5, 0x38, 0xf3, 0xe6, 0x4c, 0xcc, 0x4d, 0xdc, 0xa1, 0xa1, 0xd5, + 0xce, 0x44, 0xae, 0xc2, 0x05, 0xd1, 0xfa, 0x8c, 0xb3, 0x88, 0xd6, 0x60, 0xc1, 0x6e, 0x13, 0xec, + 0xf1, 0x68, 0x2f, 0x2f, 0xf6, 0x96, 0xe3, 0x85, 0x1d, 0xa7, 0xf2, 0x6d, 0x09, 0x2e, 0x08, 0x27, + 0xa8, 0x0f, 0xe0, 0x6a, 0xd6, 0x99, 0x45, 0xb5, 0xa9, 0x68, 0xcf, 0x08, 0x8a, 0x52, 0xff, 0x07, + 0x85, 0x78, 0x8a, 0xda, 0xa3, 0x8f, 0x27, 0xbf, 0xbe, 0xe6, 0xab, 0x68, 0xf3, 0xfc, 0x4b, 0x28, + 0x89, 0x4a, 0x4b, 0x66, 0xc2, 0x78, 0x9b, 0x4c, 0xe6, 0x3d, 0x3a, 0x01, 0xf0, 0x4a, 0xc6, 0xe1, + 0x47, 0xd5, 0xd9, 0x09, 0x47, 0x42, 0xa5, 0xd4, 0xe6, 0x17, 0x90, 0x0e, 0xef, 0x0b, 0x87, 0x1b, + 0xc8, 0x9c, 0xc1, 0x61, 0x1c, 0x37, 0xf4, 0x21, 0x0f, 0x8b, 0x13, 0x32, 0xc4, 0xd0, 0xee, 0x9c, + 0x64, 0x99, 0x71, 0x55, 0x9e, 0x5e, 0x90, 0x9a, 0x34, 0xfd, 0x58, 0x98, 0x6e, 0xa0, 0xda, 0xac, + 0xa6, 0xa3, 0x6b, 0x33, 0xe0, 0xad, 0x34, 0x09, 0xe8, 0x37, 0x80, 0x57, 0xb3, 0x23, 0xc9, 0xd0, + 0x93, 0xb9, 0xa1, 0xc7, 0xb3, 0xaf, 0xec, 0x5e, 0x8c, 0x98, 0x1c, 0xc0, 0xb6, 0x18, 0x40, 0x1d, + 0x55, 0xe7, 0x18, 0x00, 0xf5, 0x87, 0xfe, 0x1b, 0x2f, 0x8e, 0xfa, 0x2a, 0x38, 0xee, 0xab, 0xe0, + 0x67, 0x5f, 0x05, 0x5f, 0x06, 0x6a, 0xee, 0x78, 0xa0, 0xe6, 0xbe, 0x0f, 0xd4, 0xdc, 0xcb, 0x07, + 0x2e, 0xe1, 0x07, 0xdd, 0x7d, 0xdd, 0xa6, 0x1d, 0xc3, 0xa6, 0xac, 0x43, 0xd9, 0xa9, 0x5e, 0x77, + 0xd3, 0x5e, 0x6f, 0x46, 0xbb, 0xf1, 0x9e, 0x8f, 0xd9, 0xfe, 0xa2, 0xf8, 0x10, 0x6e, 0xfc, 0x09, + 0x00, 0x00, 0xff, 0xff, 0xc5, 0x68, 0x22, 0xa9, 0xfb, 0x07, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -168,7 +491,14 @@ const _ = grpc.SupportPackageIsVersion4 type QueryClient interface { // ConsumerGenesis queries the genesis state needed to start a consumer chain // whose proposal has been accepted - ConsumerGenesis(ctx context.Context, in *QueryConsumerGenesisRequest, opts ...grpc.CallOption) (*QueryConsumerGenesisResponse, error) + QueryConsumerGenesis(ctx context.Context, in *QueryConsumerGenesisRequest, opts ...grpc.CallOption) (*QueryConsumerGenesisResponse, error) + // ConsumerChains queries active consumer chains supported by the provider + // chain + QueryConsumerChains(ctx context.Context, in *QueryConsumerChainsRequest, opts ...grpc.CallOption) (*QueryConsumerChainsResponse, error) + // QueryConsumerChainStarts queries consumer chain start proposals. + QueryConsumerChainStarts(ctx context.Context, in *QueryConsumerChainStartProposalsRequest, opts ...grpc.CallOption) (*QueryConsumerChainStartProposalsResponse, error) + // QueryConsumerChainStops queries consumer chain stop proposals. + QueryConsumerChainStops(ctx context.Context, in *QueryConsumerChainStopProposalsRequest, opts ...grpc.CallOption) (*QueryConsumerChainStopProposalsResponse, error) } type queryClient struct { @@ -179,9 +509,36 @@ func NewQueryClient(cc grpc1.ClientConn) QueryClient { return &queryClient{cc} } -func (c *queryClient) ConsumerGenesis(ctx context.Context, in *QueryConsumerGenesisRequest, opts ...grpc.CallOption) (*QueryConsumerGenesisResponse, error) { +func (c *queryClient) QueryConsumerGenesis(ctx context.Context, in *QueryConsumerGenesisRequest, opts ...grpc.CallOption) (*QueryConsumerGenesisResponse, error) { out := new(QueryConsumerGenesisResponse) - err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/ConsumerGenesis", in, out, opts...) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryConsumerGenesis", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) QueryConsumerChains(ctx context.Context, in *QueryConsumerChainsRequest, opts ...grpc.CallOption) (*QueryConsumerChainsResponse, error) { + out := new(QueryConsumerChainsResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryConsumerChains", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) QueryConsumerChainStarts(ctx context.Context, in *QueryConsumerChainStartProposalsRequest, opts ...grpc.CallOption) (*QueryConsumerChainStartProposalsResponse, error) { + out := new(QueryConsumerChainStartProposalsResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryConsumerChainStarts", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) QueryConsumerChainStops(ctx context.Context, in *QueryConsumerChainStopProposalsRequest, opts ...grpc.CallOption) (*QueryConsumerChainStopProposalsResponse, error) { + out := new(QueryConsumerChainStopProposalsResponse) + err := c.cc.Invoke(ctx, "/interchain_security.ccv.provider.v1.Query/QueryConsumerChainStops", in, out, opts...) if err != nil { return nil, err } @@ -192,35 +549,105 @@ func (c *queryClient) ConsumerGenesis(ctx context.Context, in *QueryConsumerGene type QueryServer interface { // ConsumerGenesis queries the genesis state needed to start a consumer chain // whose proposal has been accepted - ConsumerGenesis(context.Context, *QueryConsumerGenesisRequest) (*QueryConsumerGenesisResponse, error) + QueryConsumerGenesis(context.Context, *QueryConsumerGenesisRequest) (*QueryConsumerGenesisResponse, error) + // ConsumerChains queries active consumer chains supported by the provider + // chain + QueryConsumerChains(context.Context, *QueryConsumerChainsRequest) (*QueryConsumerChainsResponse, error) + // QueryConsumerChainStarts queries consumer chain start proposals. + QueryConsumerChainStarts(context.Context, *QueryConsumerChainStartProposalsRequest) (*QueryConsumerChainStartProposalsResponse, error) + // QueryConsumerChainStops queries consumer chain stop proposals. + QueryConsumerChainStops(context.Context, *QueryConsumerChainStopProposalsRequest) (*QueryConsumerChainStopProposalsResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. type UnimplementedQueryServer struct { } -func (*UnimplementedQueryServer) ConsumerGenesis(ctx context.Context, req *QueryConsumerGenesisRequest) (*QueryConsumerGenesisResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConsumerGenesis not implemented") +func (*UnimplementedQueryServer) QueryConsumerGenesis(ctx context.Context, req *QueryConsumerGenesisRequest) (*QueryConsumerGenesisResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryConsumerGenesis not implemented") +} +func (*UnimplementedQueryServer) QueryConsumerChains(ctx context.Context, req *QueryConsumerChainsRequest) (*QueryConsumerChainsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryConsumerChains not implemented") +} +func (*UnimplementedQueryServer) QueryConsumerChainStarts(ctx context.Context, req *QueryConsumerChainStartProposalsRequest) (*QueryConsumerChainStartProposalsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryConsumerChainStarts not implemented") +} +func (*UnimplementedQueryServer) QueryConsumerChainStops(ctx context.Context, req *QueryConsumerChainStopProposalsRequest) (*QueryConsumerChainStopProposalsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryConsumerChainStops not implemented") } func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) } -func _Query_ConsumerGenesis_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _Query_QueryConsumerGenesis_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryConsumerGenesisRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(QueryServer).ConsumerGenesis(ctx, in) + return srv.(QueryServer).QueryConsumerGenesis(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryConsumerGenesis", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).QueryConsumerGenesis(ctx, req.(*QueryConsumerGenesisRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_QueryConsumerChains_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryConsumerChainsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).QueryConsumerChains(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryConsumerChains", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).QueryConsumerChains(ctx, req.(*QueryConsumerChainsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_QueryConsumerChainStarts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryConsumerChainStartProposalsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).QueryConsumerChainStarts(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/interchain_security.ccv.provider.v1.Query/ConsumerGenesis", + FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryConsumerChainStarts", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ConsumerGenesis(ctx, req.(*QueryConsumerGenesisRequest)) + return srv.(QueryServer).QueryConsumerChainStarts(ctx, req.(*QueryConsumerChainStartProposalsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_QueryConsumerChainStops_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryConsumerChainStopProposalsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).QueryConsumerChainStops(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/interchain_security.ccv.provider.v1.Query/QueryConsumerChainStops", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).QueryConsumerChainStops(ctx, req.(*QueryConsumerChainStopProposalsRequest)) } return interceptor(ctx, in, info, handler) } @@ -230,8 +657,20 @@ var _Query_serviceDesc = grpc.ServiceDesc{ HandlerType: (*QueryServer)(nil), Methods: []grpc.MethodDesc{ { - MethodName: "ConsumerGenesis", - Handler: _Query_ConsumerGenesis_Handler, + MethodName: "QueryConsumerGenesis", + Handler: _Query_QueryConsumerGenesis_Handler, + }, + { + MethodName: "QueryConsumerChains", + Handler: _Query_QueryConsumerChains_Handler, + }, + { + MethodName: "QueryConsumerChainStarts", + Handler: _Query_QueryConsumerChainStarts_Handler, + }, + { + MethodName: "QueryConsumerChainStops", + Handler: _Query_QueryConsumerChainStops_Handler, }, }, Streams: []grpc.StreamDesc{}, @@ -301,15 +740,228 @@ func (m *QueryConsumerGenesisResponse) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } -func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { - offset -= sovQuery(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ +func (m *QueryConsumerChainsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - dAtA[offset] = uint8(v) + return dAtA[:n], nil +} + +func (m *QueryConsumerChainsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryConsumerChainsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryConsumerChainsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryConsumerChainsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryConsumerChainsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Chains) > 0 { + for iNdEx := len(m.Chains) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Chains[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryConsumerChainStartProposalsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryConsumerChainStartProposalsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryConsumerChainStartProposalsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryConsumerChainStartProposalsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryConsumerChainStartProposalsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryConsumerChainStartProposalsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Proposals != nil { + { + size, err := m.Proposals.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryConsumerChainStopProposalsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryConsumerChainStopProposalsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryConsumerChainStopProposalsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryConsumerChainStopProposalsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryConsumerChainStopProposalsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryConsumerChainStopProposalsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Proposals != nil { + { + size, err := m.Proposals.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Chain) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Chain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Chain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ClientId) > 0 { + i -= len(m.ClientId) + copy(dAtA[i:], m.ClientId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) + i-- + dAtA[i] = 0x12 + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) return base } func (m *QueryConsumerGenesisRequest) Size() (n int) { @@ -336,6 +988,91 @@ func (m *QueryConsumerGenesisResponse) Size() (n int) { return n } +func (m *QueryConsumerChainsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryConsumerChainsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Chains) > 0 { + for _, e := range m.Chains { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryConsumerChainStartProposalsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryConsumerChainStartProposalsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Proposals != nil { + l = m.Proposals.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryConsumerChainStopProposalsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryConsumerChainStopProposalsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Proposals != nil { + l = m.Proposals.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *Chain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.ClientId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -507,6 +1244,526 @@ func (m *QueryConsumerGenesisResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryConsumerChainsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryConsumerChainsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryConsumerChainsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryConsumerChainsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryConsumerChainsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryConsumerChainsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Chains", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Chains = append(m.Chains, &Chain{}) + if err := m.Chains[len(m.Chains)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryConsumerChainStartProposalsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryConsumerChainStartProposalsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryConsumerChainStartProposalsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryConsumerChainStartProposalsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryConsumerChainStartProposalsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryConsumerChainStartProposalsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposals", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Proposals == nil { + m.Proposals = &ConsumerAdditionProposals{} + } + if err := m.Proposals.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryConsumerChainStopProposalsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryConsumerChainStopProposalsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryConsumerChainStopProposalsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryConsumerChainStopProposalsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryConsumerChainStopProposalsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryConsumerChainStopProposalsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposals", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Proposals == nil { + m.Proposals = &ConsumerRemovalProposals{} + } + if err := m.Proposals.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Chain) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Chain: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Chain: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClientId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/ccv/provider/types/query.pb.gw.go b/x/ccv/provider/types/query.pb.gw.go index 3cf6ee1a2a..2d660f5508 100644 --- a/x/ccv/provider/types/query.pb.gw.go +++ b/x/ccv/provider/types/query.pb.gw.go @@ -33,7 +33,7 @@ var _ = utilities.NewDoubleArray var _ = descriptor.ForMessage var _ = metadata.Join -func request_Query_ConsumerGenesis_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { +func request_Query_QueryConsumerGenesis_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryConsumerGenesisRequest var metadata runtime.ServerMetadata @@ -55,12 +55,12 @@ func request_Query_ConsumerGenesis_0(ctx context.Context, marshaler runtime.Mars return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err) } - msg, err := client.ConsumerGenesis(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.QueryConsumerGenesis(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func local_request_Query_ConsumerGenesis_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { +func local_request_Query_QueryConsumerGenesis_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryConsumerGenesisRequest var metadata runtime.ServerMetadata @@ -82,7 +82,61 @@ func local_request_Query_ConsumerGenesis_0(ctx context.Context, marshaler runtim return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "chain_id", err) } - msg, err := server.ConsumerGenesis(ctx, &protoReq) + msg, err := server.QueryConsumerGenesis(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_QueryConsumerChains_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsumerChainsRequest + var metadata runtime.ServerMetadata + + msg, err := client.QueryConsumerChains(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_QueryConsumerChains_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsumerChainsRequest + var metadata runtime.ServerMetadata + + msg, err := server.QueryConsumerChains(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_QueryConsumerChainStarts_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsumerChainStartProposalsRequest + var metadata runtime.ServerMetadata + + msg, err := client.QueryConsumerChainStarts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_QueryConsumerChainStarts_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsumerChainStartProposalsRequest + var metadata runtime.ServerMetadata + + msg, err := server.QueryConsumerChainStarts(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_QueryConsumerChainStops_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsumerChainStopProposalsRequest + var metadata runtime.ServerMetadata + + msg, err := client.QueryConsumerChainStops(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_QueryConsumerChainStops_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryConsumerChainStopProposalsRequest + var metadata runtime.ServerMetadata + + msg, err := server.QueryConsumerChainStops(ctx, &protoReq) return msg, metadata, err } @@ -93,7 +147,7 @@ func local_request_Query_ConsumerGenesis_0(ctx context.Context, marshaler runtim // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - mux.Handle("GET", pattern_Query_ConsumerGenesis_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle("GET", pattern_Query_QueryConsumerGenesis_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() var stream runtime.ServerTransportStream @@ -104,7 +158,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Query_ConsumerGenesis_0(rctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_Query_QueryConsumerGenesis_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -112,7 +166,76 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv return } - forward_Query_ConsumerGenesis_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_Query_QueryConsumerGenesis_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_QueryConsumerChains_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_QueryConsumerChains_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryConsumerChains_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_QueryConsumerChainStarts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_QueryConsumerChainStarts_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryConsumerChainStarts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_QueryConsumerChainStops_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_QueryConsumerChainStops_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryConsumerChainStops_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -157,7 +280,67 @@ func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc // "QueryClient" to call the correct interceptors. func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { - mux.Handle("GET", pattern_Query_ConsumerGenesis_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle("GET", pattern_Query_QueryConsumerGenesis_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_QueryConsumerGenesis_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryConsumerGenesis_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_QueryConsumerChains_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_QueryConsumerChains_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryConsumerChains_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_QueryConsumerChainStarts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_QueryConsumerChainStarts_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_QueryConsumerChainStarts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_QueryConsumerChainStops_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) @@ -166,14 +349,14 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Query_ConsumerGenesis_0(rctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_Query_QueryConsumerChainStops_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_Query_ConsumerGenesis_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_Query_QueryConsumerChainStops_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -181,9 +364,21 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_ConsumerGenesis_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"interchain_security", "ccv", "provider", "consumer_genesis", "chain_id"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_QueryConsumerGenesis_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"interchain_security", "ccv", "provider", "consumer_genesis", "chain_id"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_QueryConsumerChains_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"interchain_security", "ccv", "provider", "consumer_chains"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_QueryConsumerChainStarts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"interchain_security", "ccv", "provider", "consumer_chain_start_proposals"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_QueryConsumerChainStops_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"interchain_security", "ccv", "provider", "consumer_chain_stop_proposals"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( - forward_Query_ConsumerGenesis_0 = runtime.ForwardResponseMessage + forward_Query_QueryConsumerGenesis_0 = runtime.ForwardResponseMessage + + forward_Query_QueryConsumerChains_0 = runtime.ForwardResponseMessage + + forward_Query_QueryConsumerChainStarts_0 = runtime.ForwardResponseMessage + + forward_Query_QueryConsumerChainStops_0 = runtime.ForwardResponseMessage ) diff --git a/x/ccv/types/shared_params.go b/x/ccv/types/shared_params.go new file mode 100644 index 0000000000..15e2dd1acb --- /dev/null +++ b/x/ccv/types/shared_params.go @@ -0,0 +1,77 @@ +package types + +import ( + fmt "fmt" + "time" + + sdktypes "github.com/cosmos/cosmos-sdk/types" + ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host" +) + +const ( + // Default timeout period is 4 weeks to ensure channel doesn't close on timeout + DefaultCCVTimeoutPeriod = 4 * 7 * 24 * time.Hour +) + +var ( + KeyCCVTimeoutPeriod = []byte("CcvTimeoutPeriod") +) + +func ValidateDuration(i interface{}) error { + period, ok := i.(time.Duration) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + if period <= time.Duration(0) { + return fmt.Errorf("duration must be positive") + } + return nil +} + +func ValidateBool(i interface{}) error { + if _, ok := i.(bool); !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + return nil +} + +func ValidateInt64(i interface{}) error { + if _, ok := i.(int64); !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + return nil +} + +func ValidatePositiveInt64(i interface{}) error { + if err := ValidateInt64(i); err != nil { + return err + } + if i.(int64) <= int64(0) { + return fmt.Errorf("int must be positive") + } + return nil +} + +func ValidateString(i interface{}) error { + if _, ok := i.(string); !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + return nil +} + +func ValidateChannelIdentifier(i interface{}) error { + value, ok := i.(string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + return ibchost.ChannelIdentifierValidator(value) +} + +func ValidateBech32(i interface{}) error { + value, ok := i.(string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + _, err := sdktypes.AccAddressFromBech32(value) + return err +} diff --git a/x/ccv/types/utils.go b/x/ccv/types/utils.go deleted file mode 100644 index 29521da490..0000000000 --- a/x/ccv/types/utils.go +++ /dev/null @@ -1,10 +0,0 @@ -package types - -import "time" - -// TimeDelay is 4 weeks to ensure channel doesn't close on timeout -const TimeDelay = 4 * 7 * 24 * time.Hour - -func GetTimeoutTimestamp(currentTime time.Time) time.Time { - return currentTime.Add(TimeDelay) -} diff --git a/x/ccv/utils/utils.go b/x/ccv/utils/utils.go index 6caed432d6..8cfd01220c 100644 --- a/x/ccv/utils/utils.go +++ b/x/ccv/utils/utils.go @@ -13,10 +13,6 @@ import ( abci "github.com/tendermint/tendermint/abci/types" ) -// TrustingPeriodFraction is used to compute the IBC clients TrustingPeriod -// as UnbondingPeriod / TrustingPeriodFraction -const TrustingPeriodFraction = 2 - func AccumulateChanges(currentChanges, newChanges []abci.ValidatorUpdate) []abci.ValidatorUpdate { m := make(map[string]abci.ValidatorUpdate) @@ -54,6 +50,7 @@ func SendIBCPacket( channelID string, portID string, packetData []byte, + timeoutPeriod time.Duration, ) error { channel, ok := channelKeeper.GetChannel(ctx, portID, channelID) if !ok { @@ -76,30 +73,7 @@ func SendIBCPacket( packetData, sequence, portID, channelID, channel.Counterparty.PortId, channel.Counterparty.ChannelId, - clienttypes.Height{}, uint64(ccv.GetTimeoutTimestamp(ctx.BlockTime()).UnixNano()), + clienttypes.Height{}, uint64(ctx.BlockTime().Add(timeoutPeriod).UnixNano()), ) return channelKeeper.SendPacket(ctx, channelCap, packet) } - -// ComputeConsumerUnbondingPeriod computes the unbonding period on the consumer -// from the unbonding period on the provider (providerUnbondingPeriod). -// In general, the consumer unbonding period should be a bit smaller (e.g., one day) -// than the provider unbonding period so that it covers the delays of relaying IBC packets. -// As a result, delegators on the provider would not have to wait longer to unbond their tokens. -func ComputeConsumerUnbondingPeriod(providerUnbondingPeriod time.Duration) time.Duration { - if providerUnbondingPeriod > 7*24*time.Hour { - // In general, the unbonding period on the consumer - // is one day less than the unbonding period on the provider - return providerUnbondingPeriod - 24*time.Hour // one day less - } else if providerUnbondingPeriod >= 24*time.Hour { - // If the unbonding period on the provider is - // between one day and one week, then the unbonding period - // on the consumer is one hour less - return providerUnbondingPeriod - time.Hour // one hour less - } else { - // If the unbonding period on the provider is - // less than one day, then the unbonding period - // on the consumer is the same as on the provider - return providerUnbondingPeriod - } -}