Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: store proposed chainID before voting finishes #1289

Merged
merged 38 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ac7e1b9
feat: store chain in proposal
Sep 12, 2023
0eea515
add govHook
Sep 12, 2023
a79f384
delete GetChainsInProposal
Sep 14, 2023
690c61c
check proposal type
Sep 14, 2023
658b5f5
update key
Sep 15, 2023
b0a3721
feat: add query proposed chainIDs
Sep 19, 2023
fbb74fc
feat: set govhook
Sep 19, 2023
b61bd85
feat: parse key
Sep 19, 2023
d13c124
refactor: names
Sep 19, 2023
1c6d099
feat: add list proposed consumer chains
Sep 20, 2023
2f007f5
test: add e2e test
Sep 20, 2023
402fcd4
merge main
Sep 20, 2023
27daf3a
add e2e test
Sep 20, 2023
114db15
update comments
Sep 20, 2023
74b7d91
update ProposeConsumerChains in e2e test
Sep 21, 2023
8db40a8
remove wait for block
Sep 21, 2023
5a26420
docs: update changelog
Sep 21, 2023
956b4cc
fix: lint
Sep 21, 2023
f193361
add TestParseProposedConsumerChainKey
Sep 21, 2023
c2cb529
refactor gov hook
Sep 21, 2023
8253ee7
Update proto/interchain_security/ccv/provider/v1/query.proto
yaruwangway Sep 21, 2023
f0c591e
update proto
Sep 21, 2023
4aa274a
add test for set kv
Sep 21, 2023
979b383
refactor key to be prefix_proposalID
Sep 21, 2023
b020e49
formatting
Sep 21, 2023
a90f87c
update e2e test
Sep 21, 2023
c159764
format
Sep 21, 2023
1f2f388
Update x/ccv/provider/keeper/gov_hook.go
yaruwangway Sep 22, 2023
39ca877
Update x/ccv/provider/keeper/keeper.go
yaruwangway Sep 22, 2023
85d0f33
Update x/ccv/provider/keeper/keeper.go
yaruwangway Sep 22, 2023
e094e42
fix e2e test
Sep 22, 2023
c7cda12
fix gosec
Sep 22, 2023
6bf0f39
remove type url check
Oct 2, 2023
dc7371b
test: add unit test
Oct 2, 2023
5ee3116
lint
Oct 2, 2023
d31f4c8
fix lint
Oct 2, 2023
533ea06
fix err
Oct 2, 2023
834a2af
Merge branch 'feat/refactor-key-assignment' into chain-in-proposal
yaruwangway Oct 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
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 / 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
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 / 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
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 / 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
tr.useGorelayer = useRly
}

// validateStringLiterals enforces that configs follow the constraints
Expand All @@ -423,9 +423,8 @@
// 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 / 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
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 @@
}
}

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 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 @@
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 / 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)
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 @@
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 / 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
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 {
yaruwangway marked this conversation as resolved.
Show resolved Hide resolved
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 {
yaruwangway marked this conversation as resolved.
Show resolved Hide resolved
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
Loading