Skip to content

Commit

Permalink
store opted in and opted out validators
Browse files Browse the repository at this point in the history
  • Loading branch information
insumity committed Feb 1, 2024
1 parent 0ffacfb commit fde165e
Show file tree
Hide file tree
Showing 8 changed files with 359 additions and 40 deletions.
87 changes: 87 additions & 0 deletions x/ccv/provider/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ func GetTxCmd() *cobra.Command {
cmd.AddCommand(NewAssignConsumerKeyCmd())
cmd.AddCommand(NewSubmitConsumerMisbehaviourCmd())
cmd.AddCommand(NewSubmitConsumerDoubleVotingCmd())
cmd.AddCommand(NewOptInCmd())
cmd.AddCommand(NewOptOutCmd())

return cmd
}
Expand Down Expand Up @@ -202,3 +204,88 @@ Example:

return cmd
}

func NewOptInCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "opt-in [consumer-chain-id] [consumer-pubkey]",
Short: "opts in validator to the consumer chain, and if given uses the " +
"provided consensus public key for this consumer chain",
Args: cobra.RangeArgs(1, 2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

txf, err := tx.NewFactoryCLI(clientCtx, cmd.Flags())
if err != nil {
return err
}
txf = txf.WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever)

providerValAddr := clientCtx.GetFromAddress()

var consumerPubKey types.MsgOptIn_ConsumerKey
if len(args) == 2 {
// consumer public key was provided
consumerPubKey = types.MsgOptIn_ConsumerKey{ConsumerKey: args[1]}
} else {
consumerPubKey = types.MsgOptIn_ConsumerKey{}
}
msg, err := types.NewMsgOptIn(args[0], sdk.ValAddress(providerValAddr), consumerPubKey)

if err != nil {
return err
}
if err := msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg)
},
}

flags.AddTxFlagsToCmd(cmd)

_ = cmd.MarkFlagRequired(flags.FlagFrom)

return cmd
}

func NewOptOutCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "opt-out [consumer-chain-id]",
Short: "opts out validator from this consumer chain",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

txf, err := tx.NewFactoryCLI(clientCtx, cmd.Flags())
if err != nil {
return err
}
txf = txf.WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever)

providerValAddr := clientCtx.GetFromAddress()

msg, err := types.NewMsgOptOut(args[0], sdk.ValAddress(providerValAddr))
if err != nil {
return err
}
if err := msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg)
},
}

flags.AddTxFlagsToCmd(cmd)

_ = cmd.MarkFlagRequired(flags.FlagFrom)

return cmd
}
143 changes: 143 additions & 0 deletions x/ccv/provider/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -1136,3 +1136,146 @@ func (k Keeper) GetAllRegisteredAndProposedChainIDs(ctx sdk.Context) []string {

return allConsumerChains
}

func (k Keeper) SetOptedIn(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
blockHeight uint64,
) {
store := ctx.KVStore(k.storeKey)

// validator is considered opted in
isOptedIn := []byte{1}
blockHeightBytes := make([]byte, 8)
binary.BigEndian.PutUint64(blockHeightBytes, blockHeight)
toStore := append(isOptedIn, blockHeightBytes...)

store.Set(types.OptedInKey(chainID, providerAddr), toStore)
}

func (k Keeper) RemoveOptedIn(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
) {
store := ctx.KVStore(k.storeKey)
buf := store.Get(types.OptedInKey(chainID, providerAddr))

buf[0] = 0 // consider it not opted in anymore
store.Set(types.OptedInKey(chainID, providerAddr), buf)
}

func (k Keeper) SetToBeOptedIn(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
) {
store := ctx.KVStore(k.storeKey)
store.Set(types.ToBeOptedInKey(chainID, providerAddr), []byte{})
}

func (k Keeper) IsOptedIn(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
) bool {
store := ctx.KVStore(k.storeKey)
return store.Get(types.OptedInKey(chainID, providerAddr)) != nil
}

func (k Keeper) GetOptedIn(
ctx sdk.Context,
chainID string) (addresses []types.ProviderConsAddress) {

store := ctx.KVStore(k.storeKey)
key := types.ChainIdWithLenKey(types.OptedInBytePrefix, chainID)
iterator := sdk.KVStorePrefixIterator(store, key)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):])
addresses = append(addresses, providerAddr)
}

return addresses
}

func (k Keeper) IsToBeOptedIn(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
) bool {
store := ctx.KVStore(k.storeKey)
return store.Get(types.ToBeOptedInKey(chainID, providerAddr)) != nil
}

func (k Keeper) GetToBeOptedIn(
ctx sdk.Context,
chainID string) (addresses []types.ProviderConsAddress) {

store := ctx.KVStore(k.storeKey)
key := types.ChainIdWithLenKey(types.ToBeOptedInBytePrefix, chainID)
iterator := sdk.KVStorePrefixIterator(store, key)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):])
addresses = append(addresses, providerAddr)
}

return addresses
}

func (k Keeper) RemoveToBeOptedIn(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.ToBeOptedOutKey(chainID, providerAddr))
}

func (k Keeper) SetToBeOptedOut(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
) {
store := ctx.KVStore(k.storeKey)
store.Set(types.ToBeOptedOutKey(chainID, providerAddr), []byte{})
}

func (k Keeper) IsToBeOptedOut(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
) bool {
store := ctx.KVStore(k.storeKey)
return store.Get(types.ToBeOptedOutKey(chainID, providerAddr)) != nil
}

