Skip to content

Commit

Permalink
Merge pull request #61 from TimmyExogenous/cli-rpc-usd-value
Browse files Browse the repository at this point in the history
[feat] add the new slash implementation and some missed RPC and CLI
  • Loading branch information
TimmyExogenous authored Jun 21, 2024
2 parents 002d277 + be3b8e5 commit dd27216
Show file tree
Hide file tree
Showing 43 changed files with 4,817 additions and 1,030 deletions.
3 changes: 2 additions & 1 deletion precompiles/avsTask/task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package task_test

import (
"encoding/hex"
"math/big"

"github.com/ExocoreNetwork/exocore/x/avs/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"math/big"

"github.com/ExocoreNetwork/exocore/app"
"github.com/ExocoreNetwork/exocore/precompiles/avsTask"
Expand Down
37 changes: 37 additions & 0 deletions proto/exocore/delegation/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package exocore.delegation.v1;

import "cosmos/query/v1/query.proto";
import "cosmos_proto/cosmos.proto";
import "exocore/delegation/v1/tx.proto";
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";

Expand Down Expand Up @@ -81,6 +82,28 @@ message UndelegationHoldCountResponse {
uint64 hold_count = 1;
}

// UndelegationsReq is the request to obtain all delegations
// by staker id and asset id.
message UndelegationsReq {
// staker_id is the staker id.
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
// asset_id is the asset id.
string asset_id = 2 [(gogoproto.customname) = "AssetID"];
}

// UndelegationsByHeightReq is the request to obtain all undelegations waiting to be completed
// by height.
message UndelegationsByHeightReq {
// block_height is the block height to query.
uint64 block_height = 1;
}

// UndelegationRecordList is the response to query undelegations.
message UndelegationRecordList {
// UndelegationRecord is the returned undelegations
repeated UndelegationRecord undelegations = 1;
}

// Query is the service API for the delegation module.
service Query {
// DelegationInfo queries the delegation information for {stakerID, assetID}.
Expand All @@ -100,5 +123,19 @@ service Query {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/QueryUndelegationHoldCount/{record_key}";
}

// QueryUndelegations queries all undelegations for
// {staker, asset}.
rpc QueryUndelegations(UndelegationsReq) returns (UndelegationRecordList) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/QueryUndelegations";
}

// QueryUndelegationsByHeight queries all undelegations waiting to be completed by
// {height}.
rpc QueryUndelegationsByHeight(UndelegationsByHeightReq) returns (UndelegationRecordList) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/exocore/delegation/v1/QueryUndelegationsByHeight";
}
}

