Skip to content

Commit

Permalink
Merge pull request #21 from TimmyExogenous/integrate-with-dogfood
Browse files Browse the repository at this point in the history
[feat] implement the operator interfaces expected by dogfood
  • Loading branch information
TimmyExogenous authored Apr 10, 2024
2 parents d28c021 + ff6edf5 commit c973d8a
Show file tree
Hide file tree
Showing 15 changed files with 688 additions and 375 deletions.
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ proto-download-deps:
git remote add origin "https://github.com/cosmos/cosmos-sdk.git" && \
git config core.sparseCheckout true && \
printf "proto\nthird_party\n" > .git/info/sparse-checkout && \
git pull origin main && \
git pull origin release/v0.47.x && \
rm -f ./proto/buf.* && \
mv ./proto/* ..
rm -rf "$(THIRD_PARTY_DIR)/cosmos_tmp"
Expand All @@ -441,7 +441,7 @@ proto-download-deps:
git remote add origin "https://github.com/cosmos/ibc-go.git" && \
git config core.sparseCheckout true && \
printf "proto\n" > .git/info/sparse-checkout && \
git pull origin main && \
git pull origin release/v7.2.x && \
rm -f ./proto/buf.* && \
mv ./proto/* ..
rm -rf "$(THIRD_PARTY_DIR)/ibc_tmp"
Expand All @@ -452,7 +452,8 @@ proto-download-deps:
git remote add origin "https://github.com/cosmos/cosmos-proto.git" && \
git config core.sparseCheckout true && \
printf "proto\n" > .git/info/sparse-checkout && \
git pull origin main && \
git fetch origin tags/v1.0.0-beta.3 && \
git checkout -b my_branch FETCH_HEAD && \
rm -f ./proto/buf.* && \
mv ./proto/* ..
rm -rf "$(THIRD_PARTY_DIR)/cosmos_proto_tmp"
Expand Down
5 changes: 5 additions & 0 deletions proto/exocore/operator/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package exocore.operator.v1;

import "amino/amino.proto";
import "cosmos/msg/v1/msg.proto";
import "cosmos/staking/v1beta1/staking.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";

Expand Down Expand Up @@ -45,6 +46,8 @@ message OperatorInfo {
string operator_meta_info = 3;
// client_chain_earning_addr_list is the client chain earning address list.
ClientChainEarningAddrList client_chain_earnings_addr = 4;
// commission defines the commission parameters.
cosmos.staking.v1beta1.Commission commission = 5 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
}

// OptedInfo is the opted information about operator
Expand All @@ -55,6 +58,8 @@ message OptedInfo {
uint64 opted_in_height = 2;
// opted_out_height is the exocore block height at which the operator opted out
uint64 opted_out_height = 3;
// jailed defined whether the operator has been jailed from bonded status or not.
bool jailed = 4;
}

// OptedInAssetState is the state of opted-in asset
Expand Down
4 changes: 2 additions & 2 deletions x/dogfood/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ func (k Keeper) EndBlock(ctx sdk.Context) []abci.ValidatorUpdate {
prev := k.getKeyPowerMapping(ctx).List
res := make([]abci.ValidatorUpdate, 0, len(prev))
operators, keys := k.operatorKeeper.GetActiveOperatorsForChainID(ctx, ctx.ChainID())
powers, err := k.restakingKeeper.GetAvgDelegatedValue(
ctx, operators, k.GetAssetIDs(ctx), k.GetEpochIdentifier(ctx),
powers, err := k.operatorKeeper.GetAvgDelegatedValue(
ctx, operators, ctx.ChainID(), k.GetEpochIdentifier(ctx),
)
if err != nil {
return []abci.ValidatorUpdate{}
Expand Down
24 changes: 5 additions & 19 deletions x/dogfood/keeper/impl_sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,8 @@ func (k Keeper) ValidatorByConsAddr(
ctx sdk.Context,
addr sdk.ConsAddress,
) stakingtypes.ValidatorI {
found, accAddr := k.operatorKeeper.GetOperatorAddressForChainIDAndConsAddr(
ctx, ctx.ChainID(), addr,
)
if !found {
// replicate the behavior of the SDK's staking module; do not panic.
return nil
}
return stakingtypes.Validator{
Jailed: k.operatorKeeper.IsOperatorJailedForChainID(ctx, accAddr, ctx.ChainID()),
Jailed: k.operatorKeeper.IsOperatorJailedForChainID(ctx, addr, ctx.ChainID()),
}
}

Expand Down Expand Up @@ -104,7 +97,7 @@ func (k Keeper) SlashWithInfractionReason(
}
// TODO(mm): add list of assets to be slashed (and not just all of them).
// based on yet to be finalized slashing design.
return k.slashingKeeper.SlashWithInfractionReason(
return k.operatorKeeper.SlashWithInfractionReason(
ctx, accAddress, infractionHeight,
power, slashFactor, infraction,
)
Expand All @@ -124,8 +117,8 @@ func (k Keeper) Jail(ctx sdk.Context, addr sdk.ConsAddress) {
// The function is called by the slashing module only when it receives a request from the
// operator to do so. TODO(mm): We need to use the SDK's slashing module to allow for downtime
// slashing but somehow we need to prevent its Unjail function from being called by anyone.
func (k Keeper) Unjail(sdk.Context, sdk.ConsAddress) {
panic("unimplemented on this keeper")
func (k Keeper) Unjail(ctx sdk.Context, addr sdk.ConsAddress) {
k.operatorKeeper.Unjail(ctx, addr, ctx.ChainID())
}

// Delegation is an implementation of the staking interface expected by the SDK's slashing
Expand Down Expand Up @@ -155,14 +148,7 @@ func (k Keeper) GetAllValidators(sdk.Context) (validators []stakingtypes.Validat
// slashing module. It is called by the slashing module to record validator signatures
// for downtime tracking. We delegate the call to the operator keeper.
func (k Keeper) IsValidatorJailed(ctx sdk.Context, addr sdk.ConsAddress) bool {
found, accAddr := k.operatorKeeper.GetOperatorAddressForChainIDAndConsAddr(
ctx, ctx.ChainID(), addr,
)
if !found {
// replicate the behavior of the SDK's staking module
return false
}
return k.operatorKeeper.IsOperatorJailedForChainID(ctx, accAddr, ctx.ChainID())
return k.operatorKeeper.IsOperatorJailedForChainID(ctx, addr, ctx.ChainID())
}

// ApplyAndReturnValidatorSetUpdates is an implementation of the staking interface expected
Expand Down
23 changes: 11 additions & 12 deletions x/dogfood/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,22 @@ type OperatorKeeper interface {
GetOperatorAddressForChainIDAndConsAddr(
sdk.Context, string, sdk.ConsAddress,
) (bool, sdk.AccAddress)
IsOperatorJailedForChainID(sdk.Context, sdk.AccAddress, string) bool
IsOperatorJailedForChainID(sdk.Context, sdk.ConsAddress, string) bool
Jail(sdk.Context, sdk.ConsAddress, string)
Unjail(sdk.Context, sdk.ConsAddress, string)
// GetActiveOperatorsForChainID should return a list of operators and their public keys.
// These operators should not be in the process of opting our, and should not be jailed
// These operators should not be in the process of opting out, and should not be jailed
// whether permanently or temporarily.
GetActiveOperatorsForChainID(
sdk.Context, string,
) ([]sdk.AccAddress, []tmprotocrypto.PublicKey)
GetAvgDelegatedValue(
sdk.Context, []sdk.AccAddress, string, string,
) ([]int64, error)
SlashWithInfractionReason(
sdk.Context, sdk.AccAddress, int64,
int64, sdk.Dec, stakingtypes.Infraction,
) math.Int
}

// DelegationKeeper represents the expected keeper interface for the delegation module.
Expand All @@ -77,17 +85,8 @@ type EpochsHooks interface {

// AssetsKeeper represents the expected keeper interface for the assets module.
type AssetsKeeper interface {
GetOperatorAssetValue(sdk.Context, sdk.AccAddress) (int64, error)
IsStakingAsset(sdk.Context, string) bool
GetAvgDelegatedValue(
sdk.Context, []sdk.AccAddress, []string, string,
) ([]int64, error)
}

// SlashingKeeper represents the expected keeper interface for the (exo-)slashing module.
type SlashingKeeper interface {
SlashWithInfractionReason(
sdk.Context, sdk.AccAddress, int64,
int64, sdk.Dec, stakingtypes.Infraction,
) math.Int
}
type SlashingKeeper interface{}
32 changes: 32 additions & 0 deletions x/operator/keeper/avs_operator_shares.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,35 @@ func (k *Keeper) GetStakerShare(ctx sdk.Context, avsAddr, stakerID, operatorAddr

return ret.Amount, nil
}

func (k *Keeper) GetAvgDelegatedValue(
ctx sdk.Context, operators []sdk.AccAddress, chainID, _ string,
) ([]int64, error) {
avsAddr, err := k.avsKeeper.GetAvsAddrByChainID(ctx, chainID)
if err != nil {
return nil, err
}
ret := make([]int64, 0)
for _, operator := range operators {
share, err := k.GetOperatorShare(ctx, operator.String(), avsAddr)
if err != nil {
return nil, err
}
// truncate the USD value to int64
ret = append(ret, share.TruncateInt64())
}
return ret, nil
}

func (k *Keeper) GetOperatorAssetValue(ctx sdk.Context, operator sdk.AccAddress, chainID string) (int64, error) {
avsAddr, err := k.avsKeeper.GetAvsAddrByChainID(ctx, chainID)
if err != nil {
return 0, err
}
share, err := k.GetOperatorShare(ctx, operator.String(), avsAddr)
if err != nil {
return 0, err
}
// truncate the USD value to int64
return share.TruncateInt64(), nil
}
6 changes: 0 additions & 6 deletions x/operator/keeper/consensus_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -435,12 +435,6 @@ func (k *Keeper) CompleteOperatorOptOutFromChainID(
store.Delete(types.KeyForOperatorOptOutFromChainID(opAccAddr, chainID))
}

// IsOperatorJailedForChainID add for dogfood
func (k *Keeper) IsOperatorJailedForChainID(sdk.Context, sdk.AccAddress, string) bool {
return false
}
func (k *Keeper) Jail(sdk.Context, sdk.ConsAddress, string) {}

func (k *Keeper) GetActiveOperatorsForChainID(
sdk.Context, string,
) ([]sdk.AccAddress, []*tmprotocrypto.PublicKey) {
Expand Down
9 changes: 9 additions & 0 deletions x/operator/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ func (k *Keeper) OptInToCosmosChain(
if err != nil {
return nil, err
}
// call the basic OptIn
avsAddr, err := k.avsKeeper.GetAvsAddrByChainID(ctx, req.ChainId)
if err != nil {
return nil, err
}
err = k.OptIn(ctx, addr, avsAddr)
if err != nil {
return nil, err
}
return &types.OptInToCosmosChainResponse{}, nil
}

Expand Down
54 changes: 52 additions & 2 deletions x/operator/keeper/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ func (k *Keeper) SetOperatorInfo(ctx sdk.Context, addr string, info *operatortyp
if err != nil {
return errorsmod.Wrap(err, "SetOperatorInfo: error occurred when parse acc address from Bech32")
}
// todo: to check the validation of input info
store := prefix.NewStore(ctx.KVStore(k.storeKey), operatortypes.KeyPrefixOperatorInfo)
// todo: think about the difference between init and update in future

Expand Down Expand Up @@ -49,12 +48,49 @@ func (k *Keeper) OperatorInfo(ctx sdk.Context, addr string) (info *operatortypes
return &ret, nil
}

// AllOperators return the address list of all operators
func (k *Keeper) AllOperators(ctx sdk.Context) []string {
store := prefix.NewStore(ctx.KVStore(k.storeKey), operatortypes.KeyPrefixOperatorInfo)
iterator := sdk.KVStorePrefixIterator(store, nil)
defer iterator.Close()

ret := make([]string, 0)
for ; iterator.Valid(); iterator.Next() {
accAddr := sdk.AccAddress(iterator.Key())
ret = append(ret, accAddr.String())
}
return ret
}

func (k *Keeper) IsOperator(ctx sdk.Context, addr sdk.AccAddress) bool {
store := prefix.NewStore(ctx.KVStore(k.storeKey), operatortypes.KeyPrefixOperatorInfo)
return store.Has(addr)
}

func (k *Keeper) UpdateOptedInfo(ctx sdk.Context, operatorAddr, avsAddr string, info *operatortypes.OptedInfo) error {
func (k *Keeper) HandleOptedInfo(ctx sdk.Context, operatorAddr, avsAddr string, handleFunc func(info *operatortypes.OptedInfo)) error {
opAccAddr, err := sdk.AccAddressFromBech32(operatorAddr)
if err != nil {
return errorsmod.Wrap(err, "HandleOptedInfo: error occurred when parse acc address from Bech32")
}
store := prefix.NewStore(ctx.KVStore(k.storeKey), operatortypes.KeyPrefixOperatorOptedAVSInfo)
infoKey := assetstype.GetJoinedStoreKey(operatorAddr, avsAddr)
ifExist := store.Has(infoKey)
if !ifExist {
return errorsmod.Wrap(operatortypes.ErrNoKeyInTheStore, fmt.Sprintf("HandleOptedInfo: key is %suite", opAccAddr))
}
// get info from the store
value := store.Get(infoKey)
info := &operatortypes.OptedInfo{}
k.cdc.MustUnmarshal(value, info)
// call the handleFunc
handleFunc(info)
// restore the info after handling
bz := k.cdc.MustMarshal(info)
store.Set(infoKey, bz)
return nil
}

func (k *Keeper) SetOptedInfo(ctx sdk.Context, operatorAddr, avsAddr string, info *operatortypes.OptedInfo) error {
store := prefix.NewStore(ctx.KVStore(k.storeKey), operatortypes.KeyPrefixOperatorOptedAVSInfo)

// check operator address validation
Expand Down Expand Up @@ -99,6 +135,20 @@ func (k *Keeper) IsOptedIn(ctx sdk.Context, operatorAddr, avsAddr string) bool {
return true
}

func (k *Keeper) IsActive(ctx sdk.Context, operatorAddr, avsAddr string) bool {
optedInfo, err := k.GetOptedInfo(ctx, operatorAddr, avsAddr)
if err != nil {
return false
}
if optedInfo.OptedOutHeight != operatortypes.DefaultOptedOutHeight {
return false
}
if optedInfo.Jailed {
return false
}
return true
}

func (k *Keeper) GetOptedInAVSForOperator(ctx sdk.Context, operatorAddr string) ([]string, error) {
// get all opted-in info
store := prefix.NewStore(ctx.KVStore(k.storeKey), operatortypes.KeyPrefixOperatorOptedAVSInfo)
Expand Down
14 changes: 14 additions & 0 deletions x/operator/keeper/operator_info_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package keeper_test

import (
"cosmossdk.io/math"
"github.com/ExocoreNetwork/exocore/x/assets/types"
operatortype "github.com/ExocoreNetwork/exocore/x/operator/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

func (suite *OperatorTestSuite) TestOperatorInfo() {
Expand All @@ -15,6 +17,7 @@ func (suite *OperatorTestSuite) TestOperatorInfo() {
{101, "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984"},
},
},
Commission: stakingtypes.NewCommission(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()),
}
err := suite.App.OperatorKeeper.SetOperatorInfo(suite.Ctx, suite.AccAddress.String(), info)
suite.NoError(err)
Expand All @@ -24,6 +27,17 @@ func (suite *OperatorTestSuite) TestOperatorInfo() {
suite.Equal(*info, *getOperatorInfo)
}

func (suite *OperatorTestSuite) TestAllOperators() {
suite.prepare()
operators := []string{suite.operatorAddr.String(), suite.AccAddress.String()}
info := &operatortype.OperatorInfo{}
err := suite.App.OperatorKeeper.SetOperatorInfo(suite.Ctx, suite.AccAddress.String(), info)
suite.NoError(err)

getOperators := suite.App.OperatorKeeper.AllOperators(suite.Ctx)
suite.Equal(operators, getOperators)
}

func (suite *OperatorTestSuite) TestHistoricalOperatorInfo() {
height := suite.Ctx.BlockHeight()
info := &operatortype.OperatorInfo{
Expand Down
Loading

0 comments on commit c973d8a

Please sign in to comment.