diff --git a/x/dogfood/keeper/abci.go b/x/dogfood/keeper/abci.go index 7c7b517ea..ab913abf5 100644 --- a/x/dogfood/keeper/abci.go +++ b/x/dogfood/keeper/abci.go @@ -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{} diff --git a/x/dogfood/keeper/impl_sdk.go b/x/dogfood/keeper/impl_sdk.go index 759b87c84..5b342af5c 100644 --- a/x/dogfood/keeper/impl_sdk.go +++ b/x/dogfood/keeper/impl_sdk.go @@ -96,7 +96,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, ) diff --git a/x/dogfood/types/expected_keepers.go b/x/dogfood/types/expected_keepers.go index 3c6146ab5..8b7412685 100644 --- a/x/dogfood/types/expected_keepers.go +++ b/x/dogfood/types/expected_keepers.go @@ -62,6 +62,13 @@ type OperatorKeeper interface { 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. @@ -78,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{} diff --git a/x/operator/keeper/avs_operator_shares.go b/x/operator/keeper/avs_operator_shares.go index a2ae08356..a846a1971 100644 --- a/x/operator/keeper/avs_operator_shares.go +++ b/x/operator/keeper/avs_operator_shares.go @@ -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 +} diff --git a/x/operator/keeper/msg_server.go b/x/operator/keeper/msg_server.go index fcc018a67..7a16c10c4 100644 --- a/x/operator/keeper/msg_server.go +++ b/x/operator/keeper/msg_server.go @@ -44,6 +44,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 } diff --git a/x/operator/keeper/slash.go b/x/operator/keeper/slash.go index f996b3e77..e70c86006 100644 --- a/x/operator/keeper/slash.go +++ b/x/operator/keeper/slash.go @@ -3,6 +3,9 @@ package keeper import ( "fmt" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/ethereum/go-ethereum/common/hexutil" + errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" @@ -12,6 +15,12 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// GetSlashIDForDogfood It use infractionType+'/'+'infractionHeight' as the slashID, because the slash event occurs in dogfood doesn't have a TxID. It isn't submitted through an external transaction. +func GetSlashIDForDogfood(infraction stakingtypes.Infraction, infractionHeight int64) string { + // #nosec G701 + return string(assetstype.GetJoinedStoreKey(hexutil.EncodeUint64(uint64(infraction)), hexutil.EncodeUint64(uint64(infractionHeight)))) +} + // GetAssetsAmountToSlash It will slash the assets that are opting into AVS first, and if there isn't enough to slash, then it will slash the assets that have requested to undelegate but still locked. func (k *Keeper) GetAssetsAmountToSlash(ctx sdk.Context, operatorAddress sdk.AccAddress, avsAddr string, slashEventHeight int64, slashProportion sdkmath.LegacyDec) (*SlashAssets, error) { ret := &SlashAssets{ @@ -230,6 +239,33 @@ func (k *Keeper) Slash(ctx sdk.Context, operatorAddress sdk.AccAddress, avsAddr, return nil } +// SlashWithInfractionReason is an expected slash interface for the dogfood module. +func (k *Keeper) SlashWithInfractionReason( + ctx sdk.Context, addr sdk.AccAddress, infractionHeight, _ int64, + slashFactor sdk.Dec, infraction stakingtypes.Infraction, +) sdkmath.Int { + chainID := ctx.ChainID() + avsAddr, err := k.avsKeeper.GetAvsAddrByChainID(ctx, chainID) + if err != nil { + k.Logger(ctx).Error(err.Error(), chainID) + return sdkmath.NewInt(0) + } + slashContract, err := k.avsKeeper.GetAvsSlashContract(ctx, avsAddr) + if err != nil { + k.Logger(ctx).Error(err.Error(), avsAddr) + return sdkmath.NewInt(0) + } + slashID := GetSlashIDForDogfood(infraction, infractionHeight) + err = k.Slash(ctx, addr, avsAddr, slashContract, slashID, infractionHeight, slashFactor) + if err != nil { + k.Logger(ctx).Error(err.Error(), avsAddr) + return sdkmath.NewInt(0) + } + // todo: The returned value should be the amount of burned Exo if we considering a slash from the reward + // Now it doesn't slash from the reward, so just return 0 + return sdkmath.NewInt(0) +} + // IsOperatorJailedForChainID add for dogfood func (k *Keeper) IsOperatorJailedForChainID(ctx sdk.Context, consAddr sdk.ConsAddress, chainID string) bool { found, operatorAddr := k.GetOperatorAddressForChainIDAndConsAddr(ctx, chainID, consAddr)