82 changes: 72 additions & 10 deletions proto/exocore/operator/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,54 @@ message QueryAllOperatorsResponse {
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QueryOperatorConsKeyRequest is a request to obtain the consensus public key of the operator.
// OperatorAVSAddressDetails includes the address of operator and AVS
message OperatorAVSAddressDetails {
// operator_addr should be the string type of sdk.AccAddress
string operator_addr = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// avs_address is the address of the AVS - either an 0x address or a chainID.
string avs_address = 2 [(gogoproto.customname) = "AVSAddress"];
}

// QueryOperatorUSDValueRequest is the request to obtain the USD value for operator.
message QueryOperatorUSDValueRequest {
// details is the operator and AVS address
OperatorAVSAddressDetails details = 1;
}

// QueryAVSUSDValueRequest is the request to obtain the USD value for AVS.
message QueryAVSUSDValueRequest {
// avs_address is the AVS address opted-in by the operator
string avs_address = 1
[(gogoproto.customname) = "AVSAddress"];
}

// QueryOperatorSlashInfoRequest is the request to obtain the slash information for the specified
// operator and AVS
message QueryOperatorSlashInfoRequest {
// details is the operator and AVS address
OperatorAVSAddressDetails details = 1;
// pagination related options.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}

// OperatorSlashInfoByID includes the slash information and the slashID
message OperatorSlashInfoByID {
// slash_id is stored as the key of the slash information,
// so it will be parsed and padding here.
string slash_id = 1 [(gogoproto.customname) = "SlashID"];
// info is the specified detailed information for the slashing event.
OperatorSlashInfo info = 2;
}

// QueryOperatorSlashInfoResponse is the response for GetOperatorSlashInfoRequest
message QueryOperatorSlashInfoResponse{
// all_slash_info is a list of the slash information for the specified operator and AVS
repeated OperatorSlashInfoByID all_slash_info = 1;
// pagination related response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QueryOperatorConsKeyRequest is the request to obtain the consensus public key of the operator
message QueryOperatorConsKeyRequest {
// operator_acc_addr is the operator account address.
string operator_acc_addr = 1;
Expand All @@ -44,7 +91,7 @@ message QueryOperatorConsKeyRequest {
// QueryOperatorConsKeyResponse is the response for QueryOperatorConsKeyRequest.
message QueryOperatorConsKeyResponse {
// public_key is the consensus public key of the operator.
tendermint.crypto.PublicKey public_key = 1 [ (gogoproto.nullable) = false ];
tendermint.crypto.PublicKey public_key = 1 [(gogoproto.nullable) = false];
// opting_out is a flag to indicate if the operator is opting out of consensus.
bool opting_out = 2;
}
Expand Down Expand Up @@ -147,17 +194,17 @@ service Query {

// QueryOperatorConsKeyForChainID queries the consensus public key for the operator
rpc QueryOperatorConsKeyForChainID(QueryOperatorConsKeyRequest) returns (
QueryOperatorConsKeyResponse
) {
QueryOperatorConsKeyResponse
) {
option (google.api.http) = {
get: "/exocore/operator/v1/operator_cons_key/{operator_acc_addr}/{chain}"
};
}

// QueryOperatorConsAddressForChainID queries the consensus address for the operator.
rpc QueryOperatorConsAddressForChainID(QueryOperatorConsAddressRequest) returns (
QueryOperatorConsAddressResponse
) {
QueryOperatorConsAddressResponse
) {
option (google.api.http) = {
get: "/exocore/operator/v1/operator_cons_addr/{operator_acc_addr}/{chain}"
};
Expand All @@ -166,18 +213,33 @@ service Query {
// QueryAllOperatorConsKeysByChainID queries all operators and their consensus public keys
// for a specific chain ID
rpc QueryAllOperatorConsKeysByChainID(QueryAllOperatorConsKeysByChainIDRequest) returns (
QueryAllOperatorConsKeysByChainIDResponse
) {
QueryAllOperatorConsKeysByChainIDResponse
) {
option (google.api.http) = {
get: "/exocore/operator/v1/all_operator_cons_keys/{chain}"
};
}

// QueryOperatorUSDValue queries the opted-in USD value for the operator
rpc QueryOperatorUSDValue(QueryOperatorUSDValueRequest) returns(DecValueField){
option (google.api.http).get = "/exocore/operator/v1/QueryOperatorUSDValue";
}

// QueryAVSUSDValue queries the USD value for the AVS
rpc QueryAVSUSDValue(QueryAVSUSDValueRequest) returns(DecValueField){
option (google.api.http).get = "/exocore/operator/v1/QueryAVSUSDValue";
}

// QueryOperatorSlashInfo queries the slash information for the specified operator and AVS
rpc QueryOperatorSlashInfo(QueryOperatorSlashInfoRequest) returns(QueryOperatorSlashInfoResponse){
option (google.api.http).get = "/exocore/operator/v1/QueryOperatorSlashInfo";
}

// QueryAllOperatorConsAddrsByChainID queries all operators and their consensus addresses
// for a specific chain ID
rpc QueryAllOperatorConsAddrsByChainID(QueryAllOperatorConsAddrsByChainIDRequest) returns (
QueryAllOperatorConsAddrsByChainIDResponse
) {
QueryAllOperatorConsAddrsByChainIDResponse
) {
option (google.api.http) = {
get: "/exocore/operator/v1/all_operator_cons_addrs/{chain}"
};
Expand Down
62 changes: 56 additions & 6 deletions proto/exocore/operator/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,56 @@ enum SlashType {
SLASH_TYPE_NO_INSTANTANEOUS_SLASH = 2;
}

// SlashFromUndelegation records the slash detail from the undelegation
message SlashFromUndelegation {
// staker_id is the staker id.
string staker_id = 1 [(gogoproto.customname) = "StakerID"];
// asset_id is the asset id.
string asset_id = 2 [(gogoproto.customname) = "AssetID"];
// amount is the slashed amount from the undelegation.
string amount = 3
[
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
}
// SlashFromAssetsPool records the slash detail from the operator assets pool
message SlashFromAssetsPool {
// asset_id is the asset id.
string asset_id = 1 [(gogoproto.customname) = "AssetID"];
// amount is the slashed amount from the assets pool.
string amount = 2
[
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
}


// SlashExecutionInfo is the actual execution state for a slash event
message SlashExecutionInfo {
// slash_proportion is the new calculated proportion when execute the slash
string slash_proportion = 1
[
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
// slash_value is the usd value of all slashed assets
string slash_value = 2
[
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
// SlashUndelegations records all slash info related to the undelegation
repeated SlashFromUndelegation slash_undelegations = 3;
// SlashFromAssetsPool records all slash info related to the assets pool
repeated SlashFromAssetsPool slash_assets_pool = 4;
}

// OperatorSlashInfo is the slash info of operator
message OperatorSlashInfo {
// slash_contract is the address of slash contract
Expand All @@ -101,19 +151,19 @@ message OperatorSlashInfo {
int64 submitted_height = 2;
// event_height is the exocore block height at which the slash event occurs
int64 event_height = 3;
// processed_height is the exocore block height at which the slash event is processed
int64 processed_height = 4;
// is_vetoed is a flag to indicate if this slash is vetoed
bool is_vetoed = 5;
bool is_vetoed = 4;
// slash_proportion is the proportion of assets that need to be slashed
string slash_proportion = 6
string slash_proportion = 5
[
(cosmos_proto.scalar) = "cosmos.Dec",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
// type indicates the slash type.
SlashType slash_type = 7;
// slash_type indicates the slash type of specified AVS.
uint32 slash_type = 6;
// SlashExecutionInfo stores the slashed execution information
SlashExecutionInfo execution_info = 7;
}

// RegisterOperatorReq is the request to register a new operator.
Expand Down
9 changes: 7 additions & 2 deletions x/assets/keeper/operator_asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func (k Keeper) GetOperatorAssetInfos(ctx sdk.Context, operatorAddr sdk.Address,
ret[assetID] = state
return nil
}
err = k.IteratorAssetsForOperator(ctx, operatorAddr.String(), assetsFilter, opFunc)
err = k.IteratorAssetsForOperator(ctx, false, operatorAddr.String(), assetsFilter, opFunc)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -96,7 +96,7 @@ func (k Keeper) UpdateOperatorAssetState(ctx sdk.Context, operatorAddr sdk.Addre
// IteratorAssetsForOperator iterates all assets for the specified operator
// if `assetsFilter` is nil, the `opFunc` will handle all assets, it equals to an iterator without filter
// if `assetsFilter` isn't nil, the `opFunc` will only handle the assets that is in the filter map.
func (k Keeper) IteratorAssetsForOperator(ctx sdk.Context, operator string, assetsFilter map[string]interface{}, opFunc func(assetID string, state *assetstype.OperatorAssetInfo) error) error {
func (k Keeper) IteratorAssetsForOperator(ctx sdk.Context, isUpdate bool, operator string, assetsFilter map[string]interface{}, opFunc func(assetID string, state *assetstype.OperatorAssetInfo) error) error {
store := prefix.NewStore(ctx.KVStore(k.storeKey), assetstype.KeyPrefixOperatorAssetInfos)
iterator := sdk.KVStorePrefixIterator(store, []byte(operator))
defer iterator.Close()
Expand All @@ -116,6 +116,11 @@ func (k Keeper) IteratorAssetsForOperator(ctx sdk.Context, operator string, asse
if err != nil {
return err
}
if isUpdate {
// store the updated state
bz := k.cdc.MustMarshal(&amounts)
store.Set(iterator.Key(), bz)
}
}
return nil
}
4 changes: 2 additions & 2 deletions x/assets/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import (
var (
amino = codec.NewLegacyAmino()

// ModuleCdc references the global erc20 module codec. Note, the codec should
// ModuleCdc references the global module codec. Note, the codec should
// ONLY be used in certain instances of tests and for JSON encoding.
//
// The actual codec used for serialization should be provided to modules/erc20 and
// The actual codec used for serialization should be provided to modules and
// defined at the application level.
ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())

Expand Down
6 changes: 6 additions & 0 deletions x/assets/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ func GetJoinedStoreKey(keys ...string) []byte {
return []byte(strings.Join(keys, "/"))
}

func GetJoinedStoreKeyForPrefix(keys ...string) []byte {
ret := []byte(strings.Join(keys, "/"))
ret = append(ret, '/')
return ret
}

func ParseJoinedKey(key []byte) (keys []string, err error) {
stringList := strings.Split(string(key), "/")
return stringList, nil
Expand Down
15 changes: 6 additions & 9 deletions x/avs/keeper/avs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ func (suite *AVSTestSuite) TestAVS() {

suite.NoError(err)
suite.Equal(avsAddres, info.GetInfo().AvsAddress)

}

func (suite *AVSTestSuite) TestAVSInfoUpdate_Register() {
Expand Down Expand Up @@ -64,8 +63,8 @@ func (suite *AVSTestSuite) TestAVSInfoUpdate_Register() {
err = suite.App.AVSManagerKeeper.AVSInfoUpdate(suite.Ctx, avsParams)
suite.Error(err)
suite.Contains(err.Error(), types.ErrAlreadyRegistered.Error())

}

func (suite *AVSTestSuite) TestAVSInfoUpdate_DeRegister() {
// Test case setup
avsName, avsAddres, slashAddress := "avsTest", "exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkjr", "exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutash"
Expand Down Expand Up @@ -100,7 +99,6 @@ func (suite *AVSTestSuite) TestAVSInfoUpdate_DeRegister() {
info, err = suite.App.AVSManagerKeeper.GetAVSInfo(suite.Ctx, avsAddres)
suite.Error(err)
suite.Contains(err.Error(), types.ErrNoKeyInTheStore.Error())

}

func (suite *AVSTestSuite) TestAVSInfoUpdateWithOperator_Register() {
Expand All @@ -116,7 +114,7 @@ func (suite *AVSTestSuite) TestAVSInfoUpdateWithOperator_Register() {
suite.Error(err)
suite.Contains(err.Error(), delegationtypes.ErrOperatorNotExist.Error())

//register operator but avs not register
// register operator but avs not register
info := &operatortype.OperatorInfo{
EarningsAddr: suite.AccAddress.String(),
ApproveAddr: "",
Expand All @@ -135,7 +133,7 @@ func (suite *AVSTestSuite) TestAVSInfoUpdateWithOperator_Register() {
suite.Error(err)
suite.Contains(err.Error(), types.ErrNoKeyInTheStore.Error())

//register avs
// register avs
avsName, avsAddres, slashAddress := "avsTest", "exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkjr", "exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutash"
avsOwnerAddress := []string{"exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkjr", "exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkj1", "exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkj2"}
assetID := []string{"11", "22", "33"}
Expand All @@ -158,19 +156,18 @@ func (suite *AVSTestSuite) TestAVSInfoUpdateWithOperator_Register() {
operatorParams.AvsAddress = avsAddres
err = suite.App.AVSManagerKeeper.AVSInfoUpdateWithOperator(suite.Ctx, operatorParams)
suite.NoError(err)
//duplicate register operator
// duplicate register operator
err = suite.App.AVSManagerKeeper.AVSInfoUpdateWithOperator(suite.Ctx, operatorParams)
suite.Error(err)
suite.Contains(err.Error(), types.ErrAlreadyRegistered.Error())
//deregister operator
// deregister operator
operatorParams.Action = avstypes.DeRegisterAction
err = suite.App.AVSManagerKeeper.AVSInfoUpdateWithOperator(suite.Ctx, operatorParams)
suite.NoError(err)

//duplicate deregister operator
// duplicate deregister operator
operatorParams.Action = avstypes.DeRegisterAction
err = suite.App.AVSManagerKeeper.AVSInfoUpdateWithOperator(suite.Ctx, operatorParams)
suite.Error(err)
suite.Contains(err.Error(), types.ErrUnregisterNonExistent.Error())

}
Loading

0 comments on commit dd27216

Please sign in to comment.