Skip to content

Commit

Permalink
feat!: store proposed chainID before voting finishes (#1289)
Browse files Browse the repository at this point in the history
* feat: store chain in proposal

* add govHook

* delete GetChainsInProposal

* check proposal type

* update key

* feat: add query proposed chainIDs

* feat: set govhook

* feat: parse key

* refactor: names

* feat: add list proposed consumer chains

* test: add e2e test

* add e2e test

* update comments

* update ProposeConsumerChains in e2e test

* remove wait for block

* docs: update changelog

* fix: lint

* add  TestParseProposedConsumerChainKey

* refactor gov hook

* Update proto/interchain_security/ccv/provider/v1/query.proto

Co-authored-by: MSalopek <[email protected]>

* update proto

* add test for set kv

* refactor key to be prefix_proposalID

* formatting

* update e2e test

* format

* Update x/ccv/provider/keeper/gov_hook.go

Co-authored-by: Shawn <[email protected]>

* Update x/ccv/provider/keeper/keeper.go

Co-authored-by: Shawn <[email protected]>

* Update x/ccv/provider/keeper/keeper.go

Co-authored-by: Shawn <[email protected]>

* fix e2e test

* fix gosec

* remove type url check

* test: add unit test

* lint

* fix lint

* fix err

---------

Co-authored-by: MSalopek <[email protected]>
Co-authored-by: Shawn <[email protected]>
  • Loading branch information
3 people authored Oct 2, 2023
1 parent 3cbf9c8 commit 67ec715
Show file tree
Hide file tree
Showing 15 changed files with 1,086 additions and 98 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Add an entry to the unreleased provider section whenever merging a PR to main th
* (deps) [#1258](https://github.com/cosmos/interchain-security/pull/1258) Bump [cosmos-sdk](https://github.com/cosmos/cosmos-sdk) to [v0.47.4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.47.4).
* (deps!) [#1196](https://github.com/cosmos/interchain-security/pull/1196) Bump [ibc-go](https://github.com/cosmos/ibc-go) to [v7.2.0](https://github.com/cosmos/ibc-go/releases/tag/v7.2.0).
* `[x/ccv/provider]` (fix) [#1076](https://github.com/cosmos/interchain-security/pull/1076) Add `InitTimeoutTimestamps` and `ExportedVscSendTimestamps` to exported genesis.
* (feature) [#1282](https://github.com/cosmos/interchain-security/issues/1282) In the `ConsumerAdditionProposal`, consumer chainIDs proposed before the voting period finishes are now stored in the state. The gRPC query `/interchain_security/ccv/provider/proposed_consumer_chainids` and CLI command `query provider proposed-consumer-chains` can be used to retrieve this information.

## [Unreleased for Consumer]

Expand Down
9 changes: 7 additions & 2 deletions app/provider/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ func New(
AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
govConfig := govtypes.DefaultConfig()

app.GovKeeper = *govkeeper.NewKeeper(
govKeeper := govkeeper.NewKeeper(
appCodec,
keys[govtypes.StoreKey],
app.AccountKeeper,
Expand All @@ -455,7 +455,12 @@ func New(
)

// Set legacy router for backwards compatibility with gov v1beta1
app.GovKeeper.SetLegacyRouter(govRouter)
govKeeper.SetLegacyRouter(govRouter)

govHook := app.ProviderKeeper.GovHooks(govKeeper)
app.GovKeeper = *govKeeper.SetHooks(
govtypes.NewMultiGovHooks(govHook),
)

app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec,
Expand Down
21 changes: 21 additions & 0 deletions proto/interchain_security/ccv/provider/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ service Query {
option (google.api.http).get =
"/interchain_security/ccv/provider/registered_consumer_reward_denoms";
}

// QueryProposedConsumerChainIDs query chainIDs in consumerAdditionProposals
// before voting period finishes, after voting period finishes, this chainID will be removed from the result
rpc QueryProposedConsumerChainIDs(
QueryProposedChainIDsRequest)
returns (QueryProposedChainIDsResponse) {
option (google.api.http).get =
"/interchain_security/ccv/provider/proposed_consumer_chains";
}
}

message QueryConsumerGenesisRequest { string chain_id = 1; }
Expand Down Expand Up @@ -187,3 +196,15 @@ message QueryRegisteredConsumerRewardDenomsRequest {}
message QueryRegisteredConsumerRewardDenomsResponse {
repeated string denoms = 1;
}

message QueryProposedChainIDsRequest {}

message QueryProposedChainIDsResponse {
repeated ProposedChain proposedChains = 1
[ (gogoproto.nullable) = false ];
}

message ProposedChain {
string chainID = 1;
uint64 proposalID = 2;
}
23 changes: 11 additions & 12 deletions tests/e2e/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,25 +395,25 @@ func ChangeoverTestConfig() TestConfig {
return tr
}

func (s *TestConfig) SetDockerConfig(localSdkPath string, useGaia bool, gaiaTag string) {
func (tr *TestRun) SetDockerConfig(localSdkPath string, useGaia bool, gaiaTag string) {

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 398 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun
if localSdkPath != "" {
fmt.Println("USING LOCAL SDK", localSdkPath)
}
if useGaia {
fmt.Println("USING GAIA INSTEAD OF ICS provider app", gaiaTag)
}

s.useGaia = useGaia
s.gaiaTag = gaiaTag
s.localSdkPath = localSdkPath
tr.useGaia = useGaia
tr.gaiaTag = gaiaTag
tr.localSdkPath = localSdkPath
}

func (s *TestConfig) SetCometMockConfig(useCometmock bool) {
s.useCometmock = useCometmock
func (tr *TestRun) SetCometMockConfig(useCometmock bool) {

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 411 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun
tr.useCometmock = useCometmock
}

func (s *TestConfig) SetRelayerConfig(useRly bool) {
s.useGorelayer = useRly
func (tr *TestRun) SetRelayerConfig(useRly bool) {

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 415 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun
tr.useGorelayer = useRly
}

// validateStringLiterals enforces that configs follow the constraints
Expand All @@ -423,9 +423,8 @@ func (s *TestConfig) SetRelayerConfig(useRly bool) {
// within the container will be named as "$CHAIN_ID-$VAL_ID-out" etc.
// where this name is constrained to 15 bytes or less. Therefore each string literal
// used as a validatorID or chainID needs to be 5 char or less.
func (s *TestConfig) validateStringLiterals() {
for valID, valConfig := range s.validatorConfigs {

func (tr *TestRun) validateStringLiterals() {

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 426 in tests/e2e/config.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun
for valID, valConfig := range tr.validatorConfigs {
if len(valID) > 5 {
panic("validator id string literal must be 5 char or less")
}
Expand All @@ -448,7 +447,7 @@ func (s *TestConfig) validateStringLiterals() {
}
}

for chainID, chainConfig := range s.chainConfigs {
for chainID, chainConfig := range tr.chainConfigs {
if len(chainID) > 5 {
panic("chain id string literal must be 5 char or less")
}
Expand Down
28 changes: 28 additions & 0 deletions tests/e2e/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type State map[ChainID]ChainState
type ChainState struct {
ValBalances *map[ValidatorID]uint
Proposals *map[uint]Proposal
ProposedConsumerChains *[]string
ValPowers *map[ValidatorID]uint
StakedTokens *map[ValidatorID]uint
Params *[]Param
Expand Down Expand Up @@ -132,6 +133,11 @@ func (tr TestConfig) getChainState(chain ChainID, modelState ChainState) ChainSt
chainState.Proposals = &proposals
}

if modelState.ProposedConsumerChains != nil {
proposedConsumerChains := tr.getProposedConsumerChains(chain)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / lint

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / lint

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / SonarCloud

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / lint

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / SonarCloud

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)

Check failure on line 137 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / SonarCloud

tr.getProposedConsumerChains undefined (type TestConfig has no field or method getProposedConsumerChains)
chainState.ProposedConsumerChains = &proposedConsumerChains
}

if modelState.ValPowers != nil {
tr.waitBlocks(chain, 1, 10*time.Second)
powers := tr.getValPowers(chain, *modelState.ValPowers)
Expand Down Expand Up @@ -772,3 +778,25 @@ func (tr TestConfig) curlJsonRPCRequest(method, params, address string) {
verbosity := false
executeCommandWithVerbosity(cmd, "curlJsonRPCRequest", verbosity)
}

func (tr TestRun) getProposedConsumerChains(chain ChainID) []string {

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Cometmock_Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Trace-Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / E2E_Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / lint

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / Automated_Tests

undefined: TestRun

Check failure on line 782 in tests/e2e/state.go

View workflow job for this annotation

GitHub Actions / SonarCloud

undefined: TestRun
tr.waitBlocks(chain, 1, 10*time.Second)
//#nosec G204 -- Bypass linter warning for spawning subprocess with cmd arguments.
bz, err := exec.Command("docker", "exec", tr.containerConfig.InstanceName, tr.chainConfigs[chain].BinaryName,
"query", "provider", "list-proposed-consumer-chains",
`--node`, tr.getQueryNode(chain),
`-o`, `json`,
).CombinedOutput()
if err != nil {
log.Fatal(err, "\n", string(bz))
}

arr := gjson.Get(string(bz), "proposedChains").Array()
chains := []string{}
for _, c := range arr {
cid := c.Get("chainID").String()
chains = append(chains, cid)
}

return chains
}
2 changes: 2 additions & 0 deletions tests/e2e/steps_start_chains.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func stepsStartConsumerChain(consumerName string, proposalIndex, chainIndex uint
Status: "PROPOSAL_STATUS_VOTING_PERIOD",
},
},
ProposedConsumerChains: &[]string{consumerName},
},
},
},
Expand Down Expand Up @@ -163,6 +164,7 @@ func stepsStartConsumerChain(consumerName string, proposalIndex, chainIndex uint
ValidatorID("bob"): 9500000000,
ValidatorID("carol"): 9500000000,
},
ProposedConsumerChains: &[]string{},
},
ChainID(consumerName): ChainState{
ValBalances: &map[ValidatorID]uint{
Expand Down
28 changes: 28 additions & 0 deletions x/ccv/provider/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func NewQueryCmd() *cobra.Command {
cmd.AddCommand(CmdThrottleState())
cmd.AddCommand(CmdThrottledConsumerPacketData())
cmd.AddCommand(CmdRegisteredConsumerRewardDenoms())
cmd.AddCommand(CmdProposedConsumerChains())

return cmd
}
Expand Down Expand Up @@ -93,6 +94,33 @@ func CmdConsumerChains() *cobra.Command {
return cmd
}

func CmdProposedConsumerChains() *cobra.Command {
cmd := &cobra.Command{
Use: "list-proposed-consumer-chains",
Short: "Query chainIDs in consumer addition proposal before voting finishes",
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.QueryProposedChainIDsRequest{}
res, err := queryClient.QueryProposedConsumerChainIDs(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",
Expand Down
93 changes: 93 additions & 0 deletions x/ccv/provider/keeper/gov_hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package keeper

import (
"fmt"

"github.com/cosmos/gogoproto/proto"

sdk "github.com/cosmos/cosmos-sdk/types"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
sdkgov "github.com/cosmos/cosmos-sdk/x/gov/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"

"github.com/cosmos/interchain-security/v3/x/ccv/provider/types"
)

type GovHooks struct {
gk *govkeeper.Keeper
k *Keeper
}

// Implements GovHooks interface
// GovHooks exist in cosmos-sdk/x/gov/keeper/hooks.go of v0.45.16-lsm-ics and on
var _ sdkgov.GovHooks = GovHooks{}

func (k *Keeper) GovHooks(gk *govkeeper.Keeper) GovHooks {
return GovHooks{
gk: gk,
k: k,
}
}

// AfterProposalSubmission - call hook if registered
// After consumerAddition proposal submission, the consumer chainID is stored
func (gh GovHooks) AfterProposalSubmission(ctx sdk.Context, proposalID uint64) {
p, ok := gh.gk.GetProposal(ctx, proposalID)
if !ok {
panic(fmt.Errorf("failed to get proposal %d in gov hook", proposalID))
}
msgs := p.GetMessages()

for _, msg := range msgs {
var msgLegacyContent v1.MsgExecLegacyContent
err := proto.Unmarshal(msg.Value, &msgLegacyContent)
if err != nil {
panic(fmt.Errorf("failed to unmarshal proposal content in gov hook: %w", err))
}

// if the consumer addition proposal cannot be unmarshaled, continue
var consAdditionProp types.ConsumerAdditionProposal
if err := proto.Unmarshal(msgLegacyContent.Content.Value, &consAdditionProp); err != nil {
continue
}

if consAdditionProp.ProposalType() == types.ProposalTypeConsumerAddition {
gh.k.SetProposedConsumerChain(ctx, consAdditionProp.ChainId, proposalID)
}
}
}

// AfterProposalVotingPeriodEnded - call hook if registered
// After proposal voting ends, the consumer chainID in store is deleted.
// When a proposal passes, this chainID will be available in providerKeeper.GetAllPendingConsumerAdditionProps
// or providerKeeper.GetAllConsumerChains(ctx).
func (gh GovHooks) AfterProposalVotingPeriodEnded(ctx sdk.Context, proposalID uint64) {
p, ok := gh.gk.GetProposal(ctx, proposalID)
if !ok {
panic(fmt.Errorf("failed to get proposal %d in gov hook", proposalID))
}
msgs := p.GetMessages()

for _, msg := range msgs {
var msgLegacyContent v1.MsgExecLegacyContent
err := proto.Unmarshal(msg.Value, &msgLegacyContent)
if err != nil {
panic(fmt.Errorf("failed to unmarshal proposal content in gov hook: %w", err))
}

var consAdditionProp types.ConsumerAdditionProposal
// if the proposal is not ConsumerAdditionProposal, return
if err := proto.Unmarshal(msgLegacyContent.Content.Value, &consAdditionProp); err != nil {
continue
}

if consAdditionProp.ProposalType() == types.ProposalTypeConsumerAddition {
gh.k.DeleteProposedConsumerChainInStore(ctx, proposalID)
}
}
}

func (gh GovHooks) AfterProposalDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) {
}
func (gh GovHooks) AfterProposalVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) {}
func (gh GovHooks) AfterProposalFailedMinDeposit(ctx sdk.Context, proposalID uint64) {}
14 changes: 14 additions & 0 deletions x/ccv/provider/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,17 @@ func (k Keeper) QueryRegisteredConsumerRewardDenoms(goCtx context.Context, req *
Denoms: denoms,
}, nil
}

func (k Keeper) QueryProposedConsumerChainIDs(goCtx context.Context, req *types.QueryProposedChainIDsRequest) (*types.QueryProposedChainIDsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

ctx := sdk.UnwrapSDKContext(goCtx)

chains := k.GetAllProposedConsumerChainIDs(ctx)

return &types.QueryProposedChainIDsResponse{
ProposedChains: chains,
}, nil
}
44 changes: 44 additions & 0 deletions x/ccv/provider/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,50 @@ func (k Keeper) DeleteChainToChannel(ctx sdk.Context, chainID string) {
store.Delete(types.ChainToChannelKey(chainID))
}

// SetProposedConsumerChain stores a consumer chainId corresponding to a submitted consumer addition proposal
// This consumer chainId is deleted once the voting period for the proposal ends
// does not end.
func (k Keeper) SetProposedConsumerChain(ctx sdk.Context, chainID string, proposalID uint64) {
store := ctx.KVStore(k.storeKey)
store.Set(types.ProposedConsumerChainKey(proposalID), []byte(chainID))
}

// GetProposedConsumerChain get the proposed chainID in consumerAddition proposal.
func (k Keeper) GetProposedConsumerChain(ctx sdk.Context, proposalID uint64) string {
store := ctx.KVStore(k.storeKey)
return string(store.Get(types.ProposedConsumerChainKey(proposalID)))
}

// DeleteProposedConsumerChainInStore deletes the consumer chainID from store
// which is in gov consumerAddition proposal
func (k Keeper) DeleteProposedConsumerChainInStore(ctx sdk.Context, proposalID uint64) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.ProposedConsumerChainKey(proposalID))
}

// GetAllProposedConsumerChainIDs get consumer chainId in gov consumerAddition proposal before voting period ends.
func (k Keeper) GetAllProposedConsumerChainIDs(ctx sdk.Context) []types.ProposedChain {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, []byte{types.ProposedConsumerChainByteKey})
defer iterator.Close()

proposedChains := []types.ProposedChain{}
for ; iterator.Valid(); iterator.Next() {
proposalID, err := types.ParseProposedConsumerChainKey(types.ProposedConsumerChainByteKey, iterator.Key())
if err != nil {
panic(fmt.Errorf("proposed chains cannot be parsed: %w", err))
}

proposedChains = append(proposedChains, types.ProposedChain{
ChainID: string(iterator.Value()),
ProposalID: proposalID,
})

}

return proposedChains
}

// GetAllConsumerChains gets all of the consumer chains, for which the provider module
// created IBC clients. Consumer chains with created clients are also referred to as registered.
//
Expand Down
Loading

0 comments on commit 67ec715

Please sign in to comment.