Skip to content

Commit

Permalink
Merge branch 'main' into sainoe/consumer-states-cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
sainoe committed Sep 21, 2022
2 parents e689029 + f9e704a commit 8f157aa
Show file tree
Hide file tree
Showing 35 changed files with 1,573 additions and 779 deletions.
8 changes: 4 additions & 4 deletions docs/interchain-security/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
- [UnbondingSequence](#interchain_security.ccv.consumer.v1.UnbondingSequence)

- [interchain_security/ccv/provider/v1/provider.proto](#interchain_security/ccv/provider/v1/provider.proto)
- [CreateConsumerChainProposal](#interchain_security.ccv.provider.v1.CreateConsumerChainProposal)
- [ConsumerAdditionProposal](#interchain_security.ccv.provider.v1.ConsumerAdditionProposal)
- [HandshakeMetadata](#interchain_security.ccv.provider.v1.HandshakeMetadata)
- [Params](#interchain_security.ccv.provider.v1.Params)

Expand Down Expand Up @@ -278,10 +278,10 @@ UnbondingSequence defines the genesis information for each unbonding packet sequ



<a name="interchain_security.ccv.provider.v1.CreateConsumerChainProposal"></a>
<a name="interchain_security.ccv.provider.v1.ConsumerAdditionProposal"></a>

### CreateConsumerChainProposal
CreateConsumerChainProposal is a governance proposal on the provider chain to spawn a new consumer chain.
### ConsumerAdditionProposal
ConsumerAdditionProposal is a governance proposal on the provider chain to spawn a new consumer chain.
If it passes, then all validators on the provider chain are expected to validate the consumer chain at spawn time
or get slashed. It is recommended that spawn time occurs after the proposal end time.

Expand Down
8 changes: 4 additions & 4 deletions docs/quality_assurance.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ The main concern addressed in this section is the correctness of the provider ch
| 4.09 | The provider chain can easily be restarted with IS enabled <br /> - `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` | `Future work` | `Future work` | `Scheduled` | `NA` |
| 4.11 | The provider chain can graciously handle a CCV packet timing out (without shuting down) <br /> - 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 `StopConsumerChainProposal` <br /> - expected outcome: consumer chain shuts down and its state in provider CCV module is removed | `Scheduled` | `Done` <br /> see [stop_consumer_test.go](../x/ccv/provider/stop_consumer_test.go) | `Future work` | `Scheduled` | `NA` |
| 4.13 | The provider chain can graciously handle a `SpawnConsumerChainProposal` <br /> - expected outcome: a consumer chain is registered and a client is created | `Scheduled` |`Done` <br /> see [TestCreateConsumerChainProposal](../x/ccv/provider/keeper/proposal_test.go#L44) | `Future work` | `Scheduled` | `NA` |
| 4.12 | The provider chain can graciously handle a `ConsumerRemovalProposal` <br /> - expected outcome: consumer chain shuts down and its state in provider CCV module is removed | `Scheduled` | `Done` <br /> see [stop_consumer_test.go](../x/ccv/provider/stop_consumer_test.go) | `Future work` | `Scheduled` | `NA` |
| 4.13 | The provider chain can graciously handle a `SpawnConsumerChainProposal` <br /> - expected outcome: a consumer chain is registered and a client is created | `Scheduled` |`Done` <br /> see [TestConsumerAdditionProposal](../x/ccv/provider/keeper/proposal_test.go#L44) | `Future work` | `Scheduled` | `NA` |

### Interchain Security Protocol Correctness

Expand Down Expand Up @@ -150,8 +150,8 @@ The main concern addressed in this section is the correctness of the consumer ch
| -- | ------- | ----------- | ------------ | ------------- | ------- | ----- |
| 10.01 | Consumer chain liveness (blocks are being produced) | `Scheduled` | `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` | `??` | `Scheduled` | `NA` |
| 10.03 | A consumer chain has the ability to restart as a normal chain after shutting down, either controlled (via `StopConsumerChainProposal`) 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 `StopConsumerChainProposal`) or due to timing out | `Scheduled` | `??` | `??` | `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` |
| TBA ...
Expand Down
5 changes: 5 additions & 0 deletions proto/interchain_security/ccv/consumer/v1/consumer.proto
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,8 @@ message SlashRequest {
interchain_security.ccv.v1.SlashPacketData packet = 1;
cosmos.staking.v1beta1.InfractionType infraction = 2;
}

// SlashRequests is a list of slash requests for CCV consumer module
message SlashRequests {
repeated SlashRequest requests = 1;
}
14 changes: 10 additions & 4 deletions proto/interchain_security/ccv/provider/v1/provider.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import "google/protobuf/timestamp.proto";
import "ibc/core/client/v1/client.proto";
import "ibc/lightclients/tendermint/v1/tendermint.proto";

// CreateConsumerChainProposal is a governance proposal on the provider chain to spawn a new consumer chain.
// ConsumerAdditionProposal is a governance proposal on the provider chain to spawn a new consumer chain.
// If it passes, then all validators on the provider chain are expected to validate the consumer chain at spawn time
// or get slashed. It is recommended that spawn time occurs after the proposal end time.
message CreateConsumerChainProposal {
message ConsumerAdditionProposal {
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;

Expand Down Expand Up @@ -40,10 +40,10 @@ message CreateConsumerChainProposal {
bool lock_unbonding_on_timeout = 8;
}

// StopConsumerProposal is a governance proposal on the provider chain to stop a consumer chain.
// 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.
message StopConsumerChainProposal {
message ConsumerRemovalProposal {
// the title of the proposal
string title = 1;
// the description of the proposal
Expand All @@ -64,3 +64,9 @@ message HandshakeMetadata {
string provider_fee_pool_addr = 1;
string version = 2;
}

// SlashAcks contains addesses of consumer chain validators
// successfully slashed on the provider chain
message SlashAcks {
repeated string addresses = 1;
}
10 changes: 10 additions & 0 deletions proto/interchain_security/ccv/v1/ccv.proto
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,13 @@ message SlashPacketData {
// tell if the slashing is for a downtime or a double-signing infraction
cosmos.staking.v1beta1.InfractionType infraction = 3;
}

// UnbondingOpsIndex defines a list of unbonding operation ids.
message UnbondingOpsIndex {
repeated uint64 ids = 1;
}

// MaturedUnbondingOps defines a list of ids corresponding to ids of matured unbonding operations.
message MaturedUnbondingOps {
repeated uint64 ids = 1;
}
31 changes: 15 additions & 16 deletions tests/e2e/channel_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -689,8 +689,8 @@ func (suite *ProviderTestSuite) TestOnChanOpenInit() {
suite.Require().Error(err, "OnChanOpenInit must error on provider chain")
}

// TestConsumerChainProposalHandler tests the handler for consumer chain proposals
// for both CreateConsumerChainProposal and StopConsumerChainProposal
// TestConsumerChainProposalHandler tests the highest level handler
// for both ConsumerAdditionProposals and ConsumerRemovalProposals
//
// TODO: Determine if it's possible to make this a unit test
func (suite *ProviderTestSuite) TestConsumerChainProposalHandler() {
Expand All @@ -706,18 +706,17 @@ func (suite *ProviderTestSuite) TestConsumerChainProposalHandler() {
expPass bool
}{
{
"valid create consumerchain proposal", func(suite *ProviderTestSuite) {
"valid consumer addition proposal", func(suite *ProviderTestSuite) {
initialHeight := clienttypes.NewHeight(2, 3)
// ctx blocktime is after proposal's spawn time
ctx = suite.providerChain.GetContext().WithBlockTime(time.Now().Add(time.Hour))
content = types.NewCreateConsumerChainProposal("title", "description", "chainID", initialHeight, []byte("gen_hash"), []byte("bin_hash"), time.Now())
content = types.NewConsumerAdditionProposal("title", "description", "chainID", initialHeight, []byte("gen_hash"), []byte("bin_hash"), time.Now())
}, true,
},
{
"valid stop consumerchain proposal", func(suite *ProviderTestSuite) {
"valid consumer removal proposal", func(suite *ProviderTestSuite) {
ctx = suite.providerChain.GetContext().WithBlockTime(time.Now().Add(time.Hour))
content, err = types.NewStopConsumerChainProposal("title", "description", "chainID", time.Now())
suite.Require().NoError(err)
content = types.NewConsumerRemovalProposal("title", "description", "chainID", time.Now())
}, true,
},
{
Expand Down Expand Up @@ -782,10 +781,10 @@ func (suite *ProviderKeeperTestSuite) TestMakeConsumerGenesis() {
suite.Require().Equal(actualGenesis, expectedGenesis, "consumer chain genesis created incorrectly")
}

func (suite *ProviderKeeperTestSuite) TestCreateConsumerChainProposal() {
func (suite *ProviderKeeperTestSuite) TestHandleConsumerAdditionProposal() {
var (
ctx sdk.Context
proposal *types.CreateConsumerChainProposal
proposal *types.ConsumerAdditionProposal
ok bool
)

Expand All @@ -800,11 +799,11 @@ func (suite *ProviderKeeperTestSuite) TestCreateConsumerChainProposal() {
spawnReached bool
}{
{
"valid create consumer chain proposal: spawn time reached", func(suite *ProviderKeeperTestSuite) {
"valid consumer addition proposal: spawn time reached", func(suite *ProviderKeeperTestSuite) {
// ctx blocktime is after proposal's spawn time
ctx = suite.providerChain.GetContext().WithBlockTime(time.Now().Add(time.Hour))
content := types.NewCreateConsumerChainProposal("title", "description", chainID, initialHeight, []byte("gen_hash"), []byte("bin_hash"), time.Now())
proposal, ok = content.(*types.CreateConsumerChainProposal)
content := types.NewConsumerAdditionProposal("title", "description", chainID, initialHeight, []byte("gen_hash"), []byte("bin_hash"), time.Now())
proposal, ok = content.(*types.ConsumerAdditionProposal)
suite.Require().True(ok)
proposal.LockUnbondingOnTimeout = lockUbdOnTimeout
}, true, true,
Expand All @@ -813,8 +812,8 @@ func (suite *ProviderKeeperTestSuite) TestCreateConsumerChainProposal() {
"valid proposal: spawn time has not yet been reached", func(suite *ProviderKeeperTestSuite) {
// ctx blocktime is before proposal's spawn time
ctx = suite.providerChain.GetContext().WithBlockTime(time.Now())
content := types.NewCreateConsumerChainProposal("title", "description", chainID, initialHeight, []byte("gen_hash"), []byte("bin_hash"), time.Now().Add(time.Hour))
proposal, ok = content.(*types.CreateConsumerChainProposal)
content := types.NewConsumerAdditionProposal("title", "description", chainID, initialHeight, []byte("gen_hash"), []byte("bin_hash"), time.Now().Add(time.Hour))
proposal, ok = content.(*types.ConsumerAdditionProposal)
suite.Require().True(ok)
proposal.LockUnbondingOnTimeout = lockUbdOnTimeout
}, true, false,
Expand All @@ -829,7 +828,7 @@ func (suite *ProviderKeeperTestSuite) TestCreateConsumerChainProposal() {

tc.malleate(suite)

err := suite.providerChain.App.(*appProvider.App).ProviderKeeper.CreateConsumerChainProposal(ctx, proposal)
err := suite.providerChain.App.(*appProvider.App).ProviderKeeper.HandleConsumerAdditionProposal(ctx, proposal)
if tc.expPass {
suite.Require().NoError(err, "error returned on valid case")
if tc.spawnReached {
Expand All @@ -844,7 +843,7 @@ func (suite *ProviderKeeperTestSuite) TestCreateConsumerChainProposal() {
suite.Require().Equal(expectedGenesis, consumerGenesis)
suite.Require().NotEqual("", clientId, "consumer client was not created after spawn time reached")
} else {
gotProposal := suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingCreateProposal(ctx, proposal.SpawnTime, chainID)
gotProposal := suite.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingConsumerAdditionProp(ctx, proposal.SpawnTime, chainID)
suite.Require().Equal(initialHeight, gotProposal.InitialHeight, "unexpected pending proposal (InitialHeight)")
suite.Require().Equal(lockUbdOnTimeout, gotProposal.LockUnbondingOnTimeout, "unexpected pending proposal (LockUnbondingOnTimeout)")
}
Expand Down
31 changes: 14 additions & 17 deletions tests/e2e/stop_consumer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ func (s *ProviderTestSuite) TestStopConsumerChain() {
s.checkConsumerChainIsRemoved(consumerChainID, false)
}

func (s *ProviderTestSuite) TestStopConsumerChainProposal() {
func (s *ProviderTestSuite) TestConsumerRemovalProposal() {
var (
ctx sdk.Context
proposal *providertypes.StopConsumerChainProposal
proposal *providertypes.ConsumerRemovalProposal
ok bool
)

Expand All @@ -113,13 +113,12 @@ func (s *ProviderTestSuite) TestStopConsumerChainProposal() {
stopReached bool
}{
{
"valid stop consumer chain proposal: stop time reached", func(suite *ProviderTestSuite) {
"valid consumer removal proposal: stop time reached", func(suite *ProviderTestSuite) {

// ctx blocktime is after proposal's stop time
ctx = s.providerCtx().WithBlockTime(time.Now().Add(time.Hour))
content, err := providertypes.NewStopConsumerChainProposal("title", "description", chainID, time.Now())
s.Require().NoError(err)
proposal, ok = content.(*providertypes.StopConsumerChainProposal)
content := providertypes.NewConsumerRemovalProposal("title", "description", chainID, time.Now())
proposal, ok = content.(*providertypes.ConsumerRemovalProposal)
s.Require().True(ok)
}, true, true,
},
Expand All @@ -128,9 +127,8 @@ func (s *ProviderTestSuite) TestStopConsumerChainProposal() {

// ctx blocktime is before proposal's stop time
ctx = s.providerCtx().WithBlockTime(time.Now())
content, err := providertypes.NewStopConsumerChainProposal("title", "description", chainID, time.Now().Add(time.Hour))
s.Require().NoError(err)
proposal, ok = content.(*providertypes.StopConsumerChainProposal)
content := providertypes.NewConsumerRemovalProposal("title", "description", chainID, time.Now().Add(time.Hour))
proposal, ok = content.(*providertypes.ConsumerRemovalProposal)
s.Require().True(ok)
}, true, false,
},
Expand All @@ -143,9 +141,8 @@ func (s *ProviderTestSuite) TestStopConsumerChainProposal() {
// set invalid unbonding op index
s.providerChain.App.(*appProvider.App).ProviderKeeper.SetUnbondingOpIndex(ctx, chainID, 0, []uint64{0})

content, err := providertypes.NewStopConsumerChainProposal("title", "description", chainID, time.Now())
s.Require().NoError(err)
proposal, ok = content.(*providertypes.StopConsumerChainProposal)
content := providertypes.NewConsumerRemovalProposal("title", "description", chainID, time.Now())
proposal, ok = content.(*providertypes.ConsumerRemovalProposal)
s.Require().True(ok)
}, false, true,
},
Expand All @@ -160,19 +157,19 @@ func (s *ProviderTestSuite) TestStopConsumerChainProposal() {

tc.malleate(s)

err := s.providerChain.App.(*appProvider.App).ProviderKeeper.StopConsumerChainProposal(ctx, proposal)
err := s.providerChain.App.(*appProvider.App).ProviderKeeper.HandleConsumerRemovalProposal(ctx, proposal)
if tc.expPass {
s.Require().NoError(err, "error returned on valid case")
if tc.stopReached {
// check that the pending stop consumer chain proposal is deleted
found := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingStopProposal(ctx, chainID, proposal.StopTime)
s.Require().False(found, "pending stop consumer proposal wasn't deleted")
// check that the pending consumer removal proposal is deleted
found := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingConsumerRemovalProp(ctx, chainID, proposal.StopTime)
s.Require().False(found, "pending consumer removal proposal wasn't deleted")

// check that the consumer chain is removed
s.checkConsumerChainIsRemoved(chainID, false)

} else {
found := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingStopProposal(ctx, chainID, proposal.StopTime)
found := s.providerChain.App.(*appProvider.App).ProviderKeeper.GetPendingConsumerRemovalProp(ctx, chainID, proposal.StopTime)
s.Require().True(found, "pending stop consumer was not found for chain ID %s", chainID)

// check that the consumer chain client exists
Expand Down
23 changes: 6 additions & 17 deletions tests/integration/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import (
"sync"
"time"

clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types"
clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types"
"github.com/cosmos/interchain-security/x/ccv/provider/client"
)

type SendTokensAction struct {
Expand Down Expand Up @@ -191,25 +192,13 @@ type submitConsumerProposalAction struct {
initialHeight clienttypes.Height
}

// TODO: import this directly from the module once it is merged
type createConsumerChainProposalJSON struct {
Title string `json:"title"`
Description string `json:"description"`
ChainId string `json:"chain_id"`
InitialHeight clienttypes.Height `json:"initial_height"`
GenesisHash []byte `json:"genesis_hash"`
BinaryHash []byte `json:"binary_hash"`
SpawnTime time.Time `json:"spawn_time"`
Deposit string `json:"deposit"`
}

func (tr TestRun) submitConsumerProposal(
func (tr TestRun) submitConsumerAdditionProposal(
action submitConsumerProposalAction,
verbose bool,
) {
spawnTime := tr.containerConfig.now.Add(time.Duration(action.spawnTime) * time.Millisecond)
prop := createConsumerChainProposalJSON{
Title: "Create a chain",
prop := client.ConsumerAdditionProposalJSON{
Title: "Propose the addition of a new chain",
Description: "Gonna be a great chain",
ChainId: string(tr.chainConfigs[action.consumerChain].chainId),
InitialHeight: action.initialHeight,
Expand Down Expand Up @@ -240,7 +229,7 @@ func (tr TestRun) submitConsumerProposal(
//#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", "create-consumer-chain",
"tx", "gov", "submit-proposal", "consumer-addition",
"/temp-proposal.json",

`--from`, `validator`+fmt.Sprint(action.from),
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (tr TestRun) runStep(step Step, verbose bool) {
case submitTextProposalAction:
tr.submitTextProposal(action, verbose)
case submitConsumerProposalAction:
tr.submitConsumerProposal(action, verbose)
tr.submitConsumerAdditionProposal(action, verbose)
case voteGovProposalAction:
tr.voteGovProposal(action, verbose)
case startConsumerChainAction:
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"strings"
"time"

clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types"
clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types"
"github.com/tidwall/gjson"
"gopkg.in/yaml.v2"
)
Expand Down Expand Up @@ -200,7 +200,7 @@ func (tr TestRun) getProposal(chain chainID, proposal uint) Proposal {
Title: title,
Description: description,
}
case "/interchain_security.ccv.provider.v1.CreateConsumerChainProposal":
case "/interchain_security.ccv.provider.v1.ConsumerAdditionProposal":
chainId := gjson.Get(string(bz), `content.chain_id`).String()
spawnTime := gjson.Get(string(bz), `content.spawn_time`).Time().Sub(tr.containerConfig.now)

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/steps.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types"
clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types"
)

type Step struct {
Expand Down
Loading

0 comments on commit 8f157aa

Please sign in to comment.