diff --git a/precompiles/delegation/delegation_test.go b/precompiles/delegation/delegation_test.go index 01dc4db78..6bcf38855 100644 --- a/precompiles/delegation/delegation_test.go +++ b/precompiles/delegation/delegation_test.go @@ -11,7 +11,6 @@ import ( "github.com/ExocoreNetwork/exocore/precompiles/delegation" "github.com/ExocoreNetwork/exocore/x/assets/types" assetstype "github.com/ExocoreNetwork/exocore/x/assets/types" - keeper2 "github.com/ExocoreNetwork/exocore/x/delegation/keeper" delegationtype "github.com/ExocoreNetwork/exocore/x/delegation/types" "github.com/ExocoreNetwork/exocore/x/deposit/keeper" sdk "github.com/cosmos/cosmos-sdk/types" @@ -308,7 +307,7 @@ func (s *DelegationPrecompileSuite) TestRunUnDelegateFromThroughClientChain() { delegateAsset := func(staker []byte, delegateAmount sdkmath.Int) { // deposit asset for delegation test - delegateToParams := &keeper2.DelegationOrUndelegationParams{ + delegateToParams := &delegationtype.DelegationOrUndelegationParams{ ClientChainLzID: 101, Action: types.DelegateTo, StakerAddress: staker, diff --git a/precompiles/delegation/types.go b/precompiles/delegation/types.go index 4dcbaed7c..d24490216 100644 --- a/precompiles/delegation/types.go +++ b/precompiles/delegation/types.go @@ -10,16 +10,16 @@ import ( exocmn "github.com/ExocoreNetwork/exocore/precompiles/common" "github.com/ExocoreNetwork/exocore/x/assets/types" - keeper2 "github.com/ExocoreNetwork/exocore/x/delegation/keeper" + delegationtypes "github.com/ExocoreNetwork/exocore/x/delegation/types" sdk "github.com/cosmos/cosmos-sdk/types" cmn "github.com/evmos/evmos/v14/precompiles/common" ) -func (p Precompile) GetDelegationParamsFromInputs(ctx sdk.Context, args []interface{}) (*keeper2.DelegationOrUndelegationParams, error) { +func (p Precompile) GetDelegationParamsFromInputs(ctx sdk.Context, args []interface{}) (*delegationtypes.DelegationOrUndelegationParams, error) { if len(args) != 6 { return nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 6, len(args)) } - delegationParams := &keeper2.DelegationOrUndelegationParams{} + delegationParams := &delegationtypes.DelegationOrUndelegationParams{} clientChainLzID, ok := args[0].(uint16) if !ok { return nil, fmt.Errorf(exocmn.ErrContractInputParaOrType, 0, reflect.TypeOf(args[0]), clientChainLzID) diff --git a/proto/exocore/delegation/v1/genesis.proto b/proto/exocore/delegation/v1/genesis.proto new file mode 100644 index 000000000..4c192dd7e --- /dev/null +++ b/proto/exocore/delegation/v1/genesis.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; + +package exocore.delegation.v1; + +import "gogoproto/gogo.proto"; + +import "exocore/delegation/v1/tx.proto"; + +option go_package = "github.com/ExocoreNetwork/exocore/x/delegation/types"; + +// GenesisState defines the delegation module's state. It needs to encompass +// all of the state that is required to start the chain from the genesis +// or in the event of a restart. At this point, it is only built with +// the former in mind. There are no params in this module. +message GenesisState { + // delegations is a list of all delegations in the system. + repeated DelegationsByStaker delegations = 1 [(gogoproto.nullable) = false]; +} + +// DelegationsByStaker is a list of delegations for a single staker. +message DelegationsByStaker { + // staker_id is the staker's account address + _ + l0 chain id (hex).`` + string staker_id = 1 [(gogoproto.customname) = "StakerID"]; + // delegations is the list of delegations for the staker, indexed by the + // asset_id. + repeated DelegatedSingleAssetInfo delegations = 2 [(gogoproto.nullable) = false]; +} \ No newline at end of file diff --git a/proto/exocore/delegation/v1/tx.proto b/proto/exocore/delegation/v1/tx.proto index 53bee0531..299f2584a 100644 --- a/proto/exocore/delegation/v1/tx.proto +++ b/proto/exocore/delegation/v1/tx.proto @@ -24,15 +24,19 @@ message ValueField { message DelegatedSingleAssetInfo { // asset_id is the asset id. string asset_id = 1 [(gogoproto.customname) = "AssetID"]; - // total_delegated_amount is the total amount of the asset delegated. - string total_delegated_amount = 2 - [ - (cosmos_proto.scalar) = "cosmos.Int", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", - (gogoproto.nullable) = false - ]; - // per_operator_amounts is the amount of the asset delegated to each operator. - map per_operator_amounts = 3; + // since Cosmos uses an IAVL+ tree where the order of insertion affects the state root (even + // if the items are unrelated), and deserializing a protobuf map into Golang does not + // guarantee order, we cannot use a map here. Instead, we use a repeated field of key-value + // pairs. + repeated KeyValue per_operator_amounts = 3 [(gogoproto.nullable) = false]; +} + +// KeyValue is a key-value pair. It is a helper struct to represent a map in Protobuf. +message KeyValue { + // key is the key of the key-value pair. + string key = 1; + // value is the value of the key-value pair. + ValueField value = 2; } // DelegationApproveInfo is the delegation approve info. diff --git a/x/delegation/keeper/cross_chain_tx_process.go b/x/delegation/keeper/cross_chain_tx_process.go index 53933714e..ca2a39161 100644 --- a/x/delegation/keeper/cross_chain_tx_process.go +++ b/x/delegation/keeper/cross_chain_tx_process.go @@ -8,21 +8,8 @@ import ( assetstype "github.com/ExocoreNetwork/exocore/x/assets/types" delegationtype "github.com/ExocoreNetwork/exocore/x/delegation/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/ethereum/go-ethereum/common" ) -type DelegationOrUndelegationParams struct { - ClientChainLzID uint64 - Action assetstype.CrossChainOpType - AssetsAddress []byte - OperatorAddress sdk.AccAddress - StakerAddress []byte - OpAmount sdkmath.Int - LzNonce uint64 - TxHash common.Hash - // todo: The operator approved signature might be needed here in future -} - // The event hook process has been deprecated, now we use precompile contract to trigger the calls. // solidity encode: bytes memory actionArgs = abi.encodePacked(token, operator, msg.sender, amount); // _sendInterchainMsg(Action.DEPOSIT, actionArgs); @@ -108,15 +95,28 @@ type DelegationOrUndelegationParams struct { }, nil }*/ -// DelegateTo : It doesn't need to check the active status of the operator in middlewares when delegating assets to the operator. This is because it adds assets to the operator's amount. But it needs to check if operator has been slashed or frozen. -func (k *Keeper) DelegateTo(ctx sdk.Context, params *DelegationOrUndelegationParams) error { +// DelegateTo : It doesn't need to check the active status of the operator in middlewares when +// delegating assets to the operator. This is because it adds assets to the operator's amount. +// But it needs to check if operator has been slashed or frozen. +func (k Keeper) DelegateTo(ctx sdk.Context, params *delegationtype.DelegationOrUndelegationParams) error { + return k.delegateTo(ctx, params, true) +} + +// delegateTo is the internal private version of DelegateTo. if the notGenesis parameter is +// false, the operator keeper and the delegation hooks are not called. +func (k *Keeper) delegateTo( + ctx sdk.Context, + params *delegationtype.DelegationOrUndelegationParams, + notGenesis bool, +) error { // check if the delegatedTo address is an operator if !k.operatorKeeper.IsOperator(ctx, params.OperatorAddress) { return errorsmod.Wrap(delegationtype.ErrOperatorNotExist, fmt.Sprintf("input operatorAddr is:%s", params.OperatorAddress)) } // check if the operator has been slashed or frozen - if k.slashKeeper.IsOperatorFrozen(ctx, params.OperatorAddress) { + // skip the check if not genesis (or chain restart) + if notGenesis && k.slashKeeper.IsOperatorFrozen(ctx, params.OperatorAddress) { return delegationtype.ErrOperatorIsFrozen } @@ -166,21 +166,23 @@ func (k *Keeper) DelegateTo(ctx sdk.Context, params *DelegationOrUndelegationPar if err != nil { return err } - // call operator module to bond the increased assets to the opted-in AVS - err = k.operatorKeeper.UpdateOptedInAssetsState(ctx, stakerID, assetID, params.OperatorAddress.String(), params.OpAmount) - if err != nil { - return err - } - // call the hooks registered by the other modules - k.Hooks().AfterDelegation(ctx, params.OperatorAddress) + if notGenesis { + // call operator module to bond the increased assets to the opted-in AVS + err = k.operatorKeeper.UpdateOptedInAssetsState(ctx, stakerID, assetID, params.OperatorAddress.String(), params.OpAmount) + if err != nil { + return err + } + // call the hooks registered by the other modules + k.Hooks().AfterDelegation(ctx, params.OperatorAddress) + } return nil } // UndelegateFrom The undelegation needs to consider whether the operator's opted-in assets can exit from the AVS. // Because only after the operator has served the AVS can the staking asset be undelegated. // So we use two steps to handle the undelegation. Fist,record the undelegation request and the corresponding exit time which needs to be obtained from the operator opt-in module. Then,we handle the record when the exit time has expired. -func (k *Keeper) UndelegateFrom(ctx sdk.Context, params *DelegationOrUndelegationParams) error { +func (k *Keeper) UndelegateFrom(ctx sdk.Context, params *delegationtype.DelegationOrUndelegationParams) error { // check if the UndelegatedFrom address is an operator if !k.operatorKeeper.IsOperator(ctx, params.OperatorAddress) { return delegationtype.ErrOperatorNotExist diff --git a/x/delegation/keeper/delegation_op_test.go b/x/delegation/keeper/delegation_op_test.go index 84edfabda..185973621 100644 --- a/x/delegation/keeper/delegation_op_test.go +++ b/x/delegation/keeper/delegation_op_test.go @@ -32,7 +32,7 @@ func (suite *DelegationTestSuite) TestDelegateTo() { opAccAddr, err := sdk.AccAddressFromBech32("exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkjr") suite.NoError(err) - delegationParams := &keeper2.DelegationOrUndelegationParams{ + delegationParams := &delegationtype.DelegationOrUndelegationParams{ ClientChainLzID: clientChainLzID, Action: types.DelegateTo, AssetsAddress: usdtAddress[:], @@ -106,7 +106,7 @@ func (suite *DelegationTestSuite) TestUndelegateFrom() { opAccAddr, err := sdk.AccAddressFromBech32("exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkjr") suite.NoError(err) - delegationEvent := &keeper2.DelegationOrUndelegationParams{ + delegationEvent := &delegationtype.DelegationOrUndelegationParams{ ClientChainLzID: clientChainLzID, Action: types.DelegateTo, AssetsAddress: usdtAddress[:], @@ -205,7 +205,7 @@ func (suite *DelegationTestSuite) TestCompleteUndelegation() { opAccAddr, err := sdk.AccAddressFromBech32("exo13h6xg79g82e2g2vhjwg7j4r2z2hlncelwutkjr") suite.NoError(err) - delegationEvent := &keeper2.DelegationOrUndelegationParams{ + delegationEvent := &delegationtype.DelegationOrUndelegationParams{ ClientChainLzID: clientChainLzID, Action: types.DelegateTo, AssetsAddress: usdtAddress[:], diff --git a/x/delegation/keeper/genesis.go b/x/delegation/keeper/genesis.go new file mode 100644 index 000000000..7dd1577bd --- /dev/null +++ b/x/delegation/keeper/genesis.go @@ -0,0 +1,60 @@ +package keeper + +import ( + assetstype "github.com/ExocoreNetwork/exocore/x/assets/types" + delegationtype "github.com/ExocoreNetwork/exocore/x/delegation/types" + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" +) + +// InitGenesis initializes the module's state from a provided genesis state. +// Since this action typically occurs on chain starts, this function is allowed to panic. +func (k Keeper) InitGenesis( + ctx sdk.Context, + gs delegationtype.GenesisState, +) []abci.ValidatorUpdate { + // TODO(mm): is it possible to parallelize these without using goroutines? + for _, level1 := range gs.Delegations { + stakerID := level1.StakerID + // #nosec G703 // already validated + stakerAddress, lzID, _ := assetstype.ParseID(stakerID) + // we have checked IsHexAddress already + stakerAddressBytes := common.HexToAddress(stakerAddress) + for _, level2 := range level1.Delegations { + assetID := level2.AssetID + // #nosec G703 // already validated + assetAddress, _, _ := assetstype.ParseID(assetID) + // we have checked IsHexAddress already + assetAddressBytes := common.HexToAddress(assetAddress) + for _, level3 := range level2.PerOperatorAmounts { + operator := level3.Key + wrappedAmount := level3.Value + amount := wrappedAmount.Amount + // #nosec G703 // already validated + accAddress, _ := sdk.AccAddressFromBech32(operator) + delegationParams := &delegationtype.DelegationOrUndelegationParams{ + ClientChainLzID: lzID, + Action: assetstype.DelegateTo, + AssetsAddress: assetAddressBytes.Bytes(), + OperatorAddress: accAddress, + StakerAddress: stakerAddressBytes.Bytes(), + OpAmount: amount, + // the uninitialized members are not used in this context + // they are the LzNonce and TxHash + } + if err := k.delegateTo(ctx, delegationParams, false); err != nil { + panic(err) + } + } + } + } + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the module's exported genesis +func (Keeper) ExportGenesis(sdk.Context) *delegationtype.GenesisState { + genesis := delegationtype.DefaultGenesis() + // TODO + return genesis +} diff --git a/x/delegation/module.go b/x/delegation/module.go index b93a5ea35..aa5af3f8e 100644 --- a/x/delegation/module.go +++ b/x/delegation/module.go @@ -2,6 +2,8 @@ package delegation import ( "context" + "encoding/json" + "fmt" "github.com/ExocoreNetwork/exocore/x/delegation/client/cli" "github.com/ExocoreNetwork/exocore/x/delegation/keeper" @@ -38,7 +40,10 @@ func (b AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry delegationtype.RegisterInterfaces(registry) } -func (b AppModuleBasic) RegisterGRPCGatewayRoutes(c client.Context, serveMux *runtime.ServeMux) { +func (b AppModuleBasic) RegisterGRPCGatewayRoutes( + c client.Context, + serveMux *runtime.ServeMux, +) { if err := delegationtype.RegisterQueryHandlerClient(context.Background(), serveMux, delegationtype.NewQueryClient(c)); err != nil { panic(err) } @@ -92,3 +97,46 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V am.keeper.EndBlock(ctx, req) return []abci.ValidatorUpdate{} } + +// DefaultGenesis returns a default GenesisState for the module, marshaled to json.RawMessage. +// The default GenesisState need to be defined by the module developer and is primarily used for +// testing +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(delegationtype.DefaultGenesis()) +} + +// ValidateGenesis used to validate the GenesisState, given in its json.RawMessage form +func (AppModuleBasic) ValidateGenesis( + cdc codec.JSONCodec, + _ client.TxEncodingConfig, + bz json.RawMessage, +) error { + var genState delegationtype.GenesisState + if err := cdc.UnmarshalJSON(bz, &genState); err != nil { + return fmt.Errorf( + "failed to unmarshal %s genesis state: %w", + delegationtype.ModuleName, + err, + ) + } + return genState.Validate() +} + +// InitGenesis performs the module's genesis initialization. It returns no validator updates. +func (am AppModule) InitGenesis( + ctx sdk.Context, + cdc codec.JSONCodec, + gs json.RawMessage, +) []abci.ValidatorUpdate { + var genState delegationtype.GenesisState + // Initialize global index to index in genesis state + cdc.MustUnmarshalJSON(gs, &genState) + + return am.keeper.InitGenesis(ctx, genState) +} + +// ExportGenesis returns the module's exported genesis state as raw JSON bytes. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + genState := am.keeper.ExportGenesis(ctx) + return cdc.MustMarshalJSON(genState) +} diff --git a/x/delegation/types/cross_chain_params.go b/x/delegation/types/cross_chain_params.go new file mode 100644 index 000000000..a43803c6e --- /dev/null +++ b/x/delegation/types/cross_chain_params.go @@ -0,0 +1,20 @@ +package types + +import ( + sdkmath "cosmossdk.io/math" + assetstype "github.com/ExocoreNetwork/exocore/x/assets/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" +) + +type DelegationOrUndelegationParams struct { + ClientChainLzID uint64 + Action assetstype.CrossChainOpType + AssetsAddress []byte + OperatorAddress sdk.AccAddress + StakerAddress []byte + OpAmount sdkmath.Int + LzNonce uint64 + TxHash common.Hash + // todo: The operator approved signature might be needed here in future +} diff --git a/x/delegation/types/errors.go b/x/delegation/types/errors.go index 1bb6446c7..e9ab8b8d6 100644 --- a/x/delegation/types/errors.go +++ b/x/delegation/types/errors.go @@ -3,28 +3,72 @@ package types import errorsmod "cosmossdk.io/errors" var ( - ErrNoKeyInTheStore = errorsmod.Register(ModuleName, 0, "there is not the key for in the store") - ErrOperatorIsFrozen = errorsmod.Register(ModuleName, 1, "the operator has been frozen") + ErrNoKeyInTheStore = errorsmod.Register( + ModuleName, 0, + "there is not the key for in the store", + ) + ErrOperatorIsFrozen = errorsmod.Register( + ModuleName, 1, + "the operator has been frozen", + ) - ErrOperatorNotExist = errorsmod.Register(ModuleName, 2, "the operator has not been registered") + ErrOperatorNotExist = errorsmod.Register( + ModuleName, 2, + "the operator has not been registered", + ) - ErrOpAmountIsNegative = errorsmod.Register(ModuleName, 3, "the delegation or Undelegation amount is negative") + ErrOpAmountIsNegative = errorsmod.Register( + ModuleName, 3, + "the delegation or Undelegation amount is negative", + ) - OperatorAddrIsNotAccAddr = errorsmod.Register(ModuleName, 4, "the operator address isn't a valid acc addr") + OperatorAddrIsNotAccAddr = errorsmod.Register( + ModuleName, 4, + "the operator address isn't a valid acc addr", + ) - ErrSubAmountIsGreaterThanOriginal = errorsmod.Register(ModuleName, 5, "the sub amount is greater than the original amount") + ErrSubAmountIsGreaterThanOriginal = errorsmod.Register( + ModuleName, 5, + "the sub amount is greater than the original amount", + ) - ErrParseDelegationKey = errorsmod.Register(ModuleName, 6, "delegation state key can't be parsed") + ErrParseDelegationKey = errorsmod.Register( + ModuleName, 6, + "delegation state key can't be parsed", + ) - ErrStakerGetRecordType = errorsmod.Register(ModuleName, 7, "the input getType is error when get staker Undelegation records") + ErrStakerGetRecordType = errorsmod.Register( + ModuleName, 7, + "the input getType is error when get staker Undelegation records", + ) - ErrUndelegationAmountTooBig = errorsmod.Register(ModuleName, 8, "the Undelegation amount is bigger than the delegated amount") + ErrUndelegationAmountTooBig = errorsmod.Register( + ModuleName, 8, + "the Undelegation amount is bigger than the delegated amount", + ) - ErrNotSupportYet = errorsmod.Register(ModuleName, 9, "don't have supported it yet") + ErrNotSupportYet = errorsmod.Register( + ModuleName, 9, + "don't have supported it yet", + ) - ErrDelegationAmountTooBig = errorsmod.Register(ModuleName, 10, "the delegation amount is bigger than the canWithdraw amount") + ErrDelegationAmountTooBig = errorsmod.Register( + ModuleName, 10, + "the delegation amount is bigger than the canWithdraw amount", + ) - ErrCannotIncHoldCount = errorsmod.Register(ModuleName, 11, "cannot increment undelegation hold count above max uint64") + ErrCannotIncHoldCount = errorsmod.Register( + ModuleName, 11, + "cannot increment undelegation hold count above max uint64", + ) - ErrCannotDecHoldCount = errorsmod.Register(ModuleName, 12, "cannot decrement undelegation hold count below zero") + ErrCannotDecHoldCount = errorsmod.Register( + ModuleName, 12, + "cannot decrement undelegation hold count below zero", + ) + + ErrInvalidGenesisData = errorsmod.Register( + ModuleName, 13, + "the genesis data supplied is invalid", + ) ) diff --git a/x/delegation/types/genesis.go b/x/delegation/types/genesis.go new file mode 100644 index 000000000..571cb0c10 --- /dev/null +++ b/x/delegation/types/genesis.go @@ -0,0 +1,106 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" + assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// NewGenesis returns a new genesis state with the given inputs. +func NewGenesis( + delegations []DelegationsByStaker, +) *GenesisState { + return &GenesisState{ + Delegations: delegations, + } +} + +// DefaultGenesis returns the default genesis state +func DefaultGenesis() *GenesisState { + return NewGenesis([]DelegationsByStaker{}) +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + // TODO(mm): this can be a very big hash table and impact system performance. + // This is likely to be the biggest one amongst the three, and the others + // are garbage collected within the loop anyway. Maybe reordering the genesis + // structure could potentially help with this. + stakers := make(map[string]struct{}, len(gs.Delegations)) + for _, level1 := range gs.Delegations { + stakerID := level1.StakerID + // validate staker ID + var stakerClientChainID uint64 + var err error + if _, stakerClientChainID, err = assetstypes.ValidateID(stakerID, true); err != nil { + return errorsmod.Wrapf( + ErrInvalidGenesisData, "invalid staker ID %s: %s", stakerID, err, + ) + } + // check for duplicate stakers + if _, ok := stakers[stakerID]; ok { + return errorsmod.Wrapf(ErrInvalidGenesisData, "duplicate staker ID %s", stakerID) + } + stakers[stakerID] = struct{}{} + assets := make(map[string]struct{}, len(level1.Delegations)) + for _, level2 := range level1.Delegations { + assetID := level2.AssetID + // check for duplicate assets + if _, ok := assets[assetID]; ok { + return errorsmod.Wrapf(ErrInvalidGenesisData, "duplicate asset ID %s", assetID) + } + assets[assetID] = struct{}{} + // validate asset ID + var assetClientChainID uint64 + if _, assetClientChainID, err = assetstypes.ValidateID(assetID, true); err != nil { + return errorsmod.Wrapf( + ErrInvalidGenesisData, "invalid asset ID %s: %s", assetID, err, + ) + } + if assetClientChainID != stakerClientChainID { + // a staker from chain A is delegating an asset on chain B, which is not + // something we support right now. + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "asset %s client chain ID %d does not match staker %s client chain ID %d", + assetID, assetClientChainID, stakerID, stakerClientChainID, + ) + } + operators := make(map[string]struct{}, len(level2.PerOperatorAmounts)) + for _, level3 := range level2.PerOperatorAmounts { + operator := level3.Key + wrappedAmount := level3.Value + // check supplied amount + if wrappedAmount == nil { + return errorsmod.Wrapf( + ErrInvalidGenesisData, "nil operator amount for operator %s", operator, + ) + } + amount := wrappedAmount.Amount + if amount.IsNil() || amount.IsNegative() { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "invalid operator amount %s for operator %s", amount, operator, + ) + } + // check operator address + if _, err := sdk.AccAddressFromBech32(operator); err != nil { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "invalid operator address for operator %s", operator, + ) + } + // check for duplicate operators + if _, ok := operators[operator]; ok { + return errorsmod.Wrapf( + ErrInvalidGenesisData, + "duplicate operator %s for asset %s", operator, assetID, + ) + } + operators[operator] = struct{}{} + } + } + } + return nil +} diff --git a/x/delegation/types/genesis.pb.go b/x/delegation/types/genesis.pb.go new file mode 100644 index 000000000..88645d085 --- /dev/null +++ b/x/delegation/types/genesis.pb.go @@ -0,0 +1,577 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: exocore/delegation/v1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the delegation module's state. It needs to encompass +// all of the state that is required to start the chain from the genesis +// or in the event of a restart. At this point, it is only built with +// the former in mind. There are no params in this module. +type GenesisState struct { + // delegations is a list of all delegations in the system. + Delegations []DelegationsByStaker `protobuf:"bytes,1,rep,name=delegations,proto3" json:"delegations"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_c26dd0d733927603, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetDelegations() []DelegationsByStaker { + if m != nil { + return m.Delegations + } + return nil +} + +// DelegationsByStaker is a list of delegations for a single staker. +type DelegationsByStaker struct { + // staker_id is the staker's account address + _ + l0 chain id (hex).`` + StakerID string `protobuf:"bytes,1,opt,name=staker_id,json=stakerId,proto3" json:"staker_id,omitempty"` + // delegations is the list of delegations for the staker, indexed by the + // asset_id. + Delegations []DelegatedSingleAssetInfo `protobuf:"bytes,2,rep,name=delegations,proto3" json:"delegations"` +} + +func (m *DelegationsByStaker) Reset() { *m = DelegationsByStaker{} } +func (m *DelegationsByStaker) String() string { return proto.CompactTextString(m) } +func (*DelegationsByStaker) ProtoMessage() {} +func (*DelegationsByStaker) Descriptor() ([]byte, []int) { + return fileDescriptor_c26dd0d733927603, []int{1} +} +func (m *DelegationsByStaker) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DelegationsByStaker) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DelegationsByStaker.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DelegationsByStaker) XXX_Merge(src proto.Message) { + xxx_messageInfo_DelegationsByStaker.Merge(m, src) +} +func (m *DelegationsByStaker) XXX_Size() int { + return m.Size() +} +func (m *DelegationsByStaker) XXX_DiscardUnknown() { + xxx_messageInfo_DelegationsByStaker.DiscardUnknown(m) +} + +var xxx_messageInfo_DelegationsByStaker proto.InternalMessageInfo + +func (m *DelegationsByStaker) GetStakerID() string { + if m != nil { + return m.StakerID + } + return "" +} + +func (m *DelegationsByStaker) GetDelegations() []DelegatedSingleAssetInfo { + if m != nil { + return m.Delegations + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "exocore.delegation.v1.GenesisState") + proto.RegisterType((*DelegationsByStaker)(nil), "exocore.delegation.v1.DelegationsByStaker") +} + +func init() { + proto.RegisterFile("exocore/delegation/v1/genesis.proto", fileDescriptor_c26dd0d733927603) +} + +var fileDescriptor_c26dd0d733927603 = []byte{ + // 282 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4e, 0xad, 0xc8, 0x4f, + 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0x49, 0xcd, 0x49, 0x4d, 0x4f, 0x2c, 0xc9, 0xcc, 0xcf, 0xd3, 0x2f, + 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, + 0x12, 0x85, 0x2a, 0xd2, 0x43, 0x28, 0xd2, 0x2b, 0x33, 0x94, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, + 0xab, 0xd0, 0x07, 0xb1, 0x20, 0x8a, 0xa5, 0xe4, 0xb0, 0x9b, 0x58, 0x52, 0x01, 0x91, 0x57, 0x4a, + 0xe2, 0xe2, 0x71, 0x87, 0x98, 0x1e, 0x5c, 0x92, 0x58, 0x92, 0x2a, 0x14, 0xc4, 0xc5, 0x8d, 0x50, + 0x59, 0x2c, 0xc1, 0xa8, 0xc0, 0xac, 0xc1, 0x6d, 0xa4, 0xa5, 0x87, 0xd5, 0x4a, 0x3d, 0x17, 0x84, + 0x4a, 0xa7, 0xca, 0xe0, 0x92, 0xc4, 0xec, 0xd4, 0x22, 0x27, 0x96, 0x13, 0xf7, 0xe4, 0x19, 0x82, + 0x90, 0x0d, 0x51, 0x9a, 0xc9, 0xc8, 0x25, 0x8c, 0x45, 0xa9, 0x90, 0x26, 0x17, 0x67, 0x31, 0x98, + 0x15, 0x9f, 0x99, 0x22, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe9, 0xc4, 0xf3, 0xe8, 0x9e, 0x3c, 0x07, + 0x44, 0xda, 0xd3, 0x25, 0x88, 0x03, 0x22, 0xed, 0x99, 0x22, 0x14, 0x8e, 0xea, 0x2c, 0x26, 0xb0, + 0xb3, 0xf4, 0xf1, 0x3b, 0x2b, 0x35, 0x25, 0x38, 0x33, 0x2f, 0x3d, 0x27, 0xd5, 0xb1, 0xb8, 0x38, + 0xb5, 0xc4, 0x33, 0x2f, 0x2d, 0x1f, 0x8b, 0xdb, 0x9c, 0xfc, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, + 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, + 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x24, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, + 0xdf, 0x15, 0x62, 0x8f, 0x5f, 0x6a, 0x49, 0x79, 0x7e, 0x51, 0xb6, 0x3e, 0x2c, 0x4c, 0x2b, 0x90, + 0x43, 0xb5, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x1c, 0xac, 0xc6, 0x80, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xa3, 0x40, 0xe3, 0x39, 0xca, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Delegations) > 0 { + for iNdEx := len(m.Delegations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Delegations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *DelegationsByStaker) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DelegationsByStaker) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DelegationsByStaker) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Delegations) > 0 { + for iNdEx := len(m.Delegations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Delegations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.StakerID) > 0 { + i -= len(m.StakerID) + copy(dAtA[i:], m.StakerID) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.StakerID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Delegations) > 0 { + for _, e := range m.Delegations { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *DelegationsByStaker) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.StakerID) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if len(m.Delegations) > 0 { + for _, e := range m.Delegations { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Delegations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Delegations = append(m.Delegations, DelegationsByStaker{}) + if err := m.Delegations[len(m.Delegations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DelegationsByStaker) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DelegationsByStaker: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DelegationsByStaker: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakerID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StakerID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Delegations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Delegations = append(m.Delegations, DelegatedSingleAssetInfo{}) + if err := m.Delegations[len(m.Delegations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/delegation/types/genesis_test.go b/x/delegation/types/genesis_test.go new file mode 100644 index 000000000..b2fede925 --- /dev/null +++ b/x/delegation/types/genesis_test.go @@ -0,0 +1,204 @@ +package types_test + +import ( + "testing" + + "cosmossdk.io/math" + utiltx "github.com/ExocoreNetwork/exocore/testutil/tx" + assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" + "github.com/ExocoreNetwork/exocore/x/delegation/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" +) + +type GenesisTestSuite struct { + suite.Suite +} + +func (suite *GenesisTestSuite) SetupTest() { +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} + +func (suite *GenesisTestSuite) TestValidateGenesis() { + assetAddress := utiltx.GenerateAddress() + stakerAddress := utiltx.GenerateAddress() + lzID := uint64(101) + stakerID, assetID := assetstypes.GetStakeIDAndAssetID( + lzID, stakerAddress[:], assetAddress[:], + ) + operatorAddress := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) + delegations := []types.DelegationsByStaker{ + { + StakerID: stakerID, + Delegations: []types.DelegatedSingleAssetInfo{ + { + AssetID: assetID, + PerOperatorAmounts: []types.KeyValue{ + { + Key: operatorAddress.String(), + Value: &types.ValueField{ + Amount: math.NewInt(1000), + }, + }, + }, + }, + }, + }, + } + testCases := []struct { + name string + genState *types.GenesisState + expPass bool + malleate func(*types.GenesisState) + unmalleate func(*types.GenesisState) + }{ + { + name: "valid empty genesis", + genState: &types.GenesisState{}, + expPass: true, + }, + { + name: "default", + genState: types.DefaultGenesis(), + expPass: true, + }, + { + name: "base, should pass", + genState: types.NewGenesis(delegations), + expPass: true, + }, + { + name: "invalid staker id", + genState: types.NewGenesis(delegations), + expPass: false, + malleate: func(gs *types.GenesisState) { + gs.Delegations[0].StakerID = "invalid" + }, + unmalleate: func(gs *types.GenesisState) { + gs.Delegations[0].StakerID = stakerID + }, + }, + { + name: "duplicate staker id", + genState: types.NewGenesis(delegations), + expPass: false, + malleate: func(gs *types.GenesisState) { + gs.Delegations = append(gs.Delegations, gs.Delegations[0]) + }, + unmalleate: func(gs *types.GenesisState) { + gs.Delegations = gs.Delegations[:1] + }, + }, + { + name: "duplicate asset id", + genState: types.NewGenesis(delegations), + expPass: false, + malleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations = append( + gs.Delegations[0].Delegations, + gs.Delegations[0].Delegations[0], + ) + }, + unmalleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations = gs.Delegations[0].Delegations[:1] + }, + }, + { + name: "invalid asset id", + genState: types.NewGenesis(delegations), + expPass: false, + malleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].AssetID = "invalid" + }, + unmalleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].AssetID = assetID + }, + }, + { + name: "asset id mismatch", + genState: types.NewGenesis(delegations), + expPass: false, + malleate: func(gs *types.GenesisState) { + stakerID, _ := assetstypes.GetStakeIDAndAssetID( + lzID+1, stakerAddress[:], assetAddress[:], + ) + gs.Delegations[0].StakerID = stakerID + }, + unmalleate: func(gs *types.GenesisState) { + gs.Delegations[0].StakerID = stakerID + }, + }, + { + name: "nil wrapped amount", + genState: types.NewGenesis(delegations), + expPass: false, + malleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].PerOperatorAmounts[0].Value = nil + }, + unmalleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].PerOperatorAmounts[0].Value = + &types.ValueField{Amount: math.NewInt(1000)} + }, + }, + { + name: "nil unwrapped amount", + genState: types.NewGenesis(delegations), + expPass: false, + malleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].PerOperatorAmounts[0].Value = + &types.ValueField{} + }, + unmalleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].PerOperatorAmounts[0].Value = + &types.ValueField{Amount: math.NewInt(1000)} + }, + }, + { + name: "negative unwrapped amount", + genState: types.NewGenesis(delegations), + expPass: false, + malleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].PerOperatorAmounts[0].Value = + &types.ValueField{Amount: math.NewInt(-1)} + }, + unmalleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].PerOperatorAmounts[0].Value = + &types.ValueField{Amount: math.NewInt(1000)} + }, + }, + { + name: "invalid operator address", + genState: types.NewGenesis(delegations), + expPass: false, + malleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].PerOperatorAmounts[0].Key = "invalid" + }, + unmalleate: func(gs *types.GenesisState) { + gs.Delegations[0].Delegations[0].PerOperatorAmounts[0].Key = + operatorAddress.String() + }, + }, + } + + for _, tc := range testCases { + tc := tc + if tc.malleate != nil { + tc.malleate(tc.genState) + // require that unmalleate is defined + suite.Require().NotNil(tc.unmalleate, tc.name) + } + err := tc.genState.Validate() + if tc.expPass { + suite.Require().NoError(err, tc.name) + } else { + suite.Require().Error(err, tc.name) + } + if tc.unmalleate != nil { + tc.unmalleate(tc.genState) + } + // fmt.Println(tc.name, err) + } +} diff --git a/x/delegation/types/tx.pb.go b/x/delegation/types/tx.pb.go index d9d9b36a2..99f3f0e45 100644 --- a/x/delegation/types/tx.pb.go +++ b/x/delegation/types/tx.pb.go @@ -75,10 +75,11 @@ var xxx_messageInfo_ValueField proto.InternalMessageInfo type DelegatedSingleAssetInfo struct { // asset_id is the asset id. AssetID string `protobuf:"bytes,1,opt,name=asset_id,json=assetId,proto3" json:"asset_id,omitempty"` - // total_delegated_amount is the total amount of the asset delegated. - TotalDelegatedAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=total_delegated_amount,json=totalDelegatedAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"total_delegated_amount"` - // per_operator_amounts is the amount of the asset delegated to each operator. - PerOperatorAmounts map[string]*ValueField `protobuf:"bytes,3,rep,name=per_operator_amounts,json=perOperatorAmounts,proto3" json:"per_operator_amounts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // since Cosmos uses an IAVL+ tree where the order of insertion affects the state root (even + // if the items are unrelated), and deserializing a protobuf map into Golang does not + // guarantee order, we cannot use a map here. Instead, we use a repeated field of key-value + // pairs. + PerOperatorAmounts []KeyValue `protobuf:"bytes,3,rep,name=per_operator_amounts,json=perOperatorAmounts,proto3" json:"per_operator_amounts"` } func (m *DelegatedSingleAssetInfo) Reset() { *m = DelegatedSingleAssetInfo{} } @@ -121,13 +122,68 @@ func (m *DelegatedSingleAssetInfo) GetAssetID() string { return "" } -func (m *DelegatedSingleAssetInfo) GetPerOperatorAmounts() map[string]*ValueField { +func (m *DelegatedSingleAssetInfo) GetPerOperatorAmounts() []KeyValue { if m != nil { return m.PerOperatorAmounts } return nil } +// KeyValue is a key-value pair. It is a helper struct to represent a map in Protobuf. +type KeyValue struct { + // key is the key of the key-value pair. + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // value is the value of the key-value pair. + Value *ValueField `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *KeyValue) Reset() { *m = KeyValue{} } +func (m *KeyValue) String() string { return proto.CompactTextString(m) } +func (*KeyValue) ProtoMessage() {} +func (*KeyValue) Descriptor() ([]byte, []int) { + return fileDescriptor_16596a15a828f109, []int{2} +} +func (m *KeyValue) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *KeyValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_KeyValue.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *KeyValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_KeyValue.Merge(m, src) +} +func (m *KeyValue) XXX_Size() int { + return m.Size() +} +func (m *KeyValue) XXX_DiscardUnknown() { + xxx_messageInfo_KeyValue.DiscardUnknown(m) +} + +var xxx_messageInfo_KeyValue proto.InternalMessageInfo + +func (m *KeyValue) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *KeyValue) GetValue() *ValueField { + if m != nil { + return m.Value + } + return nil +} + // DelegationApproveInfo is the delegation approve info. type DelegationApproveInfo struct { // signature of the delegation approve info. @@ -140,7 +196,7 @@ func (m *DelegationApproveInfo) Reset() { *m = DelegationApproveInfo{} } func (m *DelegationApproveInfo) String() string { return proto.CompactTextString(m) } func (*DelegationApproveInfo) ProtoMessage() {} func (*DelegationApproveInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_16596a15a828f109, []int{2} + return fileDescriptor_16596a15a828f109, []int{3} } func (m *DelegationApproveInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -195,7 +251,7 @@ func (m *DelegationIncOrDecInfo) Reset() { *m = DelegationIncOrDecInfo{} func (m *DelegationIncOrDecInfo) String() string { return proto.CompactTextString(m) } func (*DelegationIncOrDecInfo) ProtoMessage() {} func (*DelegationIncOrDecInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_16596a15a828f109, []int{3} + return fileDescriptor_16596a15a828f109, []int{4} } func (m *DelegationIncOrDecInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -236,7 +292,7 @@ func (m *MsgDelegation) Reset() { *m = MsgDelegation{} } func (m *MsgDelegation) String() string { return proto.CompactTextString(m) } func (*MsgDelegation) ProtoMessage() {} func (*MsgDelegation) Descriptor() ([]byte, []int) { - return fileDescriptor_16596a15a828f109, []int{4} + return fileDescriptor_16596a15a828f109, []int{5} } func (m *MsgDelegation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -309,7 +365,7 @@ func (m *UndelegationRecord) Reset() { *m = UndelegationRecord{} } func (m *UndelegationRecord) String() string { return proto.CompactTextString(m) } func (*UndelegationRecord) ProtoMessage() {} func (*UndelegationRecord) Descriptor() ([]byte, []int) { - return fileDescriptor_16596a15a828f109, []int{5} + return fileDescriptor_16596a15a828f109, []int{6} } func (m *UndelegationRecord) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -404,7 +460,7 @@ func (m *UndelegationRecordKeyList) Reset() { *m = UndelegationRecordKey func (m *UndelegationRecordKeyList) String() string { return proto.CompactTextString(m) } func (*UndelegationRecordKeyList) ProtoMessage() {} func (*UndelegationRecordKeyList) Descriptor() ([]byte, []int) { - return fileDescriptor_16596a15a828f109, []int{6} + return fileDescriptor_16596a15a828f109, []int{7} } func (m *UndelegationRecordKeyList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -448,7 +504,7 @@ func (m *DelegationResponse) Reset() { *m = DelegationResponse{} } func (m *DelegationResponse) String() string { return proto.CompactTextString(m) } func (*DelegationResponse) ProtoMessage() {} func (*DelegationResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16596a15a828f109, []int{7} + return fileDescriptor_16596a15a828f109, []int{8} } func (m *DelegationResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -487,7 +543,7 @@ func (m *MsgUndelegation) Reset() { *m = MsgUndelegation{} } func (m *MsgUndelegation) String() string { return proto.CompactTextString(m) } func (*MsgUndelegation) ProtoMessage() {} func (*MsgUndelegation) Descriptor() ([]byte, []int) { - return fileDescriptor_16596a15a828f109, []int{8} + return fileDescriptor_16596a15a828f109, []int{9} } func (m *MsgUndelegation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -531,7 +587,7 @@ func (m *UndelegationResponse) Reset() { *m = UndelegationResponse{} } func (m *UndelegationResponse) String() string { return proto.CompactTextString(m) } func (*UndelegationResponse) ProtoMessage() {} func (*UndelegationResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_16596a15a828f109, []int{9} + return fileDescriptor_16596a15a828f109, []int{10} } func (m *UndelegationResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -563,7 +619,7 @@ var xxx_messageInfo_UndelegationResponse proto.InternalMessageInfo func init() { proto.RegisterType((*ValueField)(nil), "exocore.delegation.v1.ValueField") proto.RegisterType((*DelegatedSingleAssetInfo)(nil), "exocore.delegation.v1.DelegatedSingleAssetInfo") - proto.RegisterMapType((map[string]*ValueField)(nil), "exocore.delegation.v1.DelegatedSingleAssetInfo.PerOperatorAmountsEntry") + proto.RegisterType((*KeyValue)(nil), "exocore.delegation.v1.KeyValue") proto.RegisterType((*DelegationApproveInfo)(nil), "exocore.delegation.v1.DelegationApproveInfo") proto.RegisterType((*DelegationIncOrDecInfo)(nil), "exocore.delegation.v1.DelegationIncOrDecInfo") proto.RegisterMapType((map[string]*ValueField)(nil), "exocore.delegation.v1.DelegationIncOrDecInfo.PerOperatorAmountsEntry") @@ -578,67 +634,67 @@ func init() { func init() { proto.RegisterFile("exocore/delegation/v1/tx.proto", fileDescriptor_16596a15a828f109) } var fileDescriptor_16596a15a828f109 = []byte{ - // 959 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0x41, 0x6f, 0xe3, 0x44, - 0x14, 0x8e, 0x9b, 0xb6, 0x49, 0x5e, 0x52, 0x01, 0x43, 0xda, 0xa4, 0x01, 0x92, 0xae, 0x05, 0x55, - 0xb6, 0xd0, 0x44, 0x1b, 0x10, 0xa0, 0x05, 0x0e, 0x29, 0xe9, 0x42, 0x80, 0x76, 0x17, 0xb7, 0x70, - 0x40, 0x42, 0x96, 0x63, 0x4f, 0x1d, 0x13, 0xdb, 0x63, 0xcd, 0x4c, 0xba, 0xc9, 0x9e, 0x10, 0x27, - 0xc4, 0x89, 0x3b, 0x97, 0xe5, 0x0f, 0xa0, 0x1e, 0xf6, 0x47, 0xec, 0x71, 0xb5, 0x27, 0xc4, 0xa1, - 0x42, 0xe9, 0xa1, 0x1c, 0xf8, 0x09, 0x1c, 0x90, 0x67, 0xec, 0xc4, 0x65, 0x37, 0x5b, 0x21, 0xf5, - 0xb0, 0x97, 0xc4, 0xf3, 0xde, 0x9b, 0xef, 0x7b, 0x6f, 0xbe, 0xe7, 0xe7, 0x81, 0x2a, 0x1e, 0x11, - 0x93, 0x50, 0xdc, 0xb4, 0xb0, 0x8b, 0x6d, 0x83, 0x3b, 0xc4, 0x6f, 0x1e, 0xdf, 0x68, 0xf2, 0x51, - 0x23, 0xa0, 0x84, 0x13, 0xb4, 0x1a, 0xf9, 0x1b, 0x33, 0x7f, 0xe3, 0xf8, 0x46, 0xe5, 0x25, 0xc3, - 0x73, 0x7c, 0xd2, 0x14, 0xbf, 0x32, 0xb2, 0x52, 0x32, 0x09, 0xf3, 0x08, 0x6b, 0x7a, 0xcc, 0x0e, - 0x11, 0x3c, 0x66, 0x47, 0x8e, 0x75, 0xe9, 0xd0, 0xc5, 0xaa, 0x29, 0x17, 0x91, 0xab, 0x68, 0x13, - 0x9b, 0x48, 0x7b, 0xf8, 0x24, 0xad, 0x6a, 0x0f, 0xe0, 0x6b, 0xc3, 0x1d, 0xe2, 0x5b, 0x0e, 0x76, - 0x2d, 0x74, 0x08, 0xcb, 0x86, 0x47, 0x86, 0x3e, 0x2f, 0x2b, 0x1b, 0x4a, 0x3d, 0xb7, 0xf3, 0xe1, - 0xc3, 0xd3, 0x5a, 0xea, 0x8f, 0xd3, 0xda, 0xa6, 0xed, 0xf0, 0xfe, 0xb0, 0xd7, 0x30, 0x89, 0x17, - 0x81, 0x46, 0x7f, 0xdb, 0xcc, 0x1a, 0x34, 0xf9, 0x38, 0xc0, 0xac, 0xd1, 0xf5, 0xf9, 0xe3, 0x07, - 0xdb, 0x10, 0x71, 0x76, 0x7d, 0xae, 0x45, 0x58, 0xea, 0x2f, 0x69, 0x28, 0x77, 0x64, 0x49, 0xd8, - 0x3a, 0x70, 0x7c, 0xdb, 0xc5, 0x6d, 0xc6, 0x30, 0xef, 0xfa, 0x47, 0x04, 0x6d, 0x42, 0xd6, 0x08, - 0x17, 0xba, 0x63, 0x45, 0xa4, 0xf9, 0xc9, 0x69, 0x2d, 0x23, 0x03, 0x3a, 0x5a, 0x46, 0x38, 0xbb, - 0x16, 0xa2, 0xb0, 0xc6, 0x09, 0x37, 0x5c, 0xdd, 0x8a, 0x91, 0xf4, 0x28, 0xd5, 0x85, 0x2b, 0x48, - 0xb5, 0x28, 0xb0, 0xa7, 0x49, 0xb6, 0x05, 0x32, 0x1a, 0x43, 0x31, 0xc0, 0x54, 0x27, 0x01, 0xa6, - 0x06, 0x27, 0x34, 0x22, 0x64, 0xe5, 0xf4, 0x46, 0xba, 0x9e, 0x6f, 0x7d, 0xd2, 0x78, 0xaa, 0x5e, - 0x8d, 0x79, 0xa5, 0x36, 0xee, 0x60, 0x7a, 0x3b, 0x82, 0x92, 0x04, 0x6c, 0xd7, 0xe7, 0x74, 0xac, - 0xa1, 0xe0, 0x09, 0x47, 0xa5, 0x0f, 0xa5, 0x39, 0xe1, 0xe8, 0x45, 0x48, 0x0f, 0xf0, 0x58, 0x1e, - 0x96, 0x16, 0x3e, 0xa2, 0xf7, 0x60, 0xe9, 0x38, 0x14, 0x51, 0x1c, 0x45, 0xbe, 0x75, 0x6d, 0x4e, - 0x62, 0x33, 0xa1, 0x35, 0x19, 0x7f, 0x73, 0xe1, 0x7d, 0x45, 0xed, 0xc2, 0x6a, 0x67, 0x1a, 0xd6, - 0x0e, 0x02, 0x4a, 0x8e, 0xb1, 0x50, 0xe6, 0x55, 0xc8, 0x31, 0xc7, 0xf6, 0x0d, 0x3e, 0xa4, 0x38, - 0x62, 0x9b, 0x19, 0x10, 0x82, 0x45, 0x66, 0xb8, 0xd1, 0xe9, 0x6b, 0xe2, 0x59, 0xfd, 0x67, 0x01, - 0xd6, 0x66, 0x58, 0x5d, 0xdf, 0xbc, 0x4d, 0x3b, 0xd8, 0x14, 0x60, 0x1f, 0x40, 0xe1, 0x88, 0x12, - 0x4f, 0x37, 0x2c, 0x8b, 0x62, 0xc6, 0x22, 0xa9, 0xcb, 0x8f, 0x1f, 0x6c, 0x17, 0x23, 0x19, 0xda, - 0xd2, 0x73, 0xc0, 0xa9, 0xe3, 0xdb, 0x5a, 0x3e, 0x8c, 0x8e, 0x4c, 0xe8, 0xee, 0x1c, 0x1d, 0x16, - 0x84, 0x0e, 0xbb, 0xcf, 0xd6, 0xe1, 0x3f, 0x99, 0x3c, 0x9f, 0x2a, 0xdc, 0xdc, 0xf9, 0xf1, 0x7e, - 0x2d, 0xf5, 0xd7, 0xfd, 0x5a, 0xea, 0x87, 0xf3, 0x93, 0xad, 0x64, 0xf1, 0x3f, 0x9d, 0x9f, 0x6c, - 0xbd, 0x91, 0xe8, 0xe0, 0x3d, 0x66, 0xb7, 0x2d, 0x4b, 0x94, 0x43, 0xb1, 0xc1, 0xf0, 0xac, 0x4a, - 0xf5, 0x37, 0x05, 0x56, 0xf6, 0x98, 0x3d, 0xb3, 0xa0, 0xcf, 0x20, 0xd7, 0x33, 0x18, 0xd6, 0x1d, - 0xff, 0x88, 0x88, 0x54, 0xf3, 0xad, 0xed, 0xff, 0x75, 0x5a, 0x5a, 0x36, 0xdc, 0x2f, 0x14, 0xfc, - 0x12, 0x56, 0x0c, 0xd9, 0x1d, 0x96, 0xc4, 0x93, 0x65, 0xbe, 0x75, 0x29, 0x5e, 0xa2, 0xa7, 0xb4, - 0x42, 0x0c, 0x11, 0xae, 0xd4, 0x5f, 0x17, 0x01, 0x7d, 0xe5, 0xcf, 0xf6, 0x69, 0xd8, 0x24, 0xd4, - 0x42, 0xd7, 0x21, 0xc7, 0xb8, 0x31, 0xc0, 0x74, 0x36, 0x13, 0x0a, 0x93, 0xd3, 0x5a, 0xf6, 0x40, - 0x18, 0xbb, 0x1d, 0x2d, 0x2b, 0xdd, 0x5d, 0xeb, 0xc2, 0xf4, 0x58, 0x78, 0xc6, 0xf4, 0xf8, 0x08, - 0x56, 0x66, 0xdd, 0x63, 0x59, 0xb4, 0x9c, 0xbe, 0xa4, 0xff, 0x0a, 0x71, 0x78, 0x68, 0x46, 0x25, - 0xc8, 0xf0, 0x91, 0xde, 0x37, 0x58, 0xbf, 0xbc, 0x28, 0x04, 0x5f, 0xe6, 0xa3, 0x4f, 0x0d, 0xd6, - 0x47, 0xaf, 0x01, 0x38, 0x4c, 0x0f, 0xb0, 0x6f, 0x39, 0xbe, 0x5d, 0x5e, 0xda, 0x50, 0xea, 0x59, - 0x2d, 0xe7, 0xb0, 0x3b, 0xd2, 0x80, 0xae, 0x41, 0xa1, 0xe7, 0x12, 0x73, 0xa0, 0xfb, 0x43, 0xaf, - 0x87, 0x69, 0x79, 0x79, 0x43, 0xa9, 0x2f, 0x6a, 0x79, 0x61, 0xdb, 0x17, 0x26, 0xd4, 0x82, 0x55, - 0x93, 0x78, 0x81, 0x8b, 0x39, 0xd6, 0x2f, 0xc4, 0x66, 0x44, 0xec, 0xcb, 0xb1, 0x73, 0x27, 0xb1, - 0xa7, 0x0a, 0x79, 0xf7, 0x9e, 0xce, 0x47, 0xba, 0x4f, 0x7c, 0x13, 0x97, 0xb3, 0x22, 0x32, 0xe7, - 0xde, 0x3b, 0x1c, 0xed, 0x87, 0x86, 0xc4, 0x18, 0xcf, 0x5d, 0xdd, 0x18, 0x47, 0x1c, 0x4a, 0x86, - 0xc9, 0x87, 0x86, 0xab, 0xc7, 0x39, 0x4d, 0x47, 0x30, 0x5c, 0x01, 0xcd, 0xaa, 0x04, 0xff, 0x38, - 0xc6, 0x96, 0x6f, 0x9b, 0xfa, 0x2e, 0xac, 0x3f, 0xd9, 0x22, 0x9f, 0xe3, 0xf1, 0x17, 0x0e, 0xe3, - 0x68, 0x1d, 0xb2, 0x03, 0x3c, 0xd6, 0x5d, 0x87, 0x85, 0x5f, 0xac, 0x74, 0x3d, 0xa7, 0x65, 0x06, - 0xd2, 0xa5, 0x16, 0x01, 0x75, 0x12, 0xbb, 0x58, 0x40, 0x7c, 0x86, 0xd5, 0x6f, 0xe1, 0x85, 0x3d, - 0x66, 0x27, 0x01, 0xaf, 0xf2, 0x1d, 0x51, 0xd7, 0xa0, 0x78, 0x31, 0x59, 0x49, 0xdb, 0xfa, 0x5b, - 0x81, 0xf4, 0x1e, 0xb3, 0xd1, 0x77, 0x50, 0x8a, 0xbf, 0x0e, 0xa2, 0x45, 0x0f, 0x49, 0x3c, 0x5b, - 0xd0, 0xeb, 0x73, 0x38, 0x2f, 0xbc, 0xd0, 0x95, 0xeb, 0x97, 0x66, 0x16, 0x73, 0x22, 0x0a, 0xaf, - 0x4c, 0x73, 0x91, 0x6c, 0xb7, 0x28, 0xf1, 0xa6, 0x7c, 0x9b, 0xf3, 0xf9, 0x92, 0x25, 0x54, 0xde, - 0x9c, 0x13, 0xf7, 0xb4, 0x3a, 0x2b, 0x4b, 0xdf, 0x9f, 0x9f, 0x6c, 0x29, 0x3b, 0xfb, 0x0f, 0x27, - 0x55, 0xe5, 0xd1, 0xa4, 0xaa, 0xfc, 0x39, 0xa9, 0x2a, 0x3f, 0x9f, 0x55, 0x53, 0x8f, 0xce, 0xaa, - 0xa9, 0xdf, 0xcf, 0xaa, 0xa9, 0x6f, 0xde, 0x49, 0xb4, 0xc6, 0xae, 0xc4, 0xdd, 0xc7, 0xfc, 0x2e, - 0xa1, 0x83, 0x66, 0x7c, 0x39, 0x1a, 0x25, 0xaf, 0x47, 0xa2, 0x59, 0x7a, 0xcb, 0xe2, 0xae, 0xf2, - 0xf6, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb9, 0xd3, 0x67, 0x2f, 0x41, 0x09, 0x00, 0x00, + // 952 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x41, 0x6f, 0xe3, 0x44, + 0x14, 0x8e, 0x9b, 0x6e, 0x9b, 0xbc, 0xb4, 0x02, 0x86, 0x74, 0xe3, 0x06, 0x48, 0xb2, 0x16, 0x54, + 0xd9, 0x42, 0x13, 0x6d, 0x40, 0x80, 0x16, 0x38, 0x24, 0xa4, 0x2b, 0xc2, 0xd2, 0xee, 0xe2, 0x76, + 0x41, 0x42, 0x42, 0x96, 0x63, 0x4f, 0x1d, 0x13, 0xdb, 0x63, 0xcd, 0x4c, 0xba, 0xc9, 0x9e, 0x10, + 0x27, 0xc4, 0x89, 0x3b, 0x97, 0xe5, 0x0f, 0xa0, 0x1e, 0xf6, 0x47, 0xec, 0x71, 0xb5, 0x27, 0xc4, + 0xa1, 0x42, 0xe9, 0xa1, 0x1c, 0xf8, 0x09, 0x1c, 0x90, 0x67, 0xec, 0xc6, 0xd5, 0x36, 0x54, 0x48, + 0xbd, 0x24, 0x9e, 0xf7, 0xbe, 0xf9, 0xbe, 0xf7, 0xde, 0xbc, 0x67, 0x0f, 0x54, 0xf0, 0x98, 0x58, + 0x84, 0xe2, 0xa6, 0x8d, 0x3d, 0xec, 0x98, 0xdc, 0x25, 0x41, 0xf3, 0xf0, 0x56, 0x93, 0x8f, 0x1b, + 0x21, 0x25, 0x9c, 0xa0, 0xb5, 0xd8, 0xdf, 0x98, 0xf9, 0x1b, 0x87, 0xb7, 0xca, 0xaf, 0x98, 0xbe, + 0x1b, 0x90, 0xa6, 0xf8, 0x95, 0xc8, 0x72, 0xc9, 0x22, 0xcc, 0x27, 0xac, 0xe9, 0x33, 0x27, 0x62, + 0xf0, 0x99, 0x13, 0x3b, 0xd6, 0xa5, 0xc3, 0x10, 0xab, 0xa6, 0x5c, 0xc4, 0xae, 0xa2, 0x43, 0x1c, + 0x22, 0xed, 0xd1, 0x93, 0xb4, 0x6a, 0x7d, 0x80, 0xaf, 0x4c, 0x6f, 0x84, 0xef, 0xb8, 0xd8, 0xb3, + 0xd1, 0x3e, 0x2c, 0x99, 0x3e, 0x19, 0x05, 0x5c, 0x55, 0x6a, 0x4a, 0x3d, 0xdf, 0xf9, 0xf8, 0xe9, + 0x71, 0x35, 0xf3, 0xc7, 0x71, 0x75, 0xc3, 0x71, 0xf9, 0x60, 0xd4, 0x6f, 0x58, 0xc4, 0x8f, 0x49, + 0xe3, 0xbf, 0x2d, 0x66, 0x0f, 0x9b, 0x7c, 0x12, 0x62, 0xd6, 0xe8, 0x05, 0xfc, 0xf9, 0x93, 0x2d, + 0x88, 0x35, 0x7b, 0x01, 0xd7, 0x63, 0x2e, 0xed, 0x17, 0x05, 0xd4, 0xae, 0x4c, 0x09, 0xdb, 0x7b, + 0x6e, 0xe0, 0x78, 0xb8, 0xcd, 0x18, 0xe6, 0xbd, 0xe0, 0x80, 0xa0, 0x0d, 0xc8, 0x99, 0xd1, 0xc2, + 0x70, 0xed, 0x58, 0xb4, 0x30, 0x3d, 0xae, 0x2e, 0x4b, 0x40, 0x57, 0x5f, 0x16, 0xce, 0x9e, 0x8d, + 0xbe, 0x86, 0x62, 0x88, 0xa9, 0x41, 0x42, 0x4c, 0x4d, 0x4e, 0xa8, 0x21, 0xb9, 0x99, 0x9a, 0xad, + 0x65, 0xeb, 0x85, 0x56, 0xb5, 0x71, 0x61, 0xed, 0x1a, 0x77, 0xf1, 0x44, 0xa4, 0xd7, 0x59, 0x8c, + 0x32, 0xd1, 0x51, 0x88, 0xe9, 0xbd, 0x98, 0xa1, 0x2d, 0x09, 0xb4, 0x07, 0x90, 0x4b, 0x50, 0xe8, + 0x65, 0xc8, 0x0e, 0xf1, 0x44, 0xc6, 0xa1, 0x47, 0x8f, 0xe8, 0x03, 0xb8, 0x76, 0x18, 0xb9, 0xd4, + 0x85, 0x9a, 0x52, 0x2f, 0xb4, 0x6e, 0xcc, 0xd1, 0x99, 0xd5, 0x50, 0x97, 0x78, 0xad, 0x07, 0x6b, + 0xdd, 0x33, 0x48, 0x3b, 0x0c, 0x29, 0x39, 0xc4, 0x22, 0xe1, 0xd7, 0x21, 0xcf, 0x5c, 0x27, 0x30, + 0xf9, 0x88, 0xe2, 0x58, 0x69, 0x66, 0x40, 0x08, 0x16, 0x99, 0xe9, 0x71, 0x21, 0x97, 0xd7, 0xc5, + 0xb3, 0xf6, 0xcf, 0x02, 0x5c, 0x9f, 0x71, 0xf5, 0x02, 0xeb, 0x1e, 0xed, 0x62, 0x4b, 0x90, 0x7d, + 0x04, 0x2b, 0x07, 0x94, 0xf8, 0x86, 0x69, 0xdb, 0x14, 0x33, 0x16, 0x57, 0x50, 0x7d, 0xfe, 0x64, + 0xab, 0x18, 0x1f, 0x44, 0x5b, 0x7a, 0xf6, 0x38, 0x75, 0x03, 0x47, 0x2f, 0x44, 0xe8, 0xd8, 0x84, + 0x1e, 0xce, 0x29, 0xe9, 0x82, 0x28, 0xe9, 0xf6, 0x9c, 0x54, 0x2f, 0x8e, 0xa4, 0x71, 0xff, 0x85, + 0xca, 0x6e, 0x07, 0x9c, 0x4e, 0x2e, 0x2a, 0x79, 0x79, 0x00, 0xa5, 0x39, 0xf0, 0x2b, 0x3c, 0x81, + 0xdb, 0x0b, 0x1f, 0x2a, 0xb7, 0x3b, 0x3f, 0x3e, 0xae, 0x66, 0xfe, 0x7a, 0x5c, 0xcd, 0xfc, 0x70, + 0x7a, 0xb4, 0x99, 0x4e, 0xfe, 0xa7, 0xd3, 0xa3, 0xcd, 0xb7, 0x52, 0x3d, 0xbc, 0xc3, 0x9c, 0xb6, + 0x6d, 0x8b, 0x74, 0x28, 0x36, 0x19, 0x9e, 0x65, 0xa9, 0xfd, 0xa6, 0xc0, 0xea, 0x0e, 0x73, 0x66, + 0x16, 0xf4, 0x39, 0xe4, 0xfb, 0x26, 0xc3, 0x86, 0x1b, 0x1c, 0x10, 0x11, 0x6a, 0xa1, 0xb5, 0xf5, + 0xbf, 0xaa, 0xa5, 0xe7, 0xa2, 0xfd, 0xe2, 0x04, 0xbf, 0x84, 0x55, 0x53, 0x76, 0x87, 0x2d, 0xf9, + 0x64, 0x9a, 0xef, 0x5c, 0xca, 0x97, 0xea, 0x29, 0x7d, 0x25, 0xa1, 0x88, 0x56, 0xda, 0xaf, 0x8b, + 0x80, 0x1e, 0x04, 0xb3, 0x7d, 0x3a, 0xb6, 0x08, 0xb5, 0xd1, 0x4d, 0xc8, 0x33, 0x6e, 0x0e, 0x31, + 0x9d, 0x8d, 0xda, 0xca, 0xf4, 0xb8, 0x9a, 0xdb, 0x13, 0xc6, 0x5e, 0x57, 0xcf, 0x49, 0x77, 0xcf, + 0x3e, 0x37, 0x94, 0x0b, 0xff, 0x31, 0x94, 0x9f, 0xc0, 0xea, 0xac, 0x7b, 0x6c, 0x9b, 0xaa, 0xd9, + 0x4b, 0xfa, 0x6f, 0x25, 0x81, 0x47, 0x66, 0x54, 0x82, 0x65, 0x3e, 0x36, 0x06, 0x26, 0x1b, 0xa8, + 0x8b, 0xe2, 0xc0, 0x97, 0xf8, 0xf8, 0x33, 0x93, 0x0d, 0xd0, 0x1b, 0x00, 0x2e, 0x33, 0x42, 0x1c, + 0xd8, 0x6e, 0xe0, 0xa8, 0xd7, 0x6a, 0x4a, 0x3d, 0xa7, 0xe7, 0x5d, 0x76, 0x5f, 0x1a, 0xd0, 0x0d, + 0x58, 0xe9, 0x7b, 0xc4, 0x1a, 0x1a, 0xc1, 0xc8, 0xef, 0x63, 0xaa, 0x2e, 0xd5, 0x94, 0xfa, 0xa2, + 0x5e, 0x10, 0xb6, 0x5d, 0x61, 0x42, 0x2d, 0x58, 0xb3, 0x88, 0x1f, 0x7a, 0x98, 0x63, 0xe3, 0x1c, + 0x76, 0x59, 0x60, 0x5f, 0x4d, 0x9c, 0x9d, 0xd4, 0x9e, 0x0a, 0x14, 0xbc, 0x47, 0x06, 0x1f, 0x1b, + 0x01, 0x09, 0x2c, 0xac, 0xe6, 0x04, 0x32, 0xef, 0x3d, 0xda, 0x1f, 0xef, 0x46, 0x86, 0xd4, 0xdb, + 0x31, 0x7f, 0x75, 0x6f, 0x47, 0xc4, 0xa1, 0x64, 0x5a, 0x7c, 0x64, 0x7a, 0x46, 0x12, 0x93, 0x1d, + 0x4f, 0xa2, 0x0a, 0x57, 0x20, 0xb3, 0x26, 0xc9, 0x3f, 0x4d, 0xb8, 0xe5, 0xb4, 0x69, 0xef, 0xc3, + 0xfa, 0x8b, 0x2d, 0x72, 0x17, 0x4f, 0xbe, 0x70, 0x19, 0x47, 0xeb, 0x90, 0x1b, 0xe2, 0x89, 0xe1, + 0xb9, 0x2c, 0xfa, 0x10, 0x64, 0xeb, 0x79, 0x7d, 0x79, 0x28, 0x5d, 0x5a, 0x11, 0x50, 0x37, 0xb5, + 0x8b, 0x85, 0x24, 0x60, 0x58, 0xfb, 0x16, 0x5e, 0xda, 0x61, 0x4e, 0x9a, 0xf0, 0x2a, 0x67, 0x44, + 0xbb, 0x0e, 0xc5, 0xf3, 0xc1, 0x4a, 0xd9, 0xd6, 0xdf, 0x0a, 0x64, 0x77, 0x98, 0x83, 0xbe, 0x83, + 0x52, 0xf2, 0x7d, 0x11, 0x2d, 0xba, 0x4f, 0x92, 0x77, 0x0b, 0x7a, 0x73, 0x8e, 0xe6, 0xb9, 0x81, + 0x2e, 0xdf, 0xbc, 0x34, 0xb2, 0x44, 0x13, 0x51, 0x78, 0xed, 0x2c, 0x16, 0xa9, 0x76, 0x87, 0x12, + 0xff, 0x4c, 0x6f, 0x63, 0xbe, 0x5e, 0x3a, 0x85, 0xf2, 0xdb, 0x73, 0x70, 0x17, 0xe5, 0x59, 0xbe, + 0xf6, 0xfd, 0xe9, 0xd1, 0xa6, 0xd2, 0xd9, 0x7d, 0x3a, 0xad, 0x28, 0xcf, 0xa6, 0x15, 0xe5, 0xcf, + 0x69, 0x45, 0xf9, 0xf9, 0xa4, 0x92, 0x79, 0x76, 0x52, 0xc9, 0xfc, 0x7e, 0x52, 0xc9, 0x7c, 0xf3, + 0x5e, 0xaa, 0x35, 0xb6, 0x25, 0xef, 0x2e, 0xe6, 0x0f, 0x09, 0x1d, 0x36, 0x93, 0x3b, 0xc7, 0x38, + 0x7d, 0xeb, 0x10, 0xcd, 0xd2, 0x5f, 0x12, 0x57, 0x80, 0x77, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, + 0xd6, 0xc6, 0x2e, 0x6c, 0x98, 0x08, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -815,41 +871,19 @@ func (m *DelegatedSingleAssetInfo) MarshalToSizedBuffer(dAtA []byte) (int, error var l int _ = l if len(m.PerOperatorAmounts) > 0 { - for k := range m.PerOperatorAmounts { - v := m.PerOperatorAmounts[k] - baseI := i - if v != nil { - { - size, err := v.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) + for iNdEx := len(m.PerOperatorAmounts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PerOperatorAmounts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0x12 + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) } - i -= len(k) - copy(dAtA[i:], k) - i = encodeVarintTx(dAtA, i, uint64(len(k))) - i-- - dAtA[i] = 0xa - i = encodeVarintTx(dAtA, i, uint64(baseI-i)) i-- dAtA[i] = 0x1a } } - { - size := m.TotalDelegatedAmount.Size() - i -= size - if _, err := m.TotalDelegatedAmount.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 if len(m.AssetID) > 0 { i -= len(m.AssetID) copy(dAtA[i:], m.AssetID) @@ -860,6 +894,48 @@ func (m *DelegatedSingleAssetInfo) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *KeyValue) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *KeyValue) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *KeyValue) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != nil { + { + size, err := m.Value.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintTx(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *DelegationApproveInfo) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1241,24 +1317,32 @@ func (m *DelegatedSingleAssetInfo) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = m.TotalDelegatedAmount.Size() - n += 1 + l + sovTx(uint64(l)) if len(m.PerOperatorAmounts) > 0 { - for k, v := range m.PerOperatorAmounts { - _ = k - _ = v - l = 0 - if v != nil { - l = v.Size() - l += 1 + sovTx(uint64(l)) - } - mapEntrySize := 1 + len(k) + sovTx(uint64(len(k))) + l - n += mapEntrySize + 1 + sovTx(uint64(mapEntrySize)) + for _, e := range m.PerOperatorAmounts { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) } } return n } +func (m *KeyValue) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Value != nil { + l = m.Value.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + func (m *DelegationApproveInfo) Size() (n int) { if m == nil { return 0 @@ -1557,9 +1641,93 @@ func (m *DelegatedSingleAssetInfo) Unmarshal(dAtA []byte) error { } m.AssetID = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PerOperatorAmounts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PerOperatorAmounts = append(m.PerOperatorAmounts, KeyValue{}) + if err := m.PerOperatorAmounts[len(m.PerOperatorAmounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *KeyValue) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: KeyValue: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: KeyValue: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TotalDelegatedAmount", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1587,13 +1755,11 @@ func (m *DelegatedSingleAssetInfo) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.TotalDelegatedAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Key = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PerOperatorAmounts", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1620,105 +1786,12 @@ func (m *DelegatedSingleAssetInfo) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.PerOperatorAmounts == nil { - m.PerOperatorAmounts = make(map[string]*ValueField) + if m.Value == nil { + m.Value = &ValueField{} } - var mapkey string - var mapvalue *ValueField - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTx - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey < 0 { - return ErrInvalidLengthTx - } - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var mapmsglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapmsglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if mapmsglen < 0 { - return ErrInvalidLengthTx - } - postmsgIndex := iNdEx + mapmsglen - if postmsgIndex < 0 { - return ErrInvalidLengthTx - } - if postmsgIndex > l { - return io.ErrUnexpectedEOF - } - mapvalue = &ValueField{} - if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { - return err - } - iNdEx = postmsgIndex - } else { - iNdEx = entryPreIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } + if err := m.Value.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err } - m.PerOperatorAmounts[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex diff --git a/x/operator/keeper/state_update_test.go b/x/operator/keeper/state_update_test.go index 10be7bf59..3f13d802e 100644 --- a/x/operator/keeper/state_update_test.go +++ b/x/operator/keeper/state_update_test.go @@ -5,7 +5,7 @@ import ( sdkmath "cosmossdk.io/math" assetstypes "github.com/ExocoreNetwork/exocore/x/assets/types" - delegationKeeper "github.com/ExocoreNetwork/exocore/x/delegation/keeper" + delegationtype "github.com/ExocoreNetwork/exocore/x/delegation/types" "github.com/ExocoreNetwork/exocore/x/deposit/keeper" operatorKeeper "github.com/ExocoreNetwork/exocore/x/operator/keeper" operatorTypes "github.com/ExocoreNetwork/exocore/x/operator/types" @@ -60,7 +60,7 @@ func (suite *OperatorTestSuite) prepare() { suite.NoError(err) // delegate to operator - delegationParam := &delegationKeeper.DelegationOrUndelegationParams{ + delegationParam := &delegationtype.DelegationOrUndelegationParams{ ClientChainLzID: suite.clientChainLzID, Action: assetstypes.DelegateTo, AssetsAddress: suite.assetAddr[:],