func (k Keeper) GetToBeOptedOut(
ctx sdk.Context,
chainID string) (addresses []types.ProviderConsAddress) {

store := ctx.KVStore(k.storeKey)
key := types.ChainIdWithLenKey(types.ToBeOptedOutBytePrefix, chainID)
iterator := sdk.KVStorePrefixIterator(store, key)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
providerAddr := types.NewProviderConsAddress(iterator.Key()[len(key):])
addresses = append(addresses, providerAddr)
}

return addresses
}

func (k Keeper) RemoveToBeOptedOut(
ctx sdk.Context,
chainID string,
providerAddr types.ProviderConsAddress,
) {
store := ctx.KVStore(k.storeKey)
store.Delete(types.ToBeOptedOutKey(chainID, providerAddr))
}
63 changes: 45 additions & 18 deletions x/ccv/provider/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,36 +177,63 @@ func (k msgServer) SubmitConsumerDoubleVoting(goCtx context.Context, msg *types.

func (k msgServer) OptIn(goCtx context.Context, msg *types.MsgOptIn) (*types.MsgOptInResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
if err := k.Keeper.HandleOptIn(ctx, *msg); err != nil {

valAddress, err := sdk.ConsAddressFromBech32(msg.ProviderAddr)
if err != nil {
return nil, err
}
providerAddr := types.NewProviderConsAddress(valAddress)
if err != nil {
return nil, err
}

// add some outpout
//ctx.EventManager().EmitEvents(sdk.Events{
// sdk.NewEvent(
// ccvtypes.EventTypeSubmitConsumerMisbehaviour,
// sdk.NewAttribute(ccvtypes.AttributeConsumerMisbehaviour, msg.Misbehaviour.String()),
//
// ),
//})
// todo also send down the consumer key ...???
if err := k.Keeper.HandleOptIn(ctx, msg.ChainId, providerAddr); err != nil {
return nil, err
}

if msg.GetConsumerKey() != "" { // FIXME: there should be a nicer way to do this
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
ccvtypes.EventTypeOptIn,
sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr),
sdk.NewAttribute(types.AttributeConsumerConsensusPubKey, msg.GetConsumerKey()),
),
})
} else {
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
ccvtypes.EventTypeOptIn,
sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr),
),
})
}

return &types.MsgOptInResponse{}, nil
}

func (k msgServer) OptOut(goCtx context.Context, msg *types.MsgOptOut) (*types.MsgOptOutResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
if err := k.Keeper.HandleOptOut(ctx, *msg); err != nil {

valAddress, err := sdk.ConsAddressFromBech32(msg.ProviderAddr)
if err != nil {
return nil, err
}
providerAddr := types.NewProviderConsAddress(valAddress)
if err != nil {
return nil, err
}

if err := k.Keeper.HandleOptOut(ctx, msg.ChainId, providerAddr); err != nil {
return nil, err
}

// add some outpout
//ctx.EventManager().EmitEvents(sdk.Events{
// sdk.NewEvent(
// ccvtypes.EventTypeSubmitConsumerMisbehaviour,
// sdk.NewAttribute(ccvtypes.AttributeConsumerMisbehaviour, msg.Misbehaviour.String()),
//
// ),
//})
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
ccvtypes.EventTypeOptOut,
sdk.NewAttribute(types.AttributeProviderValidatorAddress, msg.ProviderAddr),
),
})

return &types.MsgOptOutResponse{}, nil
}
38 changes: 32 additions & 6 deletions x/ccv/provider/keeper/partial_set_security.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,48 @@
package keeper

import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/interchain-security/v4/x/ccv/provider/types"
)

// HandleOptIn TODO
func (k Keeper) HandleOptIn(ctx sdk.Context, msg types.MsgOptIn) error {
// TODO: HandleOptIn
func (k Keeper) HandleOptIn(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) error {
logger := k.Logger(ctx)
logger.Info("something ..")

if k.IsToBeOptedOut(ctx, chainID, providerAddr) {
k.RemoveToBeOptedOut(ctx, chainID, providerAddr)
return nil
} else if k.IsToBeOptedIn(ctx, chainID, providerAddr) {
return nil
} else if k.IsOptedIn(ctx, chainID, providerAddr) {
logger.Error("That's a big no")
return fmt.Errorf("What's happening? already opted in")
} else {
k.SetToBeOptedIn(ctx, chainID, providerAddr)
}

//if msg.GetConsumerKey() != "" {
// k.AssignConsumerKey(ctx, msg.ChainId)
//}

return nil
}

// HandleOptOut TODO
func (k Keeper) HandleOptOut(ctx sdk.Context, msg types.MsgOptOut) error {
func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types.ProviderConsAddress) error {
logger := k.Logger(ctx)
logger.Info("something ..")

if k.IsToBeOptedIn(ctx, chainID, providerAddr) {
k.RemoveToBeOptedIn(ctx, chainID, providerAddr)
return nil
} else if k.IsToBeOptedOut(ctx, chainID, providerAddr) {
return nil
} else if !k.IsOptedIn(ctx, chainID, providerAddr) {
logger.Error("that's a no!")
return fmt.Errorf("What's happening? already opted in")
} else {
k.SetToBeOptedOut(ctx, chainID, providerAddr)
}

return nil
}
Loading

0 comments on commit fde165e

Please sign in to comment.