Skip to content

Commit

Permalink
feat: store chain in proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
Yaru Wang committed Sep 12, 2023
1 parent 57b96ca commit ac7e1b9
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 0 deletions.
82 changes: 82 additions & 0 deletions x/ccv/provider/keeper/gov_hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package keeper

import (
"fmt"
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/gogoproto/proto"
"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) Hooks() Hooks {
return Hooks{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()

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

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

if consadditionProp.ProposalType() == types.ProposalTypeConsumerRemoval {
gh.k.SetChainsInProposal(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()

var msgLegacyContent v1.MsgExecLegacyContent
err := proto.Unmarshal(msgs[0].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 {
return
}

gh.k.DeleteChainsInProposal(ctx, consadditionProp.ChainId)
}

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) {}
43 changes: 43 additions & 0 deletions x/ccv/provider/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,49 @@ func (k Keeper) DeleteChainToChannel(ctx sdk.Context, chainID string) {
store.Delete(types.ChainToChannelKey(chainID))
}

// GetChainsInProposal gets chainId in gov proposal before voting finishes
func (k Keeper) GetChainsInProposal(ctx sdk.Context, chainID string) (string, bool) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.ChainInProposalKey(chainID))
if bz == nil {
return "", false
}

return string(bz), true
}

// SetChainsInProposal sets consumer chainId in gov consumerAddition proposal in store
// the consumer chainId is only added when the voting period for consumerAddition proposal
// does not end.
func (k Keeper) SetChainsInProposal(ctx sdk.Context, chainID string, proposalID uint64) {
store := ctx.KVStore(k.storeKey)
store.Set(types.ChainInProposalKey(chainID), sdk.Uint64ToBigEndian(proposalID))
}

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

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

chainIDs := []string{}
for ; iterator.Valid(); iterator.Next() {
// remove 1 byte prefix from key to retrieve chainID
chainID := string(iterator.Key()[1:])
chainIDs = append(chainIDs, chainID)
}

return chainIDs
}

// 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
7 changes: 7 additions & 0 deletions x/ccv/provider/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ const (
// handled in the current block
VSCMaturedHandledThisBlockBytePrefix

// ChainInProposalByteKey is the byte prefix storing the consumer chainId in consumerAddition gov proposal submitted before voting finishes
ChainInProposalByteKey
// NOTE: DO NOT ADD NEW BYTE PREFIXES HERE WITHOUT ADDING THEM TO getAllKeyPrefixes() IN keys_test.go
)

Expand Down Expand Up @@ -414,6 +416,11 @@ func ChainIdWithLenKey(prefix byte, chainID string) []byte {
)
}

// ChainInProposalKey returns the consumer chainId in consumerAddition gov proposal submitted before voting finishes
func ChainInProposalKey(chainID string) []byte {
return append([]byte{ChainInProposalByteKey}, []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}
Expand Down
1 change: 1 addition & 0 deletions x/ccv/provider/types/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func getAllKeyPrefixes() []byte {
providertypes.ConsumerAddrsToPruneBytePrefix,
providertypes.SlashLogBytePrefix,
providertypes.VSCMaturedHandledThisBlockBytePrefix,
providertypes.ChainInProposalByteKey,
}
}

Expand Down

0 comments on commit ac7e1b9

Please sign in to comment.