From 9846ea7c6fef189d40a63ae40b7c177476728d0a Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 13 Dec 2024 10:25:54 +0100 Subject: [PATCH 01/24] feat: pool commission & stake fraction --- docs/static/openapi.yml | 32 + proto/kyve/stakers/v1beta1/events.proto | 28 +- proto/kyve/stakers/v1beta1/genesis.proto | 4 + proto/kyve/stakers/v1beta1/params.proto | 19 + proto/kyve/stakers/v1beta1/stakers.proto | 39 +- proto/kyve/stakers/v1beta1/tx.proto | 45 +- testutil/integration/checks.go | 21 +- testutil/integration/integration.go | 34 + util/expected_keepers.go | 5 +- x/bundles/keeper/abci_protocol_split_test.go | 64 +- x/bundles/keeper/keeper.go | 27 +- .../keeper_suite_dropped_bundles_test.go | 24 +- .../keeper_suite_funding_bundles_test.go | 16 +- .../keeper_suite_inflation_splitting_test.go | 81 +- .../keeper_suite_invalid_bundles_test.go | 72 +- x/bundles/keeper/keeper_suite_points_test.go | 30 +- .../keeper/keeper_suite_stakers_leave_test.go | 98 ++- .../keeper/keeper_suite_valid_bundles_test.go | 54 +- .../keeper_suite_zero_delegation_test.go | 144 ++-- x/bundles/keeper/logic_bundles.go | 62 +- x/bundles/keeper/logic_bundles_test.go | 410 ++++++---- .../logic_end_block_handle_upload_timeout.go | 4 +- ...ic_end_block_handle_upload_timeout_test.go | 145 ++-- x/bundles/keeper/logic_round_robin.go | 2 +- x/bundles/keeper/logic_round_robin_test.go | 10 +- .../msg_server_claim_uploader_role_test.go | 24 +- .../msg_server_skip_uploader_role_test.go | 24 +- .../msg_server_submit_bundle_proposal_test.go | 16 +- .../msg_server_vote_bundle_proposal_test.go | 24 +- x/bundles/module.go | 2 - x/bundles/types/expected_keepers.go | 19 +- .../keeper/msg_server_redelegate_test.go | 10 +- .../keeper/msg_server_undelegate_test.go | 10 +- x/pool/keeper/msg_server_disable_pool_test.go | 70 +- .../keeper/grpc_account_redelegation_test.go | 10 +- x/query/keeper/grpc_query_can_propose_test.go | 20 +- .../keeper/grpc_query_can_validate_test.go | 20 +- x/query/keeper/grpc_query_can_vote_test.go | 20 +- x/stakers/client/cli/tx.go | 1 + x/stakers/client/cli/tx_join_pool.go | 25 +- x/stakers/client/cli/tx_update_commission.go | 15 +- .../client/cli/tx_update_stake_fraction.go | 51 ++ x/stakers/genesis.go | 9 + x/stakers/keeper/exported_functions.go | 97 ++- x/stakers/keeper/getters_commission.go | 10 +- x/stakers/keeper/getters_params.go | 34 + x/stakers/keeper/getters_stake_fraction.go | 90 +++ x/stakers/keeper/getters_staker.go | 29 +- x/stakers/keeper/getters_valaccount.go | 49 +- x/stakers/keeper/logic_commission.go | 21 +- x/stakers/keeper/logic_leave.go | 6 +- x/stakers/keeper/logic_stake_fraction.go | 70 ++ x/stakers/keeper/logic_stakers.go | 17 +- x/stakers/keeper/msg_server_join_pool.go | 16 +- x/stakers/keeper/msg_server_join_pool_test.go | 593 +++++++++++---- x/stakers/keeper/msg_server_leave_pool.go | 4 +- .../keeper/msg_server_leave_pool_test.go | 82 +- .../keeper/msg_server_update_commission.go | 14 +- .../msg_server_update_commission_test.go | 281 +++++++ .../keeper/msg_server_update_params_test.go | 289 +++++++ .../msg_server_update_stake_fraction.go | 51 ++ .../msg_server_update_stake_fraction_test.go | 407 ++++++++++ x/stakers/module.go | 1 + x/stakers/types/codec.go | 2 + x/stakers/types/errors.go | 1 + x/stakers/types/events.pb.go | 467 +++++++++++- x/stakers/types/genesis.go | 18 + x/stakers/types/genesis.pb.go | 176 ++++- x/stakers/types/keys.go | 24 +- x/stakers/types/message_join_pool.go | 8 + .../types/message_update_stake_fraction.go | 48 ++ x/stakers/types/params.go | 45 +- x/stakers/types/params.pb.go | 220 +++++- x/stakers/types/stakers.pb.go | 571 ++++++++++++-- x/stakers/types/tx.pb.go | 714 ++++++++++++++++-- 75 files changed, 5124 insertions(+), 1171 deletions(-) create mode 100644 x/stakers/client/cli/tx_update_stake_fraction.go create mode 100644 x/stakers/keeper/getters_stake_fraction.go create mode 100644 x/stakers/keeper/logic_stake_fraction.go create mode 100644 x/stakers/keeper/msg_server_update_commission_test.go create mode 100644 x/stakers/keeper/msg_server_update_stake_fraction.go create mode 100644 x/stakers/keeper/msg_server_update_stake_fraction_test.go create mode 100644 x/stakers/types/message_update_stake_fraction.go diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index b7527647..13f9bec0 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -4698,6 +4698,19 @@ paths: type: string format: uint64 description: commission_change_time ... + stake_fraction_change_time: + type: string + format: uint64 + description: stake_fraction_change_time ... + vote_slash: + type: string + description: vote_slash ... + upload_slash: + type: string + description: upload_slash ... + timeout_slash: + type: string + description: timeout_slash ... pool_params: description: pool_params ... type: object @@ -7545,6 +7558,12 @@ paths: description: >- isLeaving indicates if a staker is leaving the given pool. + commission: + type: string + description: commission ... + stake_fraction: + type: string + description: stake_fraction ... description: StakerPoolResponse ... description: stakers ... description: >- @@ -9899,6 +9918,19 @@ paths: type: string format: uint64 description: commission_change_time ... + stake_fraction_change_time: + type: string + format: uint64 + description: stake_fraction_change_time ... + vote_slash: + type: string + description: vote_slash ... + upload_slash: + type: string + description: upload_slash ... + timeout_slash: + type: string + description: timeout_slash ... description: >- QueryParamsResponse is response type for the Query/Params RPC method. diff --git a/proto/kyve/stakers/v1beta1/events.proto b/proto/kyve/stakers/v1beta1/events.proto index 381f358e..78a7313a 100644 --- a/proto/kyve/stakers/v1beta1/events.proto +++ b/proto/kyve/stakers/v1beta1/events.proto @@ -24,8 +24,24 @@ message EventUpdateParams { message EventUpdateCommission { // staker is the account address of the protocol node. string staker = 1; + // pool_id ... + uint64 pool_id = 2; // commission ... - string commission = 2 [ + string commission = 3 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; +} + +// EventUpdateCommission ... +// emitted_by: MsgUpdateStakeFraction, EndBlock +message EventUpdateStakeFraction { + // staker is the account address of the protocol node. + string staker = 1; + // pool_id ... + uint64 pool_id = 2; + // stake_fraction ... + string stake_fraction = 3 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false ]; @@ -52,6 +68,16 @@ message EventJoinPool { string valaddress = 3; // amount is the amount of funds transferred to the valaddress uint64 amount = 4; + // commission ... + string commission = 5 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + // stake_fraction ... + string stake_fraction = 6 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; } // EventLeavePool ... diff --git a/proto/kyve/stakers/v1beta1/genesis.proto b/proto/kyve/stakers/v1beta1/genesis.proto index 7c85c711..01c285e8 100644 --- a/proto/kyve/stakers/v1beta1/genesis.proto +++ b/proto/kyve/stakers/v1beta1/genesis.proto @@ -24,4 +24,8 @@ message GenesisState { repeated LeavePoolEntry leave_pool_entries = 6 [(gogoproto.nullable) = false]; // queue_state_leave ... QueueState queue_state_leave = 7 [(gogoproto.nullable) = false]; + // stake_fraction_change_entries ... + repeated StakeFractionChangeEntry stake_fraction_change_entries = 8 [(gogoproto.nullable) = false]; + // queue_state_state_fraction ... + QueueState queue_state_state_fraction = 9 [(gogoproto.nullable) = false]; } diff --git a/proto/kyve/stakers/v1beta1/params.proto b/proto/kyve/stakers/v1beta1/params.proto index 551c9e54..4a524231 100644 --- a/proto/kyve/stakers/v1beta1/params.proto +++ b/proto/kyve/stakers/v1beta1/params.proto @@ -2,6 +2,8 @@ syntax = "proto3"; package kyve.stakers.v1beta1; +import "gogoproto/gogo.proto"; + option go_package = "github.com/KYVENetwork/chain/x/stakers/types"; // Params defines the stakers module parameters. @@ -10,4 +12,21 @@ message Params { uint64 commission_change_time = 1; // commission_change_time ... uint64 leave_pool_time = 2; + // stake_fraction_change_time ... + uint64 stake_fraction_change_time = 3; + // vote_slash ... + string vote_slash = 4 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + // upload_slash ... + string upload_slash = 5 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + // timeout_slash ... + string timeout_slash = 6 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; } diff --git a/proto/kyve/stakers/v1beta1/stakers.proto b/proto/kyve/stakers/v1beta1/stakers.proto index a897ff52..af25cb08 100644 --- a/proto/kyve/stakers/v1beta1/stakers.proto +++ b/proto/kyve/stakers/v1beta1/stakers.proto @@ -54,6 +54,16 @@ message Valaccount { uint64 points = 4; // isLeaving indicates if a staker is leaving the given pool. bool is_leaving = 5; + // commission ... + string commission = 6 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + // stake_fraction ... + string stake_fraction = 7 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; } // CommissionChangeEntry stores the information for an @@ -66,15 +76,40 @@ message CommissionChangeEntry { uint64 index = 1; // staker is the address of the affected staker string staker = 2; + // pool_id ... + uint64 pool_id = 3; // commission is the new commission which will // be applied after the waiting time is over. - string commission = 3 [ + string commission = 4 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false ]; // creation_date is the UNIX-timestamp in seconds // when the entry was created. - int64 creation_date = 4; + int64 creation_date = 5; +} + +// StakeFractionChangeEntry stores the information for an +// upcoming stake fraction change. A stake fraction change is +// only instant if it gets increased, if it gets decreased +// the staker needs to wait for the stake fraction change time +message StakeFractionChangeEntry { + // index is needed for the queue-algorithm which + // processes the commission changes + uint64 index = 1; + // staker is the address of the affected staker + string staker = 2; + // pool_id ... + uint64 pool_id = 3; + // stake_fraction is the new stake fraction which will + // be applied after the waiting time is over. + string stake_fraction = 4 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + // creation_date is the UNIX-timestamp in seconds + // when the entry was created. + int64 creation_date = 5; } // LeavePoolEntry stores the information for an upcoming diff --git a/proto/kyve/stakers/v1beta1/tx.proto b/proto/kyve/stakers/v1beta1/tx.proto index 1889f102..d765a2e2 100644 --- a/proto/kyve/stakers/v1beta1/tx.proto +++ b/proto/kyve/stakers/v1beta1/tx.proto @@ -11,25 +11,30 @@ option go_package = "github.com/KYVENetwork/chain/x/stakers/types"; // Msg defines the Msg service. service Msg { option (cosmos.msg.v1.service) = true; - // UpdateCommission ... - rpc UpdateCommission(MsgUpdateCommission) returns (MsgUpdateCommissionResponse); // JoinPool ... rpc JoinPool(MsgJoinPool) returns (MsgJoinPoolResponse); // LeavePool ... rpc LeavePool(MsgLeavePool) returns (MsgLeavePoolResponse); + // UpdateCommission ... + rpc UpdateCommission(MsgUpdateCommission) returns (MsgUpdateCommissionResponse); + // UpdateStakeFraction ... + rpc UpdateStakeFraction(MsgUpdateStakeFraction) returns (MsgUpdateStakeFractionResponse); + // UpdateParams defines a governance operation for updating the x/stakers module // parameters. The authority is hard-coded to the x/gov module account. rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); } -// MsgUpdateCommission ... +// MsgUpdateCommission ... // TODO: create v1 types and rename new to MsgUpdatePoolCommission message MsgUpdateCommission { option (cosmos.msg.v1.signer) = "creator"; // creator ... string creator = 1; + // pool_id ... + uint64 pool_id = 2; // commission ... - string commission = 2 [ + string commission = 3 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false ]; @@ -38,7 +43,24 @@ message MsgUpdateCommission { // MsgUpdateCommissionResponse ... message MsgUpdateCommissionResponse {} -// MsgJoinPool ... +// MsgUpdateStakeFraction ... +message MsgUpdateStakeFraction { + option (cosmos.msg.v1.signer) = "creator"; + // creator ... + string creator = 1; + // pool_id ... + uint64 pool_id = 2; + // commission ... + string stake_fraction = 3 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; +} + +// MsgUpdateStakeFractionResponse ... +message MsgUpdateStakeFractionResponse {} + +// MsgJoinPool ... // TODO: create v1 types message MsgJoinPool { option (cosmos.msg.v1.signer) = "creator"; // creator ... @@ -49,9 +71,16 @@ message MsgJoinPool { string valaddress = 3; // amount ... uint64 amount = 4; - - // TODO add stake fraction (in next PR) - // TODO add commission (in next PR) + // commission ... + string commission = 5 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + // stake_fraction ... + string stake_fraction = 6 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; } // MsgJoinPoolResponse ... diff --git a/testutil/integration/checks.go b/testutil/integration/checks.go index cd6b14eb..94c1de37 100644 --- a/testutil/integration/checks.go +++ b/testutil/integration/checks.go @@ -178,7 +178,7 @@ func (suite *KeeperTestSuite) VerifyPoolTotalStake() { actualBalance := suite.App().StakersKeeper.GetDelegationOfPool(suite.Ctx(), pool.Id) for _, stakerAddress := range suite.App().StakersKeeper.GetAllStakerAddressesOfPool(suite.Ctx(), pool.Id) { - expectedBalance += suite.App().StakersKeeper.GetDelegationAmount(suite.Ctx(), stakerAddress) + expectedBalance += suite.App().StakersKeeper.GetValidatorPoolStake(suite.Ctx(), stakerAddress, pool.Id) } Expect(actualBalance).To(Equal(expectedBalance)) @@ -461,20 +461,21 @@ func (suite *KeeperTestSuite) verifyFullStaker(fullStaker querytypes.FullStaker, //Expect(fullStaker.Metadata.Commission).To(Equal(staker.Commission)) //Expect(fullStaker.Metadata.Moniker).To(Equal(staker.Description.Moniker)) - pendingCommissionChange, found := suite.App().StakersKeeper.GetCommissionChangeEntryByIndex2(suite.Ctx(), stakerAddress) - if found { - Expect(fullStaker.Metadata.PendingCommissionChange.Commission).To(Equal(pendingCommissionChange.Commission)) - Expect(fullStaker.Metadata.PendingCommissionChange.CreationDate).To(Equal(pendingCommissionChange.CreationDate)) - } else { - Expect(fullStaker.Metadata.PendingCommissionChange).To(BeNil()) - } + // TODO rework after commission was implemented + //pendingCommissionChange, found := suite.App().StakersKeeper.GetCommissionChangeEntryByIndex2(suite.Ctx(), stakerAddress) + //if found { + // Expect(fullStaker.Metadata.PendingCommissionChange.Commission).To(Equal(pendingCommissionChange.Commission)) + // Expect(fullStaker.Metadata.PendingCommissionChange.CreationDate).To(Equal(pendingCommissionChange.CreationDate)) + //} else { + // Expect(fullStaker.Metadata.PendingCommissionChange).To(BeNil()) + //} poolIds := make(map[uint64]bool) for _, poolMembership := range fullStaker.Pools { poolIds[poolMembership.Pool.Id] = true - valaccount, found := suite.App().StakersKeeper.GetValaccount(suite.Ctx(), poolMembership.Pool.Id, stakerAddress) - Expect(found).To(BeTrue()) + valaccount, active := suite.App().StakersKeeper.GetValaccount(suite.Ctx(), poolMembership.Pool.Id, stakerAddress) + Expect(active).To(BeTrue()) Expect(poolMembership.Valaddress).To(Equal(valaccount.Valaddress)) Expect(poolMembership.IsLeaving).To(Equal(valaccount.IsLeaving)) diff --git a/testutil/integration/integration.go b/testutil/integration/integration.go index e1432bbf..20dc25d9 100644 --- a/testutil/integration/integration.go +++ b/testutil/integration/integration.go @@ -326,6 +326,40 @@ func (suite *KeeperTestSuite) CreateValidatorWithoutCommit(address, moniker stri suite.Commit() } +func (suite *KeeperTestSuite) SelfDelegateValidator(address string, amount uint64) { + valAddress := util.MustValaddressFromOperatorAddress(address) + + msg := stakingtypes.NewMsgDelegate( + address, + valAddress, + sdk.NewInt64Coin(globalTypes.Denom, int64(amount)), + ) + + _, err := suite.RunTx(msg) + if err != nil { + panic(err) + } + + suite.Commit() +} + +func (suite *KeeperTestSuite) SelfUndelegateValidator(address string, amount uint64) { + valAddress := util.MustValaddressFromOperatorAddress(address) + + msg := stakingtypes.NewMsgUndelegate( + address, + valAddress, + sdk.NewInt64Coin(globalTypes.Denom, int64(amount)), + ) + + _, err := suite.RunTx(msg) + if err != nil { + panic(err) + } + + suite.Commit() +} + func (suite *KeeperTestSuite) CreateValidator(address, moniker string, kyveStake int64) { suite.CreateValidatorWithoutCommit(address, moniker, kyveStake) suite.Commit() diff --git a/util/expected_keepers.go b/util/expected_keepers.go index 125f5c3c..2184544a 100644 --- a/util/expected_keepers.go +++ b/util/expected_keepers.go @@ -3,6 +3,7 @@ package util import ( "context" + "cosmossdk.io/core/address" "cosmossdk.io/math" distributionTypes "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -24,12 +25,13 @@ type BankKeeper interface { type DistributionKeeper interface { FundCommunityPool(ctx context.Context, amount sdk.Coins, sender sdk.AccAddress) error - AllocateTokensToValidator(ctx context.Context, val stakingtypes.ValidatorI, tokens sdk.DecCoins) error IncrementValidatorPeriod(ctx context.Context, val stakingtypes.ValidatorI) (uint64, error) CalculateDelegationRewards(ctx context.Context, val stakingtypes.ValidatorI, del stakingtypes.DelegationI, endingPeriod uint64) (rewards sdk.DecCoins, err error) GetValidatorAccumulatedCommission(ctx context.Context, val sdk.ValAddress) (commission distributionTypes.ValidatorAccumulatedCommission, err error) SetValidatorAccumulatedCommission(ctx context.Context, val sdk.ValAddress, commission distributionTypes.ValidatorAccumulatedCommission) error + GetValidatorCurrentRewards(ctx context.Context, val sdk.ValAddress) (rewards distributionTypes.ValidatorCurrentRewards, err error) + SetValidatorCurrentRewards(ctx context.Context, val sdk.ValAddress, rewards distributionTypes.ValidatorCurrentRewards) error GetValidatorOutstandingRewards(ctx context.Context, val sdk.ValAddress) (rewards distributionTypes.ValidatorOutstandingRewards, err error) SetValidatorOutstandingRewards(ctx context.Context, val sdk.ValAddress, rewards distributionTypes.ValidatorOutstandingRewards) error } @@ -41,6 +43,7 @@ type StakingKeeper interface { PowerReduction(ctx context.Context) math.Int SetHooks(sh stakingtypes.StakingHooks) Delegation(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (stakingtypes.DelegationI, error) + ValidatorAddressCodec() address.Codec } type UpgradeKeeper interface { diff --git a/x/bundles/keeper/abci_protocol_split_test.go b/x/bundles/keeper/abci_protocol_split_test.go index 9d5c059e..e88ee831 100644 --- a/x/bundles/keeper/abci_protocol_split_test.go +++ b/x/bundles/keeper/abci_protocol_split_test.go @@ -81,17 +81,21 @@ var _ = Describe("abci.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) b1, b2 := uint64(0), uint64(0) @@ -133,27 +137,35 @@ var _ = Describe("abci.go", Ordered, func() { s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_0_B, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_0_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 1, - Valaddress: i.VALADDRESS_1_B, + Creator: i.STAKER_1, + PoolId: 1, + Valaddress: i.VALADDRESS_1_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -192,17 +204,21 @@ var _ = Describe("abci.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT diff --git a/x/bundles/keeper/keeper.go b/x/bundles/keeper/keeper.go index d3d863aa..d1d151ee 100644 --- a/x/bundles/keeper/keeper.go +++ b/x/bundles/keeper/keeper.go @@ -23,13 +23,12 @@ type ( authority string - accountKeeper types.AccountKeeper - bankKeeper util.BankKeeper - distrkeeper util.DistributionKeeper - poolKeeper types.PoolKeeper - stakerKeeper types.StakerKeeper - delegationKeeper types.DelegationKeeper - fundersKeeper types.FundersKeeper + accountKeeper types.AccountKeeper + bankKeeper util.BankKeeper + distrkeeper util.DistributionKeeper + poolKeeper types.PoolKeeper + stakerKeeper types.StakerKeeper + fundersKeeper types.FundersKeeper Schema collections.Schema BundlesParams collections.Item[types.Params] @@ -49,7 +48,6 @@ func NewKeeper( distrKeeper util.DistributionKeeper, poolKeeper types.PoolKeeper, stakerKeeper types.StakerKeeper, - delegationKeeper types.DelegationKeeper, fundersKeeper types.FundersKeeper, ) Keeper { sb := collections.NewSchemaBuilder(storeService) @@ -61,13 +59,12 @@ func NewKeeper( authority: authority, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - distrkeeper: distrKeeper, - poolKeeper: poolKeeper, - stakerKeeper: stakerKeeper, - delegationKeeper: delegationKeeper, - fundersKeeper: fundersKeeper, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + distrkeeper: distrKeeper, + poolKeeper: poolKeeper, + stakerKeeper: stakerKeeper, + fundersKeeper: fundersKeeper, BundlesParams: collections.NewItem(sb, types.ParamsPrefix, "params", codec.CollValue[types.Params](cdc)), } diff --git a/x/bundles/keeper/keeper_suite_dropped_bundles_test.go b/x/bundles/keeper/keeper_suite_dropped_bundles_test.go index 1454c74b..0dd6d57b 100644 --- a/x/bundles/keeper/keeper_suite_dropped_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_dropped_bundles_test.go @@ -68,17 +68,21 @@ var _ = Describe("dropped bundles", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -105,9 +109,11 @@ var _ = Describe("dropped bundles", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_2) diff --git a/x/bundles/keeper/keeper_suite_funding_bundles_test.go b/x/bundles/keeper/keeper_suite_funding_bundles_test.go index 7c34eead..728e34c3 100644 --- a/x/bundles/keeper/keeper_suite_funding_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_funding_bundles_test.go @@ -107,17 +107,21 @@ var _ = Describe("funding bundles", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ diff --git a/x/bundles/keeper/keeper_suite_inflation_splitting_test.go b/x/bundles/keeper/keeper_suite_inflation_splitting_test.go index 2b6c1d65..c3f3b87d 100644 --- a/x/bundles/keeper/keeper_suite_inflation_splitting_test.go +++ b/x/bundles/keeper/keeper_suite_inflation_splitting_test.go @@ -128,17 +128,21 @@ var _ = Describe("inflation splitting", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -322,7 +326,7 @@ var _ = Describe("inflation splitting", Ordered, func() { // (total_bundle_payout - treasury_reward - storage_cost) * commission + storage_cost // storage_cost = byte_size * usd_per_byte / len(coins) * coin_weight // (2471669 - (2471669 * 0.01) - _((100 * 0.5) / (1 * 1))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(2_202_214).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(2_202_215).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -408,7 +412,7 @@ var _ = Describe("inflation splitting", Ordered, func() { // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (49433483 - (49433483 * 0.01) - _((100 * 0.5) / (1 * 1))_) * (1 - 0.1) // Due to cosmos rounding, the result is a little off. - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(44_045_219).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(44_045_220).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -610,7 +614,7 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).String()).To(Equal(i.KYVECoins(735_121).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (7_415_009 + 10_000 - ((7_415_009 + 10_000) * 0.01) - _((100 * 0.5) / (1 * 1))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(6_615_641).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(6_615_642).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -707,7 +711,7 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).String()).To(Equal(i.KYVECoins(2_447_994).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (2_471_6741 + 10_000 - ((2_471_6741 + 10_000) * 0.01) - _((100 * 0.5) / (1 * 1))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(22_031_497).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(22_031_498).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -803,7 +807,7 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).String()).To(Equal(i.KYVECoins(74).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (300 - (300 * 0.01) - _((100 * 0.5) / (1 * 1))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(222).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(223).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1006,7 +1010,7 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).String()).To(Equal(i.KYVECoins(2_447_033).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (24_716_741 + 300 - ((24_716_741 + 300) * 0.01) - _((100 * 0.5) / (1 * 1))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(22_022_855).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(22_022_856).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1102,7 +1106,7 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).String()).To(Equal(i.KYVECoins(559).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (5_000 + 200 - ((5_000 + 200) * 0.01) - _((100 * 0.5) / (1 * 1))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(4_588).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(4_589).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1207,7 +1211,7 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).String()).To(Equal(i.KYVECoins(734_646).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (7_415_009 + 5_000 + 200 - ((7_415_009 + 5_000 + 200) * 0.01) - _((100 * 0.5) / (1 * 1))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(6_611_364).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.KYVECoins(6_611_365).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1402,7 +1406,7 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.ACoin(1012), i.BCoin(1990)).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (20_000 - (20_000 * 0.01) - _((100 * 0.5) / (2 * coin_weight))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.ACoin(8887), i.BCoin(17809)).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.ACoin(8888), i.BCoin(17810)).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1511,7 +1515,7 @@ var _ = Describe("inflation splitting", Ordered, func() { // for kyve coin (7_415_009 - (7_415_009 * 0.01) - _((100 * 0.5) / (3 * 1))_) * (1 - 0.1) // for acoin (10_000 - (10_000 * 0.01) - _((100 * 0.5) / (3 * 1))_) * (1 - 0.1) // for bcoin (20_000 - (20_000 * 0.01) - _((100 * 0.5) / (3 * 2))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.KYVECoin(6_606_762), i.ACoin(8895), i.BCoin(17812)).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.KYVECoin(6_606_763), i.ACoin(8896), i.BCoin(17813)).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1621,7 +1625,7 @@ var _ = Describe("inflation splitting", Ordered, func() { // for kyve coin (24_716_741 - (24_716_741 * 0.01) - _((100 * 0.5) / (3 * 1))_) * (1 - 0.1) // for acoin (10_000 - (10_000 * 0.01) - _((100 * 0.5) / (3 * 1))_) * (1 - 0.1) // for bcoin (20_000 - (20_000 * 0.01) - _((100 * 0.5) / (3 * 2))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.KYVECoin(22_022_618), i.ACoin(8895), i.BCoin(17812)).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.KYVECoin(22_022_619), i.ACoin(8896), i.BCoin(17813)).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1758,14 +1762,18 @@ var _ = Describe("inflation splitting", Ordered, func() { s.RunTxPoolSuccess(msg) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_0_B, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_0_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 1, - Valaddress: i.VALADDRESS_1_B, + Creator: i.STAKER_1, + PoolId: 1, + Valaddress: i.VALADDRESS_1_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) preMineBalance := s.App().BankKeeper.GetSupply(s.Ctx(), globalTypes.Denom) @@ -1845,7 +1853,6 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(finalBalancePool1).To(Equal(uint64(30919246548))) // assert bundle reward - uploader, _ := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) // the total payout is here just the inflation payout // (inflation - teamRewards)*inflationShare - balancePool0 - balancePool1 @@ -1858,7 +1865,7 @@ var _ = Describe("inflation splitting", Ordered, func() { storageReward := s.App().BundlesKeeper.GetStorageCost(s.Ctx(), pool.GetCurrentStorageProviderId()).MulInt64(100).TruncateDec() totalUploaderReward := totalPayout.Sub(treasuryReward).Sub(storageReward) - uploaderPayoutReward := totalUploaderReward.Mul(uploader.Commission.Rate).TruncateDec() + uploaderPayoutReward := totalUploaderReward.Mul(math.LegacyMustNewDecFromStr("0.1")).TruncateDec() uploaderDelegationReward := totalUploaderReward.Sub(uploaderPayoutReward) // assert commission rewards @@ -1866,7 +1873,7 @@ var _ = Describe("inflation splitting", Ordered, func() { // only the commission-rewards distribution) Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).AmountOf(globalTypes.Denom).String()).To(Equal(uploaderPayoutReward.Add(storageReward).RoundInt().String())) // assert uploader self delegation rewards - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).AmountOf(globalTypes.Denom).ToLegacyDec().Add(math.LegacyOneDec()).String()).To(Equal(uploaderDelegationReward.String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).AmountOf(globalTypes.Denom).ToLegacyDec().String()).To(Equal(uploaderDelegationReward.String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1913,14 +1920,19 @@ var _ = Describe("inflation splitting", Ordered, func() { s.RunTxPoolSuccess(msg) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_0_B, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_0_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 1, - Valaddress: i.VALADDRESS_1_B, + Creator: i.STAKER_1, + PoolId: 1, + Valaddress: i.VALADDRESS_1_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // Both pools now have inflation_share=1 and zero balance @@ -1998,7 +2010,6 @@ var _ = Describe("inflation splitting", Ordered, func() { Expect(finalBalancePool1).To(Equal(uint64(17005585601))) // assert bundle reward - uploader, _ := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) // the total payout is here just the inflation payout totalPayout := math.LegacyNewDec(17005585601 - 13604468481) @@ -2008,13 +2019,13 @@ var _ = Describe("inflation splitting", Ordered, func() { storageReward := s.App().BundlesKeeper.GetStorageCost(s.Ctx(), pool.GetCurrentStorageProviderId()).MulInt64(100).TruncateDec() totalUploaderReward := totalPayout.Sub(treasuryReward).Sub(storageReward) - uploaderPayoutReward := totalUploaderReward.Mul(uploader.Commission.Rate).TruncateDec() + uploaderPayoutReward := totalUploaderReward.Mul(math.LegacyMustNewDecFromStr("0.1")).TruncateDec() uploaderDelegationReward := totalUploaderReward.Sub(uploaderPayoutReward) // assert commission rewards Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).AmountOf(globalTypes.Denom).ToLegacyDec().String()).To(Equal(uploaderPayoutReward.Add(storageReward).String())) // assert uploader self delegation rewards - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).AmountOf(globalTypes.Denom).ToLegacyDec().Add(math.LegacyOneDec()).String()).To(Equal(uploaderDelegationReward.String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).AmountOf(globalTypes.Denom).ToLegacyDec().String()).To(Equal(uploaderDelegationReward.String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) diff --git a/x/bundles/keeper/keeper_suite_invalid_bundles_test.go b/x/bundles/keeper/keeper_suite_invalid_bundles_test.go index 5359c598..32d1f9b0 100644 --- a/x/bundles/keeper/keeper_suite_invalid_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_invalid_bundles_test.go @@ -77,17 +77,21 @@ var _ = Describe("invalid bundles", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -131,9 +135,11 @@ var _ = Describe("invalid bundles", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_2) @@ -205,8 +211,8 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(bundleProposal.VotersAbstain).To(BeEmpty()) // check uploader status - _, valaccountUploaderFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(valaccountUploaderFound).To(BeFalse()) + _, uploaderActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(uploaderActive).To(BeFalse()) balanceValaddress := s.GetBalanceFromAddress(i.VALADDRESS_0_A) Expect(balanceValaddress).To(Equal(initialBalanceValaddress0)) @@ -220,7 +226,7 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(BeEmpty()) // calculate uploader slashes - fraction := s.App().DelegationKeeper.GetUploadSlash(s.Ctx()) + fraction := s.App().StakersKeeper.GetUploadSlash(s.Ctx()) slashAmount := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100*i.KYVE - slashAmount)) @@ -275,9 +281,11 @@ var _ = Describe("invalid bundles", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxSuccess(stakingTypes.NewMsgDelegate( @@ -369,8 +377,8 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(bundleProposal.VotersAbstain).To(BeEmpty()) // check uploader status - _, valaccountUploaderFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(valaccountUploaderFound).To(BeFalse()) + _, uploaderActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(uploaderActive).To(BeFalse()) balanceValaddress := s.GetBalanceFromAddress(i.VALADDRESS_0_A) Expect(balanceValaddress).To(Equal(initialBalanceValaddress0)) @@ -385,7 +393,7 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(BeEmpty()) // calculate uploader slashes - fraction := s.App().DelegationKeeper.GetUploadSlash(s.Ctx()) + fraction := s.App().StakersKeeper.GetUploadSlash(s.Ctx()) slashAmountUploader := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) slashAmountDelegator := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) @@ -443,9 +451,11 @@ var _ = Describe("invalid bundles", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxSuccess(stakingTypes.NewMsgDelegate( @@ -457,9 +467,11 @@ var _ = Describe("invalid bundles", Ordered, func() { s.CreateValidator(i.STAKER_3, "Staker-3", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_3, - PoolId: 0, - Valaddress: i.VALADDRESS_3_A, + Creator: i.STAKER_3, + PoolId: 0, + Valaddress: i.VALADDRESS_3_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // delegate a bit more so invalid voters have more than 50% @@ -561,8 +573,8 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(bundleProposal.VotersAbstain).To(BeEmpty()) // check uploader status - _, valaccountUploaderFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(valaccountUploaderFound).To(BeFalse()) + _, uploaderActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(uploaderActive).To(BeFalse()) balanceValaddress := s.GetBalanceFromAddress(i.VALADDRESS_0_A) Expect(balanceValaddress).To(Equal(initialBalanceValaddress0)) @@ -577,7 +589,7 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(BeEmpty()) // calculate uploader slashes - fraction := s.App().DelegationKeeper.GetUploadSlash(s.Ctx()) + fraction := s.App().StakersKeeper.GetUploadSlash(s.Ctx()) slashAmountUploader := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) slashAmountDelegator1 := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) @@ -585,7 +597,7 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.ALICE)).To(Equal(100*i.KYVE - slashAmountDelegator1)) // calculate voter slashes - fraction = s.App().DelegationKeeper.GetVoteSlash(s.Ctx()) + fraction = s.App().StakersKeeper.GetVoteSlash(s.Ctx()) slashAmountVoter := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) slashAmountDelegator2 := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) @@ -595,8 +607,8 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(450 * i.KYVE)) // check voter status - _, valaccountVoterFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) - Expect(valaccountVoterFound).To(BeFalse()) + _, voterActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) + Expect(voterActive).To(BeFalse()) balanceVoterValaddress := s.GetBalanceFromAddress(i.VALADDRESS_1_A) Expect(balanceVoterValaddress).To(Equal(initialBalanceValaddress2)) diff --git a/x/bundles/keeper/keeper_suite_points_test.go b/x/bundles/keeper/keeper_suite_points_test.go index e0a6bafb..0f0f23a9 100644 --- a/x/bundles/keeper/keeper_suite_points_test.go +++ b/x/bundles/keeper/keeper_suite_points_test.go @@ -68,25 +68,31 @@ var _ = Describe("points", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_2, "Staker-2", int64(50*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CommitAfterSeconds(60) @@ -346,11 +352,11 @@ var _ = Describe("points", Ordered, func() { _, stakerFound := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_2) Expect(stakerFound).To(BeTrue()) - _, valaccountFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_2) - Expect(valaccountFound).To(BeFalse()) + _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_2) + Expect(valaccountActive).To(BeFalse()) // check if voter got slashed - slashAmountRatio := s.App().DelegationKeeper.GetTimeoutSlash(s.Ctx()) + slashAmountRatio := s.App().StakersKeeper.GetTimeoutSlash(s.Ctx()) expectedBalance := 50*i.KYVE - uint64(math.LegacyNewDec(int64(50*i.KYVE)).Mul(slashAmountRatio).TruncateInt64()) Expect(expectedBalance).To(Equal(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.STAKER_2))) diff --git a/x/bundles/keeper/keeper_suite_stakers_leave_test.go b/x/bundles/keeper/keeper_suite_stakers_leave_test.go index da4a93f7..29ee4340 100644 --- a/x/bundles/keeper/keeper_suite_stakers_leave_test.go +++ b/x/bundles/keeper/keeper_suite_stakers_leave_test.go @@ -75,17 +75,21 @@ var _ = Describe("stakers leave", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -107,9 +111,11 @@ var _ = Describe("stakers leave", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -131,8 +137,8 @@ var _ = Describe("stakers leave", Ordered, func() { Expect(poolStakers).To(HaveLen(2)) Expect(poolStakers[0]).To(Equal(i.STAKER_1)) - _, valaccountFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(valaccountFound).To(BeFalse()) + _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccountActive).To(BeFalse()) Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) @@ -145,9 +151,11 @@ var _ = Describe("stakers leave", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CommitAfterSeconds(60) @@ -217,8 +225,8 @@ var _ = Describe("stakers leave", Ordered, func() { Expect(poolStakers).To(HaveLen(2)) Expect(poolStakers[0]).To(Equal(i.STAKER_1)) - _, valaccountFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(valaccountFound).To(BeFalse()) + _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccountActive).To(BeFalse()) Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) @@ -227,7 +235,6 @@ var _ = Describe("stakers leave", Ordered, func() { // check if next uploader received the uploader reward pool, _ := s.App().PoolKeeper.GetPool(s.Ctx(), 0) - uploader, _ := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) balanceUploader := s.GetBalanceFromAddress(i.STAKER_0) // calculate uploader rewards @@ -236,12 +243,15 @@ var _ = Describe("stakers leave", Ordered, func() { storageReward := s.App().BundlesKeeper.GetStorageCost(s.Ctx(), pool.CurrentStorageProviderId).MulInt64(100) totalUploaderReward := pool.InflationShareWeight.Sub(treasuryReward).Sub(storageReward) - uploaderPayoutReward := totalUploaderReward.Mul(uploader.Commission.Rate) + uploaderPayoutReward := totalUploaderReward.Mul(math.LegacyMustNewDecFromStr("0.1")) uploaderDelegationReward := totalUploaderReward.Sub(uploaderPayoutReward) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0)) + // assert payout transfer Expect(balanceUploader).To(Equal(initialBalanceStaker0)) // assert commission rewards + // TODO: fix Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), i.STAKER_0).AmountOf(globalTypes.Denom).Uint64()).To(Equal(uint64(uploaderPayoutReward.Add(storageReward).TruncateInt64()))) // assert uploader self delegation rewards Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).AmountOf(globalTypes.Denom).Uint64()).To(Equal(uint64(uploaderDelegationReward.TruncateInt64()))) @@ -252,9 +262,11 @@ var _ = Describe("stakers leave", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CommitAfterSeconds(60) @@ -324,11 +336,11 @@ var _ = Describe("stakers leave", Ordered, func() { Expect(poolStakers).To(HaveLen(2)) Expect(poolStakers[0]).To(Equal(i.STAKER_1)) - _, valaccountFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(valaccountFound).To(BeFalse()) + _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccountActive).To(BeFalse()) // check if next uploader got slashed - fraction := s.App().DelegationKeeper.GetUploadSlash(s.Ctx()) + fraction := s.App().StakersKeeper.GetUploadSlash(s.Ctx()) slashAmount := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100*i.KYVE - slashAmount)) @@ -348,9 +360,11 @@ var _ = Describe("stakers leave", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CommitAfterSeconds(60) @@ -422,11 +436,11 @@ var _ = Describe("stakers leave", Ordered, func() { Expect(poolStakers).To(HaveLen(2)) Expect(poolStakers[0]).To(Equal(i.STAKER_0)) - _, valaccountFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) - Expect(valaccountFound).To(BeFalse()) + _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) + Expect(valaccountActive).To(BeFalse()) // check if voter got slashed - fraction := s.App().DelegationKeeper.GetVoteSlash(s.Ctx()) + fraction := s.App().StakersKeeper.GetVoteSlash(s.Ctx()) slashAmount := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_1, i.STAKER_1)).To(Equal(100*i.KYVE - slashAmount)) @@ -446,9 +460,11 @@ var _ = Describe("stakers leave", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CommitAfterSeconds(60) @@ -514,8 +530,8 @@ var _ = Describe("stakers leave", Ordered, func() { Expect(poolStakers).To(HaveLen(2)) Expect(poolStakers[0]).To(Equal(i.STAKER_0)) - _, valaccountFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) - Expect(valaccountFound).To(BeFalse()) + _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) + Expect(valaccountActive).To(BeFalse()) // check if voter status @@ -536,9 +552,11 @@ var _ = Describe("stakers leave", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CommitAfterSeconds(60) @@ -608,8 +626,8 @@ var _ = Describe("stakers leave", Ordered, func() { Expect(poolStakers).To(HaveLen(2)) Expect(poolStakers[0]).To(Equal(i.STAKER_0)) - _, valaccountFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) - Expect(valaccountFound).To(BeFalse()) + _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) + Expect(valaccountActive).To(BeFalse()) // check if voter not got slashed Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_1, i.STAKER_1)).To(Equal(100 * i.KYVE)) diff --git a/x/bundles/keeper/keeper_suite_valid_bundles_test.go b/x/bundles/keeper/keeper_suite_valid_bundles_test.go index 430c34ee..b3de63d4 100644 --- a/x/bundles/keeper/keeper_suite_valid_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_valid_bundles_test.go @@ -119,17 +119,21 @@ var _ = Describe("valid bundles", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -452,9 +456,11 @@ var _ = Describe("valid bundles", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxSuccess(stakingTypes.NewMsgDelegate( @@ -616,9 +622,11 @@ var _ = Describe("valid bundles", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxSuccess(stakingTypes.NewMsgDelegate( @@ -788,9 +796,11 @@ var _ = Describe("valid bundles", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxSuccess(stakingTypes.NewMsgDelegate( @@ -905,7 +915,7 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(balanceUploaderValaddress).To(Equal(initialBalanceValaddress0)) // calculate voter slashes - fraction := s.App().DelegationKeeper.GetVoteSlash(s.Ctx()) + fraction := s.App().StakersKeeper.GetVoteSlash(s.Ctx()) slashAmountVoter := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) slashAmountDelegator := uint64(math.LegacyNewDec(int64(300 * i.KYVE)).Mul(fraction).TruncateInt64()) @@ -915,8 +925,8 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(800 * i.KYVE)) // check voter status - _, valaccountVoterFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_2) - Expect(valaccountVoterFound).To(BeFalse()) + _, voterActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_2) + Expect(voterActive).To(BeFalse()) balanceVoterValaddress := s.GetCoinsFromAddress(i.VALADDRESS_2_A) Expect(balanceVoterValaddress).To(Equal(initialBalanceValaddress2)) @@ -1221,7 +1231,7 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), valaccountUploader.Staker).String()).To(Equal(sdk.NewCoins(i.ACoin(1004), i.BCoin(1987), i.CCoin(2974)).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (coin_amount_per_bundle - (coin_amount_per_bundle * 0.01) - _((100 * 0.5) / (3 * coin_weight))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.ACoin(8895), i.BCoin(17812), i.CCoin(26725)).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.ACoin(8896), i.BCoin(17813), i.CCoin(26726)).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1390,7 +1400,7 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), valaccountUploader.Staker).String()).To(Equal(sdk.NewCoins(i.ACoin(1004), i.BCoin(997), i.CCoin(9900)).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (10_000 - (10_000 * 0.01) - _((100 * 0.5) / (3 * coin_weight))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.ACoin(8895), i.BCoin(8902)).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.ACoin(8896), i.BCoin(8903)).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1553,7 +1563,7 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), valaccountUploader.Staker).String()).To(Equal(sdk.NewCoins(i.ACoin(1012), i.BCoin(1000)).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (10_000 - (10_000 * 0.01) - _((100 * 0.5) / (2 * coin_weight))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.ACoin(8887), i.BCoin(8899)).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.ACoin(8888), i.BCoin(8900)).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) @@ -1750,7 +1760,7 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), valaccountUploader.Staker).String()).To(Equal(sdk.NewCoins(i.KYVECoin(125_973_187), i.ACoin(99_143), i.BCoin(116_661_015_771_428_571), i.CCoin(100_765)).String())) // assert uploader self delegation rewards (here we round up since the result of delegation rewards is the remainder minus the truncated commission rewards) // (amount_per_bundle - (amount_per_bundle * 0.01) - _((29970208 * 0.000000006288 * 1**coin_decimals) / (4 * coin_weight))_) * (1 - 0.1) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.KYVECoin(864_026_812), i.ACoin(890_856), i.BCoin(873_338_984_228_571_428), i.CCoin(889_234)).String())) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(sdk.NewCoins(i.KYVECoin(864_026_813), i.ACoin(890_857), i.BCoin(873_338_984_228_571_429), i.CCoin(889_235)).String())) fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) diff --git a/x/bundles/keeper/keeper_suite_zero_delegation_test.go b/x/bundles/keeper/keeper_suite_zero_delegation_test.go index 5382372a..757de27d 100644 --- a/x/bundles/keeper/keeper_suite_zero_delegation_test.go +++ b/x/bundles/keeper/keeper_suite_zero_delegation_test.go @@ -91,17 +91,21 @@ var _ = Describe("zero delegation", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -138,9 +142,11 @@ var _ = Describe("zero delegation", Ordered, func() { s.CreateZeroDelegationValidator(i.STAKER_2, "Staker-2") s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -186,17 +192,21 @@ var _ = Describe("zero delegation", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -225,9 +235,11 @@ var _ = Describe("zero delegation", Ordered, func() { s.CreateZeroDelegationValidator(i.STAKER_2, "Staker-2") s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -288,27 +300,33 @@ var _ = Describe("zero delegation", Ordered, func() { s.CreateZeroDelegationValidator(i.STAKER_0, "Staker-0") s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // create normal validator s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // create normal validator s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -461,27 +479,33 @@ var _ = Describe("zero delegation", Ordered, func() { s.CreateZeroDelegationValidator(i.STAKER_0, "Staker-0") s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // create normal validator s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // create normal validator s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -579,8 +603,8 @@ var _ = Describe("zero delegation", Ordered, func() { Expect(bundleProposal.VotersAbstain).To(BeEmpty()) // check uploader status - _, valaccountUploaderFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(valaccountUploaderFound).To(BeFalse()) + _, uploaderActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(uploaderActive).To(BeFalse()) balanceValaddress := s.GetBalanceFromAddress(i.VALADDRESS_0_A) Expect(balanceValaddress).To(Equal(initialBalanceValaddress0)) @@ -624,27 +648,33 @@ var _ = Describe("zero delegation", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // create zero delegation validator s.CreateZeroDelegationValidator(i.STAKER_1, "Staker-1") s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // create normal validator s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -722,8 +752,8 @@ var _ = Describe("zero delegation", Ordered, func() { _, stakerFound := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(stakerFound).To(BeTrue()) - _, valaccountFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) - Expect(valaccountFound).To(BeFalse()) + _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) + Expect(valaccountActive).To(BeFalse()) // check if voter got slashed slashAmountRatio := s.App().DelegationKeeper.GetTimeoutSlash(s.Ctx()) @@ -737,17 +767,21 @@ var _ = Describe("zero delegation", Ordered, func() { s.CreateZeroDelegationValidator(i.STAKER_0, "Staker-0") s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateZeroDelegationValidator(i.STAKER_1, "Staker-1") s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index 07c7cf00..1a6c68ea 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -5,8 +5,7 @@ import ( "cosmossdk.io/math" globalTypes "github.com/KYVENetwork/chain/x/global/types" poolTypes "github.com/KYVENetwork/chain/x/pool/types" - - delegationTypes "github.com/KYVENetwork/chain/x/delegation/types" + stakersTypes "github.com/KYVENetwork/chain/x/stakers/types" "github.com/KYVENetwork/chain/util" "github.com/KYVENetwork/chain/x/bundles/types" @@ -169,20 +168,8 @@ func (k Keeper) validateSubmitBundleArgs(ctx sdk.Context, bundleProposal *types. // slashDelegatorsAndRemoveStaker slashes a staker with a certain slashType and all including // delegators and removes him from the storage pool -func (k Keeper) slashDelegatorsAndRemoveStaker(ctx sdk.Context, poolId uint64, stakerAddress string, slashType delegationTypes.SlashType) { - slashAmountRatio := math.LegacyZeroDec() - - // TODO move the delegation Slash types to the Stakers module - switch slashType { - case delegationTypes.SLASH_TYPE_TIMEOUT: - slashAmountRatio = k.delegationKeeper.GetTimeoutSlash(ctx) - case delegationTypes.SLASH_TYPE_VOTE: - slashAmountRatio = k.delegationKeeper.GetVoteSlash(ctx) - case delegationTypes.SLASH_TYPE_UPLOAD: - slashAmountRatio = k.delegationKeeper.GetUploadSlash(ctx) - } - - k.stakerKeeper.Slash(ctx, poolId, stakerAddress, slashAmountRatio) +func (k Keeper) slashDelegatorsAndRemoveStaker(ctx sdk.Context, poolId uint64, stakerAddress string, slashType stakersTypes.SlashType) { + k.stakerKeeper.Slash(ctx, poolId, stakerAddress, slashType) k.stakerKeeper.LeavePool(ctx, stakerAddress, poolId) } @@ -214,7 +201,7 @@ func (k Keeper) addPoint(ctx sdk.Context, poolId uint64, stakerAddress string) { if points >= k.GetMaxPoints(ctx) { // slash all delegators with a timeout slash and remove staker from pool. // points are reset due to the valaccount being deleted while leaving the pool - k.slashDelegatorsAndRemoveStaker(ctx, poolId, stakerAddress, delegationTypes.SLASH_TYPE_TIMEOUT) + k.slashDelegatorsAndRemoveStaker(ctx, poolId, stakerAddress, stakersTypes.SLASH_TYPE_TIMEOUT) } } @@ -255,8 +242,7 @@ func (k Keeper) calculatePayouts(ctx sdk.Context, poolId uint64, totalPayout sdk // are divided between uploader and its delegators based on the uploader's commission. bundleProposal, _ := k.GetBundleProposal(ctx, poolId) - _, found := k.stakerKeeper.GetValidator(ctx, bundleProposal.Uploader) - if !found { + if _, found := k.stakerKeeper.GetValidator(ctx, bundleProposal.Uploader); !found { return } @@ -318,10 +304,9 @@ func (k Keeper) calculatePayouts(ctx sdk.Context, poolId uint64, totalPayout sdk return } - // TODO add custom commission per pool in next PR - // commission := k.stakerKeeper.GetCommission(ctx, bundleProposal.Uploader) - // commissionRewards, _ := sdk.NewDecCoinsFromCoins(totalPayout...).MulDec(commission).TruncateDecimal() - // bundleReward.UploaderCommission = commissionRewards + commission := k.stakerKeeper.GetValidatorPoolCommission(ctx, bundleProposal.Uploader, poolId) + commissionRewards, _ := sdk.NewDecCoinsFromCoins(totalPayout...).MulDec(commission).TruncateDecimal() + bundleReward.UploaderCommission = commissionRewards // the remaining total payout belongs to the delegators totalPayout = totalPayout.Sub(bundleReward.UploaderCommission...) @@ -330,7 +315,7 @@ func (k Keeper) calculatePayouts(ctx sdk.Context, poolId uint64, totalPayout sdk } // if the uploader has no delegators he receives the entire remaining amount - if k.stakerKeeper.GetDelegationAmount(ctx, bundleProposal.Uploader) > 0 { + if k.stakerKeeper.GetValidatorPoolStake(ctx, bundleProposal.Uploader, poolId) > 0 { bundleReward.Delegation = totalPayout } else { bundleReward.UploaderCommission = bundleReward.UploaderCommission.Add(totalPayout...) @@ -528,34 +513,25 @@ func (k Keeper) GetVoteDistribution(ctx sdk.Context, poolId uint64) (voteDistrib // get voting power for valid for _, voter := range bundleProposal.VotersValid { - // valaccount was found the voter is active in the pool - if k.stakerKeeper.DoesValaccountExist(ctx, poolId, voter) { - delegation := k.stakerKeeper.GetDelegationAmount(ctx, voter) - voteDistribution.Valid += k.calculateVotingPower(delegation) - } + delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) + voteDistribution.Valid += k.calculateVotingPower(delegation) } // get voting power for invalid for _, voter := range bundleProposal.VotersInvalid { - // valaccount was found the voter is active in the pool - if k.stakerKeeper.DoesValaccountExist(ctx, poolId, voter) { - delegation := k.stakerKeeper.GetDelegationAmount(ctx, voter) - voteDistribution.Invalid += k.calculateVotingPower(delegation) - } + delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) + voteDistribution.Invalid += k.calculateVotingPower(delegation) } // get voting power for abstain for _, voter := range bundleProposal.VotersAbstain { - // valaccount was found the voter is active in the pool - if k.stakerKeeper.DoesValaccountExist(ctx, poolId, voter) { - delegation := k.stakerKeeper.GetDelegationAmount(ctx, voter) - voteDistribution.Abstain += k.calculateVotingPower(delegation) - } + delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) + voteDistribution.Abstain += k.calculateVotingPower(delegation) } // get total voting power for _, staker := range k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId) { - delegation := k.stakerKeeper.GetDelegationAmount(ctx, staker) + delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, staker, poolId) voteDistribution.Total += k.calculateVotingPower(delegation) } @@ -623,7 +599,7 @@ func (k Keeper) tallyBundleProposal(ctx sdk.Context, bundleProposal types.Bundle // slash stakers who voted incorrectly for _, voter := range bundleProposal.VotersInvalid { - k.slashDelegatorsAndRemoveStaker(ctx, poolId, voter, delegationTypes.SLASH_TYPE_VOTE) + k.slashDelegatorsAndRemoveStaker(ctx, poolId, voter, stakersTypes.SLASH_TYPE_VOTE) } return types.TallyResult{ @@ -642,9 +618,9 @@ func (k Keeper) tallyBundleProposal(ctx sdk.Context, bundleProposal types.Bundle // slash stakers who voted incorrectly - uploader receives upload slash for _, voter := range bundleProposal.VotersValid { if voter == bundleProposal.Uploader { - k.slashDelegatorsAndRemoveStaker(ctx, poolId, voter, delegationTypes.SLASH_TYPE_UPLOAD) + k.slashDelegatorsAndRemoveStaker(ctx, poolId, voter, stakersTypes.SLASH_TYPE_UPLOAD) } else { - k.slashDelegatorsAndRemoveStaker(ctx, poolId, voter, delegationTypes.SLASH_TYPE_VOTE) + k.slashDelegatorsAndRemoveStaker(ctx, poolId, voter, stakersTypes.SLASH_TYPE_VOTE) } } diff --git a/x/bundles/keeper/logic_bundles_test.go b/x/bundles/keeper/logic_bundles_test.go index ee77c5bf..08d19811 100644 --- a/x/bundles/keeper/logic_bundles_test.go +++ b/x/bundles/keeper/logic_bundles_test.go @@ -103,19 +103,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -130,19 +134,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // disable pool @@ -162,19 +170,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(20*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(20*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -207,19 +219,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(101*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -252,28 +268,34 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(300*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(300*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_2, "Staker-2", int64(400*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, - Amount: 0, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -310,28 +332,34 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(300*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(300*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_2, "Staker-2", int64(401*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, - Amount: 0, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -368,10 +396,12 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(300*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -386,19 +416,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(50*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(50*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -431,19 +465,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -474,19 +512,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -527,19 +569,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -580,19 +626,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -632,19 +682,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -693,19 +747,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -754,19 +812,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -809,19 +871,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -845,19 +911,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -881,19 +951,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -920,19 +994,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ @@ -956,19 +1034,23 @@ var _ = Describe("logic_bundles.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundlesTypes.MsgClaimUploaderRole{ diff --git a/x/bundles/keeper/logic_end_block_handle_upload_timeout.go b/x/bundles/keeper/logic_end_block_handle_upload_timeout.go index 25d9aedf..338b3e5b 100644 --- a/x/bundles/keeper/logic_end_block_handle_upload_timeout.go +++ b/x/bundles/keeper/logic_end_block_handle_upload_timeout.go @@ -112,8 +112,8 @@ func (k Keeper) HandleUploadTimeout(goCtx context.Context) { } // Now we increase the points of the valaccount - // (if he is still participating in the pool) - if k.stakerKeeper.DoesValaccountExist(ctx, pool.Id, timedoutUploader) { + // (if he is still active in the pool) + if _, active := k.stakerKeeper.GetValaccount(ctx, pool.Id, timedoutUploader); active { k.addPoint(ctx, pool.Id, timedoutUploader) } } diff --git a/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go b/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go index ebff4846..ce19c849 100644 --- a/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go +++ b/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go @@ -95,15 +95,19 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), originalBundleProposal) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) }) @@ -138,11 +142,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Last staker who joins gets automatically chosen as next uploader", func() { @@ -159,11 +163,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Next uploader gets removed due to pool upgrading", func() { @@ -198,11 +202,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Next uploader gets removed due to pool being disabled", func() { @@ -230,11 +234,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Next uploader gets removed due to pool not reaching min delegation", func() { @@ -270,11 +274,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(20 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(20 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(20 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(20 * i.KYVE)) }) It("Next uploader gets removed due to pool having one node with more than 50% voting power", func() { @@ -304,11 +308,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(101 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(101 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Staker is next uploader of genesis bundle and upload interval and timeout does not pass", func() { @@ -332,11 +336,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Staker is next uploader of genesis bundle and upload timeout does not pass but upload interval passes", func() { @@ -361,11 +365,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Staker is next uploader of genesis bundle and upload timeout does pass together with upload interval", func() { @@ -449,11 +453,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Staker is next uploader of bundle proposal and upload timeout does not pass", func() { @@ -502,11 +506,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Staker is next uploader of bundle proposal and upload timeout passes with the previous bundle being valid", func() { @@ -648,9 +652,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), originalBundleProposal) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -721,7 +727,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(valaccount.Points).To(Equal(uint64(0))) // check that staker 0 (uploader) got slashed - expectedBalance := 80 * i.KYVE + expectedBalance := 100*i.KYVE - uint64(s.App().StakersKeeper.GetUploadSlash(s.Ctx()).Mul(math.LegacyNewDec(int64(100*i.KYVE))).TruncateInt64()) Expect(expectedBalance).To(Equal(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0))) // check that staker 1 (next uploader) didn't get slashed @@ -743,9 +749,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), originalBundleProposal) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -857,7 +865,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(expectedBalance).To(Equal(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_1, i.STAKER_1))) // check that staker 2 (next uploader) got slashed - expectedBalance = 98 * i.KYVE + expectedBalance = 100*i.KYVE - uint64(math.LegacyNewDec(int64(100*i.KYVE)).Mul(s.App().StakersKeeper.GetTimeoutSlash(s.Ctx())).TruncateInt64()) Expect(expectedBalance).To(Equal(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.STAKER_2))) // pool delegations equals delegations of staker 0 & 1 @@ -901,11 +909,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("A bundle proposal with no quorum does reach the upload interval", func() { @@ -957,11 +965,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_1)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) }) It("Staker who just left the pool is next uploader of dropped bundle proposal and upload timeout passes", func() { @@ -971,9 +979,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), originalBundleProposal) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -1035,9 +1045,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), originalBundleProposal) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -1121,9 +1133,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), originalBundleProposal) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -1168,8 +1182,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { s.App().StakersKeeper.RemoveValaccountFromPool(s.Ctx(), 0, i.STAKER_0) // ACT - s.CommitAfterSeconds(s.App().BundlesKeeper.GetUploadTimeout(s.Ctx())) - s.CommitAfterSeconds(60) + s.CommitAfterSeconds(s.App().BundlesKeeper.GetUploadTimeout(s.Ctx()) + 60) s.CommitAfterSeconds(1) // ASSERT @@ -1190,8 +1203,8 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) - // check that next uploader got slashed for voting invalid - expectedBalance := 80 * i.KYVE + // check that uploader received upload slash + expectedBalance := 100*i.KYVE - uint64(s.App().StakersKeeper.GetUploadSlash(s.Ctx()).Mul(math.LegacyNewDec(int64(100*i.KYVE))).TruncateInt64()) Expect(expectedBalance).To(Equal(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0))) }) @@ -1228,15 +1241,19 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { }) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_0_B, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_0_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 1, - Valaddress: i.VALADDRESS_1_B, + Creator: i.STAKER_1, + PoolId: 1, + Valaddress: i.VALADDRESS_1_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) @@ -1246,9 +1263,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), originalBundleProposalPool2) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 1, - Valaddress: i.VALADDRESS_2_B, + Creator: i.STAKER_2, + PoolId: 1, + Valaddress: i.VALADDRESS_2_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -1342,8 +1361,8 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(poolStakers).To(HaveLen(2)) // check if next uploader received a point - _, valaccountFound := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_2) - Expect(valaccountFound).To(BeFalse()) + _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_2) + Expect(valaccountActive).To(BeFalse()) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_2) Expect(found).To(BeTrue()) @@ -1351,7 +1370,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1)).To(Equal(200 * i.KYVE)) // check if next uploader not got slashed - slashAmountRatio := s.App().DelegationKeeper.GetTimeoutSlash(s.Ctx()) + slashAmountRatio := s.App().StakersKeeper.GetTimeoutSlash(s.Ctx()) expectedBalance := 100*i.KYVE - uint64(math.LegacyNewDec(int64(100*i.KYVE)).Mul(slashAmountRatio).TruncateInt64()) Expect(expectedBalance).To(Equal(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.STAKER_2))) diff --git a/x/bundles/keeper/logic_round_robin.go b/x/bundles/keeper/logic_round_robin.go index b34ee522..3edf586d 100644 --- a/x/bundles/keeper/logic_round_robin.go +++ b/x/bundles/keeper/logic_round_robin.go @@ -75,7 +75,7 @@ func (k Keeper) LoadRoundRobinValidatorSet(ctx sdk.Context, poolId uint64) Round newValidators := make(map[string]bool, 0) // Add all current pool validators to the round-robin set for _, address := range k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId) { - delegation := k.stakerKeeper.GetDelegationAmount(ctx, address) + delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, address, poolId) if delegation > 0 { // If a validator has no delegation do not add to the round-robin set. Validator is basically non-existent. vs.Validators = append(vs.Validators, RoundRobinValidatorPower{ diff --git a/x/bundles/keeper/logic_round_robin_test.go b/x/bundles/keeper/logic_round_robin_test.go index 4212287a..09582726 100644 --- a/x/bundles/keeper/logic_round_robin_test.go +++ b/x/bundles/keeper/logic_round_robin_test.go @@ -35,10 +35,12 @@ func joinDummy(s *i.KeeperTestSuite, index, kyveAmount uint64) { s.CreateValidator(i.DUMMY[index], fmt.Sprintf("dummy-%d", index), int64(kyveAmount*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.DUMMY[index], - PoolId: 0, - Valaddress: i.VALDUMMY[index], - Amount: 0, + Creator: i.DUMMY[index], + PoolId: 0, + Valaddress: i.VALDUMMY[index], + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) } diff --git a/x/bundles/keeper/msg_server_claim_uploader_role_test.go b/x/bundles/keeper/msg_server_claim_uploader_role_test.go index b31ba659..3698692b 100644 --- a/x/bundles/keeper/msg_server_claim_uploader_role_test.go +++ b/x/bundles/keeper/msg_server_claim_uploader_role_test.go @@ -61,17 +61,21 @@ var _ = Describe("msg_server_claim_uploader_role.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) }) @@ -200,9 +204,11 @@ var _ = Describe("msg_server_claim_uploader_role.go", Ordered, func() { s.RunTxPoolSuccess(msg) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_0_B, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_0_B, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT diff --git a/x/bundles/keeper/msg_server_skip_uploader_role_test.go b/x/bundles/keeper/msg_server_skip_uploader_role_test.go index e35527b3..ef6fac03 100644 --- a/x/bundles/keeper/msg_server_skip_uploader_role_test.go +++ b/x/bundles/keeper/msg_server_skip_uploader_role_test.go @@ -65,17 +65,21 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -87,9 +91,11 @@ var _ = Describe("msg_server_skip_uploader_role.go", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.Commit() diff --git a/x/bundles/keeper/msg_server_submit_bundle_proposal_test.go b/x/bundles/keeper/msg_server_submit_bundle_proposal_test.go index 35ebda23..22299c1d 100644 --- a/x/bundles/keeper/msg_server_submit_bundle_proposal_test.go +++ b/x/bundles/keeper/msg_server_submit_bundle_proposal_test.go @@ -71,17 +71,21 @@ var _ = Describe("msg_server_submit_bundle_proposal.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ diff --git a/x/bundles/keeper/msg_server_vote_bundle_proposal_test.go b/x/bundles/keeper/msg_server_vote_bundle_proposal_test.go index d6f25077..a21c2480 100644 --- a/x/bundles/keeper/msg_server_vote_bundle_proposal_test.go +++ b/x/bundles/keeper/msg_server_vote_bundle_proposal_test.go @@ -69,17 +69,21 @@ var _ = Describe("msg_server_vote_bundle_proposal.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ @@ -216,9 +220,11 @@ var _ = Describe("msg_server_vote_bundle_proposal.go", Ordered, func() { s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_2, - PoolId: 0, - Valaddress: i.VALADDRESS_2_A, + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ diff --git a/x/bundles/module.go b/x/bundles/module.go index ee970ea7..15876c00 100644 --- a/x/bundles/module.go +++ b/x/bundles/module.go @@ -218,7 +218,6 @@ type ModuleInputs struct { PoolKeeper types.PoolKeeper TeamKeeper types.TeamKeeper StakersKeeper types.StakerKeeper - DelegationKeeper types.DelegationKeeper FundersKeeper types.FundersKeeper } @@ -246,7 +245,6 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.DistributionKeeper, in.PoolKeeper, in.StakersKeeper, - in.DelegationKeeper, in.FundersKeeper, ) m := NewAppModule( diff --git a/x/bundles/types/expected_keepers.go b/x/bundles/types/expected_keepers.go index cd7b06b7..3d9c0ddd 100644 --- a/x/bundles/types/expected_keepers.go +++ b/x/bundles/types/expected_keepers.go @@ -2,8 +2,9 @@ package types import ( "cosmossdk.io/math" - "github.com/KYVENetwork/chain/x/funders/types" + fundersTypes "github.com/KYVENetwork/chain/x/funders/types" pooltypes "github.com/KYVENetwork/chain/x/pool/types" + stakersTypes "github.com/KYVENetwork/chain/x/stakers/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -30,7 +31,7 @@ type StakerKeeper interface { GetAllStakerAddressesOfPool(ctx sdk.Context, poolId uint64) (stakers []string) AssertValaccountAuthorized(ctx sdk.Context, poolId uint64, stakerAddress string, valaddress string) error - DoesValaccountExist(ctx sdk.Context, poolId uint64, stakerAddress string) bool + GetValaccount(ctx sdk.Context, poolId uint64, stakerAddress string) (valaccount stakersTypes.Valaccount, active bool) LeavePool(ctx sdk.Context, staker string, poolId uint64) @@ -38,21 +39,17 @@ type StakerKeeper interface { ResetPoints(ctx sdk.Context, poolId uint64, stakerAddress string) (previousPoints uint64) GetTotalAndHighestDelegationOfPool(ctx sdk.Context, poolId uint64) (totalDelegation, highestDelegation uint64) - GetDelegationAmount(ctx sdk.Context, validator string) uint64 GetValidator(ctx sdk.Context, staker string) (stakingtypes.Validator, bool) - Slash(ctx sdk.Context, poolId uint64, staker string, slashFraction math.LegacyDec) + GetValidatorPoolCommission(ctx sdk.Context, staker string, poolId uint64) math.LegacyDec + GetValidatorPoolStakeFraction(ctx sdk.Context, staker string, poolId uint64) math.LegacyDec + GetValidatorPoolStake(ctx sdk.Context, staker string, poolId uint64) uint64 + Slash(ctx sdk.Context, poolId uint64, staker string, slashType stakersTypes.SlashType) PayoutRewards(ctx sdk.Context, staker string, amount sdk.Coins, payerModuleName string) error PayoutAdditionalCommissionRewards(ctx sdk.Context, validator string, payerModuleName string, amount sdk.Coins) error } -type DelegationKeeper interface { - GetTimeoutSlash(ctx sdk.Context) (res math.LegacyDec) - GetUploadSlash(ctx sdk.Context) (res math.LegacyDec) - GetVoteSlash(ctx sdk.Context) (res math.LegacyDec) -} - type FundersKeeper interface { - GetCoinWhitelistMap(ctx sdk.Context) (whitelist map[string]types.WhitelistCoinEntry) + GetCoinWhitelistMap(ctx sdk.Context) (whitelist map[string]fundersTypes.WhitelistCoinEntry) ChargeFundersOfPool(ctx sdk.Context, poolId uint64, recipient string) (payout sdk.Coins, err error) } diff --git a/x/delegation/keeper/msg_server_redelegate_test.go b/x/delegation/keeper/msg_server_redelegate_test.go index d1f2b153..1be69e61 100644 --- a/x/delegation/keeper/msg_server_redelegate_test.go +++ b/x/delegation/keeper/msg_server_redelegate_test.go @@ -71,10 +71,12 @@ var _ = Describe("Delegation - Redelegation", Ordered, func() { }) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.BOB, - PoolId: 1, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.BOB, + PoolId: 1, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) _, stakerFound := s.App().StakersKeeper.GetValidator(s.Ctx(), i.ALICE) diff --git a/x/delegation/keeper/msg_server_undelegate_test.go b/x/delegation/keeper/msg_server_undelegate_test.go index b47e4a1d..4715def4 100644 --- a/x/delegation/keeper/msg_server_undelegate_test.go +++ b/x/delegation/keeper/msg_server_undelegate_test.go @@ -77,10 +77,12 @@ var _ = Describe("msg_server_undelegate.go", Ordered, func() { s.RunTxPoolSuccess(msg) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.BOB, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.BOB, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) _, aliceFound := s.App().StakersKeeper.GetValidator(s.Ctx(), i.ALICE) diff --git a/x/pool/keeper/msg_server_disable_pool_test.go b/x/pool/keeper/msg_server_disable_pool_test.go index ea86398e..5c3a9fec 100644 --- a/x/pool/keeper/msg_server_disable_pool_test.go +++ b/x/pool/keeper/msg_server_disable_pool_test.go @@ -368,19 +368,23 @@ var _ = Describe("msg_server_disable_pool.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) msgFirstPool := &types.MsgDisablePool{ @@ -430,26 +434,32 @@ var _ = Describe("msg_server_disable_pool.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_2_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_2_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) msgFirstPool := &types.MsgDisablePool{ @@ -499,19 +509,23 @@ var _ = Describe("msg_server_disable_pool.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ diff --git a/x/query/keeper/grpc_account_redelegation_test.go b/x/query/keeper/grpc_account_redelegation_test.go index 9915b7d3..4b2a0f01 100644 --- a/x/query/keeper/grpc_account_redelegation_test.go +++ b/x/query/keeper/grpc_account_redelegation_test.go @@ -51,10 +51,12 @@ var _ = Describe("grpc_account_redelegation.go", Ordered, func() { s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxDelegatorSuccess(&delegationtypes.MsgDelegate{ diff --git a/x/query/keeper/grpc_query_can_propose_test.go b/x/query/keeper/grpc_query_can_propose_test.go index fb1fc89f..37db7135 100644 --- a/x/query/keeper/grpc_query_can_propose_test.go +++ b/x/query/keeper/grpc_query_can_propose_test.go @@ -68,19 +68,23 @@ var _ = Describe("grpc_query_can_propose.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ diff --git a/x/query/keeper/grpc_query_can_validate_test.go b/x/query/keeper/grpc_query_can_validate_test.go index e6b46dbd..4900c805 100644 --- a/x/query/keeper/grpc_query_can_validate_test.go +++ b/x/query/keeper/grpc_query_can_validate_test.go @@ -45,19 +45,23 @@ var _ = Describe("grpc_query_can_validate.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 1, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 1, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) }) diff --git a/x/query/keeper/grpc_query_can_vote_test.go b/x/query/keeper/grpc_query_can_vote_test.go index 8bf76d34..465f71e5 100644 --- a/x/query/keeper/grpc_query_can_vote_test.go +++ b/x/query/keeper/grpc_query_can_vote_test.go @@ -69,19 +69,23 @@ var _ = Describe("grpc_query_can_vote.go", Ordered, func() { s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ diff --git a/x/stakers/client/cli/tx.go b/x/stakers/client/cli/tx.go index 5f108690..e1768072 100644 --- a/x/stakers/client/cli/tx.go +++ b/x/stakers/client/cli/tx.go @@ -22,6 +22,7 @@ func GetTxCmd() *cobra.Command { cmd.AddCommand(CmdJoinPool()) cmd.AddCommand(CmdLeavePool()) cmd.AddCommand(CmdUpdateCommission()) + cmd.AddCommand(CmdUpdateStakeFraction()) return cmd } diff --git a/x/stakers/client/cli/tx_join_pool.go b/x/stakers/client/cli/tx_join_pool.go index c69669bf..85bf1988 100644 --- a/x/stakers/client/cli/tx_join_pool.go +++ b/x/stakers/client/cli/tx_join_pool.go @@ -1,6 +1,7 @@ package cli import ( + "cosmossdk.io/math" "github.com/KYVENetwork/chain/x/stakers/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -11,9 +12,9 @@ import ( func CmdJoinPool() *cobra.Command { cmd := &cobra.Command{ - Use: "join-pool [pool_id] [valaddress] [amount]", + Use: "join-pool [pool_id] [valaddress] [amount] [commission] [stake_fraction]", Short: "Broadcast message join-pool", - Args: cobra.ExactArgs(3), + Args: cobra.ExactArgs(5), RunE: func(cmd *cobra.Command, args []string) (err error) { argPoolId, err := cast.ToUint64E(args[0]) if err != nil { @@ -27,16 +28,28 @@ func CmdJoinPool() *cobra.Command { return err } + argCommission, err := math.LegacyNewDecFromStr(args[3]) + if err != nil { + return err + } + + argStakeFraction, err := math.LegacyNewDecFromStr(args[4]) + if err != nil { + return err + } + clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } msg := types.MsgJoinPool{ - Creator: clientCtx.GetFromAddress().String(), - PoolId: argPoolId, - Valaddress: argValaddress, - Amount: argAmount, + Creator: clientCtx.GetFromAddress().String(), + PoolId: argPoolId, + Valaddress: argValaddress, + Amount: argAmount, + Commission: argCommission, + StakeFraction: argStakeFraction, } if err := msg.ValidateBasic(); err != nil { diff --git a/x/stakers/client/cli/tx_update_commission.go b/x/stakers/client/cli/tx_update_commission.go index 76ac8468..3884e3af 100644 --- a/x/stakers/client/cli/tx_update_commission.go +++ b/x/stakers/client/cli/tx_update_commission.go @@ -6,28 +6,35 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/spf13/cast" "github.com/spf13/cobra" ) func CmdUpdateCommission() *cobra.Command { cmd := &cobra.Command{ - Use: "update-commission [commission]", + Use: "update-commission [pool_id] [commission]", Short: "Broadcast message update-commission", - Args: cobra.ExactArgs(1), + Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } - commission, err := math.LegacyNewDecFromStr(args[0]) + argPoolId, err := cast.ToUint64E(args[0]) + if err != nil { + return err + } + + argCommission, err := math.LegacyNewDecFromStr(args[1]) if err != nil { return err } msg := types.MsgUpdateCommission{ Creator: clientCtx.GetFromAddress().String(), - Commission: commission, + PoolId: argPoolId, + Commission: argCommission, } if err := msg.ValidateBasic(); err != nil { diff --git a/x/stakers/client/cli/tx_update_stake_fraction.go b/x/stakers/client/cli/tx_update_stake_fraction.go new file mode 100644 index 00000000..e43cea9f --- /dev/null +++ b/x/stakers/client/cli/tx_update_stake_fraction.go @@ -0,0 +1,51 @@ +package cli + +import ( + "cosmossdk.io/math" + "github.com/KYVENetwork/chain/x/stakers/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/spf13/cast" + "github.com/spf13/cobra" +) + +func CmdUpdateStakeFraction() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-stake-fraction [pool_id] [stake_fraction]", + Short: "Broadcast message update-stake-fraction", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + argPoolId, err := cast.ToUint64E(args[0]) + if err != nil { + return err + } + + argStakeFraction, err := math.LegacyNewDecFromStr(args[1]) + if err != nil { + return err + } + + msg := types.MsgUpdateStakeFraction{ + Creator: clientCtx.GetFromAddress().String(), + PoolId: argPoolId, + StakeFraction: argStakeFraction, + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/stakers/genesis.go b/x/stakers/genesis.go index c134b4e8..ad2a5ee0 100644 --- a/x/stakers/genesis.go +++ b/x/stakers/genesis.go @@ -25,8 +25,13 @@ func InitGenesis(ctx sdk.Context, k *keeper.Keeper, genState types.GenesisState) k.SetLeavePoolEntry(ctx, entry) } + for _, entry := range genState.StakeFractionChangeEntries { + k.SetStakeFractionChangeEntry(ctx, entry) + } + k.SetQueueState(ctx, types.QUEUE_IDENTIFIER_COMMISSION, genState.QueueStateCommission) k.SetQueueState(ctx, types.QUEUE_IDENTIFIER_LEAVE, genState.QueueStateLeave) + k.SetQueueState(ctx, types.QUEUE_IDENTIFIER_STAKE_FRACTION, genState.QueueStateStateFraction) } // ExportGenesis returns the capability module's exported genesis. @@ -40,9 +45,13 @@ func ExportGenesis(ctx sdk.Context, k *keeper.Keeper) *types.GenesisState { genesis.LeavePoolEntries = k.GetAllLeavePoolEntries(ctx) + genesis.StakeFractionChangeEntries = k.GetAllStakeFractionChangeEntries(ctx) + genesis.QueueStateCommission = k.GetQueueState(ctx, types.QUEUE_IDENTIFIER_COMMISSION) genesis.QueueStateLeave = k.GetQueueState(ctx, types.QUEUE_IDENTIFIER_LEAVE) + genesis.QueueStateStateFraction = k.GetQueueState(ctx, types.QUEUE_IDENTIFIER_STAKE_FRACTION) + return genesis } diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 66da58c8..153c50ed 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -61,9 +61,8 @@ func (k Keeper) GetPaginatedStakersByDelegation(ctx sdk.Context, pagination *que // If the valaddress is not authorized the appropriate error is returned. // Otherwise, it returns `nil` func (k Keeper) AssertValaccountAuthorized(ctx sdk.Context, poolId uint64, stakerAddress string, valaddress string) error { - valaccount, found := k.GetValaccount(ctx, poolId, stakerAddress) - - if !found { + valaccount, active := k.GetValaccount(ctx, poolId, stakerAddress) + if !active { return types.ErrValaccountUnauthorized } @@ -85,7 +84,7 @@ func (k Keeper) GetActiveStakers(ctx sdk.Context) []string { func (k Keeper) GetDelegationOfPool(ctx sdk.Context, poolId uint64) uint64 { totalDelegation := uint64(0) for _, address := range k.GetAllStakerAddressesOfPool(ctx, poolId) { - totalDelegation += k.GetDelegationAmount(ctx, address) + totalDelegation += k.GetValidatorPoolStake(ctx, address, poolId) } return totalDelegation } @@ -94,7 +93,7 @@ func (k Keeper) GetDelegationOfPool(ctx sdk.Context, poolId uint64) uint64 { // with the highest stake and the sum of all stakes. func (k Keeper) GetTotalAndHighestDelegationOfPool(ctx sdk.Context, poolId uint64) (totalDelegation, highestDelegation uint64) { for _, address := range k.GetAllStakerAddressesOfPool(ctx, poolId) { - delegation := k.GetDelegationAmount(ctx, address) + delegation := k.GetValidatorPoolStake(ctx, address, poolId) totalDelegation += delegation if delegation > highestDelegation { @@ -105,20 +104,6 @@ func (k Keeper) GetTotalAndHighestDelegationOfPool(ctx sdk.Context, poolId uint6 return totalDelegation, highestDelegation } -// GetDelegationAmount returns the stake of a given validator in ukyve -func (k Keeper) GetDelegationAmount(ctx sdk.Context, validator string) uint64 { - validatorAddress, err := sdk.ValAddressFromBech32(util.MustValaddressFromOperatorAddress(validator)) - if err != nil { - return 0 - } - chainValidator, err := k.stakingKeeper.GetValidator(ctx, validatorAddress) - if err != nil { - return 0 - } - - return chainValidator.GetBondedTokens().Uint64() -} - // GetValidator returns the Cosmos-validator for a given kyve-address. func (k Keeper) GetValidator(ctx sdk.Context, staker string) (stakingTypes.Validator, bool) { valAddress, err := sdk.ValAddressFromBech32(util.MustValaddressFromOperatorAddress(staker)) @@ -133,6 +118,29 @@ func (k Keeper) GetValidator(ctx sdk.Context, staker string) (stakingTypes.Valid return validator, true } +// GetValidatorPoolCommission returns the commission a validator has inside the pool +func (k Keeper) GetValidatorPoolCommission(ctx sdk.Context, staker string, poolId uint64) math.LegacyDec { + valaccount, _ := k.GetValaccount(ctx, poolId, staker) + return valaccount.Commission +} + +// GetValidatorPoolStakeFraction returns the stake fraction a validator has inside the pool +func (k Keeper) GetValidatorPoolStakeFraction(ctx sdk.Context, staker string, poolId uint64) math.LegacyDec { + valaccount, _ := k.GetValaccount(ctx, poolId, staker) + return valaccount.StakeFraction +} + +// GetValidatorPoolStake returns stake a validator has inside the pool +func (k Keeper) GetValidatorPoolStake(ctx sdk.Context, staker string, poolId uint64) uint64 { + validator, found := k.GetValidator(ctx, staker) + if !found { + return 0 + } + + stakeFraction := k.GetValidatorPoolStakeFraction(ctx, staker, poolId) + return uint64(math.LegacyNewDecFromInt(validator.BondedTokens()).Mul(stakeFraction).TruncateInt64()) +} + // GetOutstandingCommissionRewards returns the outstanding commission rewards for a given validator func (k Keeper) GetOutstandingCommissionRewards(ctx sdk.Context, staker string) sdk.Coins { valAddress, err := sdk.ValAddressFromBech32(util.MustValaddressFromOperatorAddress(staker)) @@ -186,7 +194,7 @@ func (k Keeper) GetOutstandingRewards(orgCtx sdk.Context, staker string, delegat } // Slash reduces the delegation of all delegators of `staker` by fraction. The slash itself is handled by the cosmos-sdk -func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashFraction math.LegacyDec) { +func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType types.SlashType) { validator, found := k.GetValidator(ctx, staker) if !found { return @@ -194,16 +202,26 @@ func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashFracti consAddrBytes, _ := validator.GetConsAddr() - amount, err := k.stakingKeeper.Slash(ctx, consAddrBytes, ctx.BlockHeight(), validator.GetConsensusPower(math.NewInt(1000000)), slashFraction) + // the validator can only be slashed for his stake fraction in a pool, therefore we update the slash fraction + // accordingly + slashFraction := k.getSlashFraction(ctx, slashType).Mul(k.GetValidatorPoolStakeFraction(ctx, staker, poolId)) + + amount, err := k.stakingKeeper.Slash( + ctx, + consAddrBytes, + ctx.BlockHeight(), + validator.GetConsensusPower(math.NewInt(1000000)), + slashFraction, + ) if err != nil { return } _ = ctx.EventManager().EmitTypedEvent(&types.EventSlash{ - PoolId: poolId, - Staker: staker, - Amount: amount.Uint64(), - // SlashType: slashType, TODO add slash type, once migrated away from delegation module + PoolId: poolId, + Staker: staker, + Amount: amount.Uint64(), + SlashType: slashType, }) } @@ -251,12 +269,39 @@ func (k Keeper) PayoutRewards(ctx sdk.Context, staker string, amount sdk.Coins, } validator, _ := k.GetValidator(ctx, staker) + valBz, err := k.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) + if err != nil { + return err + } - err := k.distKeeper.AllocateTokensToValidator(ctx, validator, sdk.NewDecCoinsFromCoins(amount...)) + currentRewards, err := k.distKeeper.GetValidatorCurrentRewards(ctx, valBz) if err != nil { return err } + currentRewards.Rewards = currentRewards.Rewards.Add(sdk.NewDecCoinsFromCoins(amount...)...) + if err := k.distKeeper.SetValidatorCurrentRewards(ctx, valBz, currentRewards); err != nil { + return err + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + distrtypes.EventTypeRewards, + sdk.NewAttribute(sdk.AttributeKeyAmount, amount.String()), + sdk.NewAttribute(distrtypes.AttributeKeyValidator, validator.GetOperator()), + ), + ) + + outstanding, err := k.distKeeper.GetValidatorOutstandingRewards(ctx, valBz) + if err != nil { + return err + } + + outstanding.Rewards = outstanding.Rewards.Add(sdk.NewDecCoinsFromCoins(amount...)...) + if err := k.distKeeper.SetValidatorOutstandingRewards(ctx, valBz, outstanding); err != nil { + return err + } + // Transfer tokens to the delegation module if err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, payerModuleName, distrtypes.ModuleName, amount); err != nil { return err diff --git a/x/stakers/keeper/getters_commission.go b/x/stakers/keeper/getters_commission.go index 56959744..4457b770 100644 --- a/x/stakers/keeper/getters_commission.go +++ b/x/stakers/keeper/getters_commission.go @@ -24,7 +24,10 @@ func (k Keeper) SetCommissionChangeEntry(ctx sdk.Context, commissionChangeEntry binary.BigEndian.PutUint64(indexBytes, commissionChangeEntry.Index) indexStore := prefix.NewStore(storeAdapter, types.CommissionChangeEntryKeyPrefixIndex2) - indexStore.Set(types.CommissionChangeEntryKeyIndex2(commissionChangeEntry.Staker), indexBytes) + indexStore.Set(types.CommissionChangeEntryKeyIndex2( + commissionChangeEntry.Staker, + commissionChangeEntry.PoolId, + ), indexBytes) } // GetCommissionChangeEntry ... @@ -42,11 +45,11 @@ func (k Keeper) GetCommissionChangeEntry(ctx sdk.Context, index uint64) (val typ } // GetCommissionChangeEntryByIndex2 returns a pending commission change entry by staker address (if there is one) -func (k Keeper) GetCommissionChangeEntryByIndex2(ctx sdk.Context, staker string) (val types.CommissionChangeEntry, found bool) { +func (k Keeper) GetCommissionChangeEntryByIndex2(ctx sdk.Context, staker string, poolId uint64) (val types.CommissionChangeEntry, found bool) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) store := prefix.NewStore(storeAdapter, types.CommissionChangeEntryKeyPrefixIndex2) - b := store.Get(types.CommissionChangeEntryKeyIndex2(staker)) + b := store.Get(types.CommissionChangeEntryKeyIndex2(staker, poolId)) if b == nil { return val, false } @@ -65,6 +68,7 @@ func (k Keeper) RemoveCommissionChangeEntry(ctx sdk.Context, commissionChangeEnt indexStore := prefix.NewStore(storeAdapter, types.CommissionChangeEntryKeyPrefixIndex2) indexStore.Delete(types.CommissionChangeEntryKeyIndex2( commissionChangeEntry.Staker, + commissionChangeEntry.PoolId, )) } diff --git a/x/stakers/keeper/getters_params.go b/x/stakers/keeper/getters_params.go index bec033fb..8a2864f2 100644 --- a/x/stakers/keeper/getters_params.go +++ b/x/stakers/keeper/getters_params.go @@ -1,6 +1,7 @@ package keeper import ( + "cosmossdk.io/math" "github.com/KYVENetwork/chain/x/stakers/types" "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" @@ -29,6 +30,39 @@ func (k Keeper) GetLeavePoolTime(ctx sdk.Context) (res uint64) { return k.GetParams(ctx).LeavePoolTime } +// GetStakeFractionChangeTime returns the StakeFractionChangeTime param +func (k Keeper) GetStakeFractionChangeTime(ctx sdk.Context) (res uint64) { + return k.GetParams(ctx).StakeFractionChangeTime +} + +// GetVoteSlash returns the VoteSlash param +func (k Keeper) GetVoteSlash(ctx sdk.Context) (res math.LegacyDec) { + return k.GetParams(ctx).VoteSlash +} + +// GetUploadSlash returns the UploadSlash param +func (k Keeper) GetUploadSlash(ctx sdk.Context) (res math.LegacyDec) { + return k.GetParams(ctx).UploadSlash +} + +// GetTimeoutSlash returns the TimeoutSlash param +func (k Keeper) GetTimeoutSlash(ctx sdk.Context) (res math.LegacyDec) { + return k.GetParams(ctx).TimeoutSlash +} + +func (k Keeper) getSlashFraction(ctx sdk.Context, slashType types.SlashType) (slashAmountRatio math.LegacyDec) { + // Retrieve slash fraction from params + switch slashType { + case types.SLASH_TYPE_TIMEOUT: + slashAmountRatio = k.GetTimeoutSlash(ctx) + case types.SLASH_TYPE_VOTE: + slashAmountRatio = k.GetVoteSlash(ctx) + case types.SLASH_TYPE_UPLOAD: + slashAmountRatio = k.GetUploadSlash(ctx) + } + return +} + // SetParams sets the x/stakers module parameters. func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) diff --git a/x/stakers/keeper/getters_stake_fraction.go b/x/stakers/keeper/getters_stake_fraction.go new file mode 100644 index 00000000..cab95cb3 --- /dev/null +++ b/x/stakers/keeper/getters_stake_fraction.go @@ -0,0 +1,90 @@ +package keeper + +import ( + "encoding/binary" + + storeTypes "cosmossdk.io/store/types" + + "github.com/cosmos/cosmos-sdk/runtime" + + "cosmossdk.io/store/prefix" + "github.com/KYVENetwork/chain/x/stakers/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SetStakeFractionChangeEntry ... +func (k Keeper) SetStakeFractionChangeEntry(ctx sdk.Context, stakeFractionChangeEntry types.StakeFractionChangeEntry) { + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.StakeFractionChangeEntryKeyPrefix) + b := k.cdc.MustMarshal(&stakeFractionChangeEntry) + store.Set(types.StakeFractionChangeEntryKey(stakeFractionChangeEntry.Index), b) + + // Insert the same entry with a different key prefix for query lookup + indexBytes := make([]byte, 8) + binary.BigEndian.PutUint64(indexBytes, stakeFractionChangeEntry.Index) + + indexStore := prefix.NewStore(storeAdapter, types.StakeFractionChangeKeyPrefixIndex2) + indexStore.Set(types.StakeFractionChangeEntryKeyIndex2( + stakeFractionChangeEntry.Staker, + stakeFractionChangeEntry.PoolId, + ), indexBytes) +} + +// GetStakeFractionChangeEntry ... +func (k Keeper) GetStakeFractionChangeEntry(ctx sdk.Context, index uint64) (val types.StakeFractionChangeEntry, found bool) { + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.StakeFractionChangeEntryKeyPrefix) + + b := store.Get(types.StakeFractionChangeEntryKey(index)) + if b == nil { + return val, false + } + + k.cdc.MustUnmarshal(b, &val) + return val, true +} + +// GetStakeFractionChangeEntryByIndex2 returns a pending stake fraction change entry by staker address (if there is one) +func (k Keeper) GetStakeFractionChangeEntryByIndex2(ctx sdk.Context, staker string, poolId uint64) (val types.StakeFractionChangeEntry, found bool) { + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.StakeFractionChangeKeyPrefixIndex2) + + b := store.Get(types.StakeFractionChangeEntryKeyIndex2(staker, poolId)) + if b == nil { + return val, false + } + + index := binary.BigEndian.Uint64(b) + + return k.GetStakeFractionChangeEntry(ctx, index) +} + +// RemoveStakeFractionEntry ... +func (k Keeper) RemoveStakeFractionEntry(ctx sdk.Context, stakeFractionChangeEntry *types.StakeFractionChangeEntry) { + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.StakeFractionChangeEntryKeyPrefix) + store.Delete(types.StakeFractionChangeEntryKey(stakeFractionChangeEntry.Index)) + + indexStore := prefix.NewStore(storeAdapter, types.StakeFractionChangeEntryKeyPrefix) + indexStore.Delete(types.StakeFractionChangeEntryKeyIndex2( + stakeFractionChangeEntry.Staker, + stakeFractionChangeEntry.PoolId, + )) +} + +// GetAllStakeFractionChangeEntries returns all pending stake fraction change entries of all stakers +func (k Keeper) GetAllStakeFractionChangeEntries(ctx sdk.Context) (list []types.StakeFractionChangeEntry) { + storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := prefix.NewStore(storeAdapter, types.StakeFractionChangeEntryKeyPrefix) + iterator := storeTypes.KVStorePrefixIterator(store, []byte{}) + + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var val types.StakeFractionChangeEntry + k.cdc.MustUnmarshal(iterator.Value(), &val) + list = append(list, val) + } + + return +} diff --git a/x/stakers/keeper/getters_staker.go b/x/stakers/keeper/getters_staker.go index 9cc09a75..ffa270e9 100644 --- a/x/stakers/keeper/getters_staker.go +++ b/x/stakers/keeper/getters_staker.go @@ -3,6 +3,8 @@ package keeper import ( "encoding/binary" + "cosmossdk.io/math" + stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types" storeTypes "cosmossdk.io/store/types" @@ -19,14 +21,16 @@ import ( ) // AddValaccountToPool adds a valaccount to a pool. -// If valaccount already belongs to pool, nothing happens. -func (k Keeper) AddValaccountToPool(ctx sdk.Context, poolId uint64, stakerAddress string, valaddress string) { +// If valaccount already active in the to pool nothing happens. +func (k Keeper) AddValaccountToPool(ctx sdk.Context, poolId uint64, stakerAddress, valaddress string, commission, stakeFraction math.LegacyDec) { if _, validatorExists := k.GetValidator(ctx, stakerAddress); validatorExists { - if !k.DoesValaccountExist(ctx, poolId, stakerAddress) { + if _, active := k.GetValaccount(ctx, poolId, stakerAddress); !active { k.SetValaccount(ctx, types.Valaccount{ - PoolId: poolId, - Staker: stakerAddress, - Valaddress: valaddress, + PoolId: poolId, + Staker: stakerAddress, + Valaddress: valaddress, + Commission: commission, + StakeFraction: stakeFraction, }) k.AddOneToCount(ctx, poolId) k.AddActiveStaker(ctx, stakerAddress) @@ -37,13 +41,12 @@ func (k Keeper) AddValaccountToPool(ctx sdk.Context, poolId uint64, stakerAddres // RemoveValaccountFromPool removes a valaccount from a given pool and updates // all aggregated variables. If the valaccount is not in the pool nothing happens. func (k Keeper) RemoveValaccountFromPool(ctx sdk.Context, poolId uint64, stakerAddress string) { - // get valaccount - valaccount, valaccountFound := k.GetValaccount(ctx, poolId, stakerAddress) - - // if valaccount was found on pool continue - if valaccountFound { - // remove valaccount from pool - k.removeValaccount(ctx, valaccount) + if valaccount, active := k.GetValaccount(ctx, poolId, stakerAddress); active { + // remove valaccount from pool by setting valaddress to zero address + valaccount.Valaddress = "" + valaccount.Points = 0 + valaccount.IsLeaving = false + k.SetValaccount(ctx, valaccount) k.subtractOneFromCount(ctx, poolId) k.removeActiveStaker(ctx, stakerAddress) } diff --git a/x/stakers/keeper/getters_valaccount.go b/x/stakers/keeper/getters_valaccount.go index 90595e30..aa307a41 100644 --- a/x/stakers/keeper/getters_valaccount.go +++ b/x/stakers/keeper/getters_valaccount.go @@ -3,6 +3,8 @@ package keeper import ( "encoding/binary" + "cosmossdk.io/math" + storeTypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/runtime" @@ -47,7 +49,10 @@ func (k Keeper) GetAllValaccountsOfPool(ctx sdk.Context, poolId uint64) (val []* for ; iterator.Valid(); iterator.Next() { valaccount := types.Valaccount{} k.cdc.MustUnmarshal(iterator.Value(), &valaccount) - val = append(val, &valaccount) + + if valaccount.Valaddress != "" { + val = append(val, &valaccount) + } } return @@ -63,9 +68,9 @@ func (k Keeper) GetValaccountsFromStaker(ctx sdk.Context, stakerAddress string) for ; iterator.Valid(); iterator.Next() { poolId := binary.BigEndian.Uint64(iterator.Key()[len(stakerAddress) : len(stakerAddress)+8]) - valaccount, valaccountFound := k.GetValaccount(ctx, poolId, stakerAddress) + valaccount, active := k.GetValaccount(ctx, poolId, stakerAddress) - if valaccountFound { + if active { val = append(val, &valaccount) } } @@ -93,11 +98,11 @@ func (k Keeper) GetPoolCount(ctx sdk.Context, stakerAddress string) (poolCount u // DoesValaccountExist only checks if the key is present in the KV-Store // without loading and unmarshalling to full entry -func (k Keeper) DoesValaccountExist(ctx sdk.Context, poolId uint64, stakerAddress string) bool { - storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - store := prefix.NewStore(storeAdapter, types.ValaccountPrefix) - return store.Has(types.ValaccountKey(poolId, stakerAddress)) -} +//func (k Keeper) DoesValaccountExist(ctx sdk.Context, poolId uint64, stakerAddress string) bool { +// storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) +// store := prefix.NewStore(storeAdapter, types.ValaccountPrefix) +// return store.Has(types.ValaccountKey(poolId, stakerAddress)) +//} // SetValaccount set a specific Valaccount in the store from its index func (k Keeper) SetValaccount(ctx sdk.Context, valaccount types.Valaccount) { @@ -116,24 +121,8 @@ func (k Keeper) SetValaccount(ctx sdk.Context, valaccount types.Valaccount) { ), []byte{}) } -// removeValaccount removes a Valaccount from the store -func (k Keeper) removeValaccount(ctx sdk.Context, valaccount types.Valaccount) { - storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - store := prefix.NewStore(storeAdapter, types.ValaccountPrefix) - store.Delete(types.ValaccountKey( - valaccount.PoolId, - valaccount.Staker, - )) - - storeIndex2 := prefix.NewStore(storeAdapter, types.ValaccountPrefixIndex2) - storeIndex2.Delete(types.ValaccountKeyIndex2( - valaccount.Staker, - valaccount.PoolId, - )) -} - // GetValaccount returns a Valaccount from its index -func (k Keeper) GetValaccount(ctx sdk.Context, poolId uint64, stakerAddress string) (val types.Valaccount, found bool) { +func (k Keeper) GetValaccount(ctx sdk.Context, poolId uint64, stakerAddress string) (val types.Valaccount, active bool) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) store := prefix.NewStore(storeAdapter, types.ValaccountPrefix) @@ -142,14 +131,16 @@ func (k Keeper) GetValaccount(ctx sdk.Context, poolId uint64, stakerAddress stri stakerAddress, )) if b == nil { + val.Commission = math.LegacyZeroDec() + val.StakeFraction = math.LegacyZeroDec() return val, false } k.cdc.MustUnmarshal(b, &val) - return val, true + return val, val.Valaddress != "" } -// GetAllValaccounts ... +// GetAllValaccounts returns all active valaccounts func (k Keeper) GetAllValaccounts(ctx sdk.Context) (list []types.Valaccount) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) store := prefix.NewStore(storeAdapter, types.ValaccountPrefix) @@ -160,7 +151,9 @@ func (k Keeper) GetAllValaccounts(ctx sdk.Context) (list []types.Valaccount) { for ; iterator.Valid(); iterator.Next() { var val types.Valaccount k.cdc.MustUnmarshal(iterator.Value(), &val) - list = append(list, val) + if val.Valaddress != "" { + list = append(list, val) + } } return diff --git a/x/stakers/keeper/logic_commission.go b/x/stakers/keeper/logic_commission.go index 7071ce9a..f0a6460c 100644 --- a/x/stakers/keeper/logic_commission.go +++ b/x/stakers/keeper/logic_commission.go @@ -6,13 +6,13 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// OrderNewCommissionChange inserts a new change entry into the queue. +// orderNewCommissionChange inserts a new change entry into the queue. // The queue is checked in every endBlock and when the commissionChangeTime // is over the new commission will be applied to the user. // If another entry is currently in the queue it will be removed. -func (k Keeper) OrderNewCommissionChange(ctx sdk.Context, staker string, commission math.LegacyDec) { +func (k Keeper) orderNewCommissionChange(ctx sdk.Context, staker string, poolId uint64, commission math.LegacyDec) { // Remove existing queue entry - queueEntry, found := k.GetCommissionChangeEntryByIndex2(ctx, staker) + queueEntry, found := k.GetCommissionChangeEntryByIndex2(ctx, staker, poolId) if found { k.RemoveCommissionChangeEntry(ctx, &queueEntry) } @@ -22,6 +22,7 @@ func (k Keeper) OrderNewCommissionChange(ctx sdk.Context, staker string, commiss commissionChangeEntry := types.CommissionChangeEntry{ Index: queueIndex, Staker: staker, + PoolId: poolId, Commission: commission, CreationDate: ctx.BlockTime().Unix(), } @@ -36,18 +37,26 @@ func (k Keeper) ProcessCommissionChangeQueue(ctx sdk.Context) { k.processQueue(ctx, types.QUEUE_IDENTIFIER_COMMISSION, func(index uint64) bool { // Get queue entry in question queueEntry, found := k.GetCommissionChangeEntry(ctx, index) - if !found { // continue with the next entry return true - } else if queueEntry.CreationDate+int64(k.GetCommissionChangeTime(ctx)) <= ctx.BlockTime().Unix() { + } + if queueEntry.CreationDate+int64(k.GetCommissionChangeTime(ctx)) <= ctx.BlockTime().Unix() { k.RemoveCommissionChangeEntry(ctx, &queueEntry) - // TODO no-op + valaccount, valaccountFound := k.GetValaccount(ctx, queueEntry.PoolId, queueEntry.Staker) + if !valaccountFound { + // continue with the next entry + return true + } + + valaccount.Commission = queueEntry.Commission + k.SetValaccount(ctx, valaccount) _ = ctx.EventManager().EmitTypedEvent(&types.EventUpdateCommission{ Staker: queueEntry.Staker, + PoolId: queueEntry.PoolId, Commission: queueEntry.Commission, }) diff --git a/x/stakers/keeper/logic_leave.go b/x/stakers/keeper/logic_leave.go index 108f5f60..4f9dadc0 100644 --- a/x/stakers/keeper/logic_leave.go +++ b/x/stakers/keeper/logic_leave.go @@ -32,17 +32,17 @@ func (k Keeper) ProcessLeavePoolQueue(ctx sdk.Context) { k.processQueue(ctx, types.QUEUE_IDENTIFIER_LEAVE, func(index uint64) bool { // Get queue entry in question queueEntry, found := k.GetLeavePoolEntry(ctx, index) - if !found { // continue with the next entry return true - } else if queueEntry.CreationDate+int64(k.GetLeavePoolTime(ctx)) <= ctx.BlockTime().Unix() { + } + if queueEntry.CreationDate+int64(k.GetLeavePoolTime(ctx)) <= ctx.BlockTime().Unix() { k.RemoveLeavePoolEntry(ctx, &queueEntry) k.LeavePool(ctx, queueEntry.Staker, queueEntry.PoolId) - return true } + return false }) } diff --git a/x/stakers/keeper/logic_stake_fraction.go b/x/stakers/keeper/logic_stake_fraction.go new file mode 100644 index 00000000..45cc9142 --- /dev/null +++ b/x/stakers/keeper/logic_stake_fraction.go @@ -0,0 +1,70 @@ +package keeper + +import ( + "cosmossdk.io/math" + "github.com/KYVENetwork/chain/x/stakers/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// orderNewStakeFractionChange inserts a new change entry into the queue. +// The queue is checked in every endBlock and when the stakeFractionChangeTime +// is over the new stake fraction will be applied to the user. +// If another entry is currently in the queue it will be removed. +func (k Keeper) orderNewStakeFractionChange(ctx sdk.Context, staker string, poolId uint64, stakeFraction math.LegacyDec) { + // Remove existing queue entry + queueEntry, found := k.GetStakeFractionChangeEntryByIndex2(ctx, staker, poolId) + if found { + k.RemoveStakeFractionEntry(ctx, &queueEntry) + } + + queueIndex := k.getNextQueueSlot(ctx, types.QUEUE_IDENTIFIER_STAKE_FRACTION) + + stakeFractionChangeEntry := types.StakeFractionChangeEntry{ + Index: queueIndex, + Staker: staker, + PoolId: poolId, + StakeFraction: stakeFraction, + CreationDate: ctx.BlockTime().Unix(), + } + + k.SetStakeFractionChangeEntry(ctx, stakeFractionChangeEntry) +} + +// ProcessStakeFractionChangeQueue checks the queue for entries which are due +// and can be executed. If this is the case, the new stake fraction +// will be applied to the staker and the pool +func (k Keeper) ProcessStakeFractionChangeQueue(ctx sdk.Context) { + k.processQueue(ctx, types.QUEUE_IDENTIFIER_STAKE_FRACTION, func(index uint64) bool { + // Get queue entry in question + queueEntry, found := k.GetStakeFractionChangeEntry(ctx, index) + if !found { + // continue with the next entry + return true + } + + if queueEntry.CreationDate+int64(k.GetStakeFractionChangeTime(ctx)) <= ctx.BlockTime().Unix() { + k.RemoveStakeFractionEntry(ctx, &queueEntry) + + valaccount, valaccountFound := k.GetValaccount(ctx, queueEntry.PoolId, queueEntry.Staker) + if !valaccountFound { + // continue with the next entry + return true + } + + valaccount.StakeFraction = queueEntry.StakeFraction + k.SetValaccount(ctx, valaccount) + + _ = ctx.EventManager().EmitTypedEvent(&types.EventUpdateStakeFraction{ + Staker: queueEntry.Staker, + PoolId: queueEntry.PoolId, + StakeFraction: queueEntry.StakeFraction, + }) + + // Continue with next entry + return true + } + + // Stop queue processing + return false + }) +} diff --git a/x/stakers/keeper/logic_stakers.go b/x/stakers/keeper/logic_stakers.go index 74e6d110..22009d1f 100644 --- a/x/stakers/keeper/logic_stakers.go +++ b/x/stakers/keeper/logic_stakers.go @@ -1,7 +1,9 @@ package keeper import ( - "math" + m "math" + + "cosmossdk.io/math" "github.com/KYVENetwork/chain/util" stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -18,10 +20,10 @@ import ( // If all pool slots are taken, this is the staker who then // gets kicked out. func (k Keeper) getLowestStaker(ctx sdk.Context, poolId uint64) (val stakingTypes.Validator, found bool) { - var minAmount uint64 = math.MaxUint64 + var minAmount uint64 = m.MaxUint64 for _, staker := range k.getAllStakersOfPool(ctx, poolId) { - delegationAmount := k.GetDelegationAmount(ctx, util.MustAccountAddressFromValAddress(staker.OperatorAddress)) + delegationAmount := k.GetValidatorPoolStake(ctx, util.MustAccountAddressFromValAddress(staker.OperatorAddress), poolId) if delegationAmount < minAmount { minAmount = delegationAmount val = staker @@ -39,16 +41,17 @@ func (k Keeper) getLowestStaker(ctx sdk.Context, poolId uint64) (val stakingType // than the current lowest staker in that pool. // If so, the lowest staker gets removed from the pool, so that the // new staker can join. -func (k Keeper) ensureFreeSlot(ctx sdk.Context, poolId uint64, stakerAddress string) error { +func (k Keeper) ensureFreeSlot(ctx sdk.Context, poolId uint64, stakerAddress string, stakeFraction math.LegacyDec) error { // check if slots are still available if k.GetStakerCountOfPool(ctx, poolId) >= types.MaxStakers { // if not - get lowest staker lowestStaker, _ := k.getLowestStaker(ctx, poolId) lowestStakerAddress := util.MustAccountAddressFromValAddress(lowestStaker.OperatorAddress) - // if new pool joiner has more stake than lowest staker kick him out - newAmount := k.GetDelegationAmount(ctx, stakerAddress) - lowestAmount := k.GetDelegationAmount(ctx, lowestStakerAddress) + // if new pool joiner would have more stake than lowest staker kick him out + newStaker, _ := k.GetValidator(ctx, stakerAddress) + newAmount := uint64(math.LegacyNewDecFromInt(newStaker.GetBondedTokens()).Mul(stakeFraction).TruncateInt64()) + lowestAmount := k.GetValidatorPoolStake(ctx, lowestStakerAddress, poolId) if newAmount > lowestAmount { // remove lowest staker from pool k.LeavePool(ctx, lowestStakerAddress, poolId) diff --git a/x/stakers/keeper/msg_server_join_pool.go b/x/stakers/keeper/msg_server_join_pool.go index 25c9a320..c745550d 100644 --- a/x/stakers/keeper/msg_server_join_pool.go +++ b/x/stakers/keeper/msg_server_join_pool.go @@ -54,7 +54,7 @@ func (k msgServer) JoinPool(goCtx context.Context, msg *types.MsgJoinPool) (*typ } // Only join if it is possible - if errFreeSlot := k.ensureFreeSlot(ctx, msg.PoolId, msg.Creator); errFreeSlot != nil { + if errFreeSlot := k.ensureFreeSlot(ctx, msg.PoolId, msg.Creator, msg.StakeFraction); errFreeSlot != nil { return nil, errFreeSlot } @@ -76,17 +76,21 @@ func (k msgServer) JoinPool(goCtx context.Context, msg *types.MsgJoinPool) (*typ } } - k.AddValaccountToPool(ctx, msg.PoolId, msg.Creator, msg.Valaddress) + // TODO: check here if validator with his stake fraction is over the maximum join limit + + k.AddValaccountToPool(ctx, msg.PoolId, msg.Creator, msg.Valaddress, msg.Commission, msg.StakeFraction) if err := util.TransferFromAddressToAddress(k.bankKeeper, ctx, msg.Creator, msg.Valaddress, msg.Amount); err != nil { return nil, err } _ = ctx.EventManager().EmitTypedEvent(&types.EventJoinPool{ - PoolId: msg.PoolId, - Staker: msg.Creator, - Valaddress: msg.Valaddress, - Amount: msg.Amount, + PoolId: msg.PoolId, + Staker: msg.Creator, + Valaddress: msg.Valaddress, + Amount: msg.Amount, + Commission: msg.Commission, + StakeFraction: msg.StakeFraction, }) return &types.MsgJoinPoolResponse{}, nil diff --git a/x/stakers/keeper/msg_server_join_pool_test.go b/x/stakers/keeper/msg_server_join_pool_test.go index 1d3e6000..85d7f519 100644 --- a/x/stakers/keeper/msg_server_join_pool_test.go +++ b/x/stakers/keeper/msg_server_join_pool_test.go @@ -32,6 +32,9 @@ TEST CASES - msg_server_join_pool.go * Try to join another pool with the same valaddress again * Try to join another pool with a valaddress that is already used by another staker * Try to join another pool with a different valaddress +* Try to join pool with empty valaddress +* Try to join pool with empty commission +* Try to join pool with empty stake fraction * Join a pool with a valaddress which does not exist on chain yet * Join a pool with a valaddress which does not exist on chain yet and send 0 funds * Join a pool with an invalid valaddress @@ -40,6 +43,8 @@ TEST CASES - msg_server_join_pool.go * Fail to kick out lowest staker because not enough stake * Kick out lowest staker with respect to stake + delegation * Fail to kick out lowest staker because not enough stake + delegation +* Join pool again with same valaddress after staker has left pool +* Join pool again with different valaddress after staker has left pool */ @@ -48,6 +53,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { initialBalanceStaker0 := uint64(0) initialBalanceValaddress0 := uint64(0) + initialBalanceValaddress1 := uint64(0) gov := s.App().GovKeeper.GetGovernanceAccount(s.Ctx()).GetAddress().String() @@ -69,6 +75,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) + initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_0_B) }) AfterEach(func() { @@ -84,10 +91,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { It("Join the first pool as the first staker to a newly created pool", func() { // ACT s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -101,9 +110,9 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(1)) - valaccount, found := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(found).To(BeTrue()) + Expect(active).To(BeTrue()) Expect(valaccount.Staker).To(Equal(i.STAKER_0)) Expect(valaccount.PoolId).To(BeZero()) @@ -118,7 +127,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(totalStakeOfPool)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(totalStakeOfPool)) }) @@ -140,10 +149,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { // ACT _, err := s.RunTx(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) Expect(err.Error()).To(Equal("can not join disabled pool: internal logic error")) @@ -159,9 +170,9 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(0)) - _, found := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) + _, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) - Expect(found).To(BeFalse()) + Expect(active).To(BeFalse()) valaccountsOfPool := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 1) @@ -170,7 +181,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1) Expect(totalStakeOfPool).To(Equal(0 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 1)).To(Equal(0 * i.KYVE)) Expect(s.App().StakersKeeper.GetActiveStakers(s.Ctx())).To(HaveLen(0)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100 * i.KYVE)) }) @@ -180,18 +191,22 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0 * i.KYVE, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 0 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 0 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -205,9 +220,9 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(1)) - valaccount, found := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(found).To(BeTrue()) + Expect(active).To(BeTrue()) Expect(valaccount.Staker).To(Equal(i.STAKER_0)) Expect(valaccount.PoolId).To(BeZero()) @@ -222,17 +237,19 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(200 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100 * i.KYVE)) }) It("Self-Delegate more KYVE after joining a pool", func() { // ARRANGE s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) @@ -250,9 +267,9 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(1)) - valaccount, found := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(found).To(BeTrue()) + Expect(active).To(BeTrue()) Expect(valaccount.Staker).To(Equal(i.STAKER_0)) Expect(valaccount.PoolId).To(BeZero()) @@ -268,25 +285,29 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(totalStakeOfPool).To(Equal(150 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(totalStakeOfPool)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(totalStakeOfPool)) }) It("Try to join the same pool with the same valaddress again", func() { // ARRANGE s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -298,10 +319,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { It("join a pool with the same valaddress as the staker address", func() { // ACT s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.STAKER_0, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.STAKER_0, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -313,18 +336,22 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { It("Try to join the same pool with a different valaddress", func() { // ARRANGE s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -336,10 +363,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { It("Try to join another pool with the same valaddress again", func() { // ARRANGE s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) msg := &pooltypes.MsgCreatePool{ @@ -353,10 +382,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { // ACT s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -378,18 +409,22 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 1, - Valaddress: i.VALADDRESS_1_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_1, + PoolId: 1, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -400,20 +435,24 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { It("Try to join pool with a valaddress that is already used by another staker", func() { // ARRANGE s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) // ACT s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -424,10 +463,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { It("Try to join another pool with a different valaddress", func() { // ARRANGE s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) msg := &pooltypes.MsgCreatePool{ @@ -441,9 +482,11 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { // ACT s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -451,13 +494,61 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(2)) }) - It("Join a pool with a valaddress which does not exist on chain yet", func() { + It("Try to join pool with empty valaddress", func() { // ACT - s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + s.RunTxStakersError(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: "", + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ASSERT + valaccountsOfStaker := s.App().StakersKeeper.GetValaccountsFromStaker(s.Ctx(), i.STAKER_0) + Expect(valaccountsOfStaker).To(BeEmpty()) + }) + + It("Try to join pool with empty commission", func() { + // ACT + s.RunTxStakersError(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ASSERT + valaccountsOfStaker := s.App().StakersKeeper.GetValaccountsFromStaker(s.Ctx(), i.STAKER_0) + Expect(valaccountsOfStaker).To(BeEmpty()) + }) + + It("Try to join pool with empty stake fraction", func() { + // ACT + s.RunTxStakersError(&stakerstypes.MsgJoinPool{ Creator: i.STAKER_0, PoolId: 0, - Valaddress: "kyve1dx0nvx7y9d44jvr2dr6r2p636jea3f9827rn0x", + Valaddress: i.VALADDRESS_0_A, Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + }) + + // ASSERT + valaccountsOfStaker := s.App().StakersKeeper.GetValaccountsFromStaker(s.Ctx(), i.STAKER_0) + Expect(valaccountsOfStaker).To(BeEmpty()) + }) + + It("Join a pool with a valaddress which does not exist on chain yet", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: "kyve1dx0nvx7y9d44jvr2dr6r2p636jea3f9827rn0x", + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -471,9 +562,9 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(1)) - valaccount, found := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(found).To(BeTrue()) + Expect(active).To(BeTrue()) Expect(valaccount.Staker).To(Equal(i.STAKER_0)) Expect(valaccount.PoolId).To(BeZero()) @@ -488,17 +579,19 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(totalStakeOfPool)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(totalStakeOfPool)) }) It("Join a pool with a valaddress which does not exist on chain yet and send 0 funds", func() { // ACT s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: "kyve1dx0nvx7y9d44jvr2dr6r2p636jea3f9827rn0x", - Amount: 0 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: "kyve1dx0nvx7y9d44jvr2dr6r2p636jea3f9827rn0x", + Amount: 0 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -512,9 +605,9 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(1)) - valaccount, found := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(found).To(BeTrue()) + Expect(active).To(BeTrue()) Expect(valaccount.Staker).To(Equal(i.STAKER_0)) Expect(valaccount.PoolId).To(BeZero()) @@ -529,17 +622,19 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(totalStakeOfPool)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(totalStakeOfPool)) }) It("Join a pool with an invalid valaddress", func() { // ACT s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: "invalid_valaddress", - Amount: 100 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: "invalid_valaddress", + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -551,10 +646,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { It("Join a pool and fund the valaddress with more KYVE than available in balance", func() { // ACT s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: "invalid_valaddress", - Amount: initialBalanceStaker0 + 1, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: "invalid_valaddress", + Amount: initialBalanceStaker0 + 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -568,19 +665,23 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(stakerstypes.MaxStakers).To(Equal(50)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 1, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) for k := 0; k < 49; k++ { s.CreateValidator(i.DUMMY[k], fmt.Sprintf("dummy-%d", k), int64(150*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.DUMMY[k], - PoolId: 0, - Valaddress: i.VALDUMMY[k], - Amount: 1, + Creator: i.DUMMY[k], + PoolId: 0, + Valaddress: i.VALDUMMY[k], + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) } @@ -591,10 +692,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { // Act s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 1, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // Assert @@ -607,19 +710,23 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(stakerstypes.MaxStakers).To(Equal(50)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 1, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) for k := 0; k < 49; k++ { s.CreateValidator(i.DUMMY[k], fmt.Sprintf("dummy-%d", k), int64(150*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.DUMMY[k], - PoolId: 0, - Valaddress: i.VALDUMMY[k], - Amount: 1, + Creator: i.DUMMY[k], + PoolId: 0, + Valaddress: i.VALDUMMY[k], + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) } @@ -630,10 +737,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { // Act s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 1, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // Assert @@ -647,19 +756,23 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(stakerstypes.MaxStakers).To(Equal(50)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 1 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 1 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) for k := 0; k < 49; k++ { s.CreateValidator(i.DUMMY[k], fmt.Sprintf("dummy-%d", k), int64(150*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.DUMMY[k], - PoolId: 0, - Valaddress: i.VALDUMMY[k], - Amount: 1 * i.KYVE, + Creator: i.DUMMY[k], + PoolId: 0, + Valaddress: i.VALDUMMY[k], + Amount: 1 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) } @@ -676,10 +789,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { // ACT s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 1, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -693,19 +808,23 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(stakerstypes.MaxStakers).To(Equal(50)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 1, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) for k := 0; k < 49; k++ { s.CreateValidator(i.DUMMY[k], fmt.Sprintf("dummy-%d", k), int64(150*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.DUMMY[k], - PoolId: 0, - Valaddress: i.VALDUMMY[k], - Amount: 1, + Creator: i.DUMMY[k], + PoolId: 0, + Valaddress: i.VALDUMMY[k], + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) } @@ -716,10 +835,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { // Act s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 1, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 1, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // Assert @@ -733,19 +854,23 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(stakerstypes.MaxStakers).To(Equal(50)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, - Amount: 1 * i.KYVE, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 1 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) for k := 0; k < 49; k++ { s.CreateValidator(i.DUMMY[k], fmt.Sprintf("dummy-%d", k), int64(150*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.DUMMY[k], - PoolId: 0, - Valaddress: i.VALDUMMY[k], - Amount: 1 * i.KYVE, + Creator: i.DUMMY[k], + PoolId: 0, + Valaddress: i.VALDUMMY[k], + Amount: 1 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) } @@ -762,10 +887,12 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { // ACT s.RunTxStakersError(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 0, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ASSERT @@ -773,4 +900,142 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).To(ContainElement(i.STAKER_0)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).NotTo(ContainElement(i.STAKER_1)) }) + + It("Join pool again with same valaddress after staker has left pool", func() { + // ARRANGE + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.RunTxStakersSuccess(&stakerstypes.MsgLeavePool{ + Creator: i.STAKER_0, + PoolId: 0, + }) + + // wait for leave pool + s.CommitAfterSeconds(s.App().StakersKeeper.GetLeavePoolTime(s.Ctx())) + s.CommitAfterSeconds(1) + + _, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(active).To(BeFalse()) + + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 50 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.2"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ASSERT + balanceAfterStaker0 := s.GetBalanceFromAddress(i.STAKER_0) + balanceAfterValaddress0 := s.GetBalanceFromAddress(i.VALADDRESS_0_A) + + Expect(initialBalanceStaker0 - balanceAfterStaker0).To(Equal(150 * i.KYVE)) + Expect(balanceAfterValaddress0 - initialBalanceValaddress0).To(Equal(150 * i.KYVE)) + + valaccountsOfStaker := s.App().StakersKeeper.GetValaccountsFromStaker(s.Ctx(), i.STAKER_0) + + Expect(valaccountsOfStaker).To(HaveLen(1)) + + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + + Expect(active).To(BeTrue()) + + Expect(valaccount.Staker).To(Equal(i.STAKER_0)) + Expect(valaccount.PoolId).To(BeZero()) + Expect(valaccount.Valaddress).To(Equal(i.VALADDRESS_0_A)) + Expect(valaccount.Points).To(BeZero()) + Expect(valaccount.IsLeaving).To(BeFalse()) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.2"))) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) + + valaccountsOfPool := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) + + Expect(valaccountsOfPool).To(HaveLen(1)) + + totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + + Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) + + Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(totalStakeOfPool)) + }) + + It("Join pool again with different valaddress after staker has left pool", func() { + // ARRANGE + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.RunTxStakersSuccess(&stakerstypes.MsgLeavePool{ + Creator: i.STAKER_0, + PoolId: 0, + }) + + // wait for leave pool + s.CommitAfterSeconds(s.App().StakersKeeper.GetLeavePoolTime(s.Ctx())) + s.CommitAfterSeconds(1) + + _, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(active).To(BeFalse()) + + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_B, + Amount: 50 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.2"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ASSERT + balanceAfterStaker0 := s.GetBalanceFromAddress(i.STAKER_0) + balanceAfterValaddress0 := s.GetBalanceFromAddress(i.VALADDRESS_0_A) + balanceAfterValaddress1 := s.GetBalanceFromAddress(i.VALADDRESS_0_B) + + Expect(initialBalanceStaker0 - balanceAfterStaker0).To(Equal(150 * i.KYVE)) + Expect(balanceAfterValaddress0 - initialBalanceValaddress0).To(Equal(100 * i.KYVE)) + Expect(balanceAfterValaddress1 - initialBalanceValaddress1).To(Equal(50 * i.KYVE)) + + valaccountsOfStaker := s.App().StakersKeeper.GetValaccountsFromStaker(s.Ctx(), i.STAKER_0) + + Expect(valaccountsOfStaker).To(HaveLen(1)) + + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + + Expect(active).To(BeTrue()) + + Expect(valaccount.Staker).To(Equal(i.STAKER_0)) + Expect(valaccount.PoolId).To(BeZero()) + Expect(valaccount.Valaddress).To(Equal(i.VALADDRESS_0_B)) + Expect(valaccount.Points).To(BeZero()) + Expect(valaccount.IsLeaving).To(BeFalse()) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.2"))) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) + + valaccountsOfPool := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) + + Expect(valaccountsOfPool).To(HaveLen(1)) + + totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + + Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) + + Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(totalStakeOfPool)) + }) }) diff --git a/x/stakers/keeper/msg_server_leave_pool.go b/x/stakers/keeper/msg_server_leave_pool.go index bee131ad..75627d3c 100644 --- a/x/stakers/keeper/msg_server_leave_pool.go +++ b/x/stakers/keeper/msg_server_leave_pool.go @@ -16,8 +16,8 @@ import ( func (k msgServer) LeavePool(goCtx context.Context, msg *types.MsgLeavePool) (*types.MsgLeavePoolResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - valaccount, valaccountFound := k.GetValaccount(ctx, msg.PoolId, msg.Creator) - if !valaccountFound { + valaccount, active := k.GetValaccount(ctx, msg.PoolId, msg.Creator) + if !active { return nil, errors.Wrapf(errorsTypes.ErrInvalidRequest, types.ErrAlreadyLeftPool.Error()) } diff --git a/x/stakers/keeper/msg_server_leave_pool_test.go b/x/stakers/keeper/msg_server_leave_pool_test.go index 05f76838..80e5bfad 100644 --- a/x/stakers/keeper/msg_server_leave_pool_test.go +++ b/x/stakers/keeper/msg_server_leave_pool_test.go @@ -45,9 +45,11 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { // join pool s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 0, - Valaddress: i.VALADDRESS_0_A, + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) }) @@ -68,15 +70,17 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(1)) - valaccount, found := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(found).To(BeTrue()) + Expect(active).To(BeTrue()) Expect(valaccount.Staker).To(Equal(i.STAKER_0)) Expect(valaccount.PoolId).To(BeZero()) Expect(valaccount.Valaddress).To(Equal(i.VALADDRESS_0_A)) Expect(valaccount.Points).To(BeZero()) Expect(valaccount.IsLeaving).To(BeTrue()) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) valaccountsOfPool := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) @@ -85,7 +89,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(totalStakeOfPool)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(totalStakeOfPool)) s.PerformValidityChecks() @@ -98,9 +102,9 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(BeEmpty()) - _, found = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + valaccount, active = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(found).To(BeFalse()) + Expect(active).To(BeFalse()) valaccountsOfPool = s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) @@ -108,6 +112,10 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { totalStakeOfPool = s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(BeZero()) + + // check if commission and stake fraction is still available + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) }) It("Leave a pool multiple other stakers have joined previously", func() { @@ -115,10 +123,12 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_1, - PoolId: 0, - Valaddress: i.VALADDRESS_1_A, - Amount: 100 * i.KYVE, + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) // ACT @@ -133,15 +143,17 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(1)) - valaccount, found := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(found).To(BeTrue()) + Expect(active).To(BeTrue()) Expect(valaccount.Staker).To(Equal(i.STAKER_0)) Expect(valaccount.PoolId).To(BeZero()) Expect(valaccount.Valaddress).To(Equal(i.VALADDRESS_0_A)) Expect(valaccount.Points).To(BeZero()) Expect(valaccount.IsLeaving).To(BeTrue()) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) valaccountsOfPool := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) @@ -150,7 +162,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(200 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100 * i.KYVE)) s.PerformValidityChecks() @@ -163,9 +175,9 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(BeEmpty()) - _, found = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + valaccount, active = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(found).To(BeFalse()) + Expect(active).To(BeFalse()) valaccountsOfPool = s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 0) @@ -173,6 +185,10 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { totalStakeOfPool = s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) + + // check if commission and stake fraction is still available + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) }) It("Try to leave a pool again", func() { @@ -213,9 +229,11 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { s.RunTxPoolSuccess(msg) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ - Creator: i.STAKER_0, - PoolId: 1, - Valaddress: i.VALADDRESS_1_A, + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), }) s.PerformValidityChecks() @@ -230,15 +248,17 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(2)) - valaccount, found := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) - Expect(found).To(BeTrue()) + Expect(active).To(BeTrue()) Expect(valaccount.Staker).To(Equal(i.STAKER_0)) Expect(valaccount.PoolId).To(Equal(uint64(1))) Expect(valaccount.Valaddress).To(Equal(i.VALADDRESS_1_A)) Expect(valaccount.Points).To(BeZero()) Expect(valaccount.IsLeaving).To(BeTrue()) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) valaccountsOfPool := s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 1) @@ -247,7 +267,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationAmount(s.Ctx(), i.STAKER_0)).To(Equal(totalStakeOfPool)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(totalStakeOfPool)) // wait for leave pool @@ -258,9 +278,9 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfStaker).To(HaveLen(1)) - _, found = s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) + valaccount, active = s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) - Expect(found).To(BeFalse()) + Expect(active).To(BeFalse()) valaccountsOfPool = s.App().StakersKeeper.GetAllValaccountsOfPool(s.Ctx(), 1) @@ -268,6 +288,10 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { totalStakeOfPool = s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1) Expect(totalStakeOfPool).To(BeZero()) + + // check if commission and stake fraction is still available + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) }) It("Leave a pool a staker has never joined", func() { @@ -290,5 +314,13 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { valaccountsOfStaker = s.App().StakersKeeper.GetValaccountsFromStaker(s.Ctx(), i.STAKER_1) Expect(valaccountsOfStaker).To(BeEmpty()) + + valaccount, active := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) + + Expect(active).To(BeFalse()) + + // check if commission and stake fraction is still available + Expect(valaccount.Commission).To(Equal(math.LegacyZeroDec())) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyZeroDec())) }) }) diff --git a/x/stakers/keeper/msg_server_update_commission.go b/x/stakers/keeper/msg_server_update_commission.go index e303078d..7b84fd63 100644 --- a/x/stakers/keeper/msg_server_update_commission.go +++ b/x/stakers/keeper/msg_server_update_commission.go @@ -3,6 +3,10 @@ package keeper import ( "context" + sdk "github.com/cosmos/cosmos-sdk/types" + errorsTypes "github.com/cosmos/cosmos-sdk/types/errors" + + "cosmossdk.io/errors" "github.com/KYVENetwork/chain/x/stakers/types" ) @@ -11,7 +15,15 @@ import ( // If an update is currently in the queue it will get removed from the queue // and the user needs to wait again for the full time to pass. func (k msgServer) UpdateCommission(goCtx context.Context, msg *types.MsgUpdateCommission) (*types.MsgUpdateCommissionResponse, error) { - // TODO no-op, will be replaced by a per pool commission + ctx := sdk.UnwrapSDKContext(goCtx) + + // Check if creator is active in the pool + if _, active := k.GetValaccount(ctx, msg.PoolId, msg.Creator); !active { + return nil, errors.Wrap(errorsTypes.ErrUnauthorized, types.ErrNoStaker.Error()) + } + + // Insert commission change into queue + k.orderNewCommissionChange(ctx, msg.Creator, msg.PoolId, msg.Commission) return &types.MsgUpdateCommissionResponse{}, nil } diff --git a/x/stakers/keeper/msg_server_update_commission_test.go b/x/stakers/keeper/msg_server_update_commission_test.go new file mode 100644 index 00000000..89dac8e5 --- /dev/null +++ b/x/stakers/keeper/msg_server_update_commission_test.go @@ -0,0 +1,281 @@ +package keeper_test + +import ( + "cosmossdk.io/math" + pooltypes "github.com/KYVENetwork/chain/x/pool/types" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + i "github.com/KYVENetwork/chain/testutil/integration" + stakerstypes "github.com/KYVENetwork/chain/x/stakers/types" +) + +/* + +TEST CASES - msg_server_update_commission.go + +* Check if initial commission is correct +* Update commission to 50% from previous commission +* Update commission to 0% from previous commission +* Update commission to 100% from previous commission +* Update commission with a negative number from previous commission +* Update commission with a too high number from previous commission +* Update commission multiple times during the commission change time +* Update commission multiple times during the commission change time with the same value +* Update commission with multiple pools + +*/ + +var _ = Describe("msg_server_update_commission.go", Ordered, func() { + s := i.NewCleanChain() + + gov := s.App().GovKeeper.GetGovernanceAccount(s.Ctx()).GetAddress().String() + + BeforeEach(func() { + // init new clean chain + s = i.NewCleanChain() + + // create pool + msg := &pooltypes.MsgCreatePool{ + Authority: gov, + UploadInterval: 60, + MaxBundleSize: 100, + InflationShareWeight: math.LegacyZeroDec(), + Binaries: "{}", + } + s.RunTxPoolSuccess(msg) + + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + }) + + AfterEach(func() { + s.PerformValidityChecks() + }) + + It("Get the default commission from a newly joined pool", func() { + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + }) + + It("Update commission to 50% from previous commission", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyMustNewDecFromStr("0.5"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) + }) + + It("Update commission to 0% from previous commission", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyZeroDec(), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyZeroDec())) + }) + + It("Update commission to 100% from previous commission", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyOneDec(), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyOneDec())) + }) + + It("Update commission with a negative number from previous commission", func() { + // ACT + s.RunTxStakersError(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyMustNewDecFromStr("-0.5"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + }) + + It("Update commission with a too high number from previous commission", func() { + // ACT + s.RunTxStakersError(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyNewDec(2), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + }) + + It("Update commission multiple times during the commission change time", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyMustNewDecFromStr("0.5"), + }) + s.PerformValidityChecks() + + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyMustNewDecFromStr("0.2"), + }) + s.PerformValidityChecks() + + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyMustNewDecFromStr("0.3"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.3"))) + }) + + It("Update commission multiple times during the commission change time with the same value", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyMustNewDecFromStr("0.5"), + }) + + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyMustNewDecFromStr("0.2"), + }) + + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyMustNewDecFromStr("0.1"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + }) + + It("Update commission with multiple pools", func() { + // ARRANGE + msg := &pooltypes.MsgCreatePool{ + Authority: gov, + UploadInterval: 60, + MaxBundleSize: 100, + InflationShareWeight: math.LegacyZeroDec(), + Binaries: "{}", + } + s.RunTxPoolSuccess(msg) + + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_0_B, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 0, + Commission: math.LegacyMustNewDecFromStr("0.5"), + }) + + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateCommission{ + Creator: i.STAKER_0, + PoolId: 1, + Commission: math.LegacyMustNewDecFromStr("0.5"), + }) + + s.PerformValidityChecks() + + // ASSERT + valaccount0, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount0.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + + valaccount1, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) + Expect(valaccount1.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount0, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount0.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) + + valaccount1, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) + Expect(valaccount1.Commission).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) + }) +}) diff --git a/x/stakers/keeper/msg_server_update_params_test.go b/x/stakers/keeper/msg_server_update_params_test.go index a0914713..89b47d11 100644 --- a/x/stakers/keeper/msg_server_update_params_test.go +++ b/x/stakers/keeper/msg_server_update_params_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "cosmossdk.io/math" i "github.com/KYVENetwork/chain/testutil/integration" sdk "github.com/cosmos/cosmos-sdk/types" @@ -33,6 +34,18 @@ TEST CASES - msg_server_update_params.go * Update leave pool time * Update leave pool time with invalid value +* Update stake fraction change time +* Update stake fraction change time with invalid value + +* Update vote slash +* Update vote slash with invalid value + +* Update upload slash +* Update upload slash with invalid value + +* Update timeout slash +* Update timeout slash with invalid value + */ var _ = Describe("msg_server_update_params.go", Ordered, func() { @@ -234,6 +247,7 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { Expect(updatedParams.CommissionChangeTime).To(Equal(uint64(5))) Expect(updatedParams.LeavePoolTime).To(Equal(types.DefaultLeavePoolTime)) + Expect(updatedParams.StakeFractionChangeTime).To(Equal(types.DefaultStakeFractionChangeTime)) }) It("Update commission change time with invalid value", func() { @@ -264,6 +278,7 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { Expect(updatedParams.CommissionChangeTime).To(Equal(types.DefaultCommissionChangeTime)) Expect(updatedParams.LeavePoolTime).To(Equal(types.DefaultLeavePoolTime)) + Expect(updatedParams.StakeFractionChangeTime).To(Equal(types.DefaultStakeFractionChangeTime)) }) It("Update leave pool time", func() { @@ -300,6 +315,7 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { Expect(updatedParams.CommissionChangeTime).To(Equal(types.DefaultCommissionChangeTime)) Expect(updatedParams.LeavePoolTime).To(Equal(uint64(5))) + Expect(updatedParams.StakeFractionChangeTime).To(Equal(types.DefaultStakeFractionChangeTime)) }) It("Update leave pool time with invalid value", func() { @@ -330,5 +346,278 @@ var _ = Describe("msg_server_update_params.go", Ordered, func() { Expect(updatedParams.CommissionChangeTime).To(Equal(types.DefaultCommissionChangeTime)) Expect(updatedParams.LeavePoolTime).To(Equal(types.DefaultLeavePoolTime)) + Expect(updatedParams.StakeFractionChangeTime).To(Equal(types.DefaultStakeFractionChangeTime)) + }) + + It("Update stake fraction change time", func() { + // ARRANGE + payload := `{ + "stake_fraction_change_time": 5 + }` + + msg := &types.MsgUpdateParams{ + Authority: gov, + Payload: payload, + } + + proposal, _ := govV1Types.NewMsgSubmitProposal( + []sdk.Msg{msg}, minDeposit, i.DUMMY[0], "", "title", "summary", false, + ) + + vote := govV1Types.NewMsgVote( + voter, 1, govV1Types.VoteOption_VOTE_OPTION_YES, "", + ) + + // ACT + _, submitErr := s.RunTx(proposal) + _, voteErr := s.RunTx(vote) + + s.CommitAfter(*votingPeriod) + s.Commit() + + // ASSERT + updatedParams := s.App().StakersKeeper.GetParams(s.Ctx()) + + Expect(submitErr).NotTo(HaveOccurred()) + Expect(voteErr).NotTo(HaveOccurred()) + + Expect(updatedParams.CommissionChangeTime).To(Equal(types.DefaultCommissionChangeTime)) + Expect(updatedParams.LeavePoolTime).To(Equal(types.DefaultLeavePoolTime)) + Expect(updatedParams.StakeFractionChangeTime).To(Equal(uint64(5))) + }) + + It("Update stake fraction change time with invalid value", func() { + // ARRANGE + payload := `{ + "stake_fraction_change_time": "5" + }` + + msg := &types.MsgUpdateParams{ + Authority: gov, + Payload: payload, + } + + proposal, _ := govV1Types.NewMsgSubmitProposal( + []sdk.Msg{msg}, minDeposit, i.DUMMY[0], "", "title", "summary", false, + ) + + // ACT + _, submitErr := s.RunTx(proposal) + + s.CommitAfter(*votingPeriod) + s.Commit() + + // ASSERT + updatedParams := s.App().StakersKeeper.GetParams(s.Ctx()) + + Expect(submitErr).To(HaveOccurred()) + + Expect(updatedParams.CommissionChangeTime).To(Equal(types.DefaultCommissionChangeTime)) + Expect(updatedParams.LeavePoolTime).To(Equal(types.DefaultLeavePoolTime)) + Expect(updatedParams.StakeFractionChangeTime).To(Equal(types.DefaultStakeFractionChangeTime)) + }) + + It("Update vote slash", func() { + // ARRANGE + payload := `{ + "vote_slash": "0.05" + }` + + msg := &types.MsgUpdateParams{ + Authority: gov, + Payload: payload, + } + + proposal, _ := govV1Types.NewMsgSubmitProposal( + []sdk.Msg{msg}, minDeposit, i.DUMMY[0], "", "title", "summary", false, + ) + + vote := govV1Types.NewMsgVote( + voter, 1, govV1Types.VoteOption_VOTE_OPTION_YES, "", + ) + + // ACT + _, submitErr := s.RunTx(proposal) + _, voteErr := s.RunTx(vote) + + s.CommitAfter(*votingPeriod) + s.Commit() + + // ASSERT + updatedParams := s.App().StakersKeeper.GetParams(s.Ctx()) + + Expect(submitErr).NotTo(HaveOccurred()) + Expect(voteErr).NotTo(HaveOccurred()) + + Expect(updatedParams.UploadSlash).To(Equal(types.DefaultUploadSlash)) + Expect(updatedParams.TimeoutSlash).To(Equal(types.DefaultTimeoutSlash)) + Expect(updatedParams.VoteSlash).To(Equal(math.LegacyMustNewDecFromStr("0.05"))) + }) + + It("Update vote slash with invalid value", func() { + // ARRANGE + payload := `{ + "vote_slash": "invalid" + }` + + msg := &types.MsgUpdateParams{ + Authority: gov, + Payload: payload, + } + + proposal, _ := govV1Types.NewMsgSubmitProposal( + []sdk.Msg{msg}, minDeposit, i.DUMMY[0], "", "title", "summary", false, + ) + + // ACT + _, submitErr := s.RunTx(proposal) + + s.CommitAfter(*votingPeriod) + s.Commit() + + // ASSERT + updatedParams := s.App().StakersKeeper.GetParams(s.Ctx()) + + Expect(submitErr).To(HaveOccurred()) + + Expect(updatedParams.UploadSlash).To(Equal(types.DefaultUploadSlash)) + Expect(updatedParams.TimeoutSlash).To(Equal(types.DefaultTimeoutSlash)) + Expect(updatedParams.VoteSlash).To(Equal(types.DefaultVoteSlash)) + }) + + It("Update upload slash", func() { + // ARRANGE + payload := `{ + "upload_slash": "0.05" + }` + + msg := &types.MsgUpdateParams{ + Authority: gov, + Payload: payload, + } + + proposal, _ := govV1Types.NewMsgSubmitProposal( + []sdk.Msg{msg}, minDeposit, i.DUMMY[0], "", "title", "summary", false, + ) + + vote := govV1Types.NewMsgVote( + voter, 1, govV1Types.VoteOption_VOTE_OPTION_YES, "", + ) + + // ACT + _, submitErr := s.RunTx(proposal) + _, voteErr := s.RunTx(vote) + + s.CommitAfter(*votingPeriod) + s.Commit() + + // ASSERT + updatedParams := s.App().StakersKeeper.GetParams(s.Ctx()) + + Expect(submitErr).NotTo(HaveOccurred()) + Expect(voteErr).NotTo(HaveOccurred()) + + Expect(updatedParams.UploadSlash).To(Equal(math.LegacyMustNewDecFromStr("0.05"))) + Expect(updatedParams.TimeoutSlash).To(Equal(types.DefaultTimeoutSlash)) + Expect(updatedParams.VoteSlash).To(Equal(types.DefaultVoteSlash)) + }) + + It("Update upload slash with invalid value", func() { + // ARRANGE + payload := `{ + "upload_slash": "1.5" + }` + + msg := &types.MsgUpdateParams{ + Authority: gov, + Payload: payload, + } + + proposal, _ := govV1Types.NewMsgSubmitProposal( + []sdk.Msg{msg}, minDeposit, i.DUMMY[0], "", "title", "summary", false, + ) + + // ACT + _, submitErr := s.RunTx(proposal) + + s.CommitAfter(*votingPeriod) + s.Commit() + + // ASSERT + updatedParams := s.App().StakersKeeper.GetParams(s.Ctx()) + + Expect(submitErr).To(HaveOccurred()) + + Expect(updatedParams.UploadSlash).To(Equal(types.DefaultUploadSlash)) + Expect(updatedParams.TimeoutSlash).To(Equal(types.DefaultTimeoutSlash)) + Expect(updatedParams.VoteSlash).To(Equal(types.DefaultVoteSlash)) + }) + + It("Update timeout slash", func() { + // ARRANGE + payload := `{ + "timeout_slash": "0.05" + }` + + msg := &types.MsgUpdateParams{ + Authority: gov, + Payload: payload, + } + + proposal, _ := govV1Types.NewMsgSubmitProposal( + []sdk.Msg{msg}, minDeposit, i.DUMMY[0], "", "title", "summary", false, + ) + + vote := govV1Types.NewMsgVote( + voter, 1, govV1Types.VoteOption_VOTE_OPTION_YES, "", + ) + + // ACT + _, submitErr := s.RunTx(proposal) + _, voteErr := s.RunTx(vote) + + s.CommitAfter(*votingPeriod) + s.Commit() + + // ASSERT + updatedParams := s.App().StakersKeeper.GetParams(s.Ctx()) + + Expect(submitErr).NotTo(HaveOccurred()) + Expect(voteErr).NotTo(HaveOccurred()) + + Expect(updatedParams.UploadSlash).To(Equal(types.DefaultUploadSlash)) + Expect(updatedParams.TimeoutSlash).To(Equal(math.LegacyMustNewDecFromStr("0.05"))) + Expect(updatedParams.VoteSlash).To(Equal(types.DefaultVoteSlash)) + }) + + It("Update timeout slash with invalid value", func() { + // ARRANGE + payload := `{ + "upload_slash": "-0.5" + }` + + msg := &types.MsgUpdateParams{ + Authority: gov, + Payload: payload, + } + + proposal, _ := govV1Types.NewMsgSubmitProposal( + []sdk.Msg{msg}, minDeposit, i.DUMMY[0], "", "title", "summary", false, + ) + + // ACT + _, submitErr := s.RunTx(proposal) + + s.CommitAfter(*votingPeriod) + s.Commit() + + // ASSERT + updatedParams := s.App().StakersKeeper.GetParams(s.Ctx()) + + Expect(submitErr).To(HaveOccurred()) + + Expect(updatedParams.UploadSlash).To(Equal(types.DefaultUploadSlash)) + Expect(updatedParams.TimeoutSlash).To(Equal(types.DefaultTimeoutSlash)) + Expect(updatedParams.VoteSlash).To(Equal(types.DefaultVoteSlash)) }) }) diff --git a/x/stakers/keeper/msg_server_update_stake_fraction.go b/x/stakers/keeper/msg_server_update_stake_fraction.go new file mode 100644 index 00000000..8c10db46 --- /dev/null +++ b/x/stakers/keeper/msg_server_update_stake_fraction.go @@ -0,0 +1,51 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + errorsTypes "github.com/cosmos/cosmos-sdk/types/errors" + + "cosmossdk.io/errors" + "github.com/KYVENetwork/chain/x/stakers/types" +) + +// UpdateStakeFraction updates the stake fraction of a validator in the specified pool. +// If the validator wants to increase their stake fraction we can do this immediately +// since there are no security risks involved there. If the validator wants +// to decrease it however we do that only after the stake fraction change time +// so validators can not decrease their stake before e.g. doing something maliciously +func (k msgServer) UpdateStakeFraction(goCtx context.Context, msg *types.MsgUpdateStakeFraction) (*types.MsgUpdateStakeFractionResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + valaccount, active := k.GetValaccount(ctx, msg.PoolId, msg.Creator) + if !active { + return nil, errors.Wrap(errorsTypes.ErrUnauthorized, types.ErrNoValaccount.Error()) + } + + // if the validator wants to decrease their stake fraction in a pool we have + // to do that in the bonding time + if msg.StakeFraction.LT(valaccount.StakeFraction) { + // Insert commission change into queue + k.orderNewStakeFractionChange(ctx, msg.Creator, msg.PoolId, msg.StakeFraction) + return &types.MsgUpdateStakeFractionResponse{}, nil + } + + // if the validator wants to increase their stake fraction we can do this immediately. + // Before we clear any change entries if there are currently bonding + queueEntry, found := k.GetStakeFractionChangeEntryByIndex2(ctx, msg.Creator, msg.PoolId) + if found { + k.RemoveStakeFractionEntry(ctx, &queueEntry) + } + + valaccount.StakeFraction = msg.StakeFraction + k.SetValaccount(ctx, valaccount) + + _ = ctx.EventManager().EmitTypedEvent(&types.EventUpdateStakeFraction{ + Staker: msg.Creator, + PoolId: msg.PoolId, + StakeFraction: msg.StakeFraction, + }) + + return &types.MsgUpdateStakeFractionResponse{}, nil +} diff --git a/x/stakers/keeper/msg_server_update_stake_fraction_test.go b/x/stakers/keeper/msg_server_update_stake_fraction_test.go new file mode 100644 index 00000000..e406f7a9 --- /dev/null +++ b/x/stakers/keeper/msg_server_update_stake_fraction_test.go @@ -0,0 +1,407 @@ +package keeper_test + +import ( + "cosmossdk.io/math" + pooltypes "github.com/KYVENetwork/chain/x/pool/types" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + i "github.com/KYVENetwork/chain/testutil/integration" + stakerstypes "github.com/KYVENetwork/chain/x/stakers/types" +) + +/* + +TEST CASES - msg_server_update_stake_fraction.go + +* Get the default stake fraction from a newly joined pool +* Increase stake fraction to 50% from previous stake fraction +* Decrease stake fraction to 0% from previous stake fraction +* Decrease stake fraction to 1% from previous stake fraction +* Increase stake fraction to 100% from previous stake fraction +* Update stake fraction to same value from previous stake fraction +* Update stake fraction with a negative number from previous stake fraction +* Update stake fraction with a too high number from previous stake fraction +* Increase stake fraction after stake fraction has been decreased before during change time +* Decrease stake fraction after stake fraction has been decreased before during change time +* Decrease stake fraction after stake fraction has been increased before +* Update stake fraction with multiple pools +* Validator stake increases while stake fraction stays the same +* Validator stake decreases while stake fraction stays the same + +*/ + +var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { + s := i.NewCleanChain() + + gov := s.App().GovKeeper.GetGovernanceAccount(s.Ctx()).GetAddress().String() + + BeforeEach(func() { + // init new clean chain + s = i.NewCleanChain() + + // create pool + msg := &pooltypes.MsgCreatePool{ + Authority: gov, + UploadInterval: 60, + MaxBundleSize: 100, + InflationShareWeight: math.LegacyZeroDec(), + Binaries: "{}", + } + s.RunTxPoolSuccess(msg) + + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.1"), + }) + }) + + AfterEach(func() { + s.PerformValidityChecks() + }) + + It("Get the default stake fraction from a newly joined pool", func() { + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + }) + + It("Increase stake fraction to 50% from previous stake fraction", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.5"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + }) + + It("Decrease stake fraction to 0% from previous stake fraction", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetStakeFractionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(BeZero()) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(BeZero()) + }) + + It("Decrease stake fraction to 1% from previous stake fraction", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.01"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetStakeFractionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.01"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(1 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(1 * i.KYVE)) + }) + + It("Increase stake fraction to 100% from previous stake fraction", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(100 * i.KYVE)) + }) + + It("Update stake fraction to same value from previous stake fraction", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.1"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + }) + + It("Update stake fraction with a negative number from previous stake fraction", func() { + // ACT + s.RunTxStakersError(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("-0.5"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + }) + + It("Update stake fraction with a too high number from previous stake fraction during change time", func() { + // ACT + s.RunTxStakersError(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("2"), + }) + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + }) + + It("Increase stake fraction after stake fraction has been decreased before during change time", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.05"), + }) + + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.2"), + }) + + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.2"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(20 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(20 * i.KYVE)) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.2"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(20 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(20 * i.KYVE)) + }) + + It("Decrease stake fraction after stake fraction has been decreased before during change time", func() { + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.05"), + }) + + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.01"), + }) + + s.PerformValidityChecks() + + // ASSERT + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.01"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(1 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(1 * i.KYVE)) + }) + + It("Decrease stake fraction after stake fraction has been increased before", func() { + // ARRANGE + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.5"), + }) + + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + + s.PerformValidityChecks() + + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.02"), + }) + + // ASSERT + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.02"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(2 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(2 * i.KYVE)) + }) + + It("Update stake fraction with multiple pools", func() { + // ARRANGE + msg := &pooltypes.MsgCreatePool{ + Authority: gov, + UploadInterval: 60, + MaxBundleSize: 100, + InflationShareWeight: math.LegacyZeroDec(), + Binaries: "{}", + } + s.RunTxPoolSuccess(msg) + + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 1, + Valaddress: i.VALADDRESS_0_B, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.1"), + }) + + // ACT + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 0, + StakeFraction: math.LegacyMustNewDecFromStr("0.5"), + }) + + s.RunTxStakersSuccess(&stakerstypes.MsgUpdateStakeFraction{ + Creator: i.STAKER_0, + PoolId: 1, + StakeFraction: math.LegacyMustNewDecFromStr("0.03"), + }) + + s.PerformValidityChecks() + + // ASSERT + valaccount0, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount0.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + + valaccount1, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) + Expect(valaccount1.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 1)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1)).To(Equal(10 * i.KYVE)) + + // wait for update + s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) + s.CommitAfterSeconds(1) + + valaccount0, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount0.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + + valaccount1, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) + Expect(valaccount1.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.03"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 1)).To(Equal(3 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1)).To(Equal(3 * i.KYVE)) + }) + + It("Validator stake increases while stake fraction stays the same", func() { + // ARRANGE + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + + // ACT + s.SelfDelegateValidator(i.STAKER_0, 50*i.KYVE) + + // ASSERT + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(15 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(15 * i.KYVE)) + }) + + It("Validator stake decreases while stake fraction stays the same", func() { + // ARRANGE + valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + + // ACT + s.SelfUndelegateValidator(i.STAKER_0, 50*i.KYVE) + + // wait for update + unbondingTime, _ := s.App().StakingKeeper.UnbondingTime(s.Ctx()) + s.CommitAfterSeconds(uint64(unbondingTime.Seconds())) + s.CommitAfterSeconds(1) + + // ASSERT + valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(5 * i.KYVE)) + Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(5 * i.KYVE)) + }) +}) diff --git a/x/stakers/module.go b/x/stakers/module.go index 597eb916..75ebc471 100644 --- a/x/stakers/module.go +++ b/x/stakers/module.go @@ -156,6 +156,7 @@ func (am AppModule) BeginBlock(ctx context.Context) error { sdkCtx := sdk.UnwrapSDKContext(ctx) am.keeper.ProcessCommissionChangeQueue(sdkCtx) am.keeper.ProcessLeavePoolQueue(sdkCtx) + am.keeper.ProcessStakeFractionChangeQueue(sdkCtx) return nil } diff --git a/x/stakers/types/codec.go b/x/stakers/types/codec.go index 5adbe9cb..686e887f 100644 --- a/x/stakers/types/codec.go +++ b/x/stakers/types/codec.go @@ -9,6 +9,7 @@ import ( func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgUpdateCommission{}, "kyve/stakers/MsgUpdateCommission", nil) + cdc.RegisterConcrete(&MsgUpdateStakeFraction{}, "kyve/stakers/MsgUpdateStakeFraction", nil) cdc.RegisterConcrete(&MsgJoinPool{}, "kyve/stakers/MsgJoinPool", nil) cdc.RegisterConcrete(&MsgLeavePool{}, "kyve/stakers/MsgLeavePool", nil) cdc.RegisterConcrete(&MsgUpdateParams{}, "kyve/stakers/MsgUpdateParams", nil) @@ -16,6 +17,7 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { func RegisterInterfaces(registry codecTypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgUpdateCommission{}) + registry.RegisterImplementations((*sdk.Msg)(nil), &MsgUpdateStakeFraction{}) registry.RegisterImplementations((*sdk.Msg)(nil), &MsgJoinPool{}) registry.RegisterImplementations((*sdk.Msg)(nil), &MsgLeavePool{}) registry.RegisterImplementations((*sdk.Msg)(nil), &MsgUpdateParams{}) diff --git a/x/stakers/types/errors.go b/x/stakers/types/errors.go index 46b346ce..c68a8119 100644 --- a/x/stakers/types/errors.go +++ b/x/stakers/types/errors.go @@ -22,4 +22,5 @@ var ( ErrPoolLeaveAlreadyInProgress = errors.Register(ModuleName, 1117, "Pool leave is already in progress") ErrValaccountUnauthorized = errors.Register(ModuleName, 1118, "valaccount unauthorized") ErrValidatorJailed = errors.Register(ModuleName, 1119, "validator jailed") + ErrNoValaccount = errors.Register(ModuleName, 1120, "sender has no valaccount") ) diff --git a/x/stakers/types/events.pb.go b/x/stakers/types/events.pb.go index 2347afee..445aa39b 100644 --- a/x/stakers/types/events.pb.go +++ b/x/stakers/types/events.pb.go @@ -94,8 +94,10 @@ func (m *EventUpdateParams) GetPayload() string { type EventUpdateCommission struct { // staker is the account address of the protocol node. Staker string `protobuf:"bytes,1,opt,name=staker,proto3" json:"staker,omitempty"` + // pool_id ... + PoolId uint64 `protobuf:"varint,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` // commission ... - Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,2,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` + Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,3,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` } func (m *EventUpdateCommission) Reset() { *m = EventUpdateCommission{} } @@ -138,6 +140,71 @@ func (m *EventUpdateCommission) GetStaker() string { return "" } +func (m *EventUpdateCommission) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + +// EventUpdateCommission ... +// emitted_by: MsgUpdateStakeFraction, EndBlock +type EventUpdateStakeFraction struct { + // staker is the account address of the protocol node. + Staker string `protobuf:"bytes,1,opt,name=staker,proto3" json:"staker,omitempty"` + // pool_id ... + PoolId uint64 `protobuf:"varint,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + // stake_fraction ... + StakeFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,3,opt,name=stake_fraction,json=stakeFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"stake_fraction"` +} + +func (m *EventUpdateStakeFraction) Reset() { *m = EventUpdateStakeFraction{} } +func (m *EventUpdateStakeFraction) String() string { return proto.CompactTextString(m) } +func (*EventUpdateStakeFraction) ProtoMessage() {} +func (*EventUpdateStakeFraction) Descriptor() ([]byte, []int) { + return fileDescriptor_7a1b3dc9634155a0, []int{2} +} +func (m *EventUpdateStakeFraction) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventUpdateStakeFraction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventUpdateStakeFraction.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 *EventUpdateStakeFraction) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventUpdateStakeFraction.Merge(m, src) +} +func (m *EventUpdateStakeFraction) XXX_Size() int { + return m.Size() +} +func (m *EventUpdateStakeFraction) XXX_DiscardUnknown() { + xxx_messageInfo_EventUpdateStakeFraction.DiscardUnknown(m) +} + +var xxx_messageInfo_EventUpdateStakeFraction proto.InternalMessageInfo + +func (m *EventUpdateStakeFraction) GetStaker() string { + if m != nil { + return m.Staker + } + return "" +} + +func (m *EventUpdateStakeFraction) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + // EventClaimCommissionRewards ... // emitted_by: MsgClaimCommissionRewards type EventClaimCommissionRewards struct { @@ -151,7 +218,7 @@ func (m *EventClaimCommissionRewards) Reset() { *m = EventClaimCommissio func (m *EventClaimCommissionRewards) String() string { return proto.CompactTextString(m) } func (*EventClaimCommissionRewards) ProtoMessage() {} func (*EventClaimCommissionRewards) Descriptor() ([]byte, []int) { - return fileDescriptor_7a1b3dc9634155a0, []int{2} + return fileDescriptor_7a1b3dc9634155a0, []int{3} } func (m *EventClaimCommissionRewards) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -206,13 +273,17 @@ type EventJoinPool struct { Valaddress string `protobuf:"bytes,3,opt,name=valaddress,proto3" json:"valaddress,omitempty"` // amount is the amount of funds transferred to the valaddress Amount uint64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + // commission ... + Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,5,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` + // stake_fraction ... + StakeFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,6,opt,name=stake_fraction,json=stakeFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"stake_fraction"` } func (m *EventJoinPool) Reset() { *m = EventJoinPool{} } func (m *EventJoinPool) String() string { return proto.CompactTextString(m) } func (*EventJoinPool) ProtoMessage() {} func (*EventJoinPool) Descriptor() ([]byte, []int) { - return fileDescriptor_7a1b3dc9634155a0, []int{3} + return fileDescriptor_7a1b3dc9634155a0, []int{4} } func (m *EventJoinPool) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -282,7 +353,7 @@ func (m *EventLeavePool) Reset() { *m = EventLeavePool{} } func (m *EventLeavePool) String() string { return proto.CompactTextString(m) } func (*EventLeavePool) ProtoMessage() {} func (*EventLeavePool) Descriptor() ([]byte, []int) { - return fileDescriptor_7a1b3dc9634155a0, []int{4} + return fileDescriptor_7a1b3dc9634155a0, []int{5} } func (m *EventLeavePool) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -342,7 +413,7 @@ func (m *EventSlash) Reset() { *m = EventSlash{} } func (m *EventSlash) String() string { return proto.CompactTextString(m) } func (*EventSlash) ProtoMessage() {} func (*EventSlash) Descriptor() ([]byte, []int) { - return fileDescriptor_7a1b3dc9634155a0, []int{5} + return fileDescriptor_7a1b3dc9634155a0, []int{6} } func (m *EventSlash) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -402,6 +473,7 @@ func (m *EventSlash) GetSlashType() SlashType { func init() { proto.RegisterType((*EventUpdateParams)(nil), "kyve.stakers.v1beta1.EventUpdateParams") proto.RegisterType((*EventUpdateCommission)(nil), "kyve.stakers.v1beta1.EventUpdateCommission") + proto.RegisterType((*EventUpdateStakeFraction)(nil), "kyve.stakers.v1beta1.EventUpdateStakeFraction") proto.RegisterType((*EventClaimCommissionRewards)(nil), "kyve.stakers.v1beta1.EventClaimCommissionRewards") proto.RegisterType((*EventJoinPool)(nil), "kyve.stakers.v1beta1.EventJoinPool") proto.RegisterType((*EventLeavePool)(nil), "kyve.stakers.v1beta1.EventLeavePool") @@ -411,37 +483,41 @@ func init() { func init() { proto.RegisterFile("kyve/stakers/v1beta1/events.proto", fileDescriptor_7a1b3dc9634155a0) } var fileDescriptor_7a1b3dc9634155a0 = []byte{ - // 478 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x93, 0xcf, 0x6a, 0xd4, 0x50, - 0x14, 0xc6, 0x27, 0xed, 0x30, 0x43, 0x8e, 0x58, 0x30, 0x54, 0x0d, 0x53, 0xc9, 0xd4, 0xb8, 0xe9, - 0x42, 0x12, 0x5a, 0xf7, 0x42, 0x67, 0xac, 0xa0, 0x16, 0x2d, 0xf1, 0x0f, 0xe8, 0x66, 0xb8, 0x93, - 0x7b, 0x98, 0x09, 0x93, 0xe4, 0x84, 0xdc, 0xdb, 0x4c, 0xf3, 0x16, 0x6e, 0x7c, 0x12, 0x5f, 0xa2, - 0xcb, 0x2e, 0xc5, 0x45, 0x91, 0x99, 0x17, 0x91, 0xdc, 0x24, 0x9d, 0x08, 0x11, 0xb4, 0xbb, 0x7b, - 0xc2, 0x77, 0x7e, 0xdf, 0x8f, 0x4b, 0x2e, 0x3c, 0x5e, 0xe4, 0x19, 0xba, 0x42, 0xb2, 0x05, 0xa6, - 0xc2, 0xcd, 0x0e, 0xa7, 0x28, 0xd9, 0xa1, 0x8b, 0x19, 0xc6, 0x52, 0x38, 0x49, 0x4a, 0x92, 0x8c, - 0xdd, 0x22, 0xe2, 0x54, 0x11, 0xa7, 0x8a, 0x0c, 0x76, 0x67, 0x34, 0x23, 0x15, 0x70, 0x8b, 0x53, - 0x99, 0x1d, 0xb4, 0xe3, 0x12, 0x96, 0xb2, 0xa8, 0xc2, 0x0d, 0xec, 0xd6, 0x48, 0x8d, 0x57, 0x19, - 0xfb, 0xbb, 0x06, 0xf7, 0x4e, 0x0a, 0x87, 0x8f, 0x09, 0x67, 0x12, 0xcf, 0xd4, 0xbe, 0x71, 0x0c, - 0x40, 0x21, 0x9f, 0x94, 0x34, 0x53, 0xdb, 0xd7, 0x0e, 0xee, 0x1c, 0x3d, 0x72, 0xda, 0xec, 0x9c, - 0x72, 0x63, 0xd4, 0xbd, 0xbc, 0x1e, 0x76, 0x3c, 0x9d, 0x42, 0xbe, 0x41, 0xc4, 0xb8, 0xac, 0x11, - 0x5b, 0xff, 0x8e, 0x88, 0x71, 0x59, 0x21, 0x4c, 0xe8, 0x27, 0x2c, 0x0f, 0x89, 0x71, 0x73, 0x7b, - 0x5f, 0x3b, 0xd0, 0xbd, 0x7a, 0xb4, 0x25, 0xdc, 0x6f, 0x48, 0x8f, 0x29, 0x8a, 0x02, 0x21, 0x02, - 0x8a, 0x8d, 0x07, 0xd0, 0x2b, 0xe9, 0x4a, 0x5a, 0xf7, 0xaa, 0xc9, 0x18, 0x03, 0xf8, 0x37, 0x29, - 0x65, 0xa3, 0x8f, 0x9e, 0x14, 0x7d, 0x3f, 0xaf, 0x87, 0x7b, 0x3e, 0x89, 0x88, 0x84, 0xe0, 0x0b, - 0x27, 0x20, 0x37, 0x62, 0x72, 0xee, 0x9c, 0xe2, 0x8c, 0xf9, 0xf9, 0x0b, 0xf4, 0xbd, 0xc6, 0x9a, - 0xfd, 0x0e, 0xf6, 0x54, 0xeb, 0x38, 0x64, 0x41, 0xb4, 0x29, 0xf5, 0x70, 0xc9, 0x52, 0x2e, 0xfe, - 0xda, 0x6d, 0x42, 0x9f, 0x45, 0x74, 0x1e, 0xcb, 0xf2, 0x1a, 0x74, 0xaf, 0x1e, 0xed, 0x0b, 0xb8, - 0xab, 0x80, 0xaf, 0x29, 0x88, 0xcf, 0x88, 0x42, 0xe3, 0x21, 0xf4, 0x13, 0xa2, 0x70, 0x12, 0x70, - 0xc5, 0xe8, 0x7a, 0xbd, 0x62, 0x7c, 0xc5, 0x1b, 0xec, 0xad, 0x3f, 0xd8, 0x16, 0x40, 0xc6, 0x42, - 0xc6, 0x79, 0x8a, 0x42, 0x54, 0xb7, 0xd4, 0xf8, 0x52, 0xec, 0x95, 0x65, 0x66, 0xb7, 0xe4, 0x95, - 0x93, 0x7d, 0x0c, 0x3b, 0xaa, 0xf9, 0x14, 0x59, 0x86, 0xb7, 0xaa, 0xb6, 0xbf, 0x69, 0x00, 0x8a, - 0xf1, 0x3e, 0x64, 0x62, 0xfe, 0xff, 0xea, 0x1b, 0xb5, 0xed, 0xa6, 0x9a, 0xf1, 0x1c, 0x40, 0x14, - 0xc4, 0x89, 0xcc, 0x13, 0x54, 0xda, 0x3b, 0x47, 0xc3, 0xf6, 0x1f, 0x47, 0x35, 0x7f, 0xc8, 0x13, - 0xf4, 0x74, 0x51, 0x1f, 0x47, 0x2f, 0x2f, 0x57, 0x96, 0x76, 0xb5, 0xb2, 0xb4, 0x5f, 0x2b, 0x4b, - 0xfb, 0xba, 0xb6, 0x3a, 0x57, 0x6b, 0xab, 0xf3, 0x63, 0x6d, 0x75, 0xbe, 0x3c, 0x9d, 0x05, 0x72, - 0x7e, 0x3e, 0x75, 0x7c, 0x8a, 0xdc, 0x37, 0x9f, 0x3f, 0x9d, 0xbc, 0x45, 0xb9, 0xa4, 0x74, 0xe1, - 0xfa, 0x73, 0x16, 0xc4, 0xee, 0xc5, 0xcd, 0x4b, 0x29, 0x8a, 0xc5, 0xb4, 0xa7, 0x1e, 0xc8, 0xb3, - 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6c, 0x29, 0x77, 0x9c, 0xb8, 0x03, 0x00, 0x00, + // 532 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x86, 0xb3, 0x69, 0x48, 0x94, 0x41, 0x8d, 0x44, 0x54, 0xc0, 0x4a, 0x91, 0x53, 0xcc, 0xa5, + 0x07, 0x64, 0xab, 0xe5, 0x8e, 0xd4, 0x84, 0x56, 0xa2, 0x54, 0x50, 0xb9, 0x80, 0x04, 0x97, 0x68, + 0xe3, 0x5d, 0x12, 0x2b, 0xb6, 0xc7, 0xf2, 0x6e, 0x13, 0xfc, 0x08, 0x1c, 0x90, 0xb8, 0x20, 0x1e, + 0x84, 0x97, 0xe8, 0xb1, 0x47, 0xc4, 0xa1, 0x42, 0xc9, 0x8b, 0x20, 0xaf, 0xed, 0xc6, 0x41, 0x46, + 0x6a, 0x73, 0xdb, 0xb1, 0xfe, 0xf9, 0xe6, 0xdf, 0x7f, 0xe4, 0x85, 0xc7, 0x93, 0x78, 0xca, 0x2d, + 0x21, 0xe9, 0x84, 0x47, 0xc2, 0x9a, 0xee, 0x0d, 0xb9, 0xa4, 0x7b, 0x16, 0x9f, 0xf2, 0x40, 0x0a, + 0x33, 0x8c, 0x50, 0x62, 0x7b, 0x2b, 0x91, 0x98, 0x99, 0xc4, 0xcc, 0x24, 0x9d, 0xad, 0x11, 0x8e, + 0x50, 0x09, 0xac, 0xe4, 0x94, 0x6a, 0x3b, 0xe5, 0xb8, 0x90, 0x46, 0xd4, 0xcf, 0x70, 0x1d, 0xa3, + 0x54, 0x92, 0xe3, 0x95, 0xc6, 0xf8, 0x49, 0xe0, 0xde, 0x61, 0xe2, 0xe1, 0x5d, 0xc8, 0xa8, 0xe4, + 0xa7, 0xaa, 0xbf, 0x7d, 0x00, 0x80, 0x1e, 0x1b, 0xa4, 0x34, 0x8d, 0xec, 0x90, 0xdd, 0xbb, 0xfb, + 0x8f, 0xcc, 0x32, 0x77, 0x66, 0xda, 0xd1, 0xab, 0x5d, 0x5c, 0x75, 0x2b, 0x76, 0x13, 0x3d, 0xb6, + 0x44, 0x04, 0x7c, 0x96, 0x23, 0xaa, 0x37, 0x47, 0x04, 0x7c, 0x96, 0x21, 0x34, 0x68, 0x84, 0x34, + 0xf6, 0x90, 0x32, 0x6d, 0x63, 0x87, 0xec, 0x36, 0xed, 0xbc, 0x34, 0xbe, 0x12, 0xb8, 0x5f, 0x70, + 0xdd, 0x47, 0xdf, 0x77, 0x85, 0x70, 0x31, 0x68, 0x3f, 0x80, 0x7a, 0x8a, 0x57, 0xae, 0x9b, 0x76, + 0x56, 0xb5, 0x1f, 0x42, 0x23, 0x44, 0xf4, 0x06, 0x2e, 0x53, 0x5e, 0x6a, 0x76, 0x3d, 0x29, 0x5f, + 0xb2, 0x76, 0x1f, 0xc0, 0xb9, 0x6e, 0x4f, 0xe7, 0xf4, 0x9e, 0x24, 0x4e, 0x7e, 0x5f, 0x75, 0xb7, + 0x1d, 0x14, 0x3e, 0x0a, 0xc1, 0x26, 0xa6, 0x8b, 0x96, 0x4f, 0xe5, 0xd8, 0x3c, 0xe1, 0x23, 0xea, + 0xc4, 0x2f, 0xb8, 0x63, 0x17, 0xda, 0x8c, 0x1f, 0x04, 0xb4, 0x82, 0x9f, 0xb3, 0x64, 0xe6, 0x51, + 0x44, 0x1d, 0xb9, 0x96, 0xa5, 0x63, 0x68, 0x29, 0xc9, 0xe0, 0x53, 0x86, 0xb8, 0x8d, 0xad, 0x4d, + 0x51, 0x1c, 0x6e, 0xbc, 0x81, 0x6d, 0x65, 0xac, 0xef, 0x51, 0xd7, 0x5f, 0xe6, 0x64, 0xf3, 0x19, + 0x8d, 0x98, 0xf8, 0xaf, 0x37, 0x0d, 0x1a, 0xd4, 0xc7, 0xf3, 0x40, 0xa6, 0xab, 0x6b, 0xda, 0x79, + 0x69, 0x7c, 0xa9, 0xc2, 0xa6, 0x22, 0x1e, 0xa3, 0x1b, 0x9c, 0x22, 0x7a, 0xc5, 0x7b, 0x90, 0x95, + 0x7b, 0x2c, 0xe1, 0xd5, 0x15, 0xb8, 0x0e, 0x30, 0xa5, 0x1e, 0x65, 0x2c, 0xe2, 0x42, 0x64, 0xab, + 0x2d, 0x7c, 0x49, 0xfa, 0xd2, 0x69, 0x5a, 0x2d, 0xe5, 0xa5, 0xd5, 0x3f, 0xab, 0xba, 0xb3, 0xd6, + 0xaa, 0x4a, 0xc2, 0xad, 0xaf, 0x1d, 0xee, 0x01, 0xb4, 0x54, 0x14, 0x27, 0x9c, 0x4e, 0xf9, 0x5a, + 0x59, 0x18, 0xdf, 0x09, 0x80, 0x62, 0x9c, 0x79, 0x54, 0x8c, 0x6f, 0x9f, 0xe5, 0x32, 0xab, 0x8d, + 0x95, 0xac, 0x9e, 0x03, 0x88, 0x84, 0x38, 0x90, 0x71, 0xc8, 0x55, 0x8e, 0xad, 0xfd, 0x6e, 0xf9, + 0xef, 0xa7, 0x26, 0xbf, 0x8d, 0x43, 0x6e, 0x37, 0x45, 0x7e, 0xec, 0x1d, 0x5d, 0xcc, 0x75, 0x72, + 0x39, 0xd7, 0xc9, 0x9f, 0xb9, 0x4e, 0xbe, 0x2d, 0xf4, 0xca, 0xe5, 0x42, 0xaf, 0xfc, 0x5a, 0xe8, + 0x95, 0x8f, 0x4f, 0x47, 0xae, 0x1c, 0x9f, 0x0f, 0x4d, 0x07, 0x7d, 0xeb, 0xd5, 0x87, 0xf7, 0x87, + 0xaf, 0xb9, 0x9c, 0x61, 0x34, 0xb1, 0x9c, 0x31, 0x75, 0x03, 0xeb, 0xf3, 0xf5, 0x7b, 0x93, 0x0c, + 0x16, 0xc3, 0xba, 0x7a, 0x66, 0x9e, 0xfd, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x42, 0x2b, 0x27, 0xf7, + 0xfe, 0x04, 0x00, 0x00, } func (m *EventUpdateParams) Marshal() (dAtA []byte, err error) { @@ -523,7 +599,57 @@ func (m *EventUpdateCommission) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintEvents(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x12 + dAtA[i] = 0x1a + if m.PoolId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Staker) > 0 { + i -= len(m.Staker) + copy(dAtA[i:], m.Staker) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Staker))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventUpdateStakeFraction) 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 *EventUpdateStakeFraction) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventUpdateStakeFraction) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.StakeFraction.Size() + i -= size + if _, err := m.StakeFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.PoolId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x10 + } if len(m.Staker) > 0 { i -= len(m.Staker) copy(dAtA[i:], m.Staker) @@ -591,6 +717,26 @@ func (m *EventJoinPool) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.StakeFraction.Size() + i -= size + if _, err := m.StakeFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + { + size := m.Commission.Size() + i -= size + if _, err := m.Commission.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a if m.Amount != 0 { i = encodeVarintEvents(dAtA, i, uint64(m.Amount)) i-- @@ -736,11 +882,32 @@ func (m *EventUpdateCommission) Size() (n int) { if l > 0 { n += 1 + l + sovEvents(uint64(l)) } + if m.PoolId != 0 { + n += 1 + sovEvents(uint64(m.PoolId)) + } l = m.Commission.Size() n += 1 + l + sovEvents(uint64(l)) return n } +func (m *EventUpdateStakeFraction) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Staker) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + if m.PoolId != 0 { + n += 1 + sovEvents(uint64(m.PoolId)) + } + l = m.StakeFraction.Size() + n += 1 + l + sovEvents(uint64(l)) + return n +} + func (m *EventClaimCommissionRewards) Size() (n int) { if m == nil { return 0 @@ -778,6 +945,10 @@ func (m *EventJoinPool) Size() (n int) { if m.Amount != 0 { n += 1 + sovEvents(uint64(m.Amount)) } + l = m.Commission.Size() + n += 1 + l + sovEvents(uint64(l)) + l = m.StakeFraction.Size() + n += 1 + l + sovEvents(uint64(l)) return n } @@ -1035,6 +1206,25 @@ func (m *EventUpdateCommission) Unmarshal(dAtA []byte) error { m.Staker = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Commission", wireType) } @@ -1089,6 +1279,141 @@ func (m *EventUpdateCommission) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventUpdateStakeFraction) 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 ErrIntOverflowEvents + } + 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: EventUpdateStakeFraction: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventUpdateStakeFraction: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Staker", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Staker = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StakeFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *EventClaimCommissionRewards) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -1334,6 +1659,74 @@ func (m *EventJoinPool) Unmarshal(dAtA []byte) error { break } } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commission", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Commission.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StakeFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipEvents(dAtA[iNdEx:]) diff --git a/x/stakers/types/genesis.go b/x/stakers/types/genesis.go index dc1f54b3..a17aca21 100644 --- a/x/stakers/types/genesis.go +++ b/x/stakers/types/genesis.go @@ -65,5 +65,23 @@ func (gs GenesisState) Validate() error { } } + // Stake Fraction Change + stakeFractionChangeMap := make(map[string]struct{}) + + for _, elem := range gs.StakeFractionChangeEntries { + index := string(StakeFractionChangeEntryKey(elem.Index)) + if _, ok := stakeFractionChangeMap[index]; ok { + return fmt.Errorf("duplicated index for stake fraction change entry %v", elem) + } + if elem.Index > gs.QueueStateStateFraction.HighIndex { + return fmt.Errorf("stake fraction change entry index too high: %v", elem) + } + if elem.Index < gs.QueueStateStateFraction.LowIndex { + return fmt.Errorf("stake fraction change entry index too low: %v", elem) + } + + stakeFractionChangeMap[index] = struct{}{} + } + return gs.Params.Validate() } diff --git a/x/stakers/types/genesis.pb.go b/x/stakers/types/genesis.pb.go index 4786bc8f..ea526ff1 100644 --- a/x/stakers/types/genesis.pb.go +++ b/x/stakers/types/genesis.pb.go @@ -39,6 +39,10 @@ type GenesisState struct { LeavePoolEntries []LeavePoolEntry `protobuf:"bytes,6,rep,name=leave_pool_entries,json=leavePoolEntries,proto3" json:"leave_pool_entries"` // queue_state_leave ... QueueStateLeave QueueState `protobuf:"bytes,7,opt,name=queue_state_leave,json=queueStateLeave,proto3" json:"queue_state_leave"` + // stake_fraction_change_entries ... + StakeFractionChangeEntries []StakeFractionChangeEntry `protobuf:"bytes,8,rep,name=stake_fraction_change_entries,json=stakeFractionChangeEntries,proto3" json:"stake_fraction_change_entries"` + // queue_state_state_fraction ... + QueueStateStateFraction QueueState `protobuf:"bytes,9,opt,name=queue_state_state_fraction,json=queueStateStateFraction,proto3" json:"queue_state_state_fraction"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -123,6 +127,20 @@ func (m *GenesisState) GetQueueStateLeave() QueueState { return QueueState{} } +func (m *GenesisState) GetStakeFractionChangeEntries() []StakeFractionChangeEntry { + if m != nil { + return m.StakeFractionChangeEntries + } + return nil +} + +func (m *GenesisState) GetQueueStateStateFraction() QueueState { + if m != nil { + return m.QueueStateStateFraction + } + return QueueState{} +} + func init() { proto.RegisterType((*GenesisState)(nil), "kyve.stakers.v1beta1.GenesisState") } @@ -132,34 +150,37 @@ func init() { } var fileDescriptor_0deb2ee89d595051 = []byte{ - // 417 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x51, 0x6b, 0xda, 0x50, - 0x14, 0xc7, 0x93, 0xe9, 0x1c, 0x5c, 0xc7, 0xdc, 0x82, 0x6c, 0x99, 0x8c, 0xcc, 0xc9, 0x1e, 0x06, - 0x1b, 0x09, 0x6e, 0x6f, 0x7b, 0x54, 0x6c, 0x1f, 0x2a, 0xad, 0x55, 0x90, 0xb6, 0x14, 0xc2, 0x35, - 0x1c, 0xe2, 0xc5, 0x24, 0x37, 0xe6, 0xde, 0xa4, 0xf5, 0x5b, 0xf4, 0x63, 0xf9, 0xe8, 0x63, 0xa1, - 0x50, 0x8a, 0x7e, 0x91, 0x92, 0x9b, 0xdb, 0xc4, 0x87, 0xf8, 0xd0, 0x37, 0xbd, 0xe7, 0x77, 0x7e, - 0xe7, 0x7f, 0x6e, 0x2e, 0xea, 0x2c, 0x56, 0x09, 0x58, 0x8c, 0xe3, 0x05, 0x44, 0xcc, 0x4a, 0xba, - 0x33, 0xe0, 0xb8, 0x6b, 0xb9, 0x10, 0x00, 0x23, 0xcc, 0x0c, 0x23, 0xca, 0xa9, 0xd6, 0x4c, 0x19, - 0x53, 0x32, 0xa6, 0x64, 0x5a, 0x4d, 0x97, 0xba, 0x54, 0x00, 0x56, 0xfa, 0x2b, 0x63, 0x5b, 0x3f, - 0x4a, 0x7d, 0x21, 0x8e, 0xb0, 0x2f, 0x75, 0xad, 0xf2, 0x91, 0x2f, 0x7a, 0xc1, 0x74, 0x1e, 0xaa, - 0xe8, 0xfd, 0x71, 0x16, 0x62, 0xc2, 0x31, 0x07, 0xed, 0x3f, 0xaa, 0x65, 0x12, 0x5d, 0x6d, 0xab, - 0xbf, 0xea, 0x7f, 0xbf, 0x99, 0x65, 0xa1, 0xcc, 0x91, 0x60, 0x7a, 0xd5, 0xf5, 0xe3, 0x77, 0x65, - 0x2c, 0x3b, 0xb4, 0x3e, 0xaa, 0x67, 0x9c, 0xed, 0x11, 0xc6, 0xf5, 0x37, 0xed, 0xca, 0x61, 0xc1, - 0x44, 0xfc, 0x97, 0x02, 0x94, 0x55, 0x87, 0x84, 0x71, 0xed, 0x0c, 0x35, 0x12, 0xec, 0x61, 0xc7, - 0xa1, 0x71, 0xc0, 0x33, 0x51, 0x45, 0x88, 0xda, 0xe5, 0xa2, 0x69, 0x0e, 0x4b, 0xd9, 0x87, 0xa2, - 0x5d, 0x08, 0x7d, 0xf4, 0xd5, 0xa1, 0xbe, 0x4f, 0x18, 0x23, 0x34, 0xb0, 0x9d, 0x39, 0x0e, 0x5c, - 0xb0, 0x21, 0xe0, 0x11, 0x01, 0xa6, 0x57, 0x85, 0xfa, 0x77, 0xb9, 0xba, 0x9f, 0xb7, 0xf5, 0x45, - 0xd7, 0x20, 0xe0, 0xd1, 0x4a, 0x4e, 0xf9, 0xe2, 0x94, 0x14, 0x09, 0x30, 0xed, 0x1a, 0x7d, 0x5e, - 0xc6, 0x10, 0x83, 0xcd, 0xd2, 0xfb, 0xb4, 0x0b, 0x4c, 0x7f, 0x2b, 0x2e, 0xf4, 0xc0, 0x1a, 0xe7, - 0x69, 0x8f, 0xf8, 0x04, 0x72, 0x40, 0x73, 0x99, 0x9f, 0x14, 0x39, 0xb4, 0x0b, 0xa4, 0x79, 0x80, - 0x13, 0xb0, 0x43, 0x4a, 0xbd, 0x7c, 0x8b, 0x9a, 0xd8, 0xe2, 0x67, 0xb9, 0x79, 0x98, 0xf2, 0x23, - 0x4a, 0xbd, 0xfd, 0xf8, 0x1f, 0xbd, 0xfd, 0xd3, 0x34, 0xf7, 0x18, 0x7d, 0xda, 0xcf, 0x2d, 0xea, - 0xfa, 0xbb, 0x57, 0x45, 0x6e, 0x14, 0x91, 0xc5, 0xd0, 0xde, 0xd1, 0x7a, 0x6b, 0xa8, 0x9b, 0xad, - 0xa1, 0x3e, 0x6d, 0x0d, 0xf5, 0x6e, 0x67, 0x28, 0x9b, 0x9d, 0xa1, 0xdc, 0xef, 0x0c, 0xe5, 0xea, - 0x8f, 0x4b, 0xf8, 0x3c, 0x9e, 0x99, 0x0e, 0xf5, 0xad, 0x93, 0xcb, 0xe9, 0xe0, 0x14, 0xf8, 0x0d, - 0x8d, 0x16, 0x96, 0x33, 0xc7, 0x24, 0xb0, 0x6e, 0xf3, 0x57, 0xcb, 0x57, 0x21, 0xb0, 0x59, 0x4d, - 0x3c, 0xd6, 0x7f, 0xcf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x65, 0x34, 0xdb, 0xba, 0x45, 0x03, 0x00, - 0x00, + // 468 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0x1b, 0x36, 0x0a, 0x78, 0x88, 0x81, 0x55, 0xb1, 0x10, 0x41, 0x28, 0x13, 0x07, 0x24, + 0x50, 0xa2, 0xc1, 0x8d, 0xe3, 0xaa, 0x8d, 0x03, 0x13, 0x8c, 0x4d, 0x9a, 0x00, 0x21, 0x45, 0xae, + 0xf5, 0x48, 0xad, 0x26, 0x71, 0x17, 0x3b, 0x19, 0xfd, 0x16, 0x7c, 0x1d, 0xbe, 0xc1, 0x8e, 0x3b, + 0x72, 0x42, 0xa8, 0xfd, 0x22, 0x28, 0x2f, 0x6e, 0x12, 0x09, 0x6f, 0xd2, 0x2e, 0x56, 0xeb, 0xf7, + 0x7f, 0xbf, 0xf7, 0xff, 0xdb, 0x31, 0xd9, 0x9e, 0xce, 0x4b, 0x08, 0x95, 0x66, 0x53, 0xc8, 0x55, + 0x58, 0xee, 0x8c, 0x41, 0xb3, 0x9d, 0x30, 0x86, 0x0c, 0x94, 0x50, 0xc1, 0x2c, 0x97, 0x5a, 0xd2, + 0x41, 0xa5, 0x09, 0x8c, 0x26, 0x30, 0x1a, 0x6f, 0x10, 0xcb, 0x58, 0xa2, 0x20, 0xac, 0x7e, 0xd5, + 0x5a, 0xef, 0x99, 0x95, 0x37, 0x63, 0x39, 0x4b, 0x0d, 0xce, 0xb3, 0x8f, 0x5c, 0xe1, 0x51, 0xb3, + 0xfd, 0xab, 0x4f, 0xee, 0xbe, 0xab, 0x4d, 0x1c, 0x6b, 0xa6, 0x81, 0xbe, 0x25, 0xfd, 0x1a, 0xe2, + 0x3a, 0x43, 0xe7, 0xc5, 0xc6, 0xeb, 0xc7, 0x81, 0xcd, 0x54, 0x70, 0x88, 0x9a, 0xdd, 0xf5, 0xf3, + 0x3f, 0x4f, 0x7b, 0x47, 0xa6, 0x83, 0x8e, 0xc8, 0x46, 0xad, 0x8b, 0x12, 0xa1, 0xb4, 0x7b, 0x63, + 0xb8, 0x76, 0x39, 0xe0, 0x18, 0xff, 0x1b, 0x00, 0xa9, 0xab, 0x07, 0x42, 0x69, 0xfa, 0x91, 0x6c, + 0x96, 0x2c, 0x61, 0x9c, 0xcb, 0x22, 0xd3, 0x35, 0x68, 0x0d, 0x41, 0x43, 0x3b, 0xe8, 0xa4, 0x11, + 0x1b, 0xd8, 0xbd, 0xb6, 0x1d, 0x81, 0x29, 0x79, 0xc4, 0x65, 0x9a, 0x0a, 0xa5, 0x84, 0xcc, 0x22, + 0x3e, 0x61, 0x59, 0x0c, 0x11, 0x64, 0x3a, 0x17, 0xa0, 0xdc, 0x75, 0x44, 0xbf, 0xb4, 0xa3, 0x47, + 0x4d, 0xdb, 0x08, 0xbb, 0xf6, 0x32, 0x9d, 0xcf, 0xcd, 0x94, 0x2d, 0x6e, 0x29, 0x0a, 0x50, 0xf4, + 0x1b, 0x79, 0x78, 0x5a, 0x40, 0x01, 0x91, 0xaa, 0xce, 0x33, 0x6a, 0x65, 0xee, 0x4d, 0x3c, 0xd0, + 0x4b, 0x62, 0x7c, 0xaa, 0x7a, 0xf0, 0x0a, 0xcc, 0x80, 0xc1, 0x69, 0xb3, 0xd3, 0xfa, 0xa0, 0x9f, + 0x09, 0x4d, 0x80, 0x95, 0x10, 0xcd, 0xa4, 0x4c, 0x9a, 0x14, 0x7d, 0x4c, 0xf1, 0xdc, 0x4e, 0x3e, + 0xa8, 0xf4, 0x87, 0x52, 0x26, 0x5d, 0xfb, 0xf7, 0x93, 0xee, 0x6e, 0xe5, 0xfb, 0x88, 0x3c, 0xe8, + 0xfa, 0xc6, 0xba, 0x7b, 0xeb, 0x5a, 0x96, 0x37, 0x5b, 0xcb, 0x38, 0x94, 0x9e, 0x91, 0x27, 0xd8, + 0x14, 0x7d, 0xcf, 0x19, 0xd7, 0x96, 0xe3, 0xbf, 0x8d, 0xc6, 0x83, 0x2b, 0x3e, 0x91, 0x7d, 0xd3, + 0xf9, 0xff, 0x0d, 0x78, 0xca, 0x5e, 0xaf, 0xc2, 0x70, 0xe2, 0x75, 0xc3, 0xd4, 0xeb, 0xca, 0x84, + 0x7b, 0xe7, 0x5a, 0xa9, 0xb6, 0xda, 0x54, 0xb8, 0xac, 0x26, 0xee, 0xee, 0x9f, 0x2f, 0x7c, 0xe7, + 0x62, 0xe1, 0x3b, 0x7f, 0x17, 0xbe, 0xf3, 0x73, 0xe9, 0xf7, 0x2e, 0x96, 0x7e, 0xef, 0xf7, 0xd2, + 0xef, 0x7d, 0x7d, 0x15, 0x0b, 0x3d, 0x29, 0xc6, 0x01, 0x97, 0x69, 0xf8, 0xfe, 0xcb, 0xc9, 0xde, + 0x07, 0xd0, 0x67, 0x32, 0x9f, 0x86, 0x7c, 0xc2, 0x44, 0x16, 0xfe, 0x68, 0xde, 0xa4, 0x9e, 0xcf, + 0x40, 0x8d, 0xfb, 0xf8, 0x14, 0xdf, 0xfc, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x96, 0xd7, 0xc8, 0x9f, + 0x23, 0x04, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -182,6 +203,30 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size, err := m.QueueStateStateFraction.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + if len(m.StakeFractionChangeEntries) > 0 { + for iNdEx := len(m.StakeFractionChangeEntries) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.StakeFractionChangeEntries[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + } { size, err := m.QueueStateLeave.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -318,6 +363,14 @@ func (m *GenesisState) Size() (n int) { } l = m.QueueStateLeave.Size() n += 1 + l + sovGenesis(uint64(l)) + if len(m.StakeFractionChangeEntries) > 0 { + for _, e := range m.StakeFractionChangeEntries { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + l = m.QueueStateStateFraction.Size() + n += 1 + l + sovGenesis(uint64(l)) return n } @@ -591,6 +644,73 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFractionChangeEntries", 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.StakeFractionChangeEntries = append(m.StakeFractionChangeEntries, StakeFractionChangeEntry{}) + if err := m.StakeFractionChangeEntries[len(m.StakeFractionChangeEntries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field QueueStateStateFraction", 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 + } + if err := m.QueueStateStateFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/stakers/types/keys.go b/x/stakers/types/keys.go index 70a5045a..6607fef1 100644 --- a/x/stakers/types/keys.go +++ b/x/stakers/types/keys.go @@ -36,7 +36,7 @@ var ( // CommissionChangeEntryKeyPrefix | CommissionChangeEntryKeyPrefix = []byte{4, 0} - // CommissionChangeEntryKeyPrefixIndex2 | + // CommissionChangeEntryKeyPrefixIndex2 | | CommissionChangeEntryKeyPrefixIndex2 = []byte{4, 1} // LeavePoolEntryKeyPrefix | @@ -45,6 +45,11 @@ var ( LeavePoolEntryKeyPrefixIndex2 = []byte{5, 1} ActiveStakerIndex = []byte{6} + + // StakeFractionChangeEntryKeyPrefix | + StakeFractionChangeEntryKeyPrefix = []byte{7, 0} + // StakeFractionChangeKeyPrefixIndex2 | | + StakeFractionChangeKeyPrefixIndex2 = []byte{7, 1} ) // ENUM aggregated data types @@ -56,8 +61,9 @@ var STAKER_STATS_COUNT STAKER_STATS = "total_stakers" type QUEUE_IDENTIFIER []byte var ( - QUEUE_IDENTIFIER_COMMISSION QUEUE_IDENTIFIER = []byte{30, 2} - QUEUE_IDENTIFIER_LEAVE QUEUE_IDENTIFIER = []byte{30, 3} + QUEUE_IDENTIFIER_COMMISSION QUEUE_IDENTIFIER = []byte{30, 2} + QUEUE_IDENTIFIER_LEAVE QUEUE_IDENTIFIER = []byte{30, 3} + QUEUE_IDENTIFIER_STAKE_FRACTION QUEUE_IDENTIFIER = []byte{30, 4} ) const MaxStakers = 50 @@ -82,8 +88,8 @@ func CommissionChangeEntryKey(index uint64) []byte { } // Important: only one queue entry per staker is allowed at a time. -func CommissionChangeEntryKeyIndex2(staker string) []byte { - return util.GetByteKey(staker) +func CommissionChangeEntryKeyIndex2(staker string, poolId uint64) []byte { + return util.GetByteKey(staker, poolId) } func LeavePoolEntryKey(index uint64) []byte { @@ -97,3 +103,11 @@ func LeavePoolEntryKeyIndex2(staker string, poolId uint64) []byte { func ActiveStakerKeyIndex(staker string) []byte { return util.GetByteKey(staker) } + +func StakeFractionChangeEntryKey(index uint64) []byte { + return util.GetByteKey(index) +} + +func StakeFractionChangeEntryKeyIndex2(staker string, poolId uint64) []byte { + return util.GetByteKey(staker, poolId) +} diff --git a/x/stakers/types/message_join_pool.go b/x/stakers/types/message_join_pool.go index 121adbfc..54cee98d 100644 --- a/x/stakers/types/message_join_pool.go +++ b/x/stakers/types/message_join_pool.go @@ -48,5 +48,13 @@ func (msg *MsgJoinPool) ValidateBasic() error { return errors.Wrapf(errorsTypes.ErrInvalidRequest, "invalid amount") } + if util.ValidatePercentage(msg.Commission) != nil { + return errors.Wrapf(errorsTypes.ErrInvalidRequest, "invalid commission") + } + + if util.ValidatePercentage(msg.StakeFraction) != nil { + return errors.Wrapf(errorsTypes.ErrInvalidRequest, "invalid stake fraction") + } + return nil } diff --git a/x/stakers/types/message_update_stake_fraction.go b/x/stakers/types/message_update_stake_fraction.go new file mode 100644 index 00000000..19341f15 --- /dev/null +++ b/x/stakers/types/message_update_stake_fraction.go @@ -0,0 +1,48 @@ +package types + +import ( + "cosmossdk.io/errors" + "github.com/KYVENetwork/chain/util" + sdk "github.com/cosmos/cosmos-sdk/types" + errorsTypes "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" +) + +var ( + _ legacytx.LegacyMsg = &MsgUpdateStakeFraction{} + _ sdk.Msg = &MsgUpdateStakeFraction{} +) + +func (msg *MsgUpdateStakeFraction) GetSignBytes() []byte { + bz := Amino.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +func (msg *MsgUpdateStakeFraction) GetSigners() []sdk.AccAddress { + creator, err := sdk.AccAddressFromBech32(msg.Creator) + if err != nil { + panic(err) + } + + return []sdk.AccAddress{creator} +} + +func (msg *MsgUpdateStakeFraction) Route() string { + return RouterKey +} + +func (msg *MsgUpdateStakeFraction) Type() string { + return "kyve/stakers/MsgUpdateStakeFraction" +} + +func (msg *MsgUpdateStakeFraction) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Creator); err != nil { + return errors.Wrapf(errorsTypes.ErrInvalidAddress, "invalid validator address: %s", err) + } + + if util.ValidatePercentage(msg.StakeFraction) != nil { + return errors.Wrapf(errorsTypes.ErrInvalidRequest, "invalid stake fraction") + } + + return nil +} diff --git a/x/stakers/types/params.go b/x/stakers/types/params.go index 2ecb0884..e2fdd5ab 100644 --- a/x/stakers/types/params.go +++ b/x/stakers/types/params.go @@ -1,6 +1,7 @@ package types import ( + "cosmossdk.io/math" "github.com/KYVENetwork/chain/util" ) @@ -10,14 +11,34 @@ var DefaultCommissionChangeTime = uint64(60 * 60 * 24 * 5) // DefaultLeavePoolTime ... var DefaultLeavePoolTime = uint64(60 * 60 * 24 * 5) +// DefaultStakeFractionChangeTime ... +var DefaultStakeFractionChangeTime = uint64(60 * 60 * 24 * 5) + +// DefaultVoteSlash ... +var DefaultVoteSlash = math.LegacyMustNewDecFromStr("0.01") + +// DefaultUploadSlash ... +var DefaultUploadSlash = math.LegacyMustNewDecFromStr("0.02") + +// DefaultTimeoutSlash ... +var DefaultTimeoutSlash = math.LegacyMustNewDecFromStr("0.002") + // NewParams creates a new Params instance func NewParams( commissionChangeTime uint64, leavePoolTime uint64, + stakeFractionChangeTime uint64, + voteSlash math.LegacyDec, + uploadSlash math.LegacyDec, + timeoutSlash math.LegacyDec, ) Params { return Params{ - CommissionChangeTime: commissionChangeTime, - LeavePoolTime: leavePoolTime, + CommissionChangeTime: commissionChangeTime, + LeavePoolTime: leavePoolTime, + StakeFractionChangeTime: stakeFractionChangeTime, + VoteSlash: voteSlash, + UploadSlash: uploadSlash, + TimeoutSlash: timeoutSlash, } } @@ -26,6 +47,10 @@ func DefaultParams() Params { return NewParams( DefaultCommissionChangeTime, DefaultLeavePoolTime, + DefaultStakeFractionChangeTime, + DefaultVoteSlash, + DefaultUploadSlash, + DefaultTimeoutSlash, ) } @@ -39,5 +64,21 @@ func (p Params) Validate() error { return err } + if err := util.ValidateNumber(p.StakeFractionChangeTime); err != nil { + return err + } + + if err := util.ValidatePercentage(p.VoteSlash); err != nil { + return err + } + + if err := util.ValidatePercentage(p.UploadSlash); err != nil { + return err + } + + if err := util.ValidatePercentage(p.TimeoutSlash); err != nil { + return err + } + return nil } diff --git a/x/stakers/types/params.pb.go b/x/stakers/types/params.pb.go index 44ba4821..b2cd010d 100644 --- a/x/stakers/types/params.pb.go +++ b/x/stakers/types/params.pb.go @@ -4,7 +4,9 @@ package types import ( + cosmossdk_io_math "cosmossdk.io/math" fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" math "math" @@ -28,6 +30,14 @@ type Params struct { CommissionChangeTime uint64 `protobuf:"varint,1,opt,name=commission_change_time,json=commissionChangeTime,proto3" json:"commission_change_time,omitempty"` // commission_change_time ... LeavePoolTime uint64 `protobuf:"varint,2,opt,name=leave_pool_time,json=leavePoolTime,proto3" json:"leave_pool_time,omitempty"` + // stake_fraction_change_time ... + StakeFractionChangeTime uint64 `protobuf:"varint,3,opt,name=stake_fraction_change_time,json=stakeFractionChangeTime,proto3" json:"stake_fraction_change_time,omitempty"` + // vote_slash ... + VoteSlash cosmossdk_io_math.LegacyDec `protobuf:"bytes,4,opt,name=vote_slash,json=voteSlash,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"vote_slash"` + // upload_slash ... + UploadSlash cosmossdk_io_math.LegacyDec `protobuf:"bytes,5,opt,name=upload_slash,json=uploadSlash,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"upload_slash"` + // timeout_slash ... + TimeoutSlash cosmossdk_io_math.LegacyDec `protobuf:"bytes,6,opt,name=timeout_slash,json=timeoutSlash,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"timeout_slash"` } func (m *Params) Reset() { *m = Params{} } @@ -77,6 +87,13 @@ func (m *Params) GetLeavePoolTime() uint64 { return 0 } +func (m *Params) GetStakeFractionChangeTime() uint64 { + if m != nil { + return m.StakeFractionChangeTime + } + return 0 +} + func init() { proto.RegisterType((*Params)(nil), "kyve.stakers.v1beta1.Params") } @@ -84,21 +101,29 @@ func init() { func init() { proto.RegisterFile("kyve/stakers/v1beta1/params.proto", fileDescriptor_405cabd7005fc18b) } var fileDescriptor_405cabd7005fc18b = []byte{ - // 219 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xcc, 0xae, 0x2c, 0x4b, - 0xd5, 0x2f, 0x2e, 0x49, 0xcc, 0x4e, 0x2d, 0x2a, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, - 0xd4, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x01, - 0x29, 0xd1, 0x83, 0x2a, 0xd1, 0x83, 0x2a, 0x51, 0x4a, 0xe3, 0x62, 0x0b, 0x00, 0xab, 0x12, 0x32, - 0xe1, 0x12, 0x4b, 0xce, 0xcf, 0xcd, 0xcd, 0x2c, 0x2e, 0xce, 0xcc, 0xcf, 0x8b, 0x4f, 0xce, 0x48, - 0xcc, 0x4b, 0x4f, 0x8d, 0x2f, 0xc9, 0xcc, 0x4d, 0x95, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x09, 0x12, - 0x41, 0xc8, 0x3a, 0x83, 0x25, 0x43, 0x32, 0x73, 0x53, 0x85, 0xd4, 0xb8, 0xf8, 0x73, 0x52, 0x13, - 0xcb, 0x52, 0xe3, 0x0b, 0xf2, 0xf3, 0x73, 0x20, 0xca, 0x99, 0xc0, 0xca, 0x79, 0xc1, 0xc2, 0x01, - 0xf9, 0xf9, 0x39, 0x20, 0x75, 0x4e, 0x6e, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, - 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, - 0x10, 0xa5, 0x93, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0xef, 0x1d, 0x19, - 0xe6, 0xea, 0x97, 0x5a, 0x52, 0x9e, 0x5f, 0x94, 0xad, 0x9f, 0x9c, 0x91, 0x98, 0x99, 0xa7, 0x5f, - 0x01, 0xf7, 0x54, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0x33, 0xc6, 0x80, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x44, 0x61, 0x13, 0x9a, 0xf1, 0x00, 0x00, 0x00, + // 347 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x41, 0x4b, 0xc3, 0x30, + 0x14, 0x80, 0xdb, 0x39, 0x07, 0x8b, 0x1b, 0x42, 0x19, 0x3a, 0x26, 0x74, 0x53, 0x41, 0x76, 0x90, + 0x86, 0xa1, 0x37, 0x6f, 0x53, 0x87, 0xa0, 0xc8, 0x98, 0x22, 0xe8, 0xa5, 0x64, 0x59, 0x6c, 0x43, + 0x9b, 0xbd, 0xd2, 0x64, 0xd5, 0xfd, 0x0b, 0x7f, 0xd6, 0x8e, 0x3b, 0x8a, 0x87, 0x21, 0xdb, 0xaf, + 0xf0, 0x26, 0x4d, 0x8b, 0x8a, 0xa7, 0xdd, 0x4a, 0xf3, 0x7d, 0xdf, 0x7b, 0xf0, 0xd0, 0x7e, 0x30, + 0x4d, 0x18, 0x96, 0x8a, 0x04, 0x2c, 0x96, 0x38, 0xe9, 0x0c, 0x99, 0x22, 0x1d, 0x1c, 0x91, 0x98, + 0x08, 0xe9, 0x44, 0x31, 0x28, 0xb0, 0x6a, 0x29, 0xe2, 0xe4, 0x88, 0x93, 0x23, 0x8d, 0x9a, 0x07, + 0x1e, 0x68, 0x00, 0xa7, 0x5f, 0x19, 0x7b, 0xf0, 0x55, 0x40, 0xa5, 0xbe, 0x96, 0xad, 0x53, 0xb4, + 0x43, 0x41, 0x08, 0x2e, 0x25, 0x87, 0xb1, 0x4b, 0x7d, 0x32, 0xf6, 0x98, 0xab, 0xb8, 0x60, 0x75, + 0xb3, 0x65, 0xb6, 0x8b, 0x83, 0xda, 0xef, 0xeb, 0xb9, 0x7e, 0xbc, 0xe7, 0x82, 0x59, 0x47, 0x68, + 0x3b, 0x64, 0x24, 0x61, 0x6e, 0x04, 0x10, 0x66, 0x78, 0x41, 0xe3, 0x55, 0xfd, 0xbb, 0x0f, 0x10, + 0x6a, 0xee, 0x0c, 0x35, 0xf4, 0x46, 0xee, 0x73, 0x4c, 0xa8, 0xfa, 0x3f, 0x61, 0x43, 0x2b, 0xbb, + 0x9a, 0xe8, 0xe5, 0xc0, 0x9f, 0x21, 0x5d, 0x84, 0x12, 0x50, 0xcc, 0x95, 0x21, 0x91, 0x7e, 0xbd, + 0xd8, 0x32, 0xdb, 0xe5, 0xee, 0xe1, 0x6c, 0xd1, 0x34, 0x3e, 0x16, 0xcd, 0x3d, 0x0a, 0x52, 0x80, + 0x94, 0xa3, 0xc0, 0xe1, 0x80, 0x05, 0x51, 0xbe, 0x73, 0xc3, 0x3c, 0x42, 0xa7, 0x17, 0x8c, 0x0e, + 0xca, 0xa9, 0x76, 0x97, 0x5a, 0x56, 0x0f, 0x55, 0x26, 0x51, 0x08, 0x64, 0x94, 0x57, 0x36, 0xd7, + 0xaf, 0x6c, 0x65, 0x62, 0xd6, 0xb9, 0x42, 0xd5, 0x74, 0x65, 0x98, 0xa8, 0x3c, 0x54, 0x5a, 0x3f, + 0x54, 0xc9, 0x4d, 0x5d, 0xea, 0xf6, 0x66, 0x4b, 0xdb, 0x9c, 0x2f, 0x6d, 0xf3, 0x73, 0x69, 0x9b, + 0x6f, 0x2b, 0xdb, 0x98, 0xaf, 0x6c, 0xe3, 0x7d, 0x65, 0x1b, 0x4f, 0xc7, 0x1e, 0x57, 0xfe, 0x64, + 0xe8, 0x50, 0x10, 0xf8, 0xfa, 0xf1, 0xe1, 0xf2, 0x96, 0xa9, 0x17, 0x88, 0x03, 0x4c, 0x7d, 0xc2, + 0xc7, 0xf8, 0xf5, 0xe7, 0xfc, 0x6a, 0x1a, 0x31, 0x39, 0x2c, 0xe9, 0x53, 0x9e, 0x7c, 0x07, 0x00, + 0x00, 0xff, 0xff, 0xc8, 0xcb, 0x77, 0x48, 0x1b, 0x02, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -121,6 +146,41 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.TimeoutSlash.Size() + i -= size + if _, err := m.TimeoutSlash.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + { + size := m.UploadSlash.Size() + i -= size + if _, err := m.UploadSlash.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + { + size := m.VoteSlash.Size() + i -= size + if _, err := m.VoteSlash.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.StakeFractionChangeTime != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.StakeFractionChangeTime)) + i-- + dAtA[i] = 0x18 + } if m.LeavePoolTime != 0 { i = encodeVarintParams(dAtA, i, uint64(m.LeavePoolTime)) i-- @@ -157,6 +217,15 @@ func (m *Params) Size() (n int) { if m.LeavePoolTime != 0 { n += 1 + sovParams(uint64(m.LeavePoolTime)) } + if m.StakeFractionChangeTime != 0 { + n += 1 + sovParams(uint64(m.StakeFractionChangeTime)) + } + l = m.VoteSlash.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.UploadSlash.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.TimeoutSlash.Size() + n += 1 + l + sovParams(uint64(l)) return n } @@ -233,6 +302,127 @@ func (m *Params) Unmarshal(dAtA []byte) error { break } } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFractionChangeTime", wireType) + } + m.StakeFractionChangeTime = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.StakeFractionChangeTime |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteSlash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + 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 ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.VoteSlash.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UploadSlash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + 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 ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.UploadSlash.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeoutSlash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + 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 ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.TimeoutSlash.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/stakers/types/stakers.pb.go b/x/stakers/types/stakers.pb.go index 58491d2b..b82f2d01 100644 --- a/x/stakers/types/stakers.pb.go +++ b/x/stakers/types/stakers.pb.go @@ -184,6 +184,10 @@ type Valaccount struct { Points uint64 `protobuf:"varint,4,opt,name=points,proto3" json:"points,omitempty"` // isLeaving indicates if a staker is leaving the given pool. IsLeaving bool `protobuf:"varint,5,opt,name=is_leaving,json=isLeaving,proto3" json:"is_leaving,omitempty"` + // commission ... + Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,6,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` + // stake_fraction ... + StakeFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,7,opt,name=stake_fraction,json=stakeFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"stake_fraction"` } func (m *Valaccount) Reset() { *m = Valaccount{} } @@ -264,12 +268,14 @@ type CommissionChangeEntry struct { Index uint64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` // staker is the address of the affected staker Staker string `protobuf:"bytes,2,opt,name=staker,proto3" json:"staker,omitempty"` + // pool_id ... + PoolId uint64 `protobuf:"varint,3,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` // commission is the new commission which will // be applied after the waiting time is over. - Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,3,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` + Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,4,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` // creation_date is the UNIX-timestamp in seconds // when the entry was created. - CreationDate int64 `protobuf:"varint,4,opt,name=creation_date,json=creationDate,proto3" json:"creation_date,omitempty"` + CreationDate int64 `protobuf:"varint,5,opt,name=creation_date,json=creationDate,proto3" json:"creation_date,omitempty"` } func (m *CommissionChangeEntry) Reset() { *m = CommissionChangeEntry{} } @@ -319,6 +325,13 @@ func (m *CommissionChangeEntry) GetStaker() string { return "" } +func (m *CommissionChangeEntry) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + func (m *CommissionChangeEntry) GetCreationDate() int64 { if m != nil { return m.CreationDate @@ -326,6 +339,87 @@ func (m *CommissionChangeEntry) GetCreationDate() int64 { return 0 } +// StakeFractionChangeEntry stores the information for an +// upcoming stake fraction change. A stake fraction change is +// only instant if it gets increased, if it gets decreased +// the staker needs to wait for the stake fraction change time +type StakeFractionChangeEntry struct { + // index is needed for the queue-algorithm which + // processes the commission changes + Index uint64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + // staker is the address of the affected staker + Staker string `protobuf:"bytes,2,opt,name=staker,proto3" json:"staker,omitempty"` + // pool_id ... + PoolId uint64 `protobuf:"varint,3,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + // stake_fraction is the new stake fraction which will + // be applied after the waiting time is over. + StakeFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,4,opt,name=stake_fraction,json=stakeFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"stake_fraction"` + // creation_date is the UNIX-timestamp in seconds + // when the entry was created. + CreationDate int64 `protobuf:"varint,5,opt,name=creation_date,json=creationDate,proto3" json:"creation_date,omitempty"` +} + +func (m *StakeFractionChangeEntry) Reset() { *m = StakeFractionChangeEntry{} } +func (m *StakeFractionChangeEntry) String() string { return proto.CompactTextString(m) } +func (*StakeFractionChangeEntry) ProtoMessage() {} +func (*StakeFractionChangeEntry) Descriptor() ([]byte, []int) { + return fileDescriptor_d209d1a2a74d375d, []int{3} +} +func (m *StakeFractionChangeEntry) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *StakeFractionChangeEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_StakeFractionChangeEntry.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 *StakeFractionChangeEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_StakeFractionChangeEntry.Merge(m, src) +} +func (m *StakeFractionChangeEntry) XXX_Size() int { + return m.Size() +} +func (m *StakeFractionChangeEntry) XXX_DiscardUnknown() { + xxx_messageInfo_StakeFractionChangeEntry.DiscardUnknown(m) +} + +var xxx_messageInfo_StakeFractionChangeEntry proto.InternalMessageInfo + +func (m *StakeFractionChangeEntry) GetIndex() uint64 { + if m != nil { + return m.Index + } + return 0 +} + +func (m *StakeFractionChangeEntry) GetStaker() string { + if m != nil { + return m.Staker + } + return "" +} + +func (m *StakeFractionChangeEntry) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + +func (m *StakeFractionChangeEntry) GetCreationDate() int64 { + if m != nil { + return m.CreationDate + } + return 0 +} + // LeavePoolEntry stores the information for an upcoming // pool leave. A staker can't leave a pool instantly. // Instead a the `LeaveTime` needs to be awaited. @@ -348,7 +442,7 @@ func (m *LeavePoolEntry) Reset() { *m = LeavePoolEntry{} } func (m *LeavePoolEntry) String() string { return proto.CompactTextString(m) } func (*LeavePoolEntry) ProtoMessage() {} func (*LeavePoolEntry) Descriptor() ([]byte, []int) { - return fileDescriptor_d209d1a2a74d375d, []int{3} + return fileDescriptor_d209d1a2a74d375d, []int{4} } func (m *LeavePoolEntry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -420,7 +514,7 @@ func (m *QueueState) Reset() { *m = QueueState{} } func (m *QueueState) String() string { return proto.CompactTextString(m) } func (*QueueState) ProtoMessage() {} func (*QueueState) Descriptor() ([]byte, []int) { - return fileDescriptor_d209d1a2a74d375d, []int{4} + return fileDescriptor_d209d1a2a74d375d, []int{5} } func (m *QueueState) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -468,6 +562,7 @@ func init() { proto.RegisterType((*Staker)(nil), "kyve.stakers.v1beta1.Staker") proto.RegisterType((*Valaccount)(nil), "kyve.stakers.v1beta1.Valaccount") proto.RegisterType((*CommissionChangeEntry)(nil), "kyve.stakers.v1beta1.CommissionChangeEntry") + proto.RegisterType((*StakeFractionChangeEntry)(nil), "kyve.stakers.v1beta1.StakeFractionChangeEntry") proto.RegisterType((*LeavePoolEntry)(nil), "kyve.stakers.v1beta1.LeavePoolEntry") proto.RegisterType((*QueueState)(nil), "kyve.stakers.v1beta1.QueueState") } @@ -477,51 +572,54 @@ func init() { } var fileDescriptor_d209d1a2a74d375d = []byte{ - // 696 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x41, 0x4f, 0x13, 0x4f, - 0x14, 0xef, 0xb6, 0x50, 0xda, 0xf7, 0xff, 0x2b, 0x65, 0x04, 0x5c, 0x4b, 0x58, 0x48, 0xb9, 0x20, - 0xd1, 0xdd, 0xa0, 0xf1, 0x03, 0x40, 0x5b, 0x42, 0x63, 0x85, 0xba, 0x2d, 0x24, 0x78, 0x69, 0xa6, - 0xbb, 0x93, 0x76, 0xd2, 0xed, 0x4e, 0xdd, 0x99, 0xb6, 0x34, 0x31, 0xf1, 0xea, 0xd1, 0x83, 0xdf, - 0xc0, 0x8b, 0xf1, 0xa2, 0x1f, 0x83, 0x23, 0x47, 0xe3, 0x01, 0x0d, 0x1c, 0xfc, 0x14, 0x26, 0x66, - 0x67, 0xb6, 0x65, 0x39, 0x98, 0x18, 0x2e, 0xbb, 0xf3, 0xfb, 0xfd, 0xde, 0xbc, 0xf7, 0xe6, 0x37, - 0x2f, 0x03, 0x85, 0xee, 0x78, 0x48, 0x2c, 0x2e, 0x70, 0x97, 0x04, 0xdc, 0x1a, 0x6e, 0xb7, 0x88, - 0xc0, 0xdb, 0x13, 0x6c, 0xf6, 0x03, 0x26, 0x18, 0x5a, 0x0c, 0x63, 0xcc, 0x09, 0x17, 0xc5, 0xe4, - 0x17, 0x70, 0x8f, 0xfa, 0xcc, 0x92, 0x5f, 0x15, 0x98, 0x37, 0x1c, 0xc6, 0x7b, 0x8c, 0x5b, 0x2d, - 0xcc, 0xc9, 0x34, 0x97, 0xc3, 0xa8, 0x1f, 0xe9, 0x8b, 0x6d, 0xd6, 0x66, 0x72, 0x69, 0x85, 0x2b, - 0xc5, 0x16, 0x7e, 0x27, 0x21, 0x5d, 0x97, 0xc9, 0x91, 0x0e, 0x73, 0xd8, 0x75, 0x03, 0xc2, 0xb9, - 0xae, 0xad, 0x6b, 0x9b, 0x59, 0x7b, 0x02, 0x51, 0x11, 0xc0, 0x61, 0xbd, 0x1e, 0xe5, 0x9c, 0x32, - 0x5f, 0x4f, 0x86, 0xe2, 0xee, 0xc6, 0xd9, 0xc5, 0x5a, 0xe2, 0xfb, 0xc5, 0xda, 0x8a, 0x2a, 0xcb, - 0xdd, 0xae, 0x49, 0x99, 0xd5, 0xc3, 0xa2, 0x63, 0x56, 0x49, 0x1b, 0x3b, 0xe3, 0x12, 0x71, 0xec, - 0xd8, 0xb6, 0x30, 0x7d, 0x8f, 0xf9, 0xb4, 0x4b, 0x02, 0x3d, 0xa5, 0xd2, 0x47, 0x30, 0x54, 0x46, - 0xa4, 0xc5, 0xa9, 0x20, 0xfa, 0x8c, 0x52, 0x22, 0x88, 0xf2, 0x90, 0xa1, 0x2e, 0xf1, 0x05, 0x15, - 0x63, 0x7d, 0x56, 0x4a, 0x53, 0x8c, 0x1e, 0x42, 0x8e, 0x13, 0x67, 0x10, 0x50, 0x31, 0x6e, 0x3a, - 0xcc, 0x17, 0xd8, 0x11, 0x7a, 0x5a, 0xc6, 0xcc, 0x4f, 0xf8, 0xa2, 0xa2, 0xc3, 0x02, 0x2e, 0x11, - 0x98, 0x7a, 0x5c, 0x9f, 0x53, 0x05, 0x22, 0x88, 0xde, 0x02, 0xba, 0x6e, 0xb1, 0x19, 0x90, 0x11, - 0x0e, 0x5c, 0xae, 0x67, 0xd6, 0x53, 0x9b, 0xff, 0x3d, 0x79, 0x60, 0xaa, 0xa3, 0x99, 0xa1, 0xa3, - 0x13, 0xe7, 0xcd, 0x22, 0xa3, 0xfe, 0xee, 0xb3, 0xf0, 0xf0, 0x9f, 0x7f, 0xac, 0x6d, 0xb6, 0xa9, - 0xe8, 0x0c, 0x5a, 0xa6, 0xc3, 0x7a, 0x56, 0x64, 0xbf, 0xfa, 0x3d, 0xe6, 0x6e, 0xd7, 0x12, 0xe3, - 0x3e, 0xe1, 0x72, 0x03, 0xff, 0xf4, 0xeb, 0xeb, 0x96, 0x66, 0x2f, 0x5c, 0xd7, 0xb2, 0x55, 0xa9, - 0xc2, 0x07, 0x0d, 0xe0, 0x18, 0x7b, 0xd8, 0x71, 0xd8, 0xc0, 0x17, 0xe8, 0x3e, 0xcc, 0xf5, 0x19, - 0xf3, 0x9a, 0xd4, 0x95, 0x77, 0x30, 0x63, 0xa7, 0x43, 0x58, 0x71, 0xd1, 0x32, 0xa4, 0xd5, 0x0c, - 0x28, 0xfb, 0xed, 0x08, 0x21, 0x03, 0x60, 0x88, 0xbd, 0xc9, 0xbd, 0x29, 0x63, 0x63, 0x4c, 0xb8, - 0xaf, 0xcf, 0xa8, 0x2f, 0xb8, 0xb4, 0x56, 0xe6, 0x0b, 0x11, 0x5a, 0x05, 0xa0, 0xbc, 0xe9, 0x11, - 0x3c, 0xa4, 0x7e, 0x5b, 0x7a, 0x9b, 0xb1, 0xb3, 0x94, 0x57, 0x15, 0x51, 0xf8, 0xa2, 0xc1, 0x52, - 0x71, 0xda, 0x6c, 0xb1, 0x83, 0xfd, 0x36, 0x29, 0xfb, 0x22, 0x18, 0xa3, 0x45, 0x98, 0xa5, 0xbe, - 0x4b, 0x4e, 0xa3, 0xfe, 0x14, 0xf8, 0x6b, 0x7b, 0x37, 0x27, 0x27, 0x75, 0xbb, 0xc9, 0xd9, 0x80, - 0x3b, 0x4e, 0x40, 0xb0, 0x08, 0xaf, 0xc8, 0xc5, 0xd1, 0x94, 0xa4, 0xec, 0xff, 0x27, 0x64, 0x09, - 0x0b, 0x52, 0x78, 0x03, 0x77, 0xc3, 0xe6, 0x49, 0x8d, 0x31, 0xef, 0x36, 0x9d, 0xc6, 0x9c, 0x4f, - 0xdd, 0x70, 0xfe, 0x9f, 0xaa, 0xef, 0x03, 0xbc, 0x1c, 0x90, 0x01, 0xa9, 0x0b, 0x2c, 0x08, 0x5a, - 0x81, 0xac, 0xc7, 0x46, 0xcd, 0x78, 0xf5, 0x8c, 0xc7, 0x46, 0x15, 0xd9, 0xc0, 0x2a, 0x40, 0x87, - 0xb6, 0x3b, 0x91, 0x9a, 0x94, 0x6a, 0x36, 0x64, 0xa4, 0xbc, 0xf5, 0x1a, 0xb2, 0x75, 0x0f, 0xf3, - 0x4e, 0x63, 0xdc, 0x0f, 0xe7, 0x7f, 0xb9, 0x5e, 0xdd, 0xa9, 0xef, 0x37, 0x1b, 0x27, 0xb5, 0x72, - 0xf3, 0xe8, 0xa0, 0x5e, 0x2b, 0x17, 0x2b, 0x7b, 0x95, 0x72, 0x29, 0x97, 0x40, 0xcb, 0x80, 0x62, - 0x5a, 0xa3, 0xf2, 0xa2, 0x7c, 0x78, 0xd4, 0xc8, 0x69, 0xe8, 0x1e, 0xcc, 0xc7, 0xf8, 0xe3, 0xc3, - 0x46, 0x39, 0x97, 0x44, 0x4b, 0xb0, 0x10, 0x4f, 0x54, 0xab, 0x1e, 0xee, 0x94, 0x72, 0xa9, 0xfc, - 0xcc, 0xbb, 0x8f, 0x46, 0x62, 0x77, 0xef, 0xec, 0xd2, 0xd0, 0xce, 0x2f, 0x0d, 0xed, 0xe7, 0xa5, - 0xa1, 0xbd, 0xbf, 0x32, 0x12, 0xe7, 0x57, 0x46, 0xe2, 0xdb, 0x95, 0x91, 0x78, 0xf5, 0x28, 0x36, - 0xdf, 0xcf, 0x4f, 0x8e, 0xcb, 0x07, 0x44, 0x8c, 0x58, 0xd0, 0xb5, 0x9c, 0x0e, 0xa6, 0xbe, 0x75, - 0x3a, 0x7d, 0xba, 0xe4, 0xa4, 0xb7, 0xd2, 0xf2, 0x49, 0x79, 0xfa, 0x27, 0x00, 0x00, 0xff, 0xff, - 0x5f, 0xcc, 0xa7, 0xe7, 0xd7, 0x04, 0x00, 0x00, + // 750 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x4f, 0x4f, 0xdb, 0x48, + 0x1c, 0x8d, 0x93, 0x90, 0x3f, 0xb3, 0x0b, 0x84, 0x59, 0x60, 0xbd, 0x41, 0x18, 0x14, 0x2e, 0x2c, + 0xda, 0xb5, 0x45, 0xab, 0x7e, 0x00, 0x48, 0x82, 0x48, 0x9b, 0x42, 0xea, 0x04, 0x24, 0x7a, 0xb1, + 0x26, 0xf6, 0x34, 0x19, 0xc5, 0xf1, 0xa4, 0x9e, 0x49, 0x42, 0xa4, 0x4a, 0xbd, 0xf6, 0xd8, 0xef, + 0x50, 0x55, 0xaa, 0x7a, 0xea, 0xc7, 0xe0, 0x88, 0x7a, 0xaa, 0x7a, 0xa0, 0x15, 0x1c, 0xfa, 0x29, + 0x2a, 0x55, 0x33, 0x76, 0x82, 0x29, 0xad, 0x84, 0x50, 0x7b, 0x49, 0xfc, 0xde, 0x9b, 0xdf, 0xfb, + 0xcd, 0xef, 0x8d, 0x35, 0x06, 0x85, 0xce, 0x68, 0x80, 0x0d, 0xc6, 0x51, 0x07, 0xfb, 0xcc, 0x18, + 0x6c, 0x36, 0x31, 0x47, 0x9b, 0x63, 0xac, 0xf7, 0x7c, 0xca, 0x29, 0x9c, 0x17, 0x6b, 0xf4, 0x31, + 0x17, 0xae, 0xc9, 0xcf, 0xa1, 0x2e, 0xf1, 0xa8, 0x21, 0x7f, 0x83, 0x85, 0x79, 0xcd, 0xa6, 0xac, + 0x4b, 0x99, 0xd1, 0x44, 0x0c, 0x4f, 0xbc, 0x6c, 0x4a, 0xbc, 0x50, 0x9f, 0x6f, 0xd1, 0x16, 0x95, + 0x8f, 0x86, 0x78, 0x0a, 0xd8, 0xc2, 0xd7, 0x38, 0x48, 0xd5, 0xa5, 0x39, 0x54, 0x41, 0x1a, 0x39, + 0x8e, 0x8f, 0x19, 0x53, 0x95, 0x55, 0x65, 0x3d, 0x6b, 0x8e, 0x21, 0x2c, 0x02, 0x60, 0xd3, 0x6e, + 0x97, 0x30, 0x46, 0xa8, 0xa7, 0xc6, 0x85, 0xb8, 0xbd, 0x76, 0x72, 0xb6, 0x12, 0xfb, 0x78, 0xb6, + 0xb2, 0x14, 0xb4, 0x65, 0x4e, 0x47, 0x27, 0xd4, 0xe8, 0x22, 0xde, 0xd6, 0xab, 0xb8, 0x85, 0xec, + 0x51, 0x09, 0xdb, 0x66, 0xa4, 0x4c, 0xd8, 0x77, 0xa9, 0x47, 0x3a, 0xd8, 0x57, 0x13, 0x81, 0x7d, + 0x08, 0x85, 0x32, 0xc4, 0x4d, 0x46, 0x38, 0x56, 0x93, 0x81, 0x12, 0x42, 0x98, 0x07, 0x19, 0xe2, + 0x60, 0x8f, 0x13, 0x3e, 0x52, 0xa7, 0xa4, 0x34, 0xc1, 0xf0, 0x5f, 0x90, 0x63, 0xd8, 0xee, 0xfb, + 0x84, 0x8f, 0x2c, 0x9b, 0x7a, 0x1c, 0xd9, 0x5c, 0x4d, 0xc9, 0x35, 0xb3, 0x63, 0xbe, 0x18, 0xd0, + 0xa2, 0x81, 0x83, 0x39, 0x22, 0x2e, 0x53, 0xd3, 0x41, 0x83, 0x10, 0xc2, 0xe7, 0x00, 0x5e, 0x6e, + 0xd1, 0xf2, 0xf1, 0x10, 0xf9, 0x0e, 0x53, 0x33, 0xab, 0x89, 0xf5, 0x3f, 0xee, 0xfc, 0xa3, 0x07, + 0xa3, 0xe9, 0x22, 0xd1, 0x71, 0xf2, 0x7a, 0x91, 0x12, 0x6f, 0xfb, 0x9e, 0x18, 0xfe, 0xed, 0xa7, + 0x95, 0xf5, 0x16, 0xe1, 0xed, 0x7e, 0x53, 0xb7, 0x69, 0xd7, 0x08, 0xe3, 0x0f, 0xfe, 0xfe, 0x67, + 0x4e, 0xc7, 0xe0, 0xa3, 0x1e, 0x66, 0xb2, 0x80, 0xbd, 0xf9, 0xf2, 0x6e, 0x43, 0x31, 0xe7, 0x2e, + 0x7b, 0x99, 0x41, 0xab, 0xc2, 0xeb, 0x38, 0x00, 0x87, 0xc8, 0x45, 0xb6, 0x4d, 0xfb, 0x1e, 0x87, + 0x7f, 0x83, 0x74, 0x8f, 0x52, 0xd7, 0x22, 0x8e, 0x3c, 0x83, 0xa4, 0x99, 0x12, 0xb0, 0xe2, 0xc0, + 0x45, 0x90, 0x0a, 0xde, 0x81, 0x20, 0x7e, 0x33, 0x44, 0x50, 0x03, 0x60, 0x80, 0xdc, 0xf1, 0xb9, + 0x05, 0xc1, 0x46, 0x18, 0x51, 0xd7, 0xa3, 0xc4, 0xe3, 0x4c, 0x46, 0x2b, 0xfd, 0x04, 0x82, 0xcb, + 0x00, 0x10, 0x66, 0xb9, 0x18, 0x0d, 0x88, 0xd7, 0x92, 0xd9, 0x66, 0xcc, 0x2c, 0x61, 0xd5, 0x80, + 0xf8, 0xee, 0xc4, 0x53, 0xb7, 0x3b, 0xf1, 0xfb, 0x60, 0x46, 0xee, 0xd2, 0x7a, 0xe2, 0x23, 0x9b, + 0x0b, 0xa3, 0xf4, 0xcd, 0x8d, 0xa6, 0x65, 0xe9, 0x4e, 0x58, 0x59, 0x38, 0x51, 0xc0, 0x42, 0x71, + 0x62, 0x5d, 0x6c, 0x23, 0xaf, 0x85, 0xcb, 0x1e, 0xf7, 0x47, 0x70, 0x1e, 0x4c, 0x11, 0xcf, 0xc1, + 0xc7, 0x61, 0x60, 0x01, 0xf8, 0x69, 0x5e, 0x91, 0x80, 0x13, 0x57, 0x02, 0xbe, 0x3a, 0x71, 0xf2, + 0x76, 0x13, 0xaf, 0x81, 0x69, 0xdb, 0xc7, 0x48, 0xec, 0xd8, 0x72, 0x10, 0xc7, 0x32, 0xd8, 0x84, + 0xf9, 0xe7, 0x98, 0x2c, 0x21, 0x8e, 0x0b, 0xef, 0x15, 0xa0, 0xd6, 0xa3, 0xc3, 0xfd, 0x86, 0x69, + 0xae, 0x47, 0x9f, 0xbc, 0x6d, 0xf4, 0x37, 0x1b, 0xea, 0x19, 0x98, 0x11, 0xef, 0x0e, 0xae, 0x51, + 0xea, 0xfe, 0xd2, 0x49, 0xae, 0x75, 0x4f, 0xfe, 0xa0, 0xfb, 0x2e, 0x00, 0x8f, 0xfa, 0xb8, 0x8f, + 0xeb, 0x1c, 0x71, 0x0c, 0x97, 0x40, 0xd6, 0xa5, 0x43, 0x2b, 0xda, 0x3d, 0xe3, 0xd2, 0x61, 0x45, + 0x6e, 0x60, 0x19, 0x80, 0x36, 0x69, 0xb5, 0x43, 0x35, 0x2e, 0xd5, 0xac, 0x60, 0xa4, 0xbc, 0xf1, + 0x14, 0x64, 0xeb, 0x2e, 0x62, 0xed, 0xc6, 0xa8, 0x27, 0xae, 0x9f, 0xc5, 0x7a, 0x75, 0xab, 0xbe, + 0x6b, 0x35, 0x8e, 0x6a, 0x65, 0xeb, 0x60, 0xaf, 0x5e, 0x2b, 0x17, 0x2b, 0x3b, 0x95, 0x72, 0x29, + 0x17, 0x83, 0x8b, 0x00, 0x46, 0xb4, 0x46, 0xe5, 0x61, 0x79, 0xff, 0xa0, 0x91, 0x53, 0xe0, 0x5f, + 0x60, 0x36, 0xc2, 0x1f, 0xee, 0x37, 0xca, 0xb9, 0x38, 0x5c, 0x00, 0x73, 0x51, 0xa3, 0x5a, 0x75, + 0x7f, 0xab, 0x94, 0x4b, 0xe4, 0x93, 0x2f, 0x5e, 0x69, 0xb1, 0xed, 0x9d, 0x93, 0x73, 0x4d, 0x39, + 0x3d, 0xd7, 0x94, 0xcf, 0xe7, 0x9a, 0xf2, 0xf2, 0x42, 0x8b, 0x9d, 0x5e, 0x68, 0xb1, 0x0f, 0x17, + 0x5a, 0xec, 0xf1, 0x7f, 0x91, 0xeb, 0xe5, 0xc1, 0xd1, 0x61, 0x79, 0x0f, 0xf3, 0x21, 0xf5, 0x3b, + 0x86, 0xdd, 0x46, 0xc4, 0x33, 0x8e, 0x27, 0x5f, 0x0e, 0x79, 0xd1, 0x34, 0x53, 0xf2, 0x46, 0xbf, + 0xfb, 0x2d, 0x00, 0x00, 0xff, 0xff, 0x03, 0xe9, 0xa2, 0x1f, 0x56, 0x06, 0x00, 0x00, } func (m *Staker) Marshal() (dAtA []byte, err error) { @@ -633,6 +731,26 @@ func (m *Valaccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.StakeFraction.Size() + i -= size + if _, err := m.StakeFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStakers(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + { + size := m.Commission.Size() + i -= size + if _, err := m.Commission.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStakers(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 if m.IsLeaving { i-- if m.IsLeaving { @@ -693,7 +811,7 @@ func (m *CommissionChangeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { if m.CreationDate != 0 { i = encodeVarintStakers(dAtA, i, uint64(m.CreationDate)) i-- - dAtA[i] = 0x20 + dAtA[i] = 0x28 } { size := m.Commission.Size() @@ -704,7 +822,67 @@ func (m *CommissionChangeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintStakers(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x1a + dAtA[i] = 0x22 + if m.PoolId != 0 { + i = encodeVarintStakers(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x18 + } + if len(m.Staker) > 0 { + i -= len(m.Staker) + copy(dAtA[i:], m.Staker) + i = encodeVarintStakers(dAtA, i, uint64(len(m.Staker))) + i-- + dAtA[i] = 0x12 + } + if m.Index != 0 { + i = encodeVarintStakers(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *StakeFractionChangeEntry) 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 *StakeFractionChangeEntry) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StakeFractionChangeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CreationDate != 0 { + i = encodeVarintStakers(dAtA, i, uint64(m.CreationDate)) + i-- + dAtA[i] = 0x28 + } + { + size := m.StakeFraction.Size() + i -= size + if _, err := m.StakeFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStakers(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.PoolId != 0 { + i = encodeVarintStakers(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x18 + } if len(m.Staker) > 0 { i -= len(m.Staker) copy(dAtA[i:], m.Staker) @@ -873,6 +1051,10 @@ func (m *Valaccount) Size() (n int) { if m.IsLeaving { n += 2 } + l = m.Commission.Size() + n += 1 + l + sovStakers(uint64(l)) + l = m.StakeFraction.Size() + n += 1 + l + sovStakers(uint64(l)) return n } @@ -889,6 +1071,9 @@ func (m *CommissionChangeEntry) Size() (n int) { if l > 0 { n += 1 + l + sovStakers(uint64(l)) } + if m.PoolId != 0 { + n += 1 + sovStakers(uint64(m.PoolId)) + } l = m.Commission.Size() n += 1 + l + sovStakers(uint64(l)) if m.CreationDate != 0 { @@ -897,6 +1082,30 @@ func (m *CommissionChangeEntry) Size() (n int) { return n } +func (m *StakeFractionChangeEntry) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Index != 0 { + n += 1 + sovStakers(uint64(m.Index)) + } + l = len(m.Staker) + if l > 0 { + n += 1 + l + sovStakers(uint64(l)) + } + if m.PoolId != 0 { + n += 1 + sovStakers(uint64(m.PoolId)) + } + l = m.StakeFraction.Size() + n += 1 + l + sovStakers(uint64(l)) + if m.CreationDate != 0 { + n += 1 + sovStakers(uint64(m.CreationDate)) + } + return n +} + func (m *LeavePoolEntry) Size() (n int) { if m == nil { return 0 @@ -1401,6 +1610,74 @@ func (m *Valaccount) Unmarshal(dAtA []byte) error { } } m.IsLeaving = bool(v != 0) + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commission", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStakers + } + 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 ErrInvalidLengthStakers + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStakers + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Commission.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStakers + } + 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 ErrInvalidLengthStakers + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStakers + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StakeFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipStakers(dAtA[iNdEx:]) @@ -1503,6 +1780,25 @@ func (m *CommissionChangeEntry) Unmarshal(dAtA []byte) error { m.Staker = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStakers + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Commission", wireType) } @@ -1536,7 +1832,180 @@ func (m *CommissionChangeEntry) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CreationDate", wireType) + } + m.CreationDate = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStakers + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CreationDate |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipStakers(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStakers + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *StakeFractionChangeEntry) 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 ErrIntOverflowStakers + } + 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: StakeFractionChangeEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StakeFractionChangeEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStakers + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Staker", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStakers + } + 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 ErrInvalidLengthStakers + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStakers + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Staker = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStakers + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStakers + } + 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 ErrInvalidLengthStakers + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStakers + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StakeFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field CreationDate", wireType) } diff --git a/x/stakers/types/tx.pb.go b/x/stakers/types/tx.pb.go index c349403f..8a4695c8 100644 --- a/x/stakers/types/tx.pb.go +++ b/x/stakers/types/tx.pb.go @@ -31,12 +31,14 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// MsgUpdateCommission ... +// MsgUpdateCommission ... // TODO: create v1 types and rename new to MsgUpdatePoolCommission type MsgUpdateCommission struct { // creator ... Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + // pool_id ... + PoolId uint64 `protobuf:"varint,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` // commission ... - Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,2,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` + Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,3,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` } func (m *MsgUpdateCommission) Reset() { *m = MsgUpdateCommission{} } @@ -79,6 +81,13 @@ func (m *MsgUpdateCommission) GetCreator() string { return "" } +func (m *MsgUpdateCommission) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + // MsgUpdateCommissionResponse ... type MsgUpdateCommissionResponse struct { } @@ -116,7 +125,101 @@ func (m *MsgUpdateCommissionResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUpdateCommissionResponse proto.InternalMessageInfo -// MsgJoinPool ... +// MsgUpdateStakeFraction ... +type MsgUpdateStakeFraction struct { + // creator ... + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + // pool_id ... + PoolId uint64 `protobuf:"varint,2,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + // commission ... + StakeFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,3,opt,name=stake_fraction,json=stakeFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"stake_fraction"` +} + +func (m *MsgUpdateStakeFraction) Reset() { *m = MsgUpdateStakeFraction{} } +func (m *MsgUpdateStakeFraction) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateStakeFraction) ProtoMessage() {} +func (*MsgUpdateStakeFraction) Descriptor() ([]byte, []int) { + return fileDescriptor_f52b730e69b9fb06, []int{2} +} +func (m *MsgUpdateStakeFraction) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateStakeFraction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateStakeFraction.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 *MsgUpdateStakeFraction) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateStakeFraction.Merge(m, src) +} +func (m *MsgUpdateStakeFraction) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateStakeFraction) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateStakeFraction.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateStakeFraction proto.InternalMessageInfo + +func (m *MsgUpdateStakeFraction) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *MsgUpdateStakeFraction) GetPoolId() uint64 { + if m != nil { + return m.PoolId + } + return 0 +} + +// MsgUpdateStakeFractionResponse ... +type MsgUpdateStakeFractionResponse struct { +} + +func (m *MsgUpdateStakeFractionResponse) Reset() { *m = MsgUpdateStakeFractionResponse{} } +func (m *MsgUpdateStakeFractionResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateStakeFractionResponse) ProtoMessage() {} +func (*MsgUpdateStakeFractionResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f52b730e69b9fb06, []int{3} +} +func (m *MsgUpdateStakeFractionResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateStakeFractionResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateStakeFractionResponse.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 *MsgUpdateStakeFractionResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateStakeFractionResponse.Merge(m, src) +} +func (m *MsgUpdateStakeFractionResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateStakeFractionResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateStakeFractionResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateStakeFractionResponse proto.InternalMessageInfo + +// MsgJoinPool ... // TODO: create v1 types type MsgJoinPool struct { // creator ... Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` @@ -126,13 +229,17 @@ type MsgJoinPool struct { Valaddress string `protobuf:"bytes,3,opt,name=valaddress,proto3" json:"valaddress,omitempty"` // amount ... Amount uint64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + // commission ... + Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,5,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` + // stake_fraction ... + StakeFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,6,opt,name=stake_fraction,json=stakeFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"stake_fraction"` } func (m *MsgJoinPool) Reset() { *m = MsgJoinPool{} } func (m *MsgJoinPool) String() string { return proto.CompactTextString(m) } func (*MsgJoinPool) ProtoMessage() {} func (*MsgJoinPool) Descriptor() ([]byte, []int) { - return fileDescriptor_f52b730e69b9fb06, []int{2} + return fileDescriptor_f52b730e69b9fb06, []int{4} } func (m *MsgJoinPool) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -197,7 +304,7 @@ func (m *MsgJoinPoolResponse) Reset() { *m = MsgJoinPoolResponse{} } func (m *MsgJoinPoolResponse) String() string { return proto.CompactTextString(m) } func (*MsgJoinPoolResponse) ProtoMessage() {} func (*MsgJoinPoolResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f52b730e69b9fb06, []int{3} + return fileDescriptor_f52b730e69b9fb06, []int{5} } func (m *MsgJoinPoolResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -238,7 +345,7 @@ func (m *MsgLeavePool) Reset() { *m = MsgLeavePool{} } func (m *MsgLeavePool) String() string { return proto.CompactTextString(m) } func (*MsgLeavePool) ProtoMessage() {} func (*MsgLeavePool) Descriptor() ([]byte, []int) { - return fileDescriptor_f52b730e69b9fb06, []int{4} + return fileDescriptor_f52b730e69b9fb06, []int{6} } func (m *MsgLeavePool) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -289,7 +396,7 @@ func (m *MsgLeavePoolResponse) Reset() { *m = MsgLeavePoolResponse{} } func (m *MsgLeavePoolResponse) String() string { return proto.CompactTextString(m) } func (*MsgLeavePoolResponse) ProtoMessage() {} func (*MsgLeavePoolResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f52b730e69b9fb06, []int{5} + return fileDescriptor_f52b730e69b9fb06, []int{7} } func (m *MsgLeavePoolResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -330,7 +437,7 @@ func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } func (*MsgUpdateParams) ProtoMessage() {} func (*MsgUpdateParams) Descriptor() ([]byte, []int) { - return fileDescriptor_f52b730e69b9fb06, []int{6} + return fileDescriptor_f52b730e69b9fb06, []int{8} } func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -381,7 +488,7 @@ func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } func (*MsgUpdateParamsResponse) ProtoMessage() {} func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f52b730e69b9fb06, []int{7} + return fileDescriptor_f52b730e69b9fb06, []int{9} } func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -413,6 +520,8 @@ var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo func init() { proto.RegisterType((*MsgUpdateCommission)(nil), "kyve.stakers.v1beta1.MsgUpdateCommission") proto.RegisterType((*MsgUpdateCommissionResponse)(nil), "kyve.stakers.v1beta1.MsgUpdateCommissionResponse") + proto.RegisterType((*MsgUpdateStakeFraction)(nil), "kyve.stakers.v1beta1.MsgUpdateStakeFraction") + proto.RegisterType((*MsgUpdateStakeFractionResponse)(nil), "kyve.stakers.v1beta1.MsgUpdateStakeFractionResponse") proto.RegisterType((*MsgJoinPool)(nil), "kyve.stakers.v1beta1.MsgJoinPool") proto.RegisterType((*MsgJoinPoolResponse)(nil), "kyve.stakers.v1beta1.MsgJoinPoolResponse") proto.RegisterType((*MsgLeavePool)(nil), "kyve.stakers.v1beta1.MsgLeavePool") @@ -424,42 +533,46 @@ func init() { func init() { proto.RegisterFile("kyve/stakers/v1beta1/tx.proto", fileDescriptor_f52b730e69b9fb06) } var fileDescriptor_f52b730e69b9fb06 = []byte{ - // 549 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x4d, 0x6f, 0xd3, 0x40, - 0x10, 0x8d, 0x49, 0x49, 0xc9, 0x10, 0x01, 0x32, 0xa1, 0x71, 0x5d, 0xd5, 0x85, 0x20, 0x24, 0x1a, - 0x51, 0x5b, 0x01, 0x89, 0x43, 0x6f, 0xa4, 0x80, 0x04, 0x34, 0x50, 0x19, 0x81, 0xf8, 0x38, 0x54, - 0x1b, 0x7b, 0xb5, 0xb1, 0x12, 0x7b, 0x2c, 0xef, 0x26, 0x34, 0x37, 0xd4, 0x03, 0x67, 0xee, 0xfc, - 0x89, 0x1e, 0xf8, 0x11, 0x3d, 0x56, 0x9c, 0x10, 0x87, 0x0a, 0x25, 0x87, 0xfe, 0x0d, 0xe4, 0x6c, - 0xec, 0x84, 0x90, 0x92, 0xaa, 0x27, 0xfb, 0xed, 0x7b, 0x33, 0xef, 0xed, 0xce, 0x6a, 0x61, 0xb5, - 0xd5, 0xeb, 0x52, 0x8b, 0x0b, 0xd2, 0xa2, 0x11, 0xb7, 0xba, 0xd5, 0x06, 0x15, 0xa4, 0x6a, 0x89, - 0x3d, 0x33, 0x8c, 0x50, 0xa0, 0x5a, 0x8c, 0x69, 0x73, 0x44, 0x9b, 0x23, 0x5a, 0x2f, 0x39, 0xc8, - 0x7d, 0xe4, 0x96, 0xcf, 0x99, 0xd5, 0xad, 0xc6, 0x1f, 0x29, 0xd7, 0x97, 0x25, 0xb1, 0x3b, 0x44, - 0x96, 0x04, 0x23, 0xaa, 0xc8, 0x90, 0xa1, 0x5c, 0x8f, 0xff, 0xe4, 0x6a, 0x79, 0x5f, 0x81, 0xeb, - 0x75, 0xce, 0xde, 0x84, 0x2e, 0x11, 0x74, 0x0b, 0x7d, 0xdf, 0xe3, 0xdc, 0xc3, 0x40, 0xd5, 0x60, - 0xd1, 0x89, 0x28, 0x11, 0x18, 0x69, 0xca, 0x4d, 0xe5, 0x6e, 0xde, 0x4e, 0xa0, 0xba, 0x05, 0xe0, - 0xa4, 0x3a, 0xed, 0x42, 0x4c, 0xd6, 0x6e, 0x1f, 0x1e, 0xaf, 0x65, 0x7e, 0x1d, 0xaf, 0xad, 0x48, - 0x47, 0xee, 0xb6, 0x4c, 0x0f, 0x2d, 0x9f, 0x88, 0xa6, 0xb9, 0x4d, 0x19, 0x71, 0x7a, 0x8f, 0xa9, - 0x63, 0x4f, 0x94, 0x6d, 0x16, 0xf6, 0x4f, 0x0e, 0x2a, 0x49, 0xcb, 0xf2, 0x2a, 0xac, 0xcc, 0xc8, - 0x60, 0x53, 0x1e, 0x62, 0xc0, 0x69, 0xf9, 0x8b, 0x02, 0x97, 0xeb, 0x9c, 0x3d, 0x47, 0x2f, 0xd8, - 0x41, 0x6c, 0xff, 0x27, 0x5b, 0x09, 0x16, 0x43, 0xc4, 0xf6, 0xae, 0xe7, 0x0e, 0x83, 0x2d, 0xd8, - 0xb9, 0x18, 0x3e, 0x73, 0x55, 0x03, 0xa0, 0x4b, 0xda, 0xc4, 0x75, 0x23, 0xca, 0xb9, 0x96, 0x1d, - 0x56, 0x4d, 0xac, 0xa8, 0x4b, 0x90, 0x23, 0x3e, 0x76, 0x02, 0xa1, 0x2d, 0xc8, 0x3a, 0x89, 0xa6, - 0x72, 0xde, 0x18, 0x9e, 0x55, 0x92, 0x23, 0xcd, 0xf7, 0x0a, 0x0a, 0x75, 0xce, 0xb6, 0x29, 0xe9, - 0xd2, 0x73, 0xe6, 0x9b, 0xf2, 0x59, 0x82, 0xe2, 0x64, 0xc3, 0xd4, 0x88, 0xc3, 0xd5, 0xf4, 0x9c, - 0x76, 0x48, 0x44, 0x7c, 0xae, 0x3e, 0x84, 0x3c, 0xe9, 0x88, 0x26, 0x46, 0x9e, 0xe8, 0x49, 0xb7, - 0x9a, 0xf6, 0xe3, 0xfb, 0x46, 0x71, 0x34, 0xfa, 0x47, 0x72, 0x7f, 0xaf, 0x45, 0xe4, 0x05, 0xcc, - 0x1e, 0x4b, 0xe3, 0x8c, 0x21, 0xe9, 0xb5, 0x91, 0xc8, 0x24, 0x79, 0x3b, 0x81, 0x9b, 0x57, 0xe2, - 0x28, 0x63, 0x65, 0x79, 0x19, 0x4a, 0x53, 0xa6, 0x49, 0x9e, 0xfb, 0xdf, 0xb2, 0x90, 0xad, 0x73, - 0xa6, 0x86, 0x70, 0xed, 0x9f, 0x0b, 0xb4, 0x6e, 0xce, 0xba, 0xb9, 0xe6, 0x8c, 0x39, 0xeb, 0xd5, - 0x33, 0x4b, 0x13, 0x67, 0xf5, 0x1d, 0x5c, 0x4a, 0xaf, 0xc3, 0xad, 0x53, 0xcb, 0x13, 0x89, 0xbe, - 0x3e, 0x57, 0x92, 0x76, 0xfe, 0x08, 0xf9, 0xf1, 0x24, 0xcb, 0xa7, 0xd6, 0xa5, 0x1a, 0xbd, 0x32, - 0x5f, 0x93, 0x36, 0x77, 0xa1, 0xf0, 0xd7, 0xf4, 0xee, 0xcc, 0xd9, 0xb9, 0x94, 0xe9, 0x1b, 0x67, - 0x92, 0x25, 0x2e, 0xfa, 0xc5, 0xcf, 0x27, 0x07, 0x15, 0xa5, 0xf6, 0xf4, 0xb0, 0x6f, 0x28, 0x47, - 0x7d, 0x43, 0xf9, 0xdd, 0x37, 0x94, 0xaf, 0x03, 0x23, 0x73, 0x34, 0x30, 0x32, 0x3f, 0x07, 0x46, - 0xe6, 0xc3, 0x3d, 0xe6, 0x89, 0x66, 0xa7, 0x61, 0x3a, 0xe8, 0x5b, 0x2f, 0xde, 0xbf, 0x7d, 0xf2, - 0x92, 0x8a, 0x4f, 0x18, 0xb5, 0x2c, 0xa7, 0x49, 0xbc, 0xc0, 0xda, 0x4b, 0x5f, 0x23, 0xd1, 0x0b, - 0x29, 0x6f, 0xe4, 0x86, 0x2f, 0xc5, 0x83, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe4, 0xbe, 0x16, - 0xb1, 0xaa, 0x04, 0x00, 0x00, + // 622 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0x8d, 0xfb, 0x91, 0x92, 0xa1, 0x14, 0xe4, 0x86, 0xd6, 0x75, 0x55, 0xb7, 0x04, 0x21, 0x95, + 0xaa, 0xb5, 0x15, 0x40, 0x1c, 0x7a, 0x23, 0x85, 0x4a, 0x94, 0x06, 0x2a, 0x57, 0x20, 0x3e, 0x0e, + 0xd1, 0xc6, 0x5e, 0x1c, 0x2b, 0xb1, 0xd7, 0xf2, 0x6e, 0x42, 0x7d, 0x43, 0xfc, 0x02, 0x4e, 0x70, + 0xe0, 0xcc, 0xbd, 0x07, 0x7e, 0x44, 0x8f, 0x15, 0x27, 0xc4, 0xa1, 0x42, 0xc9, 0xa1, 0x7f, 0x03, + 0x39, 0x1b, 0x6f, 0xd2, 0x90, 0x2a, 0x6d, 0xc4, 0x29, 0x99, 0x9d, 0x37, 0xf3, 0xde, 0xbe, 0x5d, + 0xcf, 0xc2, 0x52, 0x35, 0x6a, 0x60, 0x83, 0x32, 0x54, 0xc5, 0x21, 0x35, 0x1a, 0xf9, 0x32, 0x66, + 0x28, 0x6f, 0xb0, 0x03, 0x3d, 0x08, 0x09, 0x23, 0x72, 0x36, 0x4e, 0xeb, 0x9d, 0xb4, 0xde, 0x49, + 0xab, 0xf3, 0x16, 0xa1, 0x1e, 0xa1, 0x86, 0x47, 0x1d, 0xa3, 0x91, 0x8f, 0x7f, 0x38, 0x5c, 0x5d, + 0xe0, 0x89, 0x52, 0x3b, 0x32, 0x78, 0xd0, 0x49, 0x65, 0x1d, 0xe2, 0x10, 0xbe, 0x1e, 0xff, 0xe3, + 0xab, 0xb9, 0x6f, 0x12, 0xcc, 0x16, 0xa9, 0xf3, 0x32, 0xb0, 0x11, 0xc3, 0x5b, 0xc4, 0xf3, 0x5c, + 0x4a, 0x5d, 0xe2, 0xcb, 0x0a, 0x4c, 0x59, 0x21, 0x46, 0x8c, 0x84, 0x8a, 0xb4, 0x22, 0xad, 0x66, + 0xcc, 0x24, 0x94, 0xe7, 0x61, 0x2a, 0x20, 0xa4, 0x56, 0x72, 0x6d, 0x65, 0x6c, 0x45, 0x5a, 0x9d, + 0x30, 0xd3, 0x71, 0xf8, 0xd4, 0x96, 0xb7, 0x00, 0x2c, 0xd1, 0x40, 0x19, 0x8f, 0xab, 0x0a, 0xb7, + 0x8f, 0x4e, 0x96, 0x53, 0xbf, 0x4f, 0x96, 0x17, 0xb9, 0x14, 0x6a, 0x57, 0x75, 0x97, 0x18, 0x1e, + 0x62, 0x15, 0x7d, 0x17, 0x3b, 0xc8, 0x8a, 0x1e, 0x63, 0xcb, 0xec, 0x29, 0xdb, 0x9c, 0xfe, 0x74, + 0x7a, 0xb8, 0x96, 0x70, 0xe5, 0x96, 0x60, 0x71, 0x80, 0x38, 0x13, 0xd3, 0x80, 0xf8, 0x14, 0xe7, + 0xbe, 0x4b, 0x30, 0x27, 0xf2, 0xfb, 0xb1, 0x47, 0xdb, 0x21, 0xb2, 0xd8, 0x88, 0xfa, 0x77, 0x60, + 0xa6, 0xed, 0x73, 0xe9, 0x7d, 0xa7, 0xc9, 0x65, 0xf6, 0x70, 0x8d, 0xf6, 0xd2, 0xf7, 0x6d, 0x63, + 0x05, 0xb4, 0xc1, 0x32, 0xc5, 0x4e, 0xbe, 0x8e, 0xc1, 0xd5, 0x22, 0x75, 0x76, 0x88, 0xeb, 0xef, + 0x11, 0x52, 0x1b, 0x45, 0xbe, 0x06, 0xd0, 0x40, 0x35, 0x64, 0xdb, 0x21, 0xa6, 0x94, 0x4b, 0x37, + 0x7b, 0x56, 0xe4, 0x39, 0x48, 0x23, 0x8f, 0xd4, 0x7d, 0xa6, 0x4c, 0xf0, 0x3a, 0x1e, 0xf5, 0x1d, + 0xdb, 0xe4, 0x48, 0xc7, 0x36, 0xc0, 0xbb, 0xf4, 0x7f, 0xf2, 0xee, 0x66, 0xfb, 0x7e, 0x26, 0xc6, + 0x08, 0xc3, 0x5e, 0xc0, 0x74, 0x91, 0x3a, 0xbb, 0x18, 0x35, 0xf0, 0x88, 0x86, 0xf5, 0xf1, 0xcc, + 0x41, 0xb6, 0xb7, 0xa1, 0x20, 0xa2, 0x70, 0x5d, 0x9c, 0xdd, 0x1e, 0x0a, 0x91, 0x47, 0xe5, 0x87, + 0x90, 0x41, 0x75, 0x56, 0x21, 0xa1, 0xcb, 0x22, 0xce, 0x56, 0x50, 0x7e, 0xfe, 0xd8, 0xc8, 0x76, + 0x3e, 0xb7, 0x47, 0xdc, 0xf0, 0x7d, 0x16, 0xba, 0xbe, 0x63, 0x76, 0xa1, 0xb1, 0xc6, 0x00, 0x45, + 0x35, 0x82, 0xb8, 0x92, 0x8c, 0x99, 0x84, 0x9b, 0x33, 0xb1, 0x94, 0x2e, 0x32, 0xb7, 0x00, 0xf3, + 0x7d, 0xa4, 0x89, 0x9e, 0x7b, 0x5f, 0x26, 0x60, 0xbc, 0x48, 0x1d, 0xf9, 0x35, 0x5c, 0x11, 0xb7, + 0xe5, 0x96, 0x3e, 0x68, 0x4a, 0xe8, 0x3d, 0xbe, 0xa9, 0x77, 0x87, 0x42, 0x12, 0x06, 0xf9, 0x1d, + 0x64, 0xba, 0xbe, 0xe6, 0xce, 0xad, 0x13, 0x18, 0x75, 0x6d, 0x38, 0x46, 0x34, 0x0f, 0xe0, 0xc6, + 0x3f, 0xb3, 0xe6, 0x7c, 0x6d, 0xfd, 0x50, 0x35, 0x7f, 0x61, 0xa8, 0x60, 0x8c, 0x60, 0x76, 0xd0, + 0x80, 0x58, 0x1f, 0xd2, 0xe9, 0x0c, 0x5a, 0x7d, 0x70, 0x19, 0xb4, 0xa0, 0xb6, 0x61, 0xfa, 0xcc, + 0xc5, 0xb9, 0x33, 0xa4, 0x0b, 0x87, 0xa9, 0x1b, 0x17, 0x82, 0x25, 0x2c, 0xea, 0xe4, 0xc7, 0xd3, + 0xc3, 0x35, 0xa9, 0xb0, 0x7d, 0xd4, 0xd4, 0xa4, 0xe3, 0xa6, 0x26, 0xfd, 0x69, 0x6a, 0xd2, 0xe7, + 0x96, 0x96, 0x3a, 0x6e, 0x69, 0xa9, 0x5f, 0x2d, 0x2d, 0xf5, 0x76, 0xdd, 0x71, 0x59, 0xa5, 0x5e, + 0xd6, 0x2d, 0xe2, 0x19, 0xcf, 0xde, 0xbc, 0x7a, 0xf2, 0x1c, 0xb3, 0x0f, 0x24, 0xac, 0x1a, 0x56, + 0x05, 0xb9, 0xbe, 0x71, 0x20, 0x1e, 0x1f, 0x16, 0x05, 0x98, 0x96, 0xd3, 0xed, 0x87, 0xe1, 0xfe, + 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x79, 0x09, 0x6c, 0x2c, 0x99, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -474,12 +587,14 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type MsgClient interface { - // UpdateCommission ... - UpdateCommission(ctx context.Context, in *MsgUpdateCommission, opts ...grpc.CallOption) (*MsgUpdateCommissionResponse, error) // JoinPool ... JoinPool(ctx context.Context, in *MsgJoinPool, opts ...grpc.CallOption) (*MsgJoinPoolResponse, error) // LeavePool ... LeavePool(ctx context.Context, in *MsgLeavePool, opts ...grpc.CallOption) (*MsgLeavePoolResponse, error) + // UpdateCommission ... + UpdateCommission(ctx context.Context, in *MsgUpdateCommission, opts ...grpc.CallOption) (*MsgUpdateCommissionResponse, error) + // UpdateStakeFraction ... + UpdateStakeFraction(ctx context.Context, in *MsgUpdateStakeFraction, opts ...grpc.CallOption) (*MsgUpdateStakeFractionResponse, error) // UpdateParams defines a governance operation for updating the x/stakers module // parameters. The authority is hard-coded to the x/gov module account. UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) @@ -493,15 +608,6 @@ func NewMsgClient(cc grpc1.ClientConn) MsgClient { return &msgClient{cc} } -func (c *msgClient) UpdateCommission(ctx context.Context, in *MsgUpdateCommission, opts ...grpc.CallOption) (*MsgUpdateCommissionResponse, error) { - out := new(MsgUpdateCommissionResponse) - err := c.cc.Invoke(ctx, "/kyve.stakers.v1beta1.Msg/UpdateCommission", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *msgClient) JoinPool(ctx context.Context, in *MsgJoinPool, opts ...grpc.CallOption) (*MsgJoinPoolResponse, error) { out := new(MsgJoinPoolResponse) err := c.cc.Invoke(ctx, "/kyve.stakers.v1beta1.Msg/JoinPool", in, out, opts...) @@ -520,6 +626,24 @@ func (c *msgClient) LeavePool(ctx context.Context, in *MsgLeavePool, opts ...grp return out, nil } +func (c *msgClient) UpdateCommission(ctx context.Context, in *MsgUpdateCommission, opts ...grpc.CallOption) (*MsgUpdateCommissionResponse, error) { + out := new(MsgUpdateCommissionResponse) + err := c.cc.Invoke(ctx, "/kyve.stakers.v1beta1.Msg/UpdateCommission", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateStakeFraction(ctx context.Context, in *MsgUpdateStakeFraction, opts ...grpc.CallOption) (*MsgUpdateStakeFractionResponse, error) { + out := new(MsgUpdateStakeFractionResponse) + err := c.cc.Invoke(ctx, "/kyve.stakers.v1beta1.Msg/UpdateStakeFraction", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { out := new(MsgUpdateParamsResponse) err := c.cc.Invoke(ctx, "/kyve.stakers.v1beta1.Msg/UpdateParams", in, out, opts...) @@ -531,12 +655,14 @@ func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts // MsgServer is the server API for Msg service. type MsgServer interface { - // UpdateCommission ... - UpdateCommission(context.Context, *MsgUpdateCommission) (*MsgUpdateCommissionResponse, error) // JoinPool ... JoinPool(context.Context, *MsgJoinPool) (*MsgJoinPoolResponse, error) // LeavePool ... LeavePool(context.Context, *MsgLeavePool) (*MsgLeavePoolResponse, error) + // UpdateCommission ... + UpdateCommission(context.Context, *MsgUpdateCommission) (*MsgUpdateCommissionResponse, error) + // UpdateStakeFraction ... + UpdateStakeFraction(context.Context, *MsgUpdateStakeFraction) (*MsgUpdateStakeFractionResponse, error) // UpdateParams defines a governance operation for updating the x/stakers module // parameters. The authority is hard-coded to the x/gov module account. UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) @@ -546,15 +672,18 @@ type MsgServer interface { type UnimplementedMsgServer struct { } -func (*UnimplementedMsgServer) UpdateCommission(ctx context.Context, req *MsgUpdateCommission) (*MsgUpdateCommissionResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateCommission not implemented") -} func (*UnimplementedMsgServer) JoinPool(ctx context.Context, req *MsgJoinPool) (*MsgJoinPoolResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method JoinPool not implemented") } func (*UnimplementedMsgServer) LeavePool(ctx context.Context, req *MsgLeavePool) (*MsgLeavePoolResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method LeavePool not implemented") } +func (*UnimplementedMsgServer) UpdateCommission(ctx context.Context, req *MsgUpdateCommission) (*MsgUpdateCommissionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateCommission not implemented") +} +func (*UnimplementedMsgServer) UpdateStakeFraction(ctx context.Context, req *MsgUpdateStakeFraction) (*MsgUpdateStakeFractionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateStakeFraction not implemented") +} func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") } @@ -563,56 +692,74 @@ func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) } -func _Msg_UpdateCommission_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgUpdateCommission) +func _Msg_JoinPool_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgJoinPool) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).UpdateCommission(ctx, in) + return srv.(MsgServer).JoinPool(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/kyve.stakers.v1beta1.Msg/UpdateCommission", + FullMethod: "/kyve.stakers.v1beta1.Msg/JoinPool", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).UpdateCommission(ctx, req.(*MsgUpdateCommission)) + return srv.(MsgServer).JoinPool(ctx, req.(*MsgJoinPool)) } return interceptor(ctx, in, info, handler) } -func _Msg_JoinPool_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgJoinPool) +func _Msg_LeavePool_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgLeavePool) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).JoinPool(ctx, in) + return srv.(MsgServer).LeavePool(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/kyve.stakers.v1beta1.Msg/JoinPool", + FullMethod: "/kyve.stakers.v1beta1.Msg/LeavePool", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).JoinPool(ctx, req.(*MsgJoinPool)) + return srv.(MsgServer).LeavePool(ctx, req.(*MsgLeavePool)) } return interceptor(ctx, in, info, handler) } -func _Msg_LeavePool_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgLeavePool) +func _Msg_UpdateCommission_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateCommission) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(MsgServer).LeavePool(ctx, in) + return srv.(MsgServer).UpdateCommission(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/kyve.stakers.v1beta1.Msg/LeavePool", + FullMethod: "/kyve.stakers.v1beta1.Msg/UpdateCommission", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).LeavePool(ctx, req.(*MsgLeavePool)) + return srv.(MsgServer).UpdateCommission(ctx, req.(*MsgUpdateCommission)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateStakeFraction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateStakeFraction) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateStakeFraction(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/kyve.stakers.v1beta1.Msg/UpdateStakeFraction", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateStakeFraction(ctx, req.(*MsgUpdateStakeFraction)) } return interceptor(ctx, in, info, handler) } @@ -640,10 +787,6 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "kyve.stakers.v1beta1.Msg", HandlerType: (*MsgServer)(nil), Methods: []grpc.MethodDesc{ - { - MethodName: "UpdateCommission", - Handler: _Msg_UpdateCommission_Handler, - }, { MethodName: "JoinPool", Handler: _Msg_JoinPool_Handler, @@ -652,6 +795,14 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "LeavePool", Handler: _Msg_LeavePool_Handler, }, + { + MethodName: "UpdateCommission", + Handler: _Msg_UpdateCommission_Handler, + }, + { + MethodName: "UpdateStakeFraction", + Handler: _Msg_UpdateStakeFraction_Handler, + }, { MethodName: "UpdateParams", Handler: _Msg_UpdateParams_Handler, @@ -690,7 +841,12 @@ func (m *MsgUpdateCommission) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintTx(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x12 + dAtA[i] = 0x1a + if m.PoolId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x10 + } if len(m.Creator) > 0 { i -= len(m.Creator) copy(dAtA[i:], m.Creator) @@ -724,6 +880,74 @@ func (m *MsgUpdateCommissionResponse) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } +func (m *MsgUpdateStakeFraction) 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 *MsgUpdateStakeFraction) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateStakeFraction) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.StakeFraction.Size() + i -= size + if _, err := m.StakeFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.PoolId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintTx(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateStakeFractionResponse) 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 *MsgUpdateStakeFractionResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateStakeFractionResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func (m *MsgJoinPool) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -744,6 +968,26 @@ func (m *MsgJoinPool) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.StakeFraction.Size() + i -= size + if _, err := m.StakeFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + { + size := m.Commission.Size() + i -= size + if _, err := m.Commission.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a if m.Amount != 0 { i = encodeVarintTx(dAtA, i, uint64(m.Amount)) i-- @@ -933,6 +1177,9 @@ func (m *MsgUpdateCommission) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } + if m.PoolId != 0 { + n += 1 + sovTx(uint64(m.PoolId)) + } l = m.Commission.Size() n += 1 + l + sovTx(uint64(l)) return n @@ -947,7 +1194,34 @@ func (m *MsgUpdateCommissionResponse) Size() (n int) { return n } -func (m *MsgJoinPool) Size() (n int) { +func (m *MsgUpdateStakeFraction) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.PoolId != 0 { + n += 1 + sovTx(uint64(m.PoolId)) + } + l = m.StakeFraction.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateStakeFractionResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgJoinPool) Size() (n int) { if m == nil { return 0 } @@ -967,6 +1241,10 @@ func (m *MsgJoinPool) Size() (n int) { if m.Amount != 0 { n += 1 + sovTx(uint64(m.Amount)) } + l = m.Commission.Size() + n += 1 + l + sovTx(uint64(l)) + l = m.StakeFraction.Size() + n += 1 + l + sovTx(uint64(l)) return n } @@ -1098,6 +1376,25 @@ func (m *MsgUpdateCommission) Unmarshal(dAtA []byte) error { m.Creator = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Commission", wireType) } @@ -1202,6 +1499,191 @@ func (m *MsgUpdateCommissionResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgUpdateStakeFraction) 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: MsgUpdateStakeFraction: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateStakeFraction: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StakeFraction.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 *MsgUpdateStakeFractionResponse) 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: MsgUpdateStakeFractionResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateStakeFractionResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + 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 *MsgJoinPool) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -1333,6 +1815,74 @@ func (m *MsgJoinPool) Unmarshal(dAtA []byte) error { break } } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commission", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Commission.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + 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 ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StakeFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) From d68da89a8dc090b18e14b404007632b411c12529 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 13 Dec 2024 15:29:24 +0100 Subject: [PATCH 02/24] chore: implemented effective stake --- proto/kyve/stakers/v1beta1/events.proto | 10 +- x/bundles/keeper/logic_bundles.go | 28 +++--- x/bundles/types/expected_keepers.go | 1 + x/pool/types/params.go | 5 + x/stakers/keeper/exported_functions.go | 94 +++++++++++++++--- x/stakers/types/events.pb.go | 121 +++++++++++++++++------- x/stakers/types/expected_keepers.go | 2 + 7 files changed, 194 insertions(+), 67 deletions(-) diff --git a/proto/kyve/stakers/v1beta1/events.proto b/proto/kyve/stakers/v1beta1/events.proto index 78a7313a..9abf0df3 100644 --- a/proto/kyve/stakers/v1beta1/events.proto +++ b/proto/kyve/stakers/v1beta1/events.proto @@ -96,8 +96,14 @@ message EventSlash { uint64 pool_id = 1; // staker is the account address of the protocol node. string staker = 2; - // amount ... + // amount is the total amount that got slashed uint64 amount = 3; - // slash_type + // slash_type is the type of the protocol slash SlashType slash_type = 4; + // stake_fraction is the percentage of how much of the validators total + // bonded amount was under risk for slashing + string stake_fraction = 5 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; } diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index 1a6c68ea..2968e783 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -3,12 +3,11 @@ package keeper import ( "cosmossdk.io/errors" "cosmossdk.io/math" + "github.com/KYVENetwork/chain/util" + "github.com/KYVENetwork/chain/x/bundles/types" globalTypes "github.com/KYVENetwork/chain/x/global/types" poolTypes "github.com/KYVENetwork/chain/x/pool/types" stakersTypes "github.com/KYVENetwork/chain/x/stakers/types" - - "github.com/KYVENetwork/chain/util" - "github.com/KYVENetwork/chain/x/bundles/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -38,18 +37,19 @@ func (k Keeper) AssertPoolCanRun(ctx sdk.Context, poolId uint64) error { } // Get the total and the highest delegation of a single validator in the pool - totalDelegation, highestDelegation := k.stakerKeeper.GetTotalAndHighestDelegationOfPool(ctx, poolId) + totalDelegation, _ := k.stakerKeeper.GetTotalAndHighestDelegationOfPool(ctx, poolId) // Error if min delegation is not reached if totalDelegation < pool.MinDelegation { return types.ErrMinDelegationNotReached } + stakers := int64(len(k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId))) maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) - maxDelegation := uint64(maxVotingPower.MulInt64(int64(totalDelegation)).TruncateInt64()) - // Error if highest delegation exceeds max voting power - if highestDelegation > maxDelegation { + // Error if max voting power is not achievable because there are not enough stakers + // in the pool + if math.LegacyOneDec().Quo(maxVotingPower).GT(math.LegacyNewDec(stakers)) { return types.ErrVotingPowerTooHigh } @@ -511,28 +511,26 @@ func (k Keeper) GetVoteDistribution(ctx sdk.Context, poolId uint64) (voteDistrib return } + effectiveStakes := k.stakerKeeper.GetEffectiveValidatorStakes(ctx, poolId) + // get voting power for valid for _, voter := range bundleProposal.VotersValid { - delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) - voteDistribution.Valid += k.calculateVotingPower(delegation) + voteDistribution.Valid += effectiveStakes[voter] } // get voting power for invalid for _, voter := range bundleProposal.VotersInvalid { - delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) - voteDistribution.Invalid += k.calculateVotingPower(delegation) + voteDistribution.Invalid += effectiveStakes[voter] } // get voting power for abstain for _, voter := range bundleProposal.VotersAbstain { - delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) - voteDistribution.Abstain += k.calculateVotingPower(delegation) + voteDistribution.Abstain += effectiveStakes[voter] } // get total voting power for _, staker := range k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId) { - delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, staker, poolId) - voteDistribution.Total += k.calculateVotingPower(delegation) + voteDistribution.Total += effectiveStakes[staker] } if voteDistribution.Total == 0 { diff --git a/x/bundles/types/expected_keepers.go b/x/bundles/types/expected_keepers.go index 3d9c0ddd..5ba661b8 100644 --- a/x/bundles/types/expected_keepers.go +++ b/x/bundles/types/expected_keepers.go @@ -46,6 +46,7 @@ type StakerKeeper interface { Slash(ctx sdk.Context, poolId uint64, staker string, slashType stakersTypes.SlashType) PayoutRewards(ctx sdk.Context, staker string, amount sdk.Coins, payerModuleName string) error PayoutAdditionalCommissionRewards(ctx sdk.Context, validator string, payerModuleName string, amount sdk.Coins) error + GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64) (effectiveStake map[string]uint64) } type FundersKeeper interface { diff --git a/x/pool/types/params.go b/x/pool/types/params.go index 2585ca6e..aa4f257e 100644 --- a/x/pool/types/params.go +++ b/x/pool/types/params.go @@ -2,6 +2,7 @@ package types import ( "cosmossdk.io/math" + "errors" "github.com/KYVENetwork/chain/util" ) @@ -50,5 +51,9 @@ func (p Params) Validate() error { return err } + if p.MaxVotingPowerPerPool.IsZero() { + return errors.New("max voting power per pool cannot be zero") + } + return nil } diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 153c50ed..afb451c9 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -2,7 +2,6 @@ package keeper import ( "context" - "cosmossdk.io/errors" "cosmossdk.io/math" "github.com/KYVENetwork/chain/util" @@ -11,8 +10,10 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "sort" + // Stakers - "github.com/KYVENetwork/chain/x/stakers/types" + stakertypes "github.com/KYVENetwork/chain/x/stakers/types" ) // These functions are meant to be called from external modules. @@ -25,7 +26,7 @@ import ( func (k Keeper) LeavePool(ctx sdk.Context, staker string, poolId uint64) { k.RemoveValaccountFromPool(ctx, poolId, staker) - _ = ctx.EventManager().EmitTypedEvent(&types.EventLeavePool{ + _ = ctx.EventManager().EmitTypedEvent(&stakertypes.EventLeavePool{ PoolId: poolId, Staker: staker, }) @@ -63,11 +64,11 @@ func (k Keeper) GetPaginatedStakersByDelegation(ctx sdk.Context, pagination *que func (k Keeper) AssertValaccountAuthorized(ctx sdk.Context, poolId uint64, stakerAddress string, valaddress string) error { valaccount, active := k.GetValaccount(ctx, poolId, stakerAddress) if !active { - return types.ErrValaccountUnauthorized + return stakertypes.ErrValaccountUnauthorized } if valaccount.Valaddress != valaddress { - return types.ErrValaccountUnauthorized + return stakertypes.ErrValaccountUnauthorized } return nil @@ -193,8 +194,68 @@ func (k Keeper) GetOutstandingRewards(orgCtx sdk.Context, staker string, delegat return util.TruncateDecCoins(rewards) } +// GetEffectiveValidatorStakes returns a map for all pool stakers their effective stake. Effective stake +// is the actual stake at risk for a validator, it can be lower than the provided stake because +// of the max voting power per pool parameter, but it can never be higher. Thus, if the effective +// stake is lower than the provided one the slash +// TODO: explain or link to formula +func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64) (effectiveStakes map[string]uint64) { + type ValidatorStake struct { + Address string + Stake uint64 + } + + alpha := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) + validators := make([]ValidatorStake, 0) + + for _, address := range k.GetAllStakerAddressesOfPool(ctx, poolId) { + stake := k.GetValidatorPoolStake(ctx, address, poolId) + effectiveStakes[address] = stake + validators = append(validators, ValidatorStake{ + Address: address, + Stake: stake, + }) + } + + // sort ascending based on stake + sort.Slice(validators, func(i, j int) bool { + return validators[i].Stake < validators[j].Stake + }) + + // return if max voting power can not be undercut because there are not enough stakers + // in the pool + if math.LegacyOneDec().Quo(alpha).GT(math.LegacyNewDec(int64(len(validators)))) { + return + } + + x := func(i int) uint64 { + totalStake := int64(0) + + for _, validator := range validators[i+1:] { + totalStake += int64(validator.Stake) + } + + return uint64(alpha.MulInt64(totalStake).Quo(math.LegacyOneDec().Sub(alpha.Mul(math.LegacyNewDec(int64(i)).Add(math.LegacyOneDec())))).TruncateInt64()) + } + + for i := range validators { + M := x(i) + + if validators[i].Stake >= M && M >= validators[i+1].Stake { + for _, v := range validators { + if v.Stake > M { + effectiveStakes[v.Address] = M + } + } + return + } + } + + return +} + // Slash reduces the delegation of all delegators of `staker` by fraction. The slash itself is handled by the cosmos-sdk -func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType types.SlashType) { +func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType stakertypes.SlashType) { validator, found := k.GetValidator(ctx, staker) if !found { return @@ -202,9 +263,13 @@ func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType t consAddrBytes, _ := validator.GetConsAddr() - // the validator can only be slashed for his stake fraction in a pool, therefore we update the slash fraction - // accordingly - slashFraction := k.getSlashFraction(ctx, slashType).Mul(k.GetValidatorPoolStakeFraction(ctx, staker, poolId)) + // get real stake fraction from the effective stake which is truly at risk for getting slashed + // by dividing it with the total bonded stake from the validator + stakeFraction := math.LegacyNewDec(int64(k.GetEffectiveValidatorStakes(ctx, poolId)[staker])).QuoInt(validator.GetBondedTokens()) + + // the validator can only be slashed for his effective stake fraction in a pool, therefore we + // update the slash fraction accordingly + slashFraction := k.getSlashFraction(ctx, slashType).Mul(stakeFraction) amount, err := k.stakingKeeper.Slash( ctx, @@ -217,11 +282,12 @@ func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType t return } - _ = ctx.EventManager().EmitTypedEvent(&types.EventSlash{ - PoolId: poolId, - Staker: staker, - Amount: amount.Uint64(), - SlashType: slashType, + _ = ctx.EventManager().EmitTypedEvent(&stakertypes.EventSlash{ + PoolId: poolId, + Staker: staker, + Amount: amount.Uint64(), + SlashType: slashType, + StakeFraction: stakeFraction, }) } diff --git a/x/stakers/types/events.pb.go b/x/stakers/types/events.pb.go index 445aa39b..393ad404 100644 --- a/x/stakers/types/events.pb.go +++ b/x/stakers/types/events.pb.go @@ -403,10 +403,13 @@ type EventSlash struct { PoolId uint64 `protobuf:"varint,1,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` // staker is the account address of the protocol node. Staker string `protobuf:"bytes,2,opt,name=staker,proto3" json:"staker,omitempty"` - // amount ... + // amount is the total amount that got slashed Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` - // slash_type + // slash_type is the type of the protocol slash SlashType SlashType `protobuf:"varint,4,opt,name=slash_type,json=slashType,proto3,enum=kyve.stakers.v1beta1.SlashType" json:"slash_type,omitempty"` + // stake_fraction is the percentage of how much of the validators total + // bonded amount was under risk for slashing + StakeFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,5,opt,name=stake_fraction,json=stakeFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"stake_fraction"` } func (m *EventSlash) Reset() { *m = EventSlash{} } @@ -483,41 +486,41 @@ func init() { func init() { proto.RegisterFile("kyve/stakers/v1beta1/events.proto", fileDescriptor_7a1b3dc9634155a0) } var fileDescriptor_7a1b3dc9634155a0 = []byte{ - // 532 bytes of a gzipped FileDescriptorProto + // 537 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xc1, 0x6e, 0xd3, 0x40, - 0x10, 0x86, 0xb3, 0x69, 0x48, 0x94, 0x41, 0x8d, 0x44, 0x54, 0xc0, 0x4a, 0x91, 0x53, 0xcc, 0xa5, - 0x07, 0x64, 0xab, 0xe5, 0x8e, 0xd4, 0x84, 0x56, 0xa2, 0x54, 0x50, 0xb9, 0x80, 0x04, 0x97, 0x68, - 0xe3, 0x5d, 0x12, 0x2b, 0xb6, 0xc7, 0xf2, 0x6e, 0x13, 0xfc, 0x08, 0x1c, 0x90, 0xb8, 0x20, 0x1e, - 0x84, 0x97, 0xe8, 0xb1, 0x47, 0xc4, 0xa1, 0x42, 0xc9, 0x8b, 0x20, 0xaf, 0xed, 0xc6, 0x41, 0x46, - 0x6a, 0x73, 0xdb, 0xb1, 0xfe, 0xf9, 0xe6, 0xdf, 0x7f, 0xe4, 0x85, 0xc7, 0x93, 0x78, 0xca, 0x2d, - 0x21, 0xe9, 0x84, 0x47, 0xc2, 0x9a, 0xee, 0x0d, 0xb9, 0xa4, 0x7b, 0x16, 0x9f, 0xf2, 0x40, 0x0a, - 0x33, 0x8c, 0x50, 0x62, 0x7b, 0x2b, 0x91, 0x98, 0x99, 0xc4, 0xcc, 0x24, 0x9d, 0xad, 0x11, 0x8e, - 0x50, 0x09, 0xac, 0xe4, 0x94, 0x6a, 0x3b, 0xe5, 0xb8, 0x90, 0x46, 0xd4, 0xcf, 0x70, 0x1d, 0xa3, - 0x54, 0x92, 0xe3, 0x95, 0xc6, 0xf8, 0x49, 0xe0, 0xde, 0x61, 0xe2, 0xe1, 0x5d, 0xc8, 0xa8, 0xe4, - 0xa7, 0xaa, 0xbf, 0x7d, 0x00, 0x80, 0x1e, 0x1b, 0xa4, 0x34, 0x8d, 0xec, 0x90, 0xdd, 0xbb, 0xfb, - 0x8f, 0xcc, 0x32, 0x77, 0x66, 0xda, 0xd1, 0xab, 0x5d, 0x5c, 0x75, 0x2b, 0x76, 0x13, 0x3d, 0xb6, - 0x44, 0x04, 0x7c, 0x96, 0x23, 0xaa, 0x37, 0x47, 0x04, 0x7c, 0x96, 0x21, 0x34, 0x68, 0x84, 0x34, - 0xf6, 0x90, 0x32, 0x6d, 0x63, 0x87, 0xec, 0x36, 0xed, 0xbc, 0x34, 0xbe, 0x12, 0xb8, 0x5f, 0x70, - 0xdd, 0x47, 0xdf, 0x77, 0x85, 0x70, 0x31, 0x68, 0x3f, 0x80, 0x7a, 0x8a, 0x57, 0xae, 0x9b, 0x76, - 0x56, 0xb5, 0x1f, 0x42, 0x23, 0x44, 0xf4, 0x06, 0x2e, 0x53, 0x5e, 0x6a, 0x76, 0x3d, 0x29, 0x5f, - 0xb2, 0x76, 0x1f, 0xc0, 0xb9, 0x6e, 0x4f, 0xe7, 0xf4, 0x9e, 0x24, 0x4e, 0x7e, 0x5f, 0x75, 0xb7, - 0x1d, 0x14, 0x3e, 0x0a, 0xc1, 0x26, 0xa6, 0x8b, 0x96, 0x4f, 0xe5, 0xd8, 0x3c, 0xe1, 0x23, 0xea, - 0xc4, 0x2f, 0xb8, 0x63, 0x17, 0xda, 0x8c, 0x1f, 0x04, 0xb4, 0x82, 0x9f, 0xb3, 0x64, 0xe6, 0x51, - 0x44, 0x1d, 0xb9, 0x96, 0xa5, 0x63, 0x68, 0x29, 0xc9, 0xe0, 0x53, 0x86, 0xb8, 0x8d, 0xad, 0x4d, - 0x51, 0x1c, 0x6e, 0xbc, 0x81, 0x6d, 0x65, 0xac, 0xef, 0x51, 0xd7, 0x5f, 0xe6, 0x64, 0xf3, 0x19, - 0x8d, 0x98, 0xf8, 0xaf, 0x37, 0x0d, 0x1a, 0xd4, 0xc7, 0xf3, 0x40, 0xa6, 0xab, 0x6b, 0xda, 0x79, - 0x69, 0x7c, 0xa9, 0xc2, 0xa6, 0x22, 0x1e, 0xa3, 0x1b, 0x9c, 0x22, 0x7a, 0xc5, 0x7b, 0x90, 0x95, - 0x7b, 0x2c, 0xe1, 0xd5, 0x15, 0xb8, 0x0e, 0x30, 0xa5, 0x1e, 0x65, 0x2c, 0xe2, 0x42, 0x64, 0xab, - 0x2d, 0x7c, 0x49, 0xfa, 0xd2, 0x69, 0x5a, 0x2d, 0xe5, 0xa5, 0xd5, 0x3f, 0xab, 0xba, 0xb3, 0xd6, - 0xaa, 0x4a, 0xc2, 0xad, 0xaf, 0x1d, 0xee, 0x01, 0xb4, 0x54, 0x14, 0x27, 0x9c, 0x4e, 0xf9, 0x5a, - 0x59, 0x18, 0xdf, 0x09, 0x80, 0x62, 0x9c, 0x79, 0x54, 0x8c, 0x6f, 0x9f, 0xe5, 0x32, 0xab, 0x8d, - 0x95, 0xac, 0x9e, 0x03, 0x88, 0x84, 0x38, 0x90, 0x71, 0xc8, 0x55, 0x8e, 0xad, 0xfd, 0x6e, 0xf9, - 0xef, 0xa7, 0x26, 0xbf, 0x8d, 0x43, 0x6e, 0x37, 0x45, 0x7e, 0xec, 0x1d, 0x5d, 0xcc, 0x75, 0x72, - 0x39, 0xd7, 0xc9, 0x9f, 0xb9, 0x4e, 0xbe, 0x2d, 0xf4, 0xca, 0xe5, 0x42, 0xaf, 0xfc, 0x5a, 0xe8, - 0x95, 0x8f, 0x4f, 0x47, 0xae, 0x1c, 0x9f, 0x0f, 0x4d, 0x07, 0x7d, 0xeb, 0xd5, 0x87, 0xf7, 0x87, - 0xaf, 0xb9, 0x9c, 0x61, 0x34, 0xb1, 0x9c, 0x31, 0x75, 0x03, 0xeb, 0xf3, 0xf5, 0x7b, 0x93, 0x0c, - 0x16, 0xc3, 0xba, 0x7a, 0x66, 0x9e, 0xfd, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x42, 0x2b, 0x27, 0xf7, - 0xfe, 0x04, 0x00, 0x00, + 0x10, 0x86, 0xb3, 0x69, 0x9a, 0x28, 0x83, 0x1a, 0x89, 0xa8, 0x80, 0x95, 0x22, 0xa7, 0x98, 0x4b, + 0x0f, 0xc8, 0x56, 0xcb, 0x1d, 0xa9, 0x09, 0xad, 0x44, 0xa9, 0xa0, 0x72, 0x01, 0x09, 0x2e, 0xd1, + 0xc6, 0xbb, 0x24, 0x56, 0x6c, 0x8f, 0xe5, 0xdd, 0x26, 0xe4, 0x11, 0x38, 0x20, 0x71, 0xe3, 0x41, + 0x78, 0x89, 0x1e, 0x7b, 0x44, 0x1c, 0x2a, 0x48, 0x5e, 0x04, 0x79, 0x6d, 0x37, 0x0e, 0x32, 0x12, + 0xf5, 0x6d, 0xc7, 0xfa, 0xe7, 0x9b, 0x7f, 0xff, 0x91, 0x17, 0x1e, 0x4d, 0xe6, 0x53, 0x6e, 0x09, + 0x49, 0x27, 0x3c, 0x12, 0xd6, 0x74, 0x7f, 0xc8, 0x25, 0xdd, 0xb7, 0xf8, 0x94, 0x07, 0x52, 0x98, + 0x61, 0x84, 0x12, 0xdb, 0xdb, 0xb1, 0xc4, 0x4c, 0x25, 0x66, 0x2a, 0xe9, 0x6c, 0x8f, 0x70, 0x84, + 0x4a, 0x60, 0xc5, 0xa7, 0x44, 0xdb, 0x29, 0xc6, 0x85, 0x34, 0xa2, 0x7e, 0x8a, 0xeb, 0x18, 0x85, + 0x92, 0x0c, 0xaf, 0x34, 0xc6, 0x77, 0x02, 0x77, 0x8f, 0x62, 0x0f, 0x6f, 0x43, 0x46, 0x25, 0x3f, + 0x53, 0xfd, 0xed, 0x43, 0x00, 0xf4, 0xd8, 0x20, 0xa1, 0x69, 0x64, 0x97, 0xec, 0xdd, 0x39, 0x78, + 0x68, 0x16, 0xb9, 0x33, 0x93, 0x8e, 0x5e, 0xed, 0xf2, 0xba, 0x5b, 0xb1, 0x9b, 0xe8, 0xb1, 0x15, + 0x22, 0xe0, 0xb3, 0x0c, 0x51, 0xfd, 0x7f, 0x44, 0xc0, 0x67, 0x29, 0x42, 0x83, 0x46, 0x48, 0xe7, + 0x1e, 0x52, 0xa6, 0x6d, 0xec, 0x92, 0xbd, 0xa6, 0x9d, 0x95, 0xc6, 0x17, 0x02, 0xf7, 0x72, 0xae, + 0xfb, 0xe8, 0xfb, 0xae, 0x10, 0x2e, 0x06, 0xed, 0xfb, 0x50, 0x4f, 0xf0, 0xca, 0x75, 0xd3, 0x4e, + 0xab, 0xf6, 0x03, 0x68, 0x84, 0x88, 0xde, 0xc0, 0x65, 0xca, 0x4b, 0xcd, 0xae, 0xc7, 0xe5, 0x0b, + 0xd6, 0xee, 0x03, 0x38, 0x37, 0xed, 0xc9, 0x9c, 0xde, 0xe3, 0xd8, 0xc9, 0xcf, 0xeb, 0xee, 0x8e, + 0x83, 0xc2, 0x47, 0x21, 0xd8, 0xc4, 0x74, 0xd1, 0xf2, 0xa9, 0x1c, 0x9b, 0xa7, 0x7c, 0x44, 0x9d, + 0xf9, 0x73, 0xee, 0xd8, 0xb9, 0x36, 0xe3, 0x1b, 0x01, 0x2d, 0xe7, 0xe7, 0x3c, 0x9e, 0x79, 0x1c, + 0x51, 0x47, 0x96, 0xb2, 0x74, 0x02, 0x2d, 0x25, 0x19, 0x7c, 0x4c, 0x11, 0xb7, 0xb1, 0xb5, 0x25, + 0xf2, 0xc3, 0x8d, 0xd7, 0xb0, 0xa3, 0x8c, 0xf5, 0x3d, 0xea, 0xfa, 0xab, 0x9c, 0x6c, 0x3e, 0xa3, + 0x11, 0x13, 0xff, 0xf4, 0xa6, 0x41, 0x83, 0xfa, 0x78, 0x11, 0xc8, 0x64, 0x75, 0x4d, 0x3b, 0x2b, + 0x8d, 0xcf, 0x55, 0xd8, 0x52, 0xc4, 0x13, 0x74, 0x83, 0x33, 0x44, 0x2f, 0x7f, 0x0f, 0xb2, 0x76, + 0x8f, 0x15, 0xbc, 0xba, 0x06, 0xd7, 0x01, 0xa6, 0xd4, 0xa3, 0x8c, 0x45, 0x5c, 0x88, 0x74, 0xb5, + 0xb9, 0x2f, 0x71, 0x5f, 0x32, 0x4d, 0xab, 0x25, 0xbc, 0xa4, 0xfa, 0x6b, 0x55, 0x9b, 0xa5, 0x56, + 0x55, 0x10, 0x6e, 0xbd, 0x74, 0xb8, 0x87, 0xd0, 0x52, 0x51, 0x9c, 0x72, 0x3a, 0xe5, 0xa5, 0xb2, + 0x30, 0x7e, 0x13, 0x00, 0xc5, 0x38, 0xf7, 0xa8, 0x18, 0xdf, 0x3e, 0xcb, 0x55, 0x56, 0x1b, 0x6b, + 0x59, 0x3d, 0x03, 0x10, 0x31, 0x71, 0x20, 0xe7, 0x21, 0x57, 0x39, 0xb6, 0x0e, 0xba, 0xc5, 0xbf, + 0x9f, 0x9a, 0xfc, 0x66, 0x1e, 0x72, 0xbb, 0x29, 0xb2, 0x63, 0x41, 0x4c, 0x9b, 0x65, 0x63, 0xea, + 0x1d, 0x5f, 0x2e, 0x74, 0x72, 0xb5, 0xd0, 0xc9, 0xaf, 0x85, 0x4e, 0xbe, 0x2e, 0xf5, 0xca, 0xd5, + 0x52, 0xaf, 0xfc, 0x58, 0xea, 0x95, 0x0f, 0x4f, 0x46, 0xae, 0x1c, 0x5f, 0x0c, 0x4d, 0x07, 0x7d, + 0xeb, 0xe5, 0xfb, 0x77, 0x47, 0xaf, 0xb8, 0x9c, 0x61, 0x34, 0xb1, 0x9c, 0x31, 0x75, 0x03, 0xeb, + 0xd3, 0xcd, 0xdb, 0x15, 0x5f, 0x42, 0x0c, 0xeb, 0xea, 0xc9, 0x7a, 0xfa, 0x27, 0x00, 0x00, 0xff, + 0xff, 0x4e, 0xa8, 0x49, 0x66, 0x4a, 0x05, 0x00, 0x00, } func (m *EventUpdateParams) Marshal() (dAtA []byte, err error) { @@ -819,6 +822,16 @@ func (m *EventSlash) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + { + size := m.StakeFraction.Size() + i -= size + if _, err := m.StakeFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a if m.SlashType != 0 { i = encodeVarintEvents(dAtA, i, uint64(m.SlashType)) i-- @@ -987,6 +1000,8 @@ func (m *EventSlash) Size() (n int) { if m.SlashType != 0 { n += 1 + sovEvents(uint64(m.SlashType)) } + l = m.StakeFraction.Size() + n += 1 + l + sovEvents(uint64(l)) return n } @@ -1967,6 +1982,40 @@ func (m *EventSlash) Unmarshal(dAtA []byte) error { break } } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + 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 ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StakeFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipEvents(dAtA[iNdEx:]) diff --git a/x/stakers/types/expected_keepers.go b/x/stakers/types/expected_keepers.go index b489cdd2..ab86eabb 100644 --- a/x/stakers/types/expected_keepers.go +++ b/x/stakers/types/expected_keepers.go @@ -1,11 +1,13 @@ package types import ( + "cosmossdk.io/math" poolTypes "github.com/KYVENetwork/chain/x/pool/types" sdk "github.com/cosmos/cosmos-sdk/types" ) type PoolKeeper interface { + GetMaxVotingPowerPerPool(ctx sdk.Context) (res math.LegacyDec) AssertPoolExists(ctx sdk.Context, poolId uint64) error GetPoolWithError(ctx sdk.Context, poolId uint64) (poolTypes.Pool, error) } From 61e11149ff9e2a6683559b9bf6b060682c45114b Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 13 Dec 2024 15:33:48 +0100 Subject: [PATCH 03/24] chore: allow zero for max pool stake --- x/bundles/keeper/logic_bundles.go | 4 ++++ x/pool/types/params.go | 5 ----- x/stakers/keeper/exported_functions.go | 4 ++++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index 2968e783..ae700c4e 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -47,6 +47,10 @@ func (k Keeper) AssertPoolCanRun(ctx sdk.Context, poolId uint64) error { stakers := int64(len(k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId))) maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) + if maxVotingPower.IsZero() { + return nil + } + // Error if max voting power is not achievable because there are not enough stakers // in the pool if math.LegacyOneDec().Quo(maxVotingPower).GT(math.LegacyNewDec(stakers)) { diff --git a/x/pool/types/params.go b/x/pool/types/params.go index aa4f257e..2585ca6e 100644 --- a/x/pool/types/params.go +++ b/x/pool/types/params.go @@ -2,7 +2,6 @@ package types import ( "cosmossdk.io/math" - "errors" "github.com/KYVENetwork/chain/util" ) @@ -51,9 +50,5 @@ func (p Params) Validate() error { return err } - if p.MaxVotingPowerPerPool.IsZero() { - return errors.New("max voting power per pool cannot be zero") - } - return nil } diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index afb451c9..ba769d9c 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -222,6 +222,10 @@ func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64) (eff return validators[i].Stake < validators[j].Stake }) + if alpha.IsZero() { + return + } + // return if max voting power can not be undercut because there are not enough stakers // in the pool if math.LegacyOneDec().Quo(alpha).GT(math.LegacyNewDec(int64(len(validators)))) { From ea3b51cc1da051b99f2dad15a9ee99f38dc24fbb Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 13 Dec 2024 17:31:48 +0100 Subject: [PATCH 04/24] chore: added required stakers --- util/arrays.go | 12 ++++ x/bundles/keeper/logic_bundles.go | 8 --- x/bundles/keeper/logic_bundles_test.go | 4 +- ...ic_end_block_handle_upload_timeout_test.go | 6 +- x/bundles/types/expected_keepers.go | 2 +- x/stakers/keeper/exported_functions.go | 60 ++++++++++--------- 6 files changed, 49 insertions(+), 43 deletions(-) diff --git a/util/arrays.go b/util/arrays.go index 8cf4815b..fd948cdc 100644 --- a/util/arrays.go +++ b/util/arrays.go @@ -38,3 +38,15 @@ func ContainsString(array []string, match string) bool { } return false } + +func RemoveDuplicateStrings(strSlice []string) []string { + allKeys := make(map[string]bool) + list := []string{} + for _, item := range strSlice { + if _, value := allKeys[item]; !value { + allKeys[item] = true + list = append(list, item) + } + } + return list +} diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index ae700c4e..93cb5aec 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -468,14 +468,6 @@ func (k Keeper) dropCurrentBundleProposal(ctx sdk.Context, poolId uint64, voteDi k.SetBundleProposal(ctx, bundleProposal) } -// calculateVotingPower calculates the voting power one staker has in a -// storage pool based only on the total delegation this staker has -func (k Keeper) calculateVotingPower(delegation uint64) (votingPower uint64) { - // voting power is linear - votingPower = delegation - return -} - // chooseNextUploader selects the next uploader based on a fixed set of stakers in a pool. // It is guaranteed that someone is chosen deterministically if the round-robin set itself is not empty. func (k Keeper) chooseNextUploader(ctx sdk.Context, poolId uint64, excluded ...string) (nextUploader string) { diff --git a/x/bundles/keeper/logic_bundles_test.go b/x/bundles/keeper/logic_bundles_test.go index 08d19811..9d3a0885 100644 --- a/x/bundles/keeper/logic_bundles_test.go +++ b/x/bundles/keeper/logic_bundles_test.go @@ -242,7 +242,7 @@ var _ = Describe("logic_bundles.go", Ordered, func() { err := s.App().BundlesKeeper.AssertPoolCanRun(s.Ctx(), 0) // ASSERT - Expect(err).To(Equal(bundlesTypes.ErrVotingPowerTooHigh)) + Expect(err).To(BeNil()) }) It("Assert pool can run while voting power of one node is 40%", func() { @@ -366,7 +366,7 @@ var _ = Describe("logic_bundles.go", Ordered, func() { err := s.App().BundlesKeeper.AssertPoolCanRun(s.Ctx(), 0) // ASSERT - Expect(err).To(Equal(bundlesTypes.ErrVotingPowerTooHigh)) + Expect(err).To(BeNil()) }) It("Assert pool can run with a single staker while voting power is 100%", func() { diff --git a/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go b/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go index ce19c849..8776dda3 100644 --- a/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go +++ b/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go @@ -24,7 +24,7 @@ TEST CASES - logic_end_block_handle_upload_timeout.go * Next uploader gets removed due to pool upgrading * Next uploader gets removed due to pool being disabled * Next uploader gets removed due to pool not reaching min delegation -* Next uploader gets removed due to pool having one node with more than 50% voting power +* Next uploader gets not removed although pool having one node with more than 50% voting power * Staker is next uploader of genesis bundle and upload interval and timeout does not pass * Staker is next uploader of genesis bundle and upload timeout does not pass but upload interval passes * Staker is next uploader of genesis bundle and upload timeout does pass together with upload interval @@ -281,7 +281,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(20 * i.KYVE)) }) - It("Next uploader gets removed due to pool having one node with more than 50% voting power", func() { + It("Next uploader gets not removed although pool having one node with more than 50% voting power", func() { // ARRANGE s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ Creator: i.VALADDRESS_0_A, @@ -300,7 +300,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { // ASSERT bundleProposal, _ := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) - Expect(bundleProposal.NextUploader).To(BeEmpty()) + Expect(bundleProposal.NextUploader).To(Equal("kyve1htgfatqevuvfzvl0sxp97ywteqhg5leha9emf4")) Expect(bundleProposal.StorageId).To(BeEmpty()) poolStakers := s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0) diff --git a/x/bundles/types/expected_keepers.go b/x/bundles/types/expected_keepers.go index 5ba661b8..0b41d0ef 100644 --- a/x/bundles/types/expected_keepers.go +++ b/x/bundles/types/expected_keepers.go @@ -46,7 +46,7 @@ type StakerKeeper interface { Slash(ctx sdk.Context, poolId uint64, staker string, slashType stakersTypes.SlashType) PayoutRewards(ctx sdk.Context, staker string, amount sdk.Coins, payerModuleName string) error PayoutAdditionalCommissionRewards(ctx sdk.Context, validator string, payerModuleName string, amount sdk.Coins) error - GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64) (effectiveStake map[string]uint64) + GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, mustIncludeStakers ...string) (effectiveStake map[string]uint64) } type FundersKeeper interface { diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index ba769d9c..0e8795e7 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -2,6 +2,8 @@ package keeper import ( "context" + "sort" + "cosmossdk.io/errors" "cosmossdk.io/math" "github.com/KYVENetwork/chain/util" @@ -10,7 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingTypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "sort" // Stakers stakertypes "github.com/KYVENetwork/chain/x/stakers/types" @@ -199,60 +200,61 @@ func (k Keeper) GetOutstandingRewards(orgCtx sdk.Context, staker string, delegat // of the max voting power per pool parameter, but it can never be higher. Thus, if the effective // stake is lower than the provided one the slash // TODO: explain or link to formula -func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64) (effectiveStakes map[string]uint64) { +func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, mustIncludeStakers ...string) (effectiveStakes map[string]uint64) { type ValidatorStake struct { Address string Stake uint64 } - alpha := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) + addresses := util.RemoveDuplicateStrings(append(k.GetAllStakerAddressesOfPool(ctx, poolId), mustIncludeStakers...)) + maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) + effectiveStakes = make(map[string]uint64) validators := make([]ValidatorStake, 0) + totalStake := int64(0) - for _, address := range k.GetAllStakerAddressesOfPool(ctx, poolId) { + for _, address := range addresses { stake := k.GetValidatorPoolStake(ctx, address, poolId) effectiveStakes[address] = stake validators = append(validators, ValidatorStake{ Address: address, Stake: stake, }) + totalStake += int64(stake) } - // sort ascending based on stake + totalStakeRemainder := totalStake + + // sort descending based on stake sort.Slice(validators, func(i, j int) bool { - return validators[i].Stake < validators[j].Stake + return validators[i].Stake > validators[j].Stake }) - if alpha.IsZero() { + if maxVotingPower.IsZero() { return } - // return if max voting power can not be undercut because there are not enough stakers - // in the pool - if math.LegacyOneDec().Quo(alpha).GT(math.LegacyNewDec(int64(len(validators)))) { - return - } + for i, validator := range validators { + if math.LegacyNewDec(int64(effectiveStakes[validator.Address])).QuoInt64(totalStake).GT(maxVotingPower) { + amount := math.LegacyNewDec(int64(effectiveStakes[validator.Address])).Sub(maxVotingPower.MulInt64(totalStake)).TruncateInt64() - x := func(i int) uint64 { - totalStake := int64(0) + totalStakeRemainder -= int64(validator.Stake) + effectiveStakes[validator.Address] -= uint64(amount) - for _, validator := range validators[i+1:] { - totalStake += int64(validator.Stake) + for _, v := range validators[i+1:] { + effectiveStakes[v.Address] += uint64(math.LegacyNewDec(int64(effectiveStakes[v.Address])).QuoInt64(totalStakeRemainder).MulInt64(amount).TruncateInt64()) + } } - - return uint64(alpha.MulInt64(totalStake).Quo(math.LegacyOneDec().Sub(alpha.Mul(math.LegacyNewDec(int64(i)).Add(math.LegacyOneDec())))).TruncateInt64()) } - for i := range validators { - M := x(i) + lowestValidator := validators[len(validators)-1] + scaleFactor := math.LegacyZeroDec() - if validators[i].Stake >= M && M >= validators[i+1].Stake { - for _, v := range validators { - if v.Stake > M { - effectiveStakes[v.Address] = M - } - } - return - } + if effectiveStakes[lowestValidator.Address] > 0 { + scaleFactor = math.LegacyNewDec(int64(lowestValidator.Stake)).QuoInt64(int64(effectiveStakes[lowestValidator.Address])) + } + + for _, validator := range validators { + effectiveStakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(effectiveStakes[validator.Address])).TruncateInt64()) } return @@ -269,7 +271,7 @@ func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType s // get real stake fraction from the effective stake which is truly at risk for getting slashed // by dividing it with the total bonded stake from the validator - stakeFraction := math.LegacyNewDec(int64(k.GetEffectiveValidatorStakes(ctx, poolId)[staker])).QuoInt(validator.GetBondedTokens()) + stakeFraction := math.LegacyNewDec(int64(k.GetEffectiveValidatorStakes(ctx, poolId, staker)[staker])).QuoInt(validator.GetBondedTokens()) // the validator can only be slashed for his effective stake fraction in a pool, therefore we // update the slash fraction accordingly From aeeb14667d70b674ded383c0f714bfd754af022d Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Mon, 16 Dec 2024 11:19:54 +0100 Subject: [PATCH 05/24] chore: continued with tests --- .../keeper_suite_zero_delegation_test.go | 10 ++++++++++ x/bundles/keeper/logic_round_robin.go | 8 ++++---- x/bundles/keeper/logic_round_robin_test.go | 18 ++++++++++-------- x/stakers/keeper/exported_functions.go | 1 + 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/x/bundles/keeper/keeper_suite_zero_delegation_test.go b/x/bundles/keeper/keeper_suite_zero_delegation_test.go index 757de27d..f087c71f 100644 --- a/x/bundles/keeper/keeper_suite_zero_delegation_test.go +++ b/x/bundles/keeper/keeper_suite_zero_delegation_test.go @@ -2,6 +2,7 @@ package keeper_test import ( "cosmossdk.io/math" + "fmt" i "github.com/KYVENetwork/chain/testutil/integration" bundletypes "github.com/KYVENetwork/chain/x/bundles/types" funderstypes "github.com/KYVENetwork/chain/x/funders/types" @@ -164,8 +165,17 @@ var _ = Describe("zero delegation", Ordered, func() { Expect(bundleProposal.VotersInvalid).NotTo(ContainElement(i.STAKER_2)) Expect(bundleProposal.VotersAbstain).NotTo(ContainElement(i.STAKER_2)) + fmt.Println(bundleProposal) + effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) + fmt.Println(effectiveStakes) + + fmt.Println("wait 60 seconds") s.CommitAfterSeconds(60) + bundleProposal, _ = s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) + fmt.Println(bundleProposal) + + // TODO: fails here s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ Creator: i.VALADDRESS_1_A, Staker: i.STAKER_1, diff --git a/x/bundles/keeper/logic_round_robin.go b/x/bundles/keeper/logic_round_robin.go index 3edf586d..6c561fbe 100644 --- a/x/bundles/keeper/logic_round_robin.go +++ b/x/bundles/keeper/logic_round_robin.go @@ -75,15 +75,15 @@ func (k Keeper) LoadRoundRobinValidatorSet(ctx sdk.Context, poolId uint64) Round newValidators := make(map[string]bool, 0) // Add all current pool validators to the round-robin set for _, address := range k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId) { - delegation := k.stakerKeeper.GetValidatorPoolStake(ctx, address, poolId) - if delegation > 0 { + effectiveStakes := k.stakerKeeper.GetEffectiveValidatorStakes(ctx, poolId) + if effectiveStakes[address] > 0 { // If a validator has no delegation do not add to the round-robin set. Validator is basically non-existent. vs.Validators = append(vs.Validators, RoundRobinValidatorPower{ Address: address, - Power: int64(delegation), + Power: int64(effectiveStakes[address]), }) vs.Progress[address] = 0 - totalDelegation += int64(delegation) + totalDelegation += int64(effectiveStakes[address]) newValidators[address] = true } } diff --git a/x/bundles/keeper/logic_round_robin_test.go b/x/bundles/keeper/logic_round_robin_test.go index 09582726..040005b4 100644 --- a/x/bundles/keeper/logic_round_robin_test.go +++ b/x/bundles/keeper/logic_round_robin_test.go @@ -182,6 +182,8 @@ var _ = Describe("logic_round_robin.go", Ordered, func() { It("Frequency analysis", func() { // ARRANGE + // NOTE that dummy with index 2 has more than 50% voting power, so his effective stake + // will be lower joinDummy(s, 0, 2) joinDummy(s, 1, 31) joinDummy(s, 2, 67) @@ -207,16 +209,16 @@ var _ = Describe("logic_round_robin.go", Ordered, func() { // ASSERT Expect(frequency1[i.DUMMY[0]]).To(Equal(0)) - Expect(frequency1[i.DUMMY[1]]).To(Equal(3)) - Expect(frequency1[i.DUMMY[2]]).To(Equal(7)) + Expect(frequency1[i.DUMMY[1]]).To(Equal(5)) + Expect(frequency1[i.DUMMY[2]]).To(Equal(5)) - Expect(frequency2[i.DUMMY[0]]).To(Equal(2)) - Expect(frequency2[i.DUMMY[1]]).To(Equal(31)) - Expect(frequency2[i.DUMMY[2]]).To(Equal(67)) + Expect(frequency2[i.DUMMY[0]]).To(Equal(3)) + Expect(frequency2[i.DUMMY[1]]).To(Equal(47)) + Expect(frequency2[i.DUMMY[2]]).To(Equal(50)) - Expect(frequency3[i.DUMMY[0]]).To(Equal(2000)) - Expect(frequency3[i.DUMMY[1]]).To(Equal(31000)) - Expect(frequency3[i.DUMMY[2]]).To(Equal(67000)) + Expect(frequency3[i.DUMMY[0]]).To(Equal(3031)) // 2/66 + Expect(frequency3[i.DUMMY[1]]).To(Equal(46969)) // 31/66 + Expect(frequency3[i.DUMMY[2]]).To(Equal(50000)) // 33/66 }) It("Frequency analysis (rounding)", func() { diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 0e8795e7..05d9d5cd 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -246,6 +246,7 @@ func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, must } } + // TODO: take lowest validator with effective stake bigger than zero lowestValidator := validators[len(validators)-1] scaleFactor := math.LegacyZeroDec() From 2487d71fc046d4cd3952e5f994d88a74fb511ed9 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Mon, 16 Dec 2024 12:29:45 +0100 Subject: [PATCH 06/24] test: fixed existing zero delegation tests --- .../keeper_suite_zero_delegation_test.go | 138 +++--------------- x/bundles/keeper/logic_bundles.go | 3 + x/bundles/types/errors.go | 1 + x/stakers/keeper/exported_functions.go | 24 ++- 4 files changed, 38 insertions(+), 128 deletions(-) diff --git a/x/bundles/keeper/keeper_suite_zero_delegation_test.go b/x/bundles/keeper/keeper_suite_zero_delegation_test.go index f087c71f..eca7fa70 100644 --- a/x/bundles/keeper/keeper_suite_zero_delegation_test.go +++ b/x/bundles/keeper/keeper_suite_zero_delegation_test.go @@ -2,7 +2,6 @@ package keeper_test import ( "cosmossdk.io/math" - "fmt" i "github.com/KYVENetwork/chain/testutil/integration" bundletypes "github.com/KYVENetwork/chain/x/bundles/types" funderstypes "github.com/KYVENetwork/chain/x/funders/types" @@ -165,17 +164,8 @@ var _ = Describe("zero delegation", Ordered, func() { Expect(bundleProposal.VotersInvalid).NotTo(ContainElement(i.STAKER_2)) Expect(bundleProposal.VotersAbstain).NotTo(ContainElement(i.STAKER_2)) - fmt.Println(bundleProposal) - effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) - fmt.Println(effectiveStakes) - - fmt.Println("wait 60 seconds") s.CommitAfterSeconds(60) - bundleProposal, _ = s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) - fmt.Println(bundleProposal) - - // TODO: fails here s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ Creator: i.VALADDRESS_1_A, Staker: i.STAKER_1, @@ -339,11 +329,10 @@ var _ = Describe("zero delegation", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ - Creator: i.VALADDRESS_0_A, - Staker: i.STAKER_0, - PoolId: 0, - }) + // manually set next uploader + bundleProposal, _ := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) + bundleProposal.NextUploader = i.STAKER_0 + s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), bundleProposal) s.CommitAfterSeconds(60) @@ -432,7 +421,7 @@ var _ = Describe("zero delegation", Ordered, func() { Expect(bundleProposal.PoolId).To(Equal(uint64(0))) Expect(bundleProposal.StorageId).To(Equal("P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg")) Expect(bundleProposal.Uploader).To(Equal(i.STAKER_1)) - Expect(bundleProposal.NextUploader).To(Equal(i.STAKER_2)) + Expect(bundleProposal.NextUploader).To(Equal(i.STAKER_1)) Expect(bundleProposal.DataSize).To(Equal(uint64(100))) Expect(bundleProposal.DataHash).To(Equal("test_hash2")) Expect(bundleProposal.BundleSize).To(Equal(uint64(100))) @@ -518,11 +507,10 @@ var _ = Describe("zero delegation", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ - Creator: i.VALADDRESS_0_A, - Staker: i.STAKER_0, - PoolId: 0, - }) + // manually set next uploader + bundleProposal, _ := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) + bundleProposal.NextUploader = i.STAKER_0 + s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), bundleProposal) s.CommitAfterSeconds(60) @@ -687,11 +675,10 @@ var _ = Describe("zero delegation", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ - Creator: i.VALADDRESS_0_A, - Staker: i.STAKER_0, - PoolId: 0, - }) + // manually set next uploader + bundleProposal, _ := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) + bundleProposal.NextUploader = i.STAKER_0 + s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), bundleProposal) s.CommitAfterSeconds(60) @@ -794,15 +781,14 @@ var _ = Describe("zero delegation", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ - Creator: i.VALADDRESS_0_A, - Staker: i.STAKER_0, - PoolId: 0, - }) + // manually set next uploader + bundleProposal, _ := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) + bundleProposal.NextUploader = i.STAKER_0 + s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), bundleProposal) s.CommitAfterSeconds(60) - s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ + s.RunTxBundlesError(&bundletypes.MsgSubmitBundleProposal{ Creator: i.VALADDRESS_0_A, Staker: i.STAKER_0, PoolId: 0, @@ -815,93 +801,5 @@ var _ = Describe("zero delegation", Ordered, func() { ToKey: "99", BundleSummary: "test_value", }) - - s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ - Creator: i.VALADDRESS_1_A, - Staker: i.STAKER_1, - PoolId: 0, - StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", - Vote: bundletypes.VOTE_TYPE_VALID, - }) - - initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) - initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) - - initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1) - initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1_A) - - // manually set next staker - bundleProposal, _ := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) - Expect(bundleProposal.NextUploader).To(BeEmpty()) - bundleProposal.NextUploader = i.STAKER_1 - s.App().BundlesKeeper.SetBundleProposal(s.Ctx(), bundleProposal) - - // ACT - s.CommitAfterSeconds(60) - s.CommitAfterSeconds(1) - - // ASSERT - // check if bundle got not finalized on pool - pool, poolFound := s.App().PoolKeeper.GetPool(s.Ctx(), 0) - Expect(poolFound).To(BeTrue()) - - Expect(pool.CurrentKey).To(Equal("")) - Expect(pool.CurrentSummary).To(BeEmpty()) - Expect(pool.CurrentIndex).To(BeZero()) - Expect(pool.TotalBundles).To(BeZero()) - - // check if finalized bundle exists - _, finalizedBundleFound := s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) - Expect(finalizedBundleFound).To(BeFalse()) - - // check if bundle proposal got dropped - bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) - Expect(bundleProposalFound).To(BeTrue()) - - Expect(bundleProposal.PoolId).To(Equal(uint64(0))) - Expect(bundleProposal.StorageId).To(BeEmpty()) - Expect(bundleProposal.Uploader).To(BeEmpty()) - Expect(bundleProposal.NextUploader).To(BeEmpty()) - Expect(bundleProposal.DataSize).To(BeZero()) - Expect(bundleProposal.DataHash).To(BeEmpty()) - Expect(bundleProposal.BundleSize).To(BeZero()) - Expect(bundleProposal.FromKey).To(BeEmpty()) - Expect(bundleProposal.ToKey).To(BeEmpty()) - Expect(bundleProposal.BundleSummary).To(BeEmpty()) - Expect(bundleProposal.UpdatedAt).NotTo(BeZero()) - Expect(bundleProposal.VotersValid).To(BeEmpty()) - Expect(bundleProposal.VotersInvalid).To(BeEmpty()) - Expect(bundleProposal.VotersAbstain).To(BeEmpty()) - - // check uploader status - valaccountUploader, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) - Expect(valaccountUploader.Points).To(BeZero()) - - balanceValaddress := s.GetBalanceFromAddress(valaccountUploader.Valaddress) - Expect(balanceValaddress).To(Equal(initialBalanceValaddress0)) - - balanceUploader := s.GetBalanceFromAddress(valaccountUploader.Staker) - - Expect(balanceUploader).To(Equal(initialBalanceStaker0)) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(BeEmpty()) - - // check voter status - valaccountVoter, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) - Expect(valaccountVoter.Points).To(BeZero()) - - balanceVoterValaddress := s.GetBalanceFromAddress(valaccountVoter.Valaddress) - Expect(balanceVoterValaddress).To(Equal(initialBalanceValaddress1)) - - balanceVoter := s.GetBalanceFromAddress(valaccountVoter.Staker) - Expect(balanceVoter).To(Equal(initialBalanceStaker1)) - - Expect(balanceVoter).To(Equal(initialBalanceStaker1)) - Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_1, i.STAKER_1)).To(BeEmpty()) - - fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) - - // assert total pool funds - Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId)[0].Amount.Uint64()).To(Equal(100 * i.KYVE)) - Expect(fundingState.ActiveFunderAddresses).To(HaveLen(1)) }) }) diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index 93cb5aec..9b318558 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -38,6 +38,9 @@ func (k Keeper) AssertPoolCanRun(ctx sdk.Context, poolId uint64) error { // Get the total and the highest delegation of a single validator in the pool totalDelegation, _ := k.stakerKeeper.GetTotalAndHighestDelegationOfPool(ctx, poolId) + if totalDelegation == 0 { + return types.ErrPoolHasZeroDelegation + } // Error if min delegation is not reached if totalDelegation < pool.MinDelegation { diff --git a/x/bundles/types/errors.go b/x/bundles/types/errors.go index 557386d6..64e00ba9 100644 --- a/x/bundles/types/errors.go +++ b/x/bundles/types/errors.go @@ -24,4 +24,5 @@ var ( ErrAlreadyVotedAbstain = errors.Register(ModuleName, 1206, "already voted abstain on bundle proposal") ErrVotingPowerTooHigh = errors.Register(ModuleName, 1207, "staker in pool has too much voting power") ErrEndKeyReached = errors.Register(ModuleName, 1208, "end key reached") + ErrPoolHasZeroDelegation = errors.Register(ModuleName, 1209, "pool has zero delegation") ) diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 05d9d5cd..4f216fbd 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -229,7 +229,7 @@ func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, must return validators[i].Stake > validators[j].Stake }) - if maxVotingPower.IsZero() { + if totalStake == 0 || maxVotingPower.IsZero() { return } @@ -240,20 +240,24 @@ func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, must totalStakeRemainder -= int64(validator.Stake) effectiveStakes[validator.Address] -= uint64(amount) - for _, v := range validators[i+1:] { - effectiveStakes[v.Address] += uint64(math.LegacyNewDec(int64(effectiveStakes[v.Address])).QuoInt64(totalStakeRemainder).MulInt64(amount).TruncateInt64()) + if totalStakeRemainder > 0 { + for _, v := range validators[i+1:] { + effectiveStakes[v.Address] += uint64(math.LegacyNewDec(int64(effectiveStakes[v.Address])).QuoInt64(totalStakeRemainder).MulInt64(amount).TruncateInt64()) + } } } } - // TODO: take lowest validator with effective stake bigger than zero - lowestValidator := validators[len(validators)-1] scaleFactor := math.LegacyZeroDec() - if effectiveStakes[lowestValidator.Address] > 0 { - scaleFactor = math.LegacyNewDec(int64(lowestValidator.Stake)).QuoInt64(int64(effectiveStakes[lowestValidator.Address])) + // get lowest validator with effective stake still bigger than zero + for i := len(validators) - 1; i >= 0; i-- { + if effectiveStakes[validators[i].Address] > 0 { + scaleFactor = math.LegacyNewDec(int64(validators[i].Stake)).QuoInt64(int64(effectiveStakes[validators[i].Address])) + } } + // scale all effective stakes down to scale factor for _, validator := range validators { effectiveStakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(effectiveStakes[validator.Address])).TruncateInt64()) } @@ -272,7 +276,11 @@ func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType s // get real stake fraction from the effective stake which is truly at risk for getting slashed // by dividing it with the total bonded stake from the validator - stakeFraction := math.LegacyNewDec(int64(k.GetEffectiveValidatorStakes(ctx, poolId, staker)[staker])).QuoInt(validator.GetBondedTokens()) + stakeFraction := math.LegacyZeroDec() + + if !validator.GetBondedTokens().IsZero() { + stakeFraction = math.LegacyNewDec(int64(k.GetEffectiveValidatorStakes(ctx, poolId, staker)[staker])).QuoInt(validator.GetBondedTokens()) + } // the validator can only be slashed for his effective stake fraction in a pool, therefore we // update the slash fraction accordingly From 29ff7b08b4200d6dd483172384fa0a112241bc2f Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Mon, 16 Dec 2024 15:04:20 +0100 Subject: [PATCH 07/24] test: added effective stake tests --- x/stakers/keeper/exported_functions.go | 24 +- .../keeper_suite_effective_stake_test.go | 318 ++++++++++++++++++ 2 files changed, 338 insertions(+), 4 deletions(-) create mode 100644 x/stakers/keeper/keeper_suite_effective_stake_test.go diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 4f216fbd..84b428e6 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -91,6 +91,16 @@ func (k Keeper) GetDelegationOfPool(ctx sdk.Context, poolId uint64) uint64 { return totalDelegation } +// GetPoolTotalStake returns the amount in uykve which actively secures +// the given pool +func (k Keeper) GetPoolTotalStake(ctx sdk.Context, poolId uint64) (totalStake uint64) { + effectiveStakes := k.GetEffectiveValidatorStakes(ctx, poolId) + for _, stake := range effectiveStakes { + totalStake += stake + } + return +} + // GetTotalAndHighestDelegationOfPool iterates all validators of a given pool and returns the stake of the validator // with the highest stake and the sum of all stakes. func (k Keeper) GetTotalAndHighestDelegationOfPool(ctx sdk.Context, poolId uint64) (totalDelegation, highestDelegation uint64) { @@ -230,11 +240,15 @@ func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, must }) if totalStake == 0 || maxVotingPower.IsZero() { - return + return make(map[string]uint64) + } + + if math.LegacyOneDec().Quo(maxVotingPower).GT(math.LegacyNewDec(int64(len(addresses)))) { + return make(map[string]uint64) } for i, validator := range validators { - if math.LegacyNewDec(int64(effectiveStakes[validator.Address])).QuoInt64(totalStake).GT(maxVotingPower) { + if math.LegacyNewDec(int64(effectiveStakes[validator.Address])).GT(maxVotingPower.MulInt64(totalStake)) { amount := math.LegacyNewDec(int64(effectiveStakes[validator.Address])).Sub(maxVotingPower.MulInt64(totalStake)).TruncateInt64() totalStakeRemainder -= int64(validator.Stake) @@ -242,7 +256,7 @@ func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, must if totalStakeRemainder > 0 { for _, v := range validators[i+1:] { - effectiveStakes[v.Address] += uint64(math.LegacyNewDec(int64(effectiveStakes[v.Address])).QuoInt64(totalStakeRemainder).MulInt64(amount).TruncateInt64()) + effectiveStakes[v.Address] += uint64(math.LegacyNewDec(int64(v.Stake)).QuoInt64(totalStakeRemainder).MulInt64(amount).TruncateInt64()) } } } @@ -254,12 +268,14 @@ func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, must for i := len(validators) - 1; i >= 0; i-- { if effectiveStakes[validators[i].Address] > 0 { scaleFactor = math.LegacyNewDec(int64(validators[i].Stake)).QuoInt64(int64(effectiveStakes[validators[i].Address])) + break } } // scale all effective stakes down to scale factor for _, validator := range validators { - effectiveStakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(effectiveStakes[validator.Address])).TruncateInt64()) + // TODO: is rounding here fine? + effectiveStakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(effectiveStakes[validator.Address])).RoundInt64()) } return diff --git a/x/stakers/keeper/keeper_suite_effective_stake_test.go b/x/stakers/keeper/keeper_suite_effective_stake_test.go new file mode 100644 index 00000000..0314ead5 --- /dev/null +++ b/x/stakers/keeper/keeper_suite_effective_stake_test.go @@ -0,0 +1,318 @@ +package keeper_test + +import ( + "cosmossdk.io/math" + stakerstypes "github.com/KYVENetwork/chain/x/stakers/types" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + i "github.com/KYVENetwork/chain/testutil/integration" + pooltypes "github.com/KYVENetwork/chain/x/pool/types" +) + +/* + +TEST CASES - keeper_suite_effective_stake_test.go + +* Test effective stake with all validators below the max pool voting power +* Test effective stake with one validator above the max pool voting power +* Test effective stake with multiple validators above the max pool voting power +* Test effective stake with fewer validators than required to undercut the max pool voting power +* Test effective stake with some validators having zero delegation +* Test effective stake with all validators having zero delegation + +*/ + +var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { + s := i.NewCleanChain() + + gov := s.App().GovKeeper.GetGovernanceAccount(s.Ctx()).GetAddress().String() + + BeforeEach(func() { + // init new clean chain + s = i.NewCleanChain() + + // create pool + msg := &pooltypes.MsgCreatePool{ + Authority: gov, + UploadInterval: 60, + MaxBundleSize: 100, + InflationShareWeight: math.LegacyZeroDec(), + Binaries: "{}", + } + s.RunTxPoolSuccess(msg) + + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.5") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + }) + + AfterEach(func() { + s.PerformValidityChecks() + }) + + It("Test effective stake with all validators below the max pool voting power", func() { + // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ACT + effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) + + // ASSERT + Expect(len(effectiveStakes)).To(Equal(3)) + Expect(effectiveStakes[i.STAKER_0]).To(Equal(100 * i.KYVE)) + Expect(effectiveStakes[i.STAKER_1]).To(Equal(100 * i.KYVE)) + Expect(effectiveStakes[i.STAKER_2]).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(Equal(300 * i.KYVE)) + }) + + It("Test effective stake with one validator above the max pool voting power", func() { + // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(250*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ACT + effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) + + // ASSERT + Expect(len(effectiveStakes)).To(Equal(3)) + Expect(effectiveStakes[i.STAKER_0]).To(Equal(100 * i.KYVE)) + Expect(effectiveStakes[i.STAKER_1]).To(Equal(200 * i.KYVE)) + Expect(effectiveStakes[i.STAKER_2]).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) + }) + + It("Test effective stake with multiple validators above the max pool voting power", func() { + // ARRANGE + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.35") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + + s.CreateValidator(i.STAKER_0, "Staker-0", int64(600*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(500*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(120*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ACT + effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) + + // ASSERT + Expect(len(effectiveStakes)).To(Equal(3)) + Expect(effectiveStakes[i.STAKER_0]).To(Equal(140 * i.KYVE)) + Expect(effectiveStakes[i.STAKER_1]).To(Equal(140 * i.KYVE)) + Expect(effectiveStakes[i.STAKER_2]).To(Equal(120 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) + }) + + It("Test effective stake with fewer validators than required to undercut the max pool voting power", func() { + // ARRANGE + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.2") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ACT + effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) + + // ASSERT + Expect(len(effectiveStakes)).To(BeZero()) + Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(BeZero()) + }) + + It("Test effective stake with some validators having zero delegation", func() { + // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(200*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateZeroDelegationValidator(i.STAKER_1, "Staker-1") + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ACT + effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) + + // ASSERT + Expect(len(effectiveStakes)).To(Equal(3)) + Expect(effectiveStakes[i.STAKER_0]).To(Equal(100 * i.KYVE)) + Expect(effectiveStakes[i.STAKER_1]).To(Equal(0 * i.KYVE)) + Expect(effectiveStakes[i.STAKER_2]).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + }) + + It("Test effective stake with all validators having zero delegation", func() { + // ARRANGE + s.CreateZeroDelegationValidator(i.STAKER_0, "Staker-0") + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateZeroDelegationValidator(i.STAKER_1, "Staker-1") + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateZeroDelegationValidator(i.STAKER_2, "Staker-2") + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ACT + effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) + + // ASSERT + Expect(len(effectiveStakes)).To(BeZero()) + Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(BeZero()) + }) +}) From 36f8f1649297e13325350a35c6481644afa56c3b Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Mon, 16 Dec 2024 16:52:35 +0100 Subject: [PATCH 08/24] test: fixed existing tests --- testutil/integration/checks.go | 4 +- .../keeper_suite_invalid_bundles_test.go | 28 ++-- .../keeper/keeper_suite_stakers_leave_test.go | 12 +- .../keeper/keeper_suite_valid_bundles_test.go | 2 +- .../keeper_suite_zero_delegation_test.go | 4 +- x/bundles/keeper/logic_bundles.go | 33 ++--- ...ic_end_block_handle_upload_timeout_test.go | 36 +++-- x/bundles/keeper/logic_round_robin.go | 8 +- x/bundles/types/expected_keepers.go | 5 +- x/query/keeper/grpc_query_pool.go | 2 +- x/query/keeper/helper.go | 13 +- x/stakers/keeper/exported_functions.go | 129 ++--------------- .../keeper_suite_effective_stake_test.go | 136 +++++++++++++----- x/stakers/keeper/logic_stakers.go | 86 ++++++++++- x/stakers/keeper/msg_server_join_pool_test.go | 42 +++--- .../keeper/msg_server_leave_pool_test.go | 16 ++- .../msg_server_update_stake_fraction_test.go | 52 +++---- 17 files changed, 316 insertions(+), 292 deletions(-) diff --git a/testutil/integration/checks.go b/testutil/integration/checks.go index 94c1de37..b76c5fdf 100644 --- a/testutil/integration/checks.go +++ b/testutil/integration/checks.go @@ -101,7 +101,7 @@ func (suite *KeeperTestSuite) VerifyPoolQueries() { for i := range poolsState { bundleProposalState, _ := suite.App().BundlesKeeper.GetBundleProposal(suite.Ctx(), poolsState[i].Id) stakersState := suite.App().StakersKeeper.GetAllStakerAddressesOfPool(suite.Ctx(), poolsState[i].Id) - totalDelegationState := suite.App().StakersKeeper.GetDelegationOfPool(suite.Ctx(), poolsState[i].Id) + totalDelegationState := suite.App().StakersKeeper.GetTotalStakeOfPool(suite.Ctx(), poolsState[i].Id) Expect(poolsQuery[i].Id).To(Equal(poolsState[i].Id)) Expect(*poolsQuery[i].Data).To(Equal(poolsState[i])) @@ -175,7 +175,7 @@ func (suite *KeeperTestSuite) VerifyStakersModuleAssetsIntegrity() { func (suite *KeeperTestSuite) VerifyPoolTotalStake() { for _, pool := range suite.App().PoolKeeper.GetAllPools(suite.Ctx()) { expectedBalance := uint64(0) - actualBalance := suite.App().StakersKeeper.GetDelegationOfPool(suite.Ctx(), pool.Id) + actualBalance := suite.App().StakersKeeper.GetTotalStakeOfPool(suite.Ctx(), pool.Id) for _, stakerAddress := range suite.App().StakersKeeper.GetAllStakerAddressesOfPool(suite.Ctx(), pool.Id) { expectedBalance += suite.App().StakersKeeper.GetValidatorPoolStake(suite.Ctx(), stakerAddress, pool.Id) diff --git a/x/bundles/keeper/keeper_suite_invalid_bundles_test.go b/x/bundles/keeper/keeper_suite_invalid_bundles_test.go index 32d1f9b0..3208c8e2 100644 --- a/x/bundles/keeper/keeper_suite_invalid_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_invalid_bundles_test.go @@ -62,6 +62,10 @@ var _ = Describe("invalid bundles", Ordered, func() { } s.RunTxPoolSuccess(msg) + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.RunTxFundersSuccess(&funderstypes.MsgCreateFunder{ Creator: i.ALICE, Moniker: "Alice", @@ -94,12 +98,6 @@ var _ = Describe("invalid bundles", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ - Creator: i.VALADDRESS_0_A, - Staker: i.STAKER_0, - PoolId: 0, - }) - initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) @@ -164,8 +162,8 @@ var _ = Describe("invalid bundles", Ordered, func() { s.CommitAfterSeconds(60) s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ - Creator: i.VALADDRESS_1_A, - Staker: i.STAKER_1, + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, PoolId: 0, StorageId: "P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg", DataSize: 100, @@ -230,7 +228,7 @@ var _ = Describe("invalid bundles", Ordered, func() { slashAmount := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100*i.KYVE - slashAmount)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check voter status valaccountVoter, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) @@ -330,8 +328,8 @@ var _ = Describe("invalid bundles", Ordered, func() { s.CommitAfterSeconds(60) s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ - Creator: i.VALADDRESS_1_A, - Staker: i.STAKER_1, + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, PoolId: 0, StorageId: "P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg", DataSize: 100, @@ -400,7 +398,7 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100*i.KYVE - slashAmountUploader)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.ALICE)).To(Equal(100*i.KYVE - slashAmountDelegator)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) // check voter status valaccountVoter, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) @@ -526,8 +524,8 @@ var _ = Describe("invalid bundles", Ordered, func() { s.CommitAfterSeconds(60) s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ - Creator: i.VALADDRESS_3_A, - Staker: i.STAKER_3, + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, PoolId: 0, StorageId: "P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg", DataSize: 100, @@ -604,7 +602,7 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_1, i.STAKER_1)).To(Equal(100*i.KYVE - slashAmountVoter)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_1, i.BOB)).To(Equal(100*i.KYVE - slashAmountDelegator2)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(450 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(450 * i.KYVE)) // check voter status _, voterActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) diff --git a/x/bundles/keeper/keeper_suite_stakers_leave_test.go b/x/bundles/keeper/keeper_suite_stakers_leave_test.go index 29ee4340..f42c26d1 100644 --- a/x/bundles/keeper/keeper_suite_stakers_leave_test.go +++ b/x/bundles/keeper/keeper_suite_stakers_leave_test.go @@ -140,7 +140,7 @@ var _ = Describe("stakers leave", Ordered, func() { _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccountActive).To(BeFalse()) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check if next uploader got not slashed Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100 * i.KYVE)) @@ -228,7 +228,7 @@ var _ = Describe("stakers leave", Ordered, func() { _, valaccountActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccountActive).To(BeFalse()) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check if next uploader got not slashed Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100 * i.KYVE)) @@ -344,7 +344,7 @@ var _ = Describe("stakers leave", Ordered, func() { slashAmount := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100*i.KYVE - slashAmount)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check if next uploader did not receive the uploader reward balanceUploader := s.GetBalanceFromAddress(i.STAKER_0) @@ -444,7 +444,7 @@ var _ = Describe("stakers leave", Ordered, func() { slashAmount := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_1, i.STAKER_1)).To(Equal(100*i.KYVE - slashAmount)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check if next uploader did not receive any rewards balanceVoter := s.GetBalanceFromAddress(i.STAKER_1) @@ -536,7 +536,7 @@ var _ = Describe("stakers leave", Ordered, func() { // check if voter status Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_1, i.STAKER_1)).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check if next uploader did not receive any rewards balanceVoter := s.GetBalanceFromAddress(i.STAKER_1) @@ -631,7 +631,7 @@ var _ = Describe("stakers leave", Ordered, func() { // check if voter not got slashed Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_1, i.STAKER_1)).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check if next uploader did not receive any rewards balanceVoter := s.GetBalanceFromAddress(i.STAKER_1) diff --git a/x/bundles/keeper/keeper_suite_valid_bundles_test.go b/x/bundles/keeper/keeper_suite_valid_bundles_test.go index b3de63d4..17e5b636 100644 --- a/x/bundles/keeper/keeper_suite_valid_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_valid_bundles_test.go @@ -922,7 +922,7 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.STAKER_2)).To(Equal(100*i.KYVE - slashAmountVoter)) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.CHARLIE)).To(Equal(300*i.KYVE - slashAmountDelegator)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(800 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(800 * i.KYVE)) // check voter status _, voterActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_2) diff --git a/x/bundles/keeper/keeper_suite_zero_delegation_test.go b/x/bundles/keeper/keeper_suite_zero_delegation_test.go index eca7fa70..7a8585f5 100644 --- a/x/bundles/keeper/keeper_suite_zero_delegation_test.go +++ b/x/bundles/keeper/keeper_suite_zero_delegation_test.go @@ -291,7 +291,7 @@ var _ = Describe("zero delegation", Ordered, func() { slashAmountVoter := uint64(math.LegacyNewDec(int64(0 * i.KYVE)).Mul(fraction).TruncateInt64()) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.STAKER_2)).To(Equal(0*i.KYVE - slashAmountVoter)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200*i.KYVE - slashAmountVoter)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200*i.KYVE - slashAmountVoter)) }) It("Staker submit bundle proposal with zero delegation", func() { @@ -619,7 +619,7 @@ var _ = Describe("zero delegation", Ordered, func() { slashAmount := uint64(math.LegacyNewDec(int64(0 * i.KYVE)).Mul(fraction).TruncateInt64()) Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(0*i.KYVE - slashAmount)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200*i.KYVE - slashAmount)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200*i.KYVE - slashAmount)) // check voter status valaccountVoter, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index 9b318558..cfa4a035 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -36,30 +36,17 @@ func (k Keeper) AssertPoolCanRun(ctx sdk.Context, poolId uint64) error { return types.ErrEndKeyReached } - // Get the total and the highest delegation of a single validator in the pool - totalDelegation, _ := k.stakerKeeper.GetTotalAndHighestDelegationOfPool(ctx, poolId) - if totalDelegation == 0 { - return types.ErrPoolHasZeroDelegation + // Error if max voting power is not achievable because there are not enough stakers + // in the pool + if k.stakerKeeper.IsVotingPowerTooHigh(ctx, poolId) { + return types.ErrVotingPowerTooHigh } // Error if min delegation is not reached - if totalDelegation < pool.MinDelegation { + if k.stakerKeeper.GetTotalStakeOfPool(ctx, poolId) < pool.MinDelegation { return types.ErrMinDelegationNotReached } - stakers := int64(len(k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId))) - maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) - - if maxVotingPower.IsZero() { - return nil - } - - // Error if max voting power is not achievable because there are not enough stakers - // in the pool - if math.LegacyOneDec().Quo(maxVotingPower).GT(math.LegacyNewDec(stakers)) { - return types.ErrVotingPowerTooHigh - } - return nil } @@ -510,26 +497,24 @@ func (k Keeper) GetVoteDistribution(ctx sdk.Context, poolId uint64) (voteDistrib return } - effectiveStakes := k.stakerKeeper.GetEffectiveValidatorStakes(ctx, poolId) - // get voting power for valid for _, voter := range bundleProposal.VotersValid { - voteDistribution.Valid += effectiveStakes[voter] + voteDistribution.Valid += k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) } // get voting power for invalid for _, voter := range bundleProposal.VotersInvalid { - voteDistribution.Invalid += effectiveStakes[voter] + voteDistribution.Invalid += k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) } // get voting power for abstain for _, voter := range bundleProposal.VotersAbstain { - voteDistribution.Abstain += effectiveStakes[voter] + voteDistribution.Abstain += k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) } // get total voting power for _, staker := range k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId) { - voteDistribution.Total += effectiveStakes[staker] + voteDistribution.Total += k.stakerKeeper.GetValidatorPoolStake(ctx, staker, poolId) } if voteDistribution.Total == 0 { diff --git a/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go b/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go index 8776dda3..bdb04f90 100644 --- a/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go +++ b/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go @@ -281,7 +281,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(20 * i.KYVE)) }) - It("Next uploader gets not removed although pool having one node with more than 50% voting power", func() { + It("Next uploader gets removed due to pool having validators with too much voting power", func() { // ARRANGE s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ Creator: i.VALADDRESS_0_A, @@ -289,18 +289,16 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { PoolId: 0, }) - s.RunTxSuccess(stakingTypes.NewMsgDelegate( - i.STAKER_0, - util.MustValaddressFromOperatorAddress(i.STAKER_0), - sdk.NewInt64Coin(globalTypes.Denom, int64(1*i.KYVE)), - )) + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.2") + s.App().PoolKeeper.SetParams(s.Ctx(), params) // ACT s.CommitAfterSeconds(1) // ASSERT bundleProposal, _ := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) - Expect(bundleProposal.NextUploader).To(Equal("kyve1htgfatqevuvfzvl0sxp97ywteqhg5leha9emf4")) + Expect(bundleProposal.NextUploader).To(BeEmpty()) Expect(bundleProposal.StorageId).To(BeEmpty()) poolStakers := s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0) @@ -308,11 +306,11 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(101 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(BeZero()) _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_1) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(BeZero()) }) It("Staker is next uploader of genesis bundle and upload interval and timeout does not pass", func() { @@ -401,7 +399,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check if next uploader not got slashed expectedBalance := 100 * i.KYVE @@ -578,7 +576,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(expectedBalance).To(Equal(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_1, i.STAKER_1))) // pool delegations equals delegations of staker 0 & 1 - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) }) It("Staker is next uploader of bundle proposal and upload timeout passes with the previous bundle not reaching quorum", func() { @@ -641,7 +639,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(found).To(BeTrue()) // pool delegations equals delegations of staker 0 & 1 - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) }) It("Staker is next uploader of bundle proposal and upload timeout passes with the previous bundle being invalid", func() { @@ -697,7 +695,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Vote: bundletypes.VOTE_TYPE_INVALID, }) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(300 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(300 * i.KYVE)) // ACT s.CommitAfterSeconds(s.App().BundlesKeeper.GetUploadTimeout(s.Ctx())) @@ -739,7 +737,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(expectedBalance).To(Equal(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.STAKER_2))) // pool delegations equals delegations of staker 1 & 2 - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) }) It("Staker with already max points is next uploader of bundle proposal and upload timeout passes", func() { @@ -869,7 +867,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { Expect(expectedBalance).To(Equal(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.STAKER_2))) // pool delegations equals delegations of staker 0 & 1 - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) }) It("A bundle proposal with no quorum does not reach the upload interval", func() { @@ -1030,7 +1028,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_2) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check if next uploader not got slashed expectedBalance := 100 * i.KYVE @@ -1118,7 +1116,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_2) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check if next uploader not got slashed expectedBalance := 100 * i.KYVE @@ -1201,7 +1199,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) // check that uploader received upload slash expectedBalance := 100*i.KYVE - uint64(s.App().StakersKeeper.GetUploadSlash(s.Ctx()).Mul(math.LegacyNewDec(int64(100*i.KYVE))).TruncateInt64()) @@ -1367,7 +1365,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { _, found = s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_2) Expect(found).To(BeTrue()) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 1)).To(Equal(200 * i.KYVE)) // check if next uploader not got slashed slashAmountRatio := s.App().StakersKeeper.GetTimeoutSlash(s.Ctx()) diff --git a/x/bundles/keeper/logic_round_robin.go b/x/bundles/keeper/logic_round_robin.go index 6c561fbe..ea9e99c9 100644 --- a/x/bundles/keeper/logic_round_robin.go +++ b/x/bundles/keeper/logic_round_robin.go @@ -75,15 +75,15 @@ func (k Keeper) LoadRoundRobinValidatorSet(ctx sdk.Context, poolId uint64) Round newValidators := make(map[string]bool, 0) // Add all current pool validators to the round-robin set for _, address := range k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId) { - effectiveStakes := k.stakerKeeper.GetEffectiveValidatorStakes(ctx, poolId) - if effectiveStakes[address] > 0 { + stake := k.stakerKeeper.GetValidatorPoolStake(ctx, address, poolId) + if stake > 0 { // If a validator has no delegation do not add to the round-robin set. Validator is basically non-existent. vs.Validators = append(vs.Validators, RoundRobinValidatorPower{ Address: address, - Power: int64(effectiveStakes[address]), + Power: int64(stake), }) vs.Progress[address] = 0 - totalDelegation += int64(effectiveStakes[address]) + totalDelegation += int64(stake) newValidators[address] = true } } diff --git a/x/bundles/types/expected_keepers.go b/x/bundles/types/expected_keepers.go index 0b41d0ef..7a667f46 100644 --- a/x/bundles/types/expected_keepers.go +++ b/x/bundles/types/expected_keepers.go @@ -38,15 +38,14 @@ type StakerKeeper interface { IncrementPoints(ctx sdk.Context, poolId uint64, stakerAddress string) (newPoints uint64) ResetPoints(ctx sdk.Context, poolId uint64, stakerAddress string) (previousPoints uint64) - GetTotalAndHighestDelegationOfPool(ctx sdk.Context, poolId uint64) (totalDelegation, highestDelegation uint64) GetValidator(ctx sdk.Context, staker string) (stakingtypes.Validator, bool) GetValidatorPoolCommission(ctx sdk.Context, staker string, poolId uint64) math.LegacyDec - GetValidatorPoolStakeFraction(ctx sdk.Context, staker string, poolId uint64) math.LegacyDec GetValidatorPoolStake(ctx sdk.Context, staker string, poolId uint64) uint64 + GetTotalStakeOfPool(ctx sdk.Context, poolId uint64) (totalStake uint64) + IsVotingPowerTooHigh(ctx sdk.Context, poolId uint64) bool Slash(ctx sdk.Context, poolId uint64, staker string, slashType stakersTypes.SlashType) PayoutRewards(ctx sdk.Context, staker string, amount sdk.Coins, payerModuleName string) error PayoutAdditionalCommissionRewards(ctx sdk.Context, validator string, payerModuleName string, amount sdk.Coins) error - GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, mustIncludeStakers ...string) (effectiveStake map[string]uint64) } type FundersKeeper interface { diff --git a/x/query/keeper/grpc_query_pool.go b/x/query/keeper/grpc_query_pool.go index e940b6c0..6062b54b 100644 --- a/x/query/keeper/grpc_query_pool.go +++ b/x/query/keeper/grpc_query_pool.go @@ -60,7 +60,7 @@ func (k Keeper) parsePoolResponse(ctx sdk.Context, pool *poolTypes.Pool) types.P totalSelfDelegation += k.stakerKeeper.GetDelegationAmountOfDelegator(ctx, address, address) } - totalDelegation := k.stakerKeeper.GetDelegationOfPool(ctx, pool.Id) + totalDelegation := k.stakerKeeper.GetTotalStakeOfPool(ctx, pool.Id) poolAccount := pool.GetPoolAccount() poolBalance := k.bankKeeper.GetBalance(ctx, poolAccount, globalTypes.Denom).Amount.Uint64() diff --git a/x/query/keeper/helper.go b/x/query/keeper/helper.go index 637486c1..364183c5 100644 --- a/x/query/keeper/helper.go +++ b/x/query/keeper/helper.go @@ -40,7 +40,7 @@ func (k Keeper) GetFullStaker(ctx sdk.Context, stakerAddress string) *types.Full InflationShareWeight: pool.InflationShareWeight, UploadInterval: pool.UploadInterval, TotalFunds: k.fundersKeeper.GetTotalActiveFunding(ctx, pool.Id), - TotalDelegation: k.stakerKeeper.GetDelegationOfPool(ctx, pool.Id), + TotalDelegation: k.stakerKeeper.GetTotalStakeOfPool(ctx, pool.Id), Status: k.GetPoolStatus(ctx, &pool), }, Points: valaccount.Points, @@ -67,11 +67,6 @@ func (k Keeper) GetFullStaker(ctx sdk.Context, stakerAddress string) *types.Full } func (k Keeper) GetPoolStatus(ctx sdk.Context, pool *pooltypes.Pool) pooltypes.PoolStatus { - // Get the total and the highest delegation of a single validator in the pool - totalDelegation, highestDelegation := k.stakerKeeper.GetTotalAndHighestDelegationOfPool(ctx, pool.Id) - maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) - maxDelegation := uint64(maxVotingPower.MulInt64(int64(totalDelegation)).TruncateInt64()) - var poolStatus pooltypes.PoolStatus poolStatus = pooltypes.POOL_STATUS_ACTIVE @@ -81,10 +76,10 @@ func (k Keeper) GetPoolStatus(ctx sdk.Context, pool *pooltypes.Pool) pooltypes.P poolStatus = pooltypes.POOL_STATUS_DISABLED } else if pool.EndKey != "" && pool.EndKey == pool.CurrentKey { poolStatus = pooltypes.POOL_STATUS_END_KEY_REACHED - } else if totalDelegation < pool.MinDelegation { - poolStatus = pooltypes.POOL_STATUS_NOT_ENOUGH_DELEGATION - } else if highestDelegation > maxDelegation { + } else if k.stakerKeeper.IsVotingPowerTooHigh(ctx, pool.Id) { poolStatus = pooltypes.POOL_STATUS_VOTING_POWER_TOO_HIGH + } else if k.stakerKeeper.GetTotalStakeOfPool(ctx, pool.Id) < pool.MinDelegation { + poolStatus = pooltypes.POOL_STATUS_NOT_ENOUGH_DELEGATION } else if k.fundersKeeper.GetTotalActiveFunding(ctx, pool.Id).IsZero() { poolStatus = pooltypes.POOL_STATUS_NO_FUNDS } diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 84b428e6..0d31c2e7 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -2,7 +2,6 @@ package keeper import ( "context" - "sort" "cosmossdk.io/errors" "cosmossdk.io/math" @@ -81,39 +80,27 @@ func (k Keeper) GetActiveStakers(ctx sdk.Context) []string { return k.getAllActiveStakers(ctx) } -// GetDelegationOfPool returns the amount of how many ukyve users have delegated -// to stakers that are participating in the given pool -func (k Keeper) GetDelegationOfPool(ctx sdk.Context, poolId uint64) uint64 { - totalDelegation := uint64(0) - for _, address := range k.GetAllStakerAddressesOfPool(ctx, poolId) { - totalDelegation += k.GetValidatorPoolStake(ctx, address, poolId) - } - return totalDelegation -} - -// GetPoolTotalStake returns the amount in uykve which actively secures +// GetTotalStakeOfPool returns the amount in uykve which actively secures // the given pool -func (k Keeper) GetPoolTotalStake(ctx sdk.Context, poolId uint64) (totalStake uint64) { - effectiveStakes := k.GetEffectiveValidatorStakes(ctx, poolId) +func (k Keeper) GetTotalStakeOfPool(ctx sdk.Context, poolId uint64) (totalStake uint64) { + effectiveStakes := k.getEffectiveValidatorStakes(ctx, poolId) for _, stake := range effectiveStakes { totalStake += stake } return } -// GetTotalAndHighestDelegationOfPool iterates all validators of a given pool and returns the stake of the validator -// with the highest stake and the sum of all stakes. -func (k Keeper) GetTotalAndHighestDelegationOfPool(ctx sdk.Context, poolId uint64) (totalDelegation, highestDelegation uint64) { - for _, address := range k.GetAllStakerAddressesOfPool(ctx, poolId) { - delegation := k.GetValidatorPoolStake(ctx, address, poolId) - totalDelegation += delegation +// IsVotingPowerTooHigh returns whether there are enough validators in a pool +// to successfully stay below the max voting power +func (k Keeper) IsVotingPowerTooHigh(ctx sdk.Context, poolId uint64) bool { + addresses := int64(len(k.GetAllStakerAddressesOfPool(ctx, poolId))) + maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) - if delegation > highestDelegation { - highestDelegation = delegation - } + if maxVotingPower.IsZero() { + return true } - return totalDelegation, highestDelegation + return math.LegacyOneDec().Quo(maxVotingPower).GT(math.LegacyNewDec(addresses)) } // GetValidator returns the Cosmos-validator for a given kyve-address. @@ -136,21 +123,9 @@ func (k Keeper) GetValidatorPoolCommission(ctx sdk.Context, staker string, poolI return valaccount.Commission } -// GetValidatorPoolStakeFraction returns the stake fraction a validator has inside the pool -func (k Keeper) GetValidatorPoolStakeFraction(ctx sdk.Context, staker string, poolId uint64) math.LegacyDec { - valaccount, _ := k.GetValaccount(ctx, poolId, staker) - return valaccount.StakeFraction -} - -// GetValidatorPoolStake returns stake a validator has inside the pool +// GetValidatorPoolStake returns stake a validator has actively and at risk inside the pool func (k Keeper) GetValidatorPoolStake(ctx sdk.Context, staker string, poolId uint64) uint64 { - validator, found := k.GetValidator(ctx, staker) - if !found { - return 0 - } - - stakeFraction := k.GetValidatorPoolStakeFraction(ctx, staker, poolId) - return uint64(math.LegacyNewDecFromInt(validator.BondedTokens()).Mul(stakeFraction).TruncateInt64()) + return k.getEffectiveValidatorStakes(ctx, poolId, staker)[staker] } // GetOutstandingCommissionRewards returns the outstanding commission rewards for a given validator @@ -205,82 +180,6 @@ func (k Keeper) GetOutstandingRewards(orgCtx sdk.Context, staker string, delegat return util.TruncateDecCoins(rewards) } -// GetEffectiveValidatorStakes returns a map for all pool stakers their effective stake. Effective stake -// is the actual stake at risk for a validator, it can be lower than the provided stake because -// of the max voting power per pool parameter, but it can never be higher. Thus, if the effective -// stake is lower than the provided one the slash -// TODO: explain or link to formula -func (k Keeper) GetEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, mustIncludeStakers ...string) (effectiveStakes map[string]uint64) { - type ValidatorStake struct { - Address string - Stake uint64 - } - - addresses := util.RemoveDuplicateStrings(append(k.GetAllStakerAddressesOfPool(ctx, poolId), mustIncludeStakers...)) - maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) - effectiveStakes = make(map[string]uint64) - validators := make([]ValidatorStake, 0) - totalStake := int64(0) - - for _, address := range addresses { - stake := k.GetValidatorPoolStake(ctx, address, poolId) - effectiveStakes[address] = stake - validators = append(validators, ValidatorStake{ - Address: address, - Stake: stake, - }) - totalStake += int64(stake) - } - - totalStakeRemainder := totalStake - - // sort descending based on stake - sort.Slice(validators, func(i, j int) bool { - return validators[i].Stake > validators[j].Stake - }) - - if totalStake == 0 || maxVotingPower.IsZero() { - return make(map[string]uint64) - } - - if math.LegacyOneDec().Quo(maxVotingPower).GT(math.LegacyNewDec(int64(len(addresses)))) { - return make(map[string]uint64) - } - - for i, validator := range validators { - if math.LegacyNewDec(int64(effectiveStakes[validator.Address])).GT(maxVotingPower.MulInt64(totalStake)) { - amount := math.LegacyNewDec(int64(effectiveStakes[validator.Address])).Sub(maxVotingPower.MulInt64(totalStake)).TruncateInt64() - - totalStakeRemainder -= int64(validator.Stake) - effectiveStakes[validator.Address] -= uint64(amount) - - if totalStakeRemainder > 0 { - for _, v := range validators[i+1:] { - effectiveStakes[v.Address] += uint64(math.LegacyNewDec(int64(v.Stake)).QuoInt64(totalStakeRemainder).MulInt64(amount).TruncateInt64()) - } - } - } - } - - scaleFactor := math.LegacyZeroDec() - - // get lowest validator with effective stake still bigger than zero - for i := len(validators) - 1; i >= 0; i-- { - if effectiveStakes[validators[i].Address] > 0 { - scaleFactor = math.LegacyNewDec(int64(validators[i].Stake)).QuoInt64(int64(effectiveStakes[validators[i].Address])) - break - } - } - - // scale all effective stakes down to scale factor - for _, validator := range validators { - // TODO: is rounding here fine? - effectiveStakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(effectiveStakes[validator.Address])).RoundInt64()) - } - - return -} - // Slash reduces the delegation of all delegators of `staker` by fraction. The slash itself is handled by the cosmos-sdk func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType stakertypes.SlashType) { validator, found := k.GetValidator(ctx, staker) @@ -295,7 +194,7 @@ func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType s stakeFraction := math.LegacyZeroDec() if !validator.GetBondedTokens().IsZero() { - stakeFraction = math.LegacyNewDec(int64(k.GetEffectiveValidatorStakes(ctx, poolId, staker)[staker])).QuoInt(validator.GetBondedTokens()) + stakeFraction = math.LegacyNewDec(int64(k.getEffectiveValidatorStakes(ctx, poolId, staker)[staker])).QuoInt(validator.GetBondedTokens()) } // the validator can only be slashed for his effective stake fraction in a pool, therefore we diff --git a/x/stakers/keeper/keeper_suite_effective_stake_test.go b/x/stakers/keeper/keeper_suite_effective_stake_test.go index 0314ead5..8697929b 100644 --- a/x/stakers/keeper/keeper_suite_effective_stake_test.go +++ b/x/stakers/keeper/keeper_suite_effective_stake_test.go @@ -21,6 +21,8 @@ TEST CASES - keeper_suite_effective_stake_test.go * Test effective stake with fewer validators than required to undercut the max pool voting power * Test effective stake with some validators having zero delegation * Test effective stake with all validators having zero delegation +* Test effective stake with 0% as max pool stake +* Test effective stake with 100% as max pool stake */ @@ -85,15 +87,15 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { }) // ACT - effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) // ASSERT - Expect(len(effectiveStakes)).To(Equal(3)) - Expect(effectiveStakes[i.STAKER_0]).To(Equal(100 * i.KYVE)) - Expect(effectiveStakes[i.STAKER_1]).To(Equal(100 * i.KYVE)) - Expect(effectiveStakes[i.STAKER_2]).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) - Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(Equal(300 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(300 * i.KYVE)) }) It("Test effective stake with one validator above the max pool voting power", func() { @@ -128,16 +130,14 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - // ACT - effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) - // ASSERT - Expect(len(effectiveStakes)).To(Equal(3)) - Expect(effectiveStakes[i.STAKER_0]).To(Equal(100 * i.KYVE)) - Expect(effectiveStakes[i.STAKER_1]).To(Equal(200 * i.KYVE)) - Expect(effectiveStakes[i.STAKER_2]).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) - Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) }) It("Test effective stake with multiple validators above the max pool voting power", func() { @@ -176,16 +176,14 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - // ACT - effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) - // ASSERT - Expect(len(effectiveStakes)).To(Equal(3)) - Expect(effectiveStakes[i.STAKER_0]).To(Equal(140 * i.KYVE)) - Expect(effectiveStakes[i.STAKER_1]).To(Equal(140 * i.KYVE)) - Expect(effectiveStakes[i.STAKER_2]).To(Equal(120 * i.KYVE)) + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) + + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(140 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(140 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(120 * i.KYVE)) - Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) }) It("Test effective stake with fewer validators than required to undercut the max pool voting power", func() { @@ -224,12 +222,10 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - // ACT - effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) - // ASSERT - Expect(len(effectiveStakes)).To(BeZero()) - Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(BeZero()) + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeTrue()) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(BeZero()) }) It("Test effective stake with some validators having zero delegation", func() { @@ -264,16 +260,14 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - // ACT - effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) - // ASSERT - Expect(len(effectiveStakes)).To(Equal(3)) - Expect(effectiveStakes[i.STAKER_0]).To(Equal(100 * i.KYVE)) - Expect(effectiveStakes[i.STAKER_1]).To(Equal(0 * i.KYVE)) - Expect(effectiveStakes[i.STAKER_2]).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) - Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(0 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) }) It("Test effective stake with all validators having zero delegation", func() { @@ -308,11 +302,75 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - // ACT - effectiveStakes := s.App().StakersKeeper.GetEffectiveValidatorStakes(s.Ctx(), 0) + // ASSERT + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(BeZero()) + }) + + It("Test effective stake with 0% as max pool stake", func() { + // ARRANGE + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) // ASSERT - Expect(len(effectiveStakes)).To(BeZero()) - Expect(s.App().StakersKeeper.GetPoolTotalStake(s.Ctx(), 0)).To(BeZero()) + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeTrue()) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(BeZero()) + }) + + It("Test effective stake with 100% as max pool stake", func() { + // ARRANGE + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // ASSERT + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) + + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(100 * i.KYVE)) }) }) diff --git a/x/stakers/keeper/logic_stakers.go b/x/stakers/keeper/logic_stakers.go index 22009d1f..2cff35ee 100644 --- a/x/stakers/keeper/logic_stakers.go +++ b/x/stakers/keeper/logic_stakers.go @@ -2,6 +2,7 @@ package keeper import ( m "math" + "sort" "cosmossdk.io/math" @@ -15,6 +16,85 @@ import ( errorsTypes "github.com/cosmos/cosmos-sdk/types/errors" ) +// getEffectiveValidatorStakes returns a map for all pool stakers their effective stake. Effective stake +// is the actual stake at risk for a validator, it can be lower than the provided stake because +// of the max voting power per pool parameter, but it can never be higher. Thus, if the effective +// stake is lower than the provided one the slash +// TODO: explain or link to formula +func (k Keeper) getEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, mustIncludeStakers ...string) (effectiveStakes map[string]uint64) { + type ValidatorStake struct { + Address string + Stake uint64 + } + + addresses := util.RemoveDuplicateStrings(append(k.GetAllStakerAddressesOfPool(ctx, poolId), mustIncludeStakers...)) + maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) + effectiveStakes = make(map[string]uint64) + validators := make([]ValidatorStake, 0) + totalStake := int64(0) + + for _, address := range addresses { + validator, _ := k.GetValidator(ctx, address) + valaccount, _ := k.GetValaccount(ctx, poolId, address) + stake := uint64(valaccount.StakeFraction.MulInt(validator.GetBondedTokens()).TruncateInt64()) + + effectiveStakes[address] = stake + validators = append(validators, ValidatorStake{ + Address: address, + Stake: stake, + }) + totalStake += int64(stake) + } + + totalStakeRemainder := totalStake + + // sort descending based on stake + sort.Slice(validators, func(i, j int) bool { + return validators[i].Stake > validators[j].Stake + }) + + if totalStake == 0 || maxVotingPower.IsZero() { + return make(map[string]uint64) + } + + if math.LegacyOneDec().Quo(maxVotingPower).GT(math.LegacyNewDec(int64(len(addresses)))) { + return make(map[string]uint64) + } + + for i, validator := range validators { + if math.LegacyNewDec(int64(effectiveStakes[validator.Address])).GT(maxVotingPower.MulInt64(totalStake)) { + amount := math.LegacyNewDec(int64(effectiveStakes[validator.Address])).Sub(maxVotingPower.MulInt64(totalStake)).TruncateInt64() + + totalStakeRemainder -= int64(validator.Stake) + effectiveStakes[validator.Address] -= uint64(amount) + + if totalStakeRemainder > 0 { + for _, v := range validators[i+1:] { + effectiveStakes[v.Address] += uint64(math.LegacyNewDec(int64(v.Stake)).QuoInt64(totalStakeRemainder).MulInt64(amount).TruncateInt64()) + } + } + } + } + + scaleFactor := math.LegacyZeroDec() + + // get lowest validator with effective stake still bigger than zero + for i := len(validators) - 1; i >= 0; i-- { + if effectiveStakes[validators[i].Address] > 0 { + scaleFactor = math.LegacyNewDec(int64(validators[i].Stake)).QuoInt64(int64(effectiveStakes[validators[i].Address])) + break + } + } + + // scale all effective stakes down to scale factor + for _, validator := range validators { + // TODO: is rounding here fine? + effectiveStakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(effectiveStakes[validator.Address])).RoundInt64()) + } + + return +} + // getLowestStaker returns the staker with the lowest total stake // (self-delegation + delegation) of a given pool. // If all pool slots are taken, this is the staker who then @@ -23,9 +103,9 @@ func (k Keeper) getLowestStaker(ctx sdk.Context, poolId uint64) (val stakingType var minAmount uint64 = m.MaxUint64 for _, staker := range k.getAllStakersOfPool(ctx, poolId) { - delegationAmount := k.GetValidatorPoolStake(ctx, util.MustAccountAddressFromValAddress(staker.OperatorAddress), poolId) - if delegationAmount < minAmount { - minAmount = delegationAmount + stake := k.GetValidatorPoolStake(ctx, util.MustAccountAddressFromValAddress(staker.OperatorAddress), poolId) + if stake < minAmount { + minAmount = stake val = staker } } diff --git a/x/stakers/keeper/msg_server_join_pool_test.go b/x/stakers/keeper/msg_server_join_pool_test.go index 85d7f519..92f7ffbd 100644 --- a/x/stakers/keeper/msg_server_join_pool_test.go +++ b/x/stakers/keeper/msg_server_join_pool_test.go @@ -71,6 +71,10 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { } s.RunTxPoolSuccess(msg) + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) @@ -124,7 +128,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(1)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) @@ -178,7 +182,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(0)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 1) Expect(totalStakeOfPool).To(Equal(0 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 1)).To(Equal(0 * i.KYVE)) @@ -234,7 +238,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(2)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(200 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) @@ -252,7 +256,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) // ACT @@ -281,7 +285,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(1)) - totalStakeOfPool = s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool = s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(150 * i.KYVE)) @@ -576,7 +580,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(1)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) @@ -619,7 +623,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(1)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) @@ -686,7 +690,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { } // STAKER_0 is lowest staker and all stakers are full now. - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) s.CreateValidator(i.STAKER_1, "Staker-1", int64(150*i.KYVE)) @@ -701,7 +705,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { }) // Assert - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 150) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 150) * i.KYVE)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).ToNot(ContainElement(i.STAKER_0)) }) @@ -731,7 +735,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { } // STAKER_0 is lowest staker and all stakers are full now. - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) s.CreateValidator(i.STAKER_1, "Staker-1", int64(50*i.KYVE)) @@ -746,7 +750,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { }) // Assert - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).To(ContainElement(i.STAKER_0)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).ToNot(ContainElement(i.STAKER_1)) }) @@ -777,7 +781,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { } // Alice is lowest staker and all stakers are full now. - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) s.CreateValidator(i.STAKER_1, "Staker-1", int64(150*i.KYVE)) @@ -798,7 +802,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { }) // ASSERT - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 250) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 250) * i.KYVE)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).To(ContainElement(i.STAKER_0)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).NotTo(ContainElement(i.STAKER_1)) }) @@ -829,7 +833,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { } // STAKER_0 is lowest staker and all stakers are full now. - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) s.CreateValidator(i.STAKER_1, "Staker-1", int64(50*i.KYVE)) @@ -844,7 +848,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { }) // Assert - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).To(ContainElement(i.STAKER_0)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).ToNot(ContainElement(i.STAKER_1)) }) @@ -875,7 +879,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { } // Alice is lowest staker and all stakers are full now. - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) s.CreateValidator(i.STAKER_1, "Staker-1", int64(50*i.KYVE)) @@ -896,7 +900,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { }) // ASSERT - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal((150*49 + 100) * i.KYVE)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).To(ContainElement(i.STAKER_0)) Expect(s.App().StakersKeeper.GetAllStakerAddressesOfPool(s.Ctx(), 0)).NotTo(ContainElement(i.STAKER_1)) }) @@ -961,7 +965,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(1)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) @@ -1031,7 +1035,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(1)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) diff --git a/x/stakers/keeper/msg_server_leave_pool_test.go b/x/stakers/keeper/msg_server_leave_pool_test.go index 80e5bfad..ca33d3e5 100644 --- a/x/stakers/keeper/msg_server_leave_pool_test.go +++ b/x/stakers/keeper/msg_server_leave_pool_test.go @@ -43,6 +43,10 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { // create staker s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + // join pool s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ Creator: i.STAKER_0, @@ -86,7 +90,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(1)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) @@ -110,7 +114,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(BeEmpty()) - totalStakeOfPool = s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool = s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(BeZero()) // check if commission and stake fraction is still available @@ -159,7 +163,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(2)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(200 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) @@ -183,7 +187,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(1)) - totalStakeOfPool = s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0) + totalStakeOfPool = s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) // check if commission and stake fraction is still available @@ -264,7 +268,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(HaveLen(1)) - totalStakeOfPool := s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1) + totalStakeOfPool := s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 1) Expect(totalStakeOfPool).To(Equal(100 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(totalStakeOfPool)) @@ -286,7 +290,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { Expect(valaccountsOfPool).To(BeEmpty()) - totalStakeOfPool = s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1) + totalStakeOfPool = s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 1) Expect(totalStakeOfPool).To(BeZero()) // check if commission and stake fraction is still available diff --git a/x/stakers/keeper/msg_server_update_stake_fraction_test.go b/x/stakers/keeper/msg_server_update_stake_fraction_test.go index e406f7a9..afb76ea5 100644 --- a/x/stakers/keeper/msg_server_update_stake_fraction_test.go +++ b/x/stakers/keeper/msg_server_update_stake_fraction_test.go @@ -50,6 +50,10 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { } s.RunTxPoolSuccess(msg) + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ @@ -71,7 +75,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) }) It("Increase stake fraction to 50% from previous stake fraction", func() { @@ -87,7 +91,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) }) It("Decrease stake fraction to 0% from previous stake fraction", func() { @@ -111,7 +115,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(BeZero()) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(BeZero()) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(BeZero()) }) It("Decrease stake fraction to 1% from previous stake fraction", func() { @@ -127,7 +131,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) // wait for update s.CommitAfterSeconds(s.App().StakersKeeper.GetStakeFractionChangeTime(s.Ctx())) @@ -136,7 +140,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.01"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(1 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(1 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(1 * i.KYVE)) }) It("Increase stake fraction to 100% from previous stake fraction", func() { @@ -152,7 +156,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(100 * i.KYVE)) }) It("Update stake fraction to same value from previous stake fraction", func() { @@ -168,7 +172,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) }) It("Update stake fraction with a negative number from previous stake fraction", func() { @@ -184,7 +188,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) }) It("Update stake fraction with a too high number from previous stake fraction during change time", func() { @@ -200,7 +204,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) }) It("Increase stake fraction after stake fraction has been decreased before during change time", func() { @@ -223,7 +227,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.2"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(20 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(20 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(20 * i.KYVE)) // wait for update s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) @@ -232,7 +236,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.2"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(20 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(20 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(20 * i.KYVE)) }) It("Decrease stake fraction after stake fraction has been decreased before during change time", func() { @@ -255,7 +259,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) // wait for update s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) @@ -264,7 +268,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.01"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(1 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(1 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(1 * i.KYVE)) }) It("Decrease stake fraction after stake fraction has been increased before", func() { @@ -278,7 +282,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) s.PerformValidityChecks() @@ -293,7 +297,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) // wait for update s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) @@ -302,7 +306,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.02"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(2 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(2 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(2 * i.KYVE)) }) It("Update stake fraction with multiple pools", func() { @@ -344,12 +348,12 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount0, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount0.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) valaccount1, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) Expect(valaccount1.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 1)).To(Equal(10 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 1)).To(Equal(10 * i.KYVE)) // wait for update s.CommitAfterSeconds(s.App().StakersKeeper.GetCommissionChangeTime(s.Ctx())) @@ -358,12 +362,12 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount0, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount0.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.5"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(50 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(50 * i.KYVE)) valaccount1, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 1, i.STAKER_0) Expect(valaccount1.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.03"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 1)).To(Equal(3 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 1)).To(Equal(3 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 1)).To(Equal(3 * i.KYVE)) }) It("Validator stake increases while stake fraction stays the same", func() { @@ -371,7 +375,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) // ACT s.SelfDelegateValidator(i.STAKER_0, 50*i.KYVE) @@ -380,7 +384,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(15 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(15 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(15 * i.KYVE)) }) It("Validator stake decreases while stake fraction stays the same", func() { @@ -388,7 +392,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(10 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(10 * i.KYVE)) // ACT s.SelfUndelegateValidator(i.STAKER_0, 50*i.KYVE) @@ -402,6 +406,6 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { valaccount, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) Expect(valaccount.StakeFraction).To(Equal(math.LegacyMustNewDecFromStr("0.1"))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(5 * i.KYVE)) - Expect(s.App().StakersKeeper.GetDelegationOfPool(s.Ctx(), 0)).To(Equal(5 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(5 * i.KYVE)) }) }) From dd4b9622273771137eda8c2d0cf0961263e4f6b3 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Tue, 17 Dec 2024 16:44:30 +0100 Subject: [PATCH 09/24] chore: export effective stake method --- x/bundles/keeper/logic_bundles.go | 10 +- x/bundles/types/expected_keepers.go | 1 + x/stakers/keeper/exported_functions.go | 135 ++++++++++- .../keeper_suite_effective_stake_test.go | 217 ++++++++++++++++++ x/stakers/keeper/logic_stakers.go | 80 ------- x/stakers/keeper/msg_server_join_pool.go | 2 - 6 files changed, 354 insertions(+), 91 deletions(-) diff --git a/x/bundles/keeper/logic_bundles.go b/x/bundles/keeper/logic_bundles.go index cfa4a035..e2a18130 100644 --- a/x/bundles/keeper/logic_bundles.go +++ b/x/bundles/keeper/logic_bundles.go @@ -497,24 +497,26 @@ func (k Keeper) GetVoteDistribution(ctx sdk.Context, poolId uint64) (voteDistrib return } + stakes := k.stakerKeeper.GetValidatorPoolStakes(ctx, poolId) + // get voting power for valid for _, voter := range bundleProposal.VotersValid { - voteDistribution.Valid += k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) + voteDistribution.Valid += stakes[voter] } // get voting power for invalid for _, voter := range bundleProposal.VotersInvalid { - voteDistribution.Invalid += k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) + voteDistribution.Invalid += stakes[voter] } // get voting power for abstain for _, voter := range bundleProposal.VotersAbstain { - voteDistribution.Abstain += k.stakerKeeper.GetValidatorPoolStake(ctx, voter, poolId) + voteDistribution.Abstain += stakes[voter] } // get total voting power for _, staker := range k.stakerKeeper.GetAllStakerAddressesOfPool(ctx, poolId) { - voteDistribution.Total += k.stakerKeeper.GetValidatorPoolStake(ctx, staker, poolId) + voteDistribution.Total += stakes[staker] } if voteDistribution.Total == 0 { diff --git a/x/bundles/types/expected_keepers.go b/x/bundles/types/expected_keepers.go index 7a667f46..e4d64802 100644 --- a/x/bundles/types/expected_keepers.go +++ b/x/bundles/types/expected_keepers.go @@ -42,6 +42,7 @@ type StakerKeeper interface { GetValidatorPoolCommission(ctx sdk.Context, staker string, poolId uint64) math.LegacyDec GetValidatorPoolStake(ctx sdk.Context, staker string, poolId uint64) uint64 GetTotalStakeOfPool(ctx sdk.Context, poolId uint64) (totalStake uint64) + GetValidatorPoolStakes(ctx sdk.Context, poolId uint64, mustIncludeStakers ...string) map[string]uint64 IsVotingPowerTooHigh(ctx sdk.Context, poolId uint64) bool Slash(ctx sdk.Context, poolId uint64, staker string, slashType stakersTypes.SlashType) PayoutRewards(ctx sdk.Context, staker string, amount sdk.Coins, payerModuleName string) error diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 0d31c2e7..0a8e02f0 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "sort" "cosmossdk.io/errors" "cosmossdk.io/math" @@ -83,7 +84,7 @@ func (k Keeper) GetActiveStakers(ctx sdk.Context) []string { // GetTotalStakeOfPool returns the amount in uykve which actively secures // the given pool func (k Keeper) GetTotalStakeOfPool(ctx sdk.Context, poolId uint64) (totalStake uint64) { - effectiveStakes := k.getEffectiveValidatorStakes(ctx, poolId) + effectiveStakes := k.GetValidatorPoolStakes(ctx, poolId) for _, stake := range effectiveStakes { totalStake += stake } @@ -125,7 +126,129 @@ func (k Keeper) GetValidatorPoolCommission(ctx sdk.Context, staker string, poolI // GetValidatorPoolStake returns stake a validator has actively and at risk inside the pool func (k Keeper) GetValidatorPoolStake(ctx sdk.Context, staker string, poolId uint64) uint64 { - return k.getEffectiveValidatorStakes(ctx, poolId, staker)[staker] + return k.GetValidatorPoolStakes(ctx, poolId, staker)[staker] +} + +// GetValidatorPoolStakes returns a map for all pool validators with their effective stake. Effective stake +// is the actual amount which determines the validator's voting power and is the actual amount at risk for +// slashing. The effective stake can be lower (never higher) than the specified stake by the validators by +// his stake fraction because of the maximum voting power which limits the voting power a validator can have +// in a pool. +// +// We limit the voting power by first sorting all validators based on their stake and start at the highest. From +// there we check if this validator exceeds the voting power with his stake, if he does we cut off an amount +// from his stake and redistribute it to all the validators below him based on their stakes. Because we are simply +// redistributing exact amounts we do not need to worry about changing the total stake which would mess up voting +// powers of other validators again. After this has been repeated for every validator that exceeds the max voting +// power we finally scale down all stakes to the lowest validator's stake. This is because the top validators lost +// stake and the lowest validators gained stake, but because it is not allowed to risk more than specified so we scale +// everything down accordingly. This results in a stake distribution where every validator who was below the max +// voting power has the same effective stake as his dedicated stake and those validators who where above it have +// less effective stake. +func (k Keeper) GetValidatorPoolStakes(ctx sdk.Context, poolId uint64, mustIncludeStakers ...string) map[string]uint64 { + type ValidatorStake struct { + Address string + Stake uint64 + } + + validators := make([]ValidatorStake, 0) + stakes := make(map[string]uint64) + + // we include given stakers since in some instances the staker we are looking for has been already kicked + // out of a pool, but we still need to payout rewards or slash him afterward depending on his last action + // right before leaving the pool + addresses := util.RemoveDuplicateStrings(append(k.GetAllStakerAddressesOfPool(ctx, poolId), mustIncludeStakers...)) + maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) + + // it is impossible regardless how many validators are in a pool to have a max voting power of 0%, + // therefore we return here + if maxVotingPower.IsZero() { + return stakes + } + + // if there are not enough validators in a pool so that the max voting power is always + // exceeded by at least one validator we return + if math.LegacyOneDec().Quo(maxVotingPower).GT(math.LegacyNewDec(int64(len(addresses)))) { + return stakes + } + + totalStake := int64(0) + + for _, address := range addresses { + validator, _ := k.GetValidator(ctx, address) + valaccount, _ := k.GetValaccount(ctx, poolId, address) + + // calculate the stake the validator has specifically chosen for this pool + // with his stake fraction + stake := uint64(valaccount.StakeFraction.MulInt(validator.GetBondedTokens()).TruncateInt64()) + + stakes[address] = stake + validators = append(validators, ValidatorStake{ + Address: address, + Stake: stake, + }) + totalStake += int64(stake) + } + + totalStakeRemainder := totalStake + + // sort descending based on stake + sort.Slice(validators, func(i, j int) bool { + return validators[i].Stake > validators[j].Stake + }) + + // if the total stake of the pool is zero we return + if totalStake == 0 { + return stakes + } + + for i, validator := range validators { + // check if the validator has a higher stake than allowed by the max voting power + if math.LegacyNewDec(int64(stakes[validator.Address])).GT(maxVotingPower.MulInt64(totalStake)) { + // if the validator got a stake which would give him a higher voting power than the maximum allowed + // one we cut off the exact amount from his stake so that he is just below the max voting power + cutoffAmount := math.LegacyNewDec(int64(stakes[validator.Address])).Sub(maxVotingPower.MulInt64(totalStake)).TruncateInt64() + + totalStakeRemainder -= int64(validator.Stake) + stakes[validator.Address] -= uint64(cutoffAmount) + + // we take the cutoff amount and distribute it on the remaining validators down the list + // who all have less voting power than the current one. We distribute the cutoff amount + // based on the validator's stake + if totalStakeRemainder > 0 { + for _, v := range validators[i+1:] { + stakes[v.Address] += uint64(math.LegacyNewDec(int64(v.Stake)).QuoInt64(totalStakeRemainder).MulInt64(cutoffAmount).TruncateInt64()) + } + } + } + } + + // after we have redistributed all cutoff amounts so that no validator exceeds the maximum voting power + // based on their remaining effective stake we now scale the stakes to get the true effective staking amount. + // This is because while the top validators who got their voting power reduced the lower validators have actually + // gained voting power relatively. But because their effective stake is now bigger than their allocated stake + // we have to scale it down again, because we are not allowed to slash more than the validator has allocated in + // this particular pool. Therefore, we take the stake of the lowest validator (with a bigger stake than 0) and scale + // down all stakes of all other validators to that accordingly + scaleFactor := math.LegacyZeroDec() + + // get the lowest validator with effective stake still bigger than zero and determine the scale factor + for i := len(validators) - 1; i >= 0; i-- { + if stakes[validators[i].Address] > 0 { + scaleFactor = math.LegacyNewDec(int64(validators[i].Stake)).QuoInt64(int64(stakes[validators[i].Address])) + break + } + } + + // scale all effective stakes down to scale factor + for _, validator := range validators { + stakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(stakes[validator.Address])).RoundInt64()) + } + + // the result is a map which contains the effective stake for every validator in a pool. The effective stake + // can not be higher than the dedicated stake specified by the validator by his stake fraction, therefore it + // represents the true amount of $KYVE which is at risk for slashing + return stakes } // GetOutstandingCommissionRewards returns the outstanding commission rewards for a given validator @@ -189,12 +312,14 @@ func (k Keeper) Slash(ctx sdk.Context, poolId uint64, staker string, slashType s consAddrBytes, _ := validator.GetConsAddr() - // get real stake fraction from the effective stake which is truly at risk for getting slashed - // by dividing it with the total bonded stake from the validator + // here the stake fraction can be actually different from the stake fraction the validator has specified + // for this pool because with the max voting power in place his effective stake in a pool could have been + // reduced because his original stake was too high. Therefore, we determine the true stake fraction + // by dividing his effective stake with his bonded amount. stakeFraction := math.LegacyZeroDec() if !validator.GetBondedTokens().IsZero() { - stakeFraction = math.LegacyNewDec(int64(k.getEffectiveValidatorStakes(ctx, poolId, staker)[staker])).QuoInt(validator.GetBondedTokens()) + stakeFraction = math.LegacyNewDec(int64(k.GetValidatorPoolStake(ctx, staker, poolId))).QuoInt(validator.GetBondedTokens()) } // the validator can only be slashed for his effective stake fraction in a pool, therefore we diff --git a/x/stakers/keeper/keeper_suite_effective_stake_test.go b/x/stakers/keeper/keeper_suite_effective_stake_test.go index 8697929b..991b7d41 100644 --- a/x/stakers/keeper/keeper_suite_effective_stake_test.go +++ b/x/stakers/keeper/keeper_suite_effective_stake_test.go @@ -23,6 +23,11 @@ TEST CASES - keeper_suite_effective_stake_test.go * Test effective stake with all validators having zero delegation * Test effective stake with 0% as max pool stake * Test effective stake with 100% as max pool stake +* Test effective stake with all validators below the max pool voting power due to stake fractions +* Test effective stake with one validator above the max pool voting power due to stake fractions +* Test effective stake with multiple validators above the max pool voting power due to stake fractions +* Test effective stake with some validators having zero delegation due to stake fractions +* Test effective stake with all validators having zero delegation due to stake fractions */ @@ -373,4 +378,216 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(100 * i.KYVE)) }) + + It("Test effective stake with all validators below the max pool voting power due to stake fractions", func() { + // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(200*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.5"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(500*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.2"), + }) + + // ACT + + // ASSERT + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) + + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(300 * i.KYVE)) + }) + + It("Test effective stake with one validator above the max pool voting power due to stake fractions", func() { + // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(200*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.5"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(300*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.9"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(500*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.2"), + }) + + // ASSERT + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) + + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) + }) + + It("Test effective stake with multiple validators above the max pool voting power due to stake fractions", func() { + // ARRANGE + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.35") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.8"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.7"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.2"), + }) + + // ASSERT + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) + + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(uint64(23333333334))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(uint64(23333333334))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(20 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(uint64(66666666668))) + }) + + It("Test effective stake with some validators having zero delegation due to stake fractions", func() { + // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(200*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.5"), + }) + + // ASSERT + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) + + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(0 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(100 * i.KYVE)) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + }) + + It("Test effective stake with all validators having zero delegation due to stake fractions", func() { + // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0"), + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Amount: 100 * i.KYVE, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0"), + }) + + // ASSERT + Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(BeZero()) + }) }) diff --git a/x/stakers/keeper/logic_stakers.go b/x/stakers/keeper/logic_stakers.go index 2cff35ee..1d888b25 100644 --- a/x/stakers/keeper/logic_stakers.go +++ b/x/stakers/keeper/logic_stakers.go @@ -2,7 +2,6 @@ package keeper import ( m "math" - "sort" "cosmossdk.io/math" @@ -16,85 +15,6 @@ import ( errorsTypes "github.com/cosmos/cosmos-sdk/types/errors" ) -// getEffectiveValidatorStakes returns a map for all pool stakers their effective stake. Effective stake -// is the actual stake at risk for a validator, it can be lower than the provided stake because -// of the max voting power per pool parameter, but it can never be higher. Thus, if the effective -// stake is lower than the provided one the slash -// TODO: explain or link to formula -func (k Keeper) getEffectiveValidatorStakes(ctx sdk.Context, poolId uint64, mustIncludeStakers ...string) (effectiveStakes map[string]uint64) { - type ValidatorStake struct { - Address string - Stake uint64 - } - - addresses := util.RemoveDuplicateStrings(append(k.GetAllStakerAddressesOfPool(ctx, poolId), mustIncludeStakers...)) - maxVotingPower := k.poolKeeper.GetMaxVotingPowerPerPool(ctx) - effectiveStakes = make(map[string]uint64) - validators := make([]ValidatorStake, 0) - totalStake := int64(0) - - for _, address := range addresses { - validator, _ := k.GetValidator(ctx, address) - valaccount, _ := k.GetValaccount(ctx, poolId, address) - stake := uint64(valaccount.StakeFraction.MulInt(validator.GetBondedTokens()).TruncateInt64()) - - effectiveStakes[address] = stake - validators = append(validators, ValidatorStake{ - Address: address, - Stake: stake, - }) - totalStake += int64(stake) - } - - totalStakeRemainder := totalStake - - // sort descending based on stake - sort.Slice(validators, func(i, j int) bool { - return validators[i].Stake > validators[j].Stake - }) - - if totalStake == 0 || maxVotingPower.IsZero() { - return make(map[string]uint64) - } - - if math.LegacyOneDec().Quo(maxVotingPower).GT(math.LegacyNewDec(int64(len(addresses)))) { - return make(map[string]uint64) - } - - for i, validator := range validators { - if math.LegacyNewDec(int64(effectiveStakes[validator.Address])).GT(maxVotingPower.MulInt64(totalStake)) { - amount := math.LegacyNewDec(int64(effectiveStakes[validator.Address])).Sub(maxVotingPower.MulInt64(totalStake)).TruncateInt64() - - totalStakeRemainder -= int64(validator.Stake) - effectiveStakes[validator.Address] -= uint64(amount) - - if totalStakeRemainder > 0 { - for _, v := range validators[i+1:] { - effectiveStakes[v.Address] += uint64(math.LegacyNewDec(int64(v.Stake)).QuoInt64(totalStakeRemainder).MulInt64(amount).TruncateInt64()) - } - } - } - } - - scaleFactor := math.LegacyZeroDec() - - // get lowest validator with effective stake still bigger than zero - for i := len(validators) - 1; i >= 0; i-- { - if effectiveStakes[validators[i].Address] > 0 { - scaleFactor = math.LegacyNewDec(int64(validators[i].Stake)).QuoInt64(int64(effectiveStakes[validators[i].Address])) - break - } - } - - // scale all effective stakes down to scale factor - for _, validator := range validators { - // TODO: is rounding here fine? - effectiveStakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(effectiveStakes[validator.Address])).RoundInt64()) - } - - return -} - // getLowestStaker returns the staker with the lowest total stake // (self-delegation + delegation) of a given pool. // If all pool slots are taken, this is the staker who then diff --git a/x/stakers/keeper/msg_server_join_pool.go b/x/stakers/keeper/msg_server_join_pool.go index c745550d..0764430b 100644 --- a/x/stakers/keeper/msg_server_join_pool.go +++ b/x/stakers/keeper/msg_server_join_pool.go @@ -76,8 +76,6 @@ func (k msgServer) JoinPool(goCtx context.Context, msg *types.MsgJoinPool) (*typ } } - // TODO: check here if validator with his stake fraction is over the maximum join limit - k.AddValaccountToPool(ctx, msg.PoolId, msg.Creator, msg.Valaddress, msg.Commission, msg.StakeFraction) if err := util.TransferFromAddressToAddress(k.bankKeeper, ctx, msg.Creator, msg.Valaddress, msg.Amount); err != nil { From 28de85bac596335c562e0b5b1417d2578a503889 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Tue, 17 Dec 2024 16:56:34 +0100 Subject: [PATCH 10/24] test: round robin with stake fractions and max voting power --- x/bundles/keeper/logic_round_robin_test.go | 94 +++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/x/bundles/keeper/logic_round_robin_test.go b/x/bundles/keeper/logic_round_robin_test.go index 040005b4..bd5229c8 100644 --- a/x/bundles/keeper/logic_round_robin_test.go +++ b/x/bundles/keeper/logic_round_robin_test.go @@ -22,6 +22,8 @@ TEST CASES - logic_bundles.go * Empty round-robin set * Partially filled round-robin set (one staker with 0 delegation) * Frequency analysis +* Frequency analysis with stake fractions +* Frequency analysis with maximum voting power cap * Frequency analysis (rounding) * Frequency analysis (excluded) * Exclude everybody @@ -32,6 +34,10 @@ TEST CASES - logic_bundles.go */ func joinDummy(s *i.KeeperTestSuite, index, kyveAmount uint64) { + joinDummyWithStakeFraction(s, index, kyveAmount, math.LegacyOneDec()) +} + +func joinDummyWithStakeFraction(s *i.KeeperTestSuite, index, kyveAmount uint64, stakeFraction math.LegacyDec) { s.CreateValidator(i.DUMMY[index], fmt.Sprintf("dummy-%d", index), int64(kyveAmount*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ @@ -40,7 +46,7 @@ func joinDummy(s *i.KeeperTestSuite, index, kyveAmount uint64) { Valaddress: i.VALDUMMY[index], Amount: 0, Commission: math.LegacyMustNewDecFromStr("0.1"), - StakeFraction: math.LegacyMustNewDecFromStr("1"), + StakeFraction: stakeFraction, }) } @@ -94,6 +100,10 @@ var _ = Describe("logic_round_robin.go", Ordered, func() { Duration: 60, } s.App().PoolKeeper.SetPool(s.Ctx(), pool) + + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") + s.App().PoolKeeper.SetParams(s.Ctx(), params) }) AfterEach(func() { @@ -182,6 +192,87 @@ var _ = Describe("logic_round_robin.go", Ordered, func() { It("Frequency analysis", func() { // ARRANGE + joinDummy(s, 0, 2) + joinDummy(s, 1, 31) + joinDummy(s, 2, 67) + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + + frequency1 := make(map[string]int, 0) + for i := 0; i < 10; i++ { + frequency1[rrvs.NextProposer()] += 1 + } + + frequency2 := make(map[string]int, 0) + for i := 0; i < 100; i++ { + frequency2[rrvs.NextProposer()] += 1 + } + + frequency3 := make(map[string]int, 0) + for i := 0; i < 100000; i++ { + frequency3[rrvs.NextProposer()] += 1 + } + + // ASSERT + + Expect(frequency1[i.DUMMY[0]]).To(Equal(0)) + Expect(frequency1[i.DUMMY[1]]).To(Equal(3)) + Expect(frequency1[i.DUMMY[2]]).To(Equal(7)) + + Expect(frequency2[i.DUMMY[0]]).To(Equal(2)) + Expect(frequency2[i.DUMMY[1]]).To(Equal(31)) + Expect(frequency2[i.DUMMY[2]]).To(Equal(67)) + + Expect(frequency3[i.DUMMY[0]]).To(Equal(2000)) + Expect(frequency3[i.DUMMY[1]]).To(Equal(31000)) + Expect(frequency3[i.DUMMY[2]]).To(Equal(67000)) + }) + + It("Frequency analysis with stake fractions", func() { + // ARRANGE + joinDummyWithStakeFraction(s, 0, 100, math.LegacyMustNewDecFromStr("0")) + joinDummyWithStakeFraction(s, 1, 100, math.LegacyMustNewDecFromStr("0.5")) + joinDummyWithStakeFraction(s, 2, 100, math.LegacyMustNewDecFromStr("1")) + + // ACT + rrvs := s.App().BundlesKeeper.LoadRoundRobinValidatorSet(s.Ctx(), 0) + + frequency1 := make(map[string]int, 0) + for i := 0; i < 10; i++ { + frequency1[rrvs.NextProposer()] += 1 + } + + frequency2 := make(map[string]int, 0) + for i := 0; i < 100; i++ { + frequency2[rrvs.NextProposer()] += 1 + } + + frequency3 := make(map[string]int, 0) + for i := 0; i < 100000; i++ { + frequency3[rrvs.NextProposer()] += 1 + } + + // ASSERT + Expect(frequency1[i.DUMMY[0]]).To(Equal(0)) + Expect(frequency1[i.DUMMY[1]]).To(Equal(3)) + Expect(frequency1[i.DUMMY[2]]).To(Equal(7)) + + Expect(frequency2[i.DUMMY[0]]).To(Equal(0)) + Expect(frequency2[i.DUMMY[1]]).To(Equal(34)) + Expect(frequency2[i.DUMMY[2]]).To(Equal(66)) + + Expect(frequency3[i.DUMMY[0]]).To(Equal(0)) + Expect(frequency3[i.DUMMY[1]]).To(Equal(33333)) + Expect(frequency3[i.DUMMY[2]]).To(Equal(66667)) + }) + + It("Frequency analysis with maximum voting power cap", func() { + // ARRANGE + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.5") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + // NOTE that dummy with index 2 has more than 50% voting power, so his effective stake // will be lower joinDummy(s, 0, 2) @@ -207,7 +298,6 @@ var _ = Describe("logic_round_robin.go", Ordered, func() { } // ASSERT - Expect(frequency1[i.DUMMY[0]]).To(Equal(0)) Expect(frequency1[i.DUMMY[1]]).To(Equal(5)) Expect(frequency1[i.DUMMY[2]]).To(Equal(5)) From cdb78fe979e885f6a186a49742ddcfe06fee5ce7 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Wed, 18 Dec 2024 10:30:05 +0100 Subject: [PATCH 11/24] test: added more unit tests --- .../keeper_suite_invalid_bundles_test.go | 462 +++++++++++++++++- .../keeper/keeper_suite_valid_bundles_test.go | 202 ++++++++ 2 files changed, 647 insertions(+), 17 deletions(-) diff --git a/x/bundles/keeper/keeper_suite_invalid_bundles_test.go b/x/bundles/keeper/keeper_suite_invalid_bundles_test.go index 3208c8e2..d6b270d0 100644 --- a/x/bundles/keeper/keeper_suite_invalid_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_invalid_bundles_test.go @@ -23,6 +23,8 @@ TEST CASES - invalid bundles * Produce an invalid bundle with multiple validators and no foreign delegations * Produce an invalid bundle with multiple validators and foreign delegations * Produce an invalid bundle with multiple validators although some voted valid +* Produce an invalid bundle with multiple validators and stake fractions +* Produce an invalid bundle with multiple validators and stake fractions and foreign delegations */ @@ -78,6 +80,22 @@ var _ = Describe("invalid bundles", Ordered, func() { AmountsPerBundle: i.KYVECoins(1 * i.T_KYVE), }) + initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) + initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) + + initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1) + initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1_A) + + initialBalanceStaker2 = s.GetBalanceFromAddress(i.STAKER_2) + initialBalanceValaddress2 = s.GetBalanceFromAddress(i.VALADDRESS_2_A) + }) + + AfterEach(func() { + s.PerformValidityChecks() + }) + + It("Produce an invalid bundle with multiple validators and no foreign delegations", func() { + // ARRANGE s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ @@ -98,24 +116,8 @@ var _ = Describe("invalid bundles", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) - initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) - - initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1) - initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1_A) - - initialBalanceStaker2 = s.GetBalanceFromAddress(i.STAKER_2) - initialBalanceValaddress2 = s.GetBalanceFromAddress(i.VALADDRESS_2_A) - s.CommitAfterSeconds(60) - }) - AfterEach(func() { - s.PerformValidityChecks() - }) - - It("Produce an invalid bundle with multiple validators and no foreign delegations", func() { - // ARRANGE s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ Creator: i.VALADDRESS_0_A, Staker: i.STAKER_0, @@ -140,7 +142,14 @@ var _ = Describe("invalid bundles", Ordered, func() { StakeFraction: math.LegacyMustNewDecFromStr("1"), }) - initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_2) + initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) + initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) + + initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1) + initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1_A) + + initialBalanceStaker2 = s.GetBalanceFromAddress(i.STAKER_2) + initialBalanceValaddress2 = s.GetBalanceFromAddress(i.VALADDRESS_2_A) // ACT s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ @@ -264,6 +273,26 @@ var _ = Describe("invalid bundles", Ordered, func() { It("Produce an invalid bundle with multiple validators and foreign delegations", func() { // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + s.RunTxSuccess(stakingTypes.NewMsgDelegate( i.ALICE, util.MustValaddressFromOperatorAddress(i.STAKER_0), @@ -292,6 +321,8 @@ var _ = Describe("invalid bundles", Ordered, func() { sdk.NewInt64Coin(globalTypes.Denom, int64(100*i.KYVE)), )) + s.CommitAfterSeconds(60) + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ Creator: i.VALADDRESS_0_A, Staker: i.STAKER_0, @@ -306,7 +337,14 @@ var _ = Describe("invalid bundles", Ordered, func() { BundleSummary: "test_value", }) + initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) + initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) + initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1) + initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1_A) + + initialBalanceStaker2 = s.GetBalanceFromAddress(i.STAKER_2) + initialBalanceValaddress2 = s.GetBalanceFromAddress(i.VALADDRESS_2_A) // ACT s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ @@ -434,6 +472,26 @@ var _ = Describe("invalid bundles", Ordered, func() { It("Produce an invalid bundle with multiple validators although some voted valid", func() { // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + s.RunTxSuccess(stakingTypes.NewMsgDelegate( i.ALICE, util.MustValaddressFromOperatorAddress(i.STAKER_0), @@ -479,6 +537,8 @@ var _ = Describe("invalid bundles", Ordered, func() { sdk.NewInt64Coin(globalTypes.Denom, int64(150*i.KYVE)), )) + s.CommitAfterSeconds(60) + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ Creator: i.VALADDRESS_0_A, Staker: i.STAKER_0, @@ -493,8 +553,14 @@ var _ = Describe("invalid bundles", Ordered, func() { BundleSummary: "test_value", }) + initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) + initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) + initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1) + initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1_A) + initialBalanceStaker2 = s.GetBalanceFromAddress(i.STAKER_2) + initialBalanceValaddress2 = s.GetBalanceFromAddress(i.VALADDRESS_2_A) // ACT s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ @@ -647,4 +713,366 @@ var _ = Describe("invalid bundles", Ordered, func() { Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId)[0].Amount.Uint64()).To(Equal(100 * i.KYVE)) Expect(fundingState.ActiveFunderAddresses).To(HaveLen(1)) }) + + It("Produce an invalid bundle with multiple validators and stake fractions", func() { + // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(200*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.5"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CommitAfterSeconds(60) + + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + DataSize: 100, + DataHash: "test_hash", + FromIndex: 0, + BundleSize: 100, + FromKey: "0", + ToKey: "99", + BundleSummary: "test_value", + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) + initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) + + initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1) + initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1_A) + + initialBalanceStaker2 = s.GetBalanceFromAddress(i.STAKER_2) + initialBalanceValaddress2 = s.GetBalanceFromAddress(i.VALADDRESS_2_A) + + // ACT + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_1_A, + Staker: i.STAKER_1, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_INVALID, + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_2_A, + Staker: i.STAKER_2, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_INVALID, + }) + + s.CommitAfterSeconds(60) + + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, + PoolId: 0, + StorageId: "P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg", + DataSize: 100, + DataHash: "test_hash2", + FromIndex: 100, + BundleSize: 100, + FromKey: "100", + ToKey: "199", + BundleSummary: "test_value2", + }) + + // ASSERT + // check if bundle got not finalized on pool + pool, poolFound := s.App().PoolKeeper.GetPool(s.Ctx(), 0) + Expect(poolFound).To(BeTrue()) + + Expect(pool.CurrentKey).To(Equal("")) + Expect(pool.CurrentSummary).To(BeEmpty()) + Expect(pool.CurrentIndex).To(BeZero()) + Expect(pool.TotalBundles).To(BeZero()) + + // check if finalized bundle exists + _, finalizedBundleFound := s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) + Expect(finalizedBundleFound).To(BeFalse()) + + // check if bundle proposal got dropped + bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) + Expect(bundleProposalFound).To(BeTrue()) + + Expect(bundleProposal.PoolId).To(Equal(uint64(0))) + Expect(bundleProposal.StorageId).To(BeEmpty()) + Expect(bundleProposal.Uploader).To(BeEmpty()) + Expect(bundleProposal.NextUploader).NotTo(BeEmpty()) + Expect(bundleProposal.DataSize).To(BeZero()) + Expect(bundleProposal.DataHash).To(BeEmpty()) + Expect(bundleProposal.BundleSize).To(BeZero()) + Expect(bundleProposal.FromKey).To(BeEmpty()) + Expect(bundleProposal.ToKey).To(BeEmpty()) + Expect(bundleProposal.BundleSummary).To(BeEmpty()) + Expect(bundleProposal.UpdatedAt).NotTo(BeZero()) + Expect(bundleProposal.VotersValid).To(BeEmpty()) + Expect(bundleProposal.VotersInvalid).To(BeEmpty()) + Expect(bundleProposal.VotersAbstain).To(BeEmpty()) + + // check uploader status + _, uploaderActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(uploaderActive).To(BeFalse()) + + balanceValaddress := s.GetBalanceFromAddress(i.VALADDRESS_0_A) + Expect(balanceValaddress).To(Equal(initialBalanceValaddress0)) + + balanceUploader := s.GetBalanceFromAddress(i.STAKER_0) + + _, uploaderFound := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) + Expect(uploaderFound).To(BeTrue()) + + Expect(balanceUploader).To(Equal(initialBalanceStaker0)) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(BeEmpty()) + + // calculate uploader slashes + fraction := s.App().StakersKeeper.GetUploadSlash(s.Ctx()) + slashAmount := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) + + Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(200*i.KYVE - slashAmount)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + + // check voter status + valaccountVoter, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) + Expect(valaccountVoter.Points).To(BeZero()) + + balanceVoterValaddress := s.GetBalanceFromAddress(valaccountVoter.Valaddress) + Expect(balanceVoterValaddress).To(Equal(initialBalanceValaddress1)) + + balanceVoter := s.GetBalanceFromAddress(valaccountVoter.Staker) + + Expect(balanceVoter).To(Equal(initialBalanceStaker1)) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_1, i.STAKER_1)).To(BeEmpty()) + + // check voter 2 status + valaccountVoter, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_2) + Expect(valaccountVoter.Points).To(BeZero()) + + balanceVoterValaddress = s.GetBalanceFromAddress(valaccountVoter.Valaddress) + Expect(balanceVoterValaddress).To(Equal(initialBalanceValaddress1)) + + balanceVoter = s.GetBalanceFromAddress(valaccountVoter.Staker) + + Expect(balanceVoter).To(Equal(initialBalanceStaker1)) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_2, i.STAKER_2)).To(BeEmpty()) + + // check pool funds + fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) + + // assert total pool funds + Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId)[0].Amount.Uint64()).To(Equal(100 * i.KYVE)) + Expect(fundingState.ActiveFunderAddresses).To(HaveLen(1)) + }) + + It("Produce an invalid bundle with multiple validators and stake fractions and foreign delegations", func() { + // ARRANGE + s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) + + s.RunTxSuccess(stakingTypes.NewMsgDelegate( + i.CHARLIE, + util.MustValaddressFromOperatorAddress(i.STAKER_0), + sdk.NewInt64Coin(globalTypes.Denom, int64(100*i.KYVE)), + )) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_0, + PoolId: 0, + Valaddress: i.VALADDRESS_0_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("0.5"), + }) + + s.CreateValidator(i.STAKER_1, "Staker-1", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_1, + PoolId: 0, + Valaddress: i.VALADDRESS_1_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.CommitAfterSeconds(60) + + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + DataSize: 100, + DataHash: "test_hash", + FromIndex: 0, + BundleSize: 100, + FromKey: "0", + ToKey: "99", + BundleSummary: "test_value", + }) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + initialBalanceStaker0 = s.GetBalanceFromAddress(i.STAKER_0) + initialBalanceValaddress0 = s.GetBalanceFromAddress(i.VALADDRESS_0_A) + + initialBalanceStaker1 = s.GetBalanceFromAddress(i.STAKER_1) + initialBalanceValaddress1 = s.GetBalanceFromAddress(i.VALADDRESS_1_A) + + initialBalanceStaker2 = s.GetBalanceFromAddress(i.STAKER_2) + initialBalanceValaddress2 = s.GetBalanceFromAddress(i.VALADDRESS_2_A) + + // ACT + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_1_A, + Staker: i.STAKER_1, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_INVALID, + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_2_A, + Staker: i.STAKER_2, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_INVALID, + }) + + s.CommitAfterSeconds(60) + + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, + PoolId: 0, + StorageId: "P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg", + DataSize: 100, + DataHash: "test_hash2", + FromIndex: 100, + BundleSize: 100, + FromKey: "100", + ToKey: "199", + BundleSummary: "test_value2", + }) + + // ASSERT + // check if bundle got not finalized on pool + pool, poolFound := s.App().PoolKeeper.GetPool(s.Ctx(), 0) + Expect(poolFound).To(BeTrue()) + + Expect(pool.CurrentKey).To(Equal("")) + Expect(pool.CurrentSummary).To(BeEmpty()) + Expect(pool.CurrentIndex).To(BeZero()) + Expect(pool.TotalBundles).To(BeZero()) + + // check if finalized bundle exists + _, finalizedBundleFound := s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) + Expect(finalizedBundleFound).To(BeFalse()) + + // check if bundle proposal got dropped + bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) + Expect(bundleProposalFound).To(BeTrue()) + + Expect(bundleProposal.PoolId).To(Equal(uint64(0))) + Expect(bundleProposal.StorageId).To(BeEmpty()) + Expect(bundleProposal.Uploader).To(BeEmpty()) + Expect(bundleProposal.NextUploader).NotTo(BeEmpty()) + Expect(bundleProposal.DataSize).To(BeZero()) + Expect(bundleProposal.DataHash).To(BeEmpty()) + Expect(bundleProposal.BundleSize).To(BeZero()) + Expect(bundleProposal.FromKey).To(BeEmpty()) + Expect(bundleProposal.ToKey).To(BeEmpty()) + Expect(bundleProposal.BundleSummary).To(BeEmpty()) + Expect(bundleProposal.UpdatedAt).NotTo(BeZero()) + Expect(bundleProposal.VotersValid).To(BeEmpty()) + Expect(bundleProposal.VotersInvalid).To(BeEmpty()) + Expect(bundleProposal.VotersAbstain).To(BeEmpty()) + + // check uploader status + _, uploaderActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(uploaderActive).To(BeFalse()) + + balanceValaddress := s.GetBalanceFromAddress(i.VALADDRESS_0_A) + Expect(balanceValaddress).To(Equal(initialBalanceValaddress0)) + + balanceUploader := s.GetBalanceFromAddress(i.STAKER_0) + + _, uploaderFound := s.App().StakersKeeper.GetValidator(s.Ctx(), i.STAKER_0) + Expect(uploaderFound).To(BeTrue()) + + Expect(balanceUploader).To(Equal(initialBalanceStaker0)) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(BeEmpty()) + + // calculate uploader slashes (stake fraction is 0.5 because only 100 kyve out of 200 are at risk) + fraction := s.App().StakersKeeper.GetUploadSlash(s.Ctx()).Mul(math.LegacyMustNewDecFromStr("0.5")) + slashAmount := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) + slashAmountDelegator := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) + + Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.STAKER_0)).To(Equal(100*i.KYVE - slashAmount)) + Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_0, i.CHARLIE)).To(Equal(100*i.KYVE - slashAmountDelegator)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + + // check voter status + valaccountVoter, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_1) + Expect(valaccountVoter.Points).To(BeZero()) + + balanceVoterValaddress := s.GetBalanceFromAddress(valaccountVoter.Valaddress) + Expect(balanceVoterValaddress).To(Equal(initialBalanceValaddress1)) + + balanceVoter := s.GetBalanceFromAddress(valaccountVoter.Staker) + + Expect(balanceVoter).To(Equal(initialBalanceStaker1)) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_1, i.STAKER_1)).To(BeEmpty()) + + // check voter 2 status + valaccountVoter, _ = s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_2) + Expect(valaccountVoter.Points).To(BeZero()) + + balanceVoterValaddress = s.GetBalanceFromAddress(valaccountVoter.Valaddress) + Expect(balanceVoterValaddress).To(Equal(initialBalanceValaddress1)) + + balanceVoter = s.GetBalanceFromAddress(valaccountVoter.Staker) + + Expect(balanceVoter).To(Equal(initialBalanceStaker1)) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_2, i.STAKER_2)).To(BeEmpty()) + + // check pool funds + fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) + + // assert total pool funds + Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId)[0].Amount.Uint64()).To(Equal(100 * i.KYVE)) + Expect(fundingState.ActiveFunderAddresses).To(HaveLen(1)) + }) }) diff --git a/x/bundles/keeper/keeper_suite_valid_bundles_test.go b/x/bundles/keeper/keeper_suite_valid_bundles_test.go index 17e5b636..addc5630 100644 --- a/x/bundles/keeper/keeper_suite_valid_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_valid_bundles_test.go @@ -25,6 +25,7 @@ TEST CASES - valid bundles * Produce a valid bundle with multiple validators and foreign delegation although some did not vote at all * Produce a valid bundle with multiple validators and foreign delegation although some voted abstain * Produce a valid bundle with multiple validators and foreign delegation although some voted invalid +* Produce a valid bundle with multiple validators and foreign delegation although some voted invalid with maximum voting power * Produce a valid bundle with multiple validators and no foreign delegations and another storage provider * Produce a valid bundle with multiple validators, multiple coins and no foreign delegations * Produce a valid bundle with multiple validators, multiple coins which are not enough for the storage reward and no foreign delegations @@ -963,6 +964,207 @@ var _ = Describe("valid bundles", Ordered, func() { Expect(fundingState.ActiveFunderAddresses).To(HaveLen(1)) }) + It("Produce a valid bundle with multiple validators and foreign delegation although some voted invalid with maximum voting power", func() { + // ARRANGE + params := s.App().PoolKeeper.GetParams(s.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.4") + s.App().PoolKeeper.SetParams(s.Ctx(), params) + + s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_2, + PoolId: 0, + Valaddress: i.VALADDRESS_2_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + // delegate to staker 2 so he runs into the max voting power limit + s.RunTxSuccess(stakingTypes.NewMsgDelegate( + i.CHARLIE, + util.MustValaddressFromOperatorAddress(i.STAKER_2), + sdk.NewInt64Coin(globalTypes.Denom, int64(300*i.KYVE)), + )) + + s.CreateValidator(i.STAKER_3, "Staker-3", int64(100*i.KYVE)) + + s.RunTxStakersSuccess(&stakertypes.MsgJoinPool{ + Creator: i.STAKER_3, + PoolId: 0, + Valaddress: i.VALADDRESS_3_A, + Commission: math.LegacyMustNewDecFromStr("0.1"), + StakeFraction: math.LegacyMustNewDecFromStr("1"), + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgClaimUploaderRole{ + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, + PoolId: 0, + }) + + s.CommitAfterSeconds(60) + + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ + Creator: i.VALADDRESS_0_A, + Staker: i.STAKER_0, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + DataSize: 100, + DataHash: "test_hash", + FromIndex: 0, + BundleSize: 100, + FromKey: "0", + ToKey: "99", + BundleSummary: "test_value", + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_1_A, + Staker: i.STAKER_1, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_VALID, + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_2_A, + Staker: i.STAKER_2, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_INVALID, + }) + + s.RunTxBundlesSuccess(&bundletypes.MsgVoteBundleProposal{ + Creator: i.VALADDRESS_3_A, + Staker: i.STAKER_3, + PoolId: 0, + StorageId: "y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI", + Vote: bundletypes.VOTE_TYPE_VALID, + }) + + initialBalanceStaker2 = s.GetCoinsFromAddress(i.STAKER_2) + initialBalanceValaddress2 = s.GetCoinsFromAddress(i.VALADDRESS_2_A) + + c1 := s.GetCoinsFromCommunityPool() + + s.CommitAfterSeconds(60) + + // ACT + // TODO: why is staker 2 selected as next uploader? + s.RunTxBundlesSuccess(&bundletypes.MsgSubmitBundleProposal{ + Creator: i.VALADDRESS_2_A, + Staker: i.STAKER_2, + PoolId: 0, + StorageId: "P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg", + DataSize: 100, + DataHash: "test_hash2", + FromIndex: 100, + BundleSize: 100, + FromKey: "100", + ToKey: "199", + BundleSummary: "test_value2", + }) + + // ASSERT + // check if bundle got finalized on pool + pool, poolFound := s.App().PoolKeeper.GetPool(s.Ctx(), 0) + Expect(poolFound).To(BeTrue()) + + Expect(pool.CurrentKey).To(Equal("99")) + Expect(pool.CurrentSummary).To(Equal("test_value")) + Expect(pool.CurrentIndex).To(Equal(uint64(100))) + Expect(pool.TotalBundles).To(Equal(uint64(1))) + + // check if finalized bundle got saved + finalizedBundle, finalizedBundleFound := s.App().BundlesKeeper.GetFinalizedBundle(s.Ctx(), 0, 0) + Expect(finalizedBundleFound).To(BeTrue()) + + Expect(finalizedBundle.PoolId).To(Equal(uint64(0))) + Expect(finalizedBundle.StorageId).To(Equal("y62A3tfbSNcNYDGoL-eXwzyV-Zc9Q0OVtDvR1biJmNI")) + Expect(finalizedBundle.Uploader).To(Equal(i.STAKER_0)) + Expect(finalizedBundle.FromIndex).To(Equal(uint64(0))) + Expect(finalizedBundle.ToIndex).To(Equal(uint64(100))) + Expect(finalizedBundle.FromKey).To(Equal("0")) + Expect(finalizedBundle.ToKey).To(Equal("99")) + Expect(finalizedBundle.BundleSummary).To(Equal("test_value")) + Expect(finalizedBundle.DataHash).To(Equal("test_hash")) + Expect(finalizedBundle.FinalizedAt).NotTo(BeZero()) + Expect(finalizedBundle.StakeSecurity.ValidVotePower).To(Equal(300 * i.KYVE)) + Expect(finalizedBundle.StakeSecurity.TotalVotePower).To(Equal(500*i.KYVE + 1)) + + // check if next bundle proposal got registered + bundleProposal, bundleProposalFound := s.App().BundlesKeeper.GetBundleProposal(s.Ctx(), 0) + Expect(bundleProposalFound).To(BeTrue()) + + Expect(bundleProposal.PoolId).To(Equal(uint64(0))) + Expect(bundleProposal.StorageId).To(Equal("P9edn0bjEfMU_lecFDIPLvGO2v2ltpFNUMWp5kgPddg")) + Expect(bundleProposal.Uploader).To(Equal(i.STAKER_2)) + Expect(bundleProposal.NextUploader).To(Equal(i.STAKER_3)) + Expect(bundleProposal.DataSize).To(Equal(uint64(100))) + Expect(bundleProposal.DataHash).To(Equal("test_hash2")) + Expect(bundleProposal.BundleSize).To(Equal(uint64(100))) + Expect(bundleProposal.FromKey).To(Equal("100")) + Expect(bundleProposal.ToKey).To(Equal("199")) + Expect(bundleProposal.BundleSummary).To(Equal("test_value2")) + Expect(bundleProposal.UpdatedAt).NotTo(BeZero()) + Expect(bundleProposal.VotersValid).To(ContainElement(i.STAKER_2)) + Expect(bundleProposal.VotersInvalid).To(BeEmpty()) + Expect(bundleProposal.VotersAbstain).To(BeEmpty()) + + // check uploader status + valaccountUploader, _ := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_0) + Expect(valaccountUploader.Points).To(BeZero()) + + balanceUploaderValaddress := s.GetCoinsFromAddress(valaccountUploader.Valaddress) + Expect(balanceUploaderValaddress).To(Equal(initialBalanceValaddress0)) + + // calculate voter slashes (due to maximum vote power only 200 kyve out of 400 where at risk for slashing) + fraction := s.App().StakersKeeper.GetVoteSlash(s.Ctx()).Mul(math.LegacyMustNewDecFromStr("0.5")) // 200 / 400 + slashAmountVoter := uint64(math.LegacyNewDec(int64(100 * i.KYVE)).Mul(fraction).TruncateInt64()) + slashAmountDelegator := uint64(math.LegacyNewDec(int64(300 * i.KYVE)).Mul(fraction).TruncateInt64()) + + Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.STAKER_2)).To(Equal(100*i.KYVE - slashAmountVoter)) + Expect(s.App().StakersKeeper.GetDelegationAmountOfDelegator(s.Ctx(), i.STAKER_2, i.CHARLIE)).To(Equal(300*i.KYVE - slashAmountDelegator)) + + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(300 * i.KYVE)) + + // check voter status + _, voterActive := s.App().StakersKeeper.GetValaccount(s.Ctx(), 0, i.STAKER_2) + Expect(voterActive).To(BeFalse()) + + balanceVoterValaddress := s.GetCoinsFromAddress(i.VALADDRESS_2_A) + Expect(balanceVoterValaddress).To(Equal(initialBalanceValaddress2)) + + balanceVoter := s.GetCoinsFromAddress(i.STAKER_2) + Expect(balanceVoter).To(Equal(initialBalanceStaker2)) + + // check uploader rewards + balanceUploader := s.GetCoinsFromAddress(valaccountUploader.Staker) + + // assert payout transfer + Expect(balanceUploader.String()).To(Equal(initialBalanceStaker0.String())) + // assert commission rewards + // (10_000 - (10_000 * 0.01) - (100 * 0.5)) * 0.1 + (100 * 0.5) + Expect(s.App().StakersKeeper.GetOutstandingCommissionRewards(s.Ctx(), valaccountUploader.Staker).String()).To(Equal(i.ACoins(1035).String())) + // assert uploader self delegation rewards + // (10_000 - (10_000 * 0.01) - (100 * 0.5)) * (1 - 0.1) + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_0, i.STAKER_0).String()).To(Equal(i.ACoins(8865).String())) + + // check voter rewards + Expect(s.App().StakersKeeper.GetOutstandingRewards(s.Ctx(), i.STAKER_2, i.CHARLIE)).To(BeEmpty()) + + fundingState, _ := s.App().FundersKeeper.GetFundingState(s.Ctx(), 0) + + // assert treasury payout + c2 := s.GetCoinsFromCommunityPool() + Expect(c2.Sub(c1...).AmountOf(i.A_DENOM).Uint64()).To(Equal(uint64(100))) + + // assert total pool funds + Expect(s.App().FundersKeeper.GetTotalActiveFunding(s.Ctx(), fundingState.PoolId).String()).To(Equal(i.ACoins(100*i.T_KYVE - amountPerBundle).String())) + Expect(fundingState.ActiveFunderAddresses).To(HaveLen(1)) + }) + It("Produce a valid bundle with multiple validators and no foreign delegations and another storage provider", func() { // ARRANGE storageProviderId := uint32(2) From ef69783fe19ccc171f2d7b5fa7e48458f49491ec Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Wed, 18 Dec 2024 11:22:59 +0100 Subject: [PATCH 12/24] chore: remove unused code --- x/stakers/keeper/getters_valaccount.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/x/stakers/keeper/getters_valaccount.go b/x/stakers/keeper/getters_valaccount.go index aa307a41..0535efb7 100644 --- a/x/stakers/keeper/getters_valaccount.go +++ b/x/stakers/keeper/getters_valaccount.go @@ -96,14 +96,6 @@ func (k Keeper) GetPoolCount(ctx sdk.Context, stakerAddress string) (poolCount u // # Raw KV-Store operations # // ############################# -// DoesValaccountExist only checks if the key is present in the KV-Store -// without loading and unmarshalling to full entry -//func (k Keeper) DoesValaccountExist(ctx sdk.Context, poolId uint64, stakerAddress string) bool { -// storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) -// store := prefix.NewStore(storeAdapter, types.ValaccountPrefix) -// return store.Has(types.ValaccountKey(poolId, stakerAddress)) -//} - // SetValaccount set a specific Valaccount in the store from its index func (k Keeper) SetValaccount(ctx sdk.Context, valaccount types.Valaccount) { storeAdapter := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) From 9037988440fe1587fc13c4059be0f15951b0d221 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Wed, 18 Dec 2024 11:42:51 +0100 Subject: [PATCH 13/24] chore: add missing changes --- CHANGELOG.md | 1 + x/stakers/keeper/getters_params.go | 2 ++ x/stakers/keeper/getters_stake_fraction.go | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 741872bc..fedf109d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ An '!' indicates a state machine breaking change. - ! (`x/stakers`) [#209](https://github.com/KYVENetwork/chain/pull/209) Shared Staking: Consensus-validator stake is now used for the protocol. - ! (`x/stakers`) [#210](https://github.com/KYVENetwork/chain/pull/210) Shared Staking: Pool specific commission and stake fraction. +- ! (`x/stakers`) [#211](https://github.com/KYVENetwork/chain/pull/211) Shared Staking: Maximum voting power per pool. ### Bug Fixes diff --git a/x/stakers/keeper/getters_params.go b/x/stakers/keeper/getters_params.go index 8a2864f2..aade9b04 100644 --- a/x/stakers/keeper/getters_params.go +++ b/x/stakers/keeper/getters_params.go @@ -59,6 +59,8 @@ func (k Keeper) getSlashFraction(ctx sdk.Context, slashType types.SlashType) (sl slashAmountRatio = k.GetVoteSlash(ctx) case types.SLASH_TYPE_UPLOAD: slashAmountRatio = k.GetUploadSlash(ctx) + default: + slashAmountRatio = math.LegacyZeroDec() } return } diff --git a/x/stakers/keeper/getters_stake_fraction.go b/x/stakers/keeper/getters_stake_fraction.go index cab95cb3..e1100bad 100644 --- a/x/stakers/keeper/getters_stake_fraction.go +++ b/x/stakers/keeper/getters_stake_fraction.go @@ -65,7 +65,7 @@ func (k Keeper) RemoveStakeFractionEntry(ctx sdk.Context, stakeFractionChangeEnt store := prefix.NewStore(storeAdapter, types.StakeFractionChangeEntryKeyPrefix) store.Delete(types.StakeFractionChangeEntryKey(stakeFractionChangeEntry.Index)) - indexStore := prefix.NewStore(storeAdapter, types.StakeFractionChangeEntryKeyPrefix) + indexStore := prefix.NewStore(storeAdapter, types.StakeFractionChangeKeyPrefixIndex2) indexStore.Delete(types.StakeFractionChangeEntryKeyIndex2( stakeFractionChangeEntry.Staker, stakeFractionChangeEntry.PoolId, From 373ec772ffcfa52e59d4b554beba6324b3c90756 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Wed, 18 Dec 2024 14:51:06 +0100 Subject: [PATCH 14/24] chore: reimplemented stakers query --- docs/static/openapi.yml | 2675 +++++++++++++++++------- go.mod | 2 +- proto/kyve/query/v1beta1/query.proto | 117 +- x/query/keeper/grpc_account_funded.go | 2 +- x/query/keeper/grpc_query_staker.go | 4 +- x/query/keeper/helper.go | 66 +- x/query/types/query.pb.go | 1070 ++++------ x/stakers/keeper/exported_functions.go | 17 +- x/stakers/keeper/getters_staker.go | 31 + 9 files changed, 2538 insertions(+), 1446 deletions(-) diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 13f9bec0..368410fe 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -530,132 +530,237 @@ paths: address: type: string title: address of the staker - metadata: - description: metadata as logo, moniker, etc. + validator: type: object properties: - commission: + operator_address: type: string - title: >- - commission is the percentage of the rewards that - will + description: >- + operator_address defines the address of the + validator's operator; bech encoded in JSON. + consensus_pubkey: + description: >- + consensus_pubkey is the consensus public key of + the validator, as a Protobuf Any. + type: object + properties: + '@type': + type: string + description: >- + A URL/resource name that uniquely identifies + the type of the serialized - get transferred to the staker before the - remaining + protocol buffer message. This string must + contain at least - rewards are split across all delegators - moniker: + one "/" character. The last segment of the + URL's path must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name + should be in a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into + the binary all types that they + + expect it to use in the context of Any. + However, for URLs which use the + + scheme `http`, `https`, or no scheme, one + can optionally set up a type + + server that maps type URLs to message + definitions as follows: + + + * If no scheme is provided, `https` is + assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup + results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently + available in the official + + protobuf release, and it is not used for + type URLs beginning with + + type.googleapis.com. As of May 2023, there + are no widely used type server + + implementations and no plans to implement + one. + + + Schemes other than `http`, `https` (or the + empty scheme) might be + + used with implementation specific semantics. + additionalProperties: {} + jailed: + type: boolean + description: >- + jailed defined whether the validator has been + jailed from bonded status or not. + status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). type: string - title: |- - moniker is a human-readable name for displaying - the staker in the UI - website: + enum: + - BOND_STATUS_UNSPECIFIED + - BOND_STATUS_UNBONDED + - BOND_STATUS_UNBONDING + - BOND_STATUS_BONDED + default: BOND_STATUS_UNSPECIFIED + tokens: type: string - title: >- - website is a https-link to the website of the - staker - identity: + description: >- + tokens define the delegated tokens (incl. + self-delegation). + delegator_shares: type: string - title: identity from keybase.io - security_contact: + description: >- + delegator_shares defines total shares issued to + a validator's delegators. + description: + description: >- + description defines the description terms for + the validator. + type: object + properties: + moniker: + type: string + description: >- + moniker defines a human-readable name for + the validator. + identity: + type: string + description: >- + identity defines an optional identity + signature (ex. UPort or Keybase). + website: + type: string + description: website defines an optional website link. + security_contact: + type: string + description: >- + security_contact defines an optional email + for security contact. + details: + type: string + description: details define other optional details. + unbonding_height: type: string - description: security_contact ... - details: + format: int64 + description: >- + unbonding_height defines, if unbonding, the + height at which this validator has begun + unbonding. + unbonding_time: type: string - description: details ... - pending_commission_change: + format: date-time description: >- - pending_commission_change shows if the staker - plans - - to change its commission. Delegators will see a - warning in - - the UI. A Commission change takes some time - until - - the commission is applied. Users have time to - redelegate - - if they not agree with the new commission. + unbonding_time defines, if unbonding, the min + time for the validator to complete unbonding. + commission: + description: commission defines the commission parameters. type: object properties: - commission: - type: string - title: |- - commission is the new commission that will - become active once the change-time is over - creation_date: + commission_rates: + description: >- + commission_rates defines the initial + commission rates to be used for creating a + validator. + type: object + properties: + rate: + type: string + description: >- + rate is the commission rate charged to + delegators, as a fraction. + max_rate: + type: string + description: >- + max_rate defines the maximum commission + rate which validator can ever charge, as + a fraction. + max_change_rate: + type: string + description: >- + max_change_rate defines the maximum + daily increase of the validator + commission, as a fraction. + update_time: type: string - format: int64 + format: date-time description: >- - creation_date is the UNIX-timestamp (in - seconds) + update_time is the last time the commission + rate was changed. + min_self_delegation: + type: string + description: >- + min_self_delegation is the validator's self + declared minimum self delegation. - of when the entry was created. - title: >- - CommissionChangeEntry shows when the old - commission - of a staker will change to the new commission - commission_rewards: + Since: cosmos-sdk 0.46 + unbonding_on_hold_ref_count: + type: string + format: int64 + title: >- + strictly positive if this validator's unbonding + has been stopped by external modules + unbonding_ids: type: array items: - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination and - an amount. - - - NOTE: The amount field is an Int which - implements the custom method - - signatures required by gogoproto. + type: string + format: uint64 title: >- - commission_rewards are the rewards through - commission and storage cost - title: >- - StakerMetadata contains static information for a - staker - self_delegation: - type: string - format: uint64 - title: amount the staker has delegated to himself - self_delegation_unbonding: - type: string - format: uint64 + list of unbonding ids, each uniquely identifing + an unbonding of this validator description: >- - unbonding_amount is the amount the staker is - currently unbonding + Validator defines a validator, together with the + total amount of the - from the self-delegation. + Validator's bond shares and their exchange rate to + coins. Slashing results in - This amount can be larger than `amount` when the - staker + a decrease in the exchange rate, allowing correct + calculation of future - got slashed during unbonding. However, at the end of + undelegations without iterating over delegators. + When coins are delegated to - the unbonding period this amount is double checked - with the + this validator, the validator is credited with a + delegation whose number of - remaining amount. - total_delegation: - type: string - format: uint64 - title: |- - total_delegation returns the sum of all $KYVE users - have delegated to this staker - delegator_count: + bond shares is based on the amount of coins + delegated divided by the current + + exchange rate. Voting power can be calculated as + total bonded shares + + multiplied by exchange rate. + total_pool_stake: type: string format: uint64 - description: |- - delegator_count is the total number of individual - delegator addresses for that user. + title: >- + total_pool_stake returns the amount the validator + has in total + + staked in all his pools pools: type: array items: @@ -716,10 +821,10 @@ paths: out of funds no more bundles will be produced - total_delegation: + total_stake: type: string format: uint64 - title: total_delegation of the pool + title: total_stake of the pool status: description: |- status of the pool if pool is able @@ -774,6 +879,108 @@ paths: funds to pay for gas fees + commission: + type: string + title: >- + commission is the commission the validator has + chosen for + + this specific pool + pending_commission_change: + description: >- + pending_commission_change shows if the staker + plans + + to change its commission. Delegators will see + a warning in + + the UI. A Commission change takes some time + until + + the commission is applied. Users have time to + redelegate + + if they not agree with the new commission. + type: object + properties: + commission: + type: string + title: |- + commission is the new commission that will + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + CommissionChangeEntry shows when the old + commission + + of a staker will change to the new commission + stake_fraction: + type: string + title: >- + stake fraction is a percentage the validator + has chosen for + + this pool. It is the fraction of how much of + his total stake + + the validator wants to stake in this specific + pool + pending_stake_fraction_change: + description: >- + pending_stake_fraction_change shows if the + staker plans + + to change its stake fraction. Delegators will + see a warning in + + the UI. A stake fraction change takes some + time until + + the stake fraction is applied. Users have time + to redelegate + + if they not agree with the new stake fraction. + type: object + properties: + stake_fraction: + type: string + title: >- + stake_fraction is the new stake_fraction + that will + + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + StakeFractionChangeEntry shows when the old + stake fraction + + of a staker will change to the new stake + fraction + pool_stake: + type: string + format: uint64 + title: >- + pool stake shows the actual amount the + validator has staked + + in this pool. It can be lower than the + specified stake fraction + + because of the max voting power limit title: |- PoolMembership shows in which pool the staker is participating @@ -1144,10 +1351,10 @@ paths: title: |- total_funds of the pool. If the pool runs out of funds no more bundles will be produced - total_delegation: + total_stake: type: string format: uint64 - title: total_delegation of the pool + title: total_stake of the pool status: description: |- status of the pool if pool is able @@ -3862,132 +4069,237 @@ paths: address: type: string title: address of the staker - metadata: - description: metadata as logo, moniker, etc. + validator: type: object properties: - commission: + operator_address: type: string - title: >- - commission is the percentage of the rewards that - will + description: >- + operator_address defines the address of the + validator's operator; bech encoded in JSON. + consensus_pubkey: + description: >- + consensus_pubkey is the consensus public key of + the validator, as a Protobuf Any. + type: object + properties: + '@type': + type: string + description: >- + A URL/resource name that uniquely identifies + the type of the serialized - get transferred to the staker before the - remaining + protocol buffer message. This string must + contain at least - rewards are split across all delegators - moniker: + one "/" character. The last segment of the + URL's path must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name + should be in a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into + the binary all types that they + + expect it to use in the context of Any. + However, for URLs which use the + + scheme `http`, `https`, or no scheme, one + can optionally set up a type + + server that maps type URLs to message + definitions as follows: + + + * If no scheme is provided, `https` is + assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup + results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently + available in the official + + protobuf release, and it is not used for + type URLs beginning with + + type.googleapis.com. As of May 2023, there + are no widely used type server + + implementations and no plans to implement + one. + + + Schemes other than `http`, `https` (or the + empty scheme) might be + + used with implementation specific semantics. + additionalProperties: {} + jailed: + type: boolean + description: >- + jailed defined whether the validator has been + jailed from bonded status or not. + status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). type: string - title: |- - moniker is a human-readable name for displaying - the staker in the UI - website: + enum: + - BOND_STATUS_UNSPECIFIED + - BOND_STATUS_UNBONDED + - BOND_STATUS_UNBONDING + - BOND_STATUS_BONDED + default: BOND_STATUS_UNSPECIFIED + tokens: type: string - title: >- - website is a https-link to the website of the - staker - identity: + description: >- + tokens define the delegated tokens (incl. + self-delegation). + delegator_shares: type: string - title: identity from keybase.io - security_contact: + description: >- + delegator_shares defines total shares issued to + a validator's delegators. + description: + description: >- + description defines the description terms for + the validator. + type: object + properties: + moniker: + type: string + description: >- + moniker defines a human-readable name for + the validator. + identity: + type: string + description: >- + identity defines an optional identity + signature (ex. UPort or Keybase). + website: + type: string + description: website defines an optional website link. + security_contact: + type: string + description: >- + security_contact defines an optional email + for security contact. + details: + type: string + description: details define other optional details. + unbonding_height: type: string - description: security_contact ... - details: + format: int64 + description: >- + unbonding_height defines, if unbonding, the + height at which this validator has begun + unbonding. + unbonding_time: type: string - description: details ... - pending_commission_change: + format: date-time description: >- - pending_commission_change shows if the staker - plans - - to change its commission. Delegators will see a - warning in - - the UI. A Commission change takes some time - until - - the commission is applied. Users have time to - redelegate - - if they not agree with the new commission. + unbonding_time defines, if unbonding, the min + time for the validator to complete unbonding. + commission: + description: commission defines the commission parameters. type: object properties: - commission: - type: string - title: |- - commission is the new commission that will - become active once the change-time is over - creation_date: + commission_rates: + description: >- + commission_rates defines the initial + commission rates to be used for creating a + validator. + type: object + properties: + rate: + type: string + description: >- + rate is the commission rate charged to + delegators, as a fraction. + max_rate: + type: string + description: >- + max_rate defines the maximum commission + rate which validator can ever charge, as + a fraction. + max_change_rate: + type: string + description: >- + max_change_rate defines the maximum + daily increase of the validator + commission, as a fraction. + update_time: type: string - format: int64 + format: date-time description: >- - creation_date is the UNIX-timestamp (in - seconds) + update_time is the last time the commission + rate was changed. + min_self_delegation: + type: string + description: >- + min_self_delegation is the validator's self + declared minimum self delegation. - of when the entry was created. - title: >- - CommissionChangeEntry shows when the old - commission - of a staker will change to the new commission - commission_rewards: + Since: cosmos-sdk 0.46 + unbonding_on_hold_ref_count: + type: string + format: int64 + title: >- + strictly positive if this validator's unbonding + has been stopped by external modules + unbonding_ids: type: array items: - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination and - an amount. - - - NOTE: The amount field is an Int which - implements the custom method - - signatures required by gogoproto. + type: string + format: uint64 title: >- - commission_rewards are the rewards through - commission and storage cost - title: >- - StakerMetadata contains static information for a - staker - self_delegation: - type: string - format: uint64 - title: amount the staker has delegated to himself - self_delegation_unbonding: - type: string - format: uint64 + list of unbonding ids, each uniquely identifing + an unbonding of this validator description: >- - unbonding_amount is the amount the staker is - currently unbonding + Validator defines a validator, together with the + total amount of the - from the self-delegation. + Validator's bond shares and their exchange rate to + coins. Slashing results in - This amount can be larger than `amount` when the - staker + a decrease in the exchange rate, allowing correct + calculation of future - got slashed during unbonding. However, at the end of + undelegations without iterating over delegators. + When coins are delegated to - the unbonding period this amount is double checked - with the + this validator, the validator is credited with a + delegation whose number of - remaining amount. - total_delegation: - type: string - format: uint64 - title: |- - total_delegation returns the sum of all $KYVE users - have delegated to this staker - delegator_count: + bond shares is based on the amount of coins + delegated divided by the current + + exchange rate. Voting power can be calculated as + total bonded shares + + multiplied by exchange rate. + total_pool_stake: type: string format: uint64 - description: |- - delegator_count is the total number of individual - delegator addresses for that user. + title: >- + total_pool_stake returns the amount the validator + has in total + + staked in all his pools pools: type: array items: @@ -4048,10 +4360,10 @@ paths: out of funds no more bundles will be produced - total_delegation: + total_stake: type: string format: uint64 - title: total_delegation of the pool + title: total_stake of the pool status: description: |- status of the pool if pool is able @@ -4106,7 +4418,109 @@ paths: funds to pay for gas fees - title: |- + commission: + type: string + title: >- + commission is the commission the validator has + chosen for + + this specific pool + pending_commission_change: + description: >- + pending_commission_change shows if the staker + plans + + to change its commission. Delegators will see + a warning in + + the UI. A Commission change takes some time + until + + the commission is applied. Users have time to + redelegate + + if they not agree with the new commission. + type: object + properties: + commission: + type: string + title: |- + commission is the new commission that will + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + CommissionChangeEntry shows when the old + commission + + of a staker will change to the new commission + stake_fraction: + type: string + title: >- + stake fraction is a percentage the validator + has chosen for + + this pool. It is the fraction of how much of + his total stake + + the validator wants to stake in this specific + pool + pending_stake_fraction_change: + description: >- + pending_stake_fraction_change shows if the + staker plans + + to change its stake fraction. Delegators will + see a warning in + + the UI. A stake fraction change takes some + time until + + the stake fraction is applied. Users have time + to redelegate + + if they not agree with the new stake fraction. + type: object + properties: + stake_fraction: + type: string + title: >- + stake_fraction is the new stake_fraction + that will + + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + StakeFractionChangeEntry shows when the old + stake fraction + + of a staker will change to the new stake + fraction + pool_stake: + type: string + format: uint64 + title: >- + pool stake shows the actual amount the + validator has staked + + in this pool. It can be lower than the + specified stake fraction + + because of the max voting power limit + title: |- PoolMembership shows in which pool the staker is participating description: |- @@ -6262,117 +6676,233 @@ paths: address: type: string title: address of the staker - metadata: - description: metadata as logo, moniker, etc. + validator: type: object properties: - commission: - type: string - title: |- - commission is the percentage of the rewards that will - get transferred to the staker before the remaining - rewards are split across all delegators - moniker: - type: string - title: |- - moniker is a human-readable name for displaying - the staker in the UI - website: - type: string - title: website is a https-link to the website of the staker - identity: - type: string - title: identity from keybase.io - security_contact: - type: string - description: security_contact ... - details: + operator_address: type: string - description: details ... - pending_commission_change: description: >- - pending_commission_change shows if the staker plans + operator_address defines the address of the + validator's operator; bech encoded in JSON. + consensus_pubkey: + description: >- + consensus_pubkey is the consensus public key of the + validator, as a Protobuf Any. + type: object + properties: + '@type': + type: string + description: >- + A URL/resource name that uniquely identifies the + type of the serialized + + protocol buffer message. This string must contain + at least + + one "/" character. The last segment of the URL's + path must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should + be in a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the + binary all types that they + + expect it to use in the context of Any. However, + for URLs which use the + + scheme `http`, `https`, or no scheme, one can + optionally set up a type + + server that maps type URLs to message definitions + as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results + based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently + available in the official + + protobuf release, and it is not used for type URLs + beginning with - to change its commission. Delegators will see a - warning in + type.googleapis.com. As of May 2023, there are no + widely used type server + + implementations and no plans to implement one. - the UI. A Commission change takes some time until - the commission is applied. Users have time to - redelegate + Schemes other than `http`, `https` (or the empty + scheme) might be - if they not agree with the new commission. + used with implementation specific semantics. + additionalProperties: {} + jailed: + type: boolean + description: >- + jailed defined whether the validator has been jailed + from bonded status or not. + status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). + type: string + enum: + - BOND_STATUS_UNSPECIFIED + - BOND_STATUS_UNBONDED + - BOND_STATUS_UNBONDING + - BOND_STATUS_BONDED + default: BOND_STATUS_UNSPECIFIED + tokens: + type: string + description: >- + tokens define the delegated tokens (incl. + self-delegation). + delegator_shares: + type: string + description: >- + delegator_shares defines total shares issued to a + validator's delegators. + description: + description: >- + description defines the description terms for the + validator. type: object properties: - commission: + moniker: type: string - title: |- - commission is the new commission that will - become active once the change-time is over - creation_date: + description: >- + moniker defines a human-readable name for the + validator. + identity: type: string - format: int64 - description: |- - creation_date is the UNIX-timestamp (in seconds) - of when the entry was created. - title: |- - CommissionChangeEntry shows when the old commission - of a staker will change to the new commission - commission_rewards: - type: array - items: - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination and an - amount. - + description: >- + identity defines an optional identity signature + (ex. UPort or Keybase). + website: + type: string + description: website defines an optional website link. + security_contact: + type: string + description: >- + security_contact defines an optional email for + security contact. + details: + type: string + description: details define other optional details. + unbonding_height: + type: string + format: int64 + description: >- + unbonding_height defines, if unbonding, the height at + which this validator has begun unbonding. + unbonding_time: + type: string + format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for + the validator to complete unbonding. + commission: + description: commission defines the commission parameters. + type: object + properties: + commission_rates: + description: >- + commission_rates defines the initial commission + rates to be used for creating a validator. + type: object + properties: + rate: + type: string + description: >- + rate is the commission rate charged to + delegators, as a fraction. + max_rate: + type: string + description: >- + max_rate defines the maximum commission rate + which validator can ever charge, as a + fraction. + max_change_rate: + type: string + description: >- + max_change_rate defines the maximum daily + increase of the validator commission, as a + fraction. + update_time: + type: string + format: date-time + description: >- + update_time is the last time the commission rate + was changed. + min_self_delegation: + type: string + description: >- + min_self_delegation is the validator's self declared + minimum self delegation. - NOTE: The amount field is an Int which implements - the custom method - signatures required by gogoproto. + Since: cosmos-sdk 0.46 + unbonding_on_hold_ref_count: + type: string + format: int64 title: >- - commission_rewards are the rewards through commission - and storage cost - title: StakerMetadata contains static information for a staker - self_delegation: - type: string - format: uint64 - title: amount the staker has delegated to himself - self_delegation_unbonding: - type: string - format: uint64 + strictly positive if this validator's unbonding has + been stopped by external modules + unbonding_ids: + type: array + items: + type: string + format: uint64 + title: >- + list of unbonding ids, each uniquely identifing an + unbonding of this validator description: >- - unbonding_amount is the amount the staker is currently - unbonding + Validator defines a validator, together with the total + amount of the - from the self-delegation. + Validator's bond shares and their exchange rate to coins. + Slashing results in - This amount can be larger than `amount` when the staker + a decrease in the exchange rate, allowing correct + calculation of future - got slashed during unbonding. However, at the end of + undelegations without iterating over delegators. When + coins are delegated to - the unbonding period this amount is double checked with - the + this validator, the validator is credited with a + delegation whose number of - remaining amount. - total_delegation: - type: string - format: uint64 - title: |- - total_delegation returns the sum of all $KYVE users - have delegated to this staker - delegator_count: + bond shares is based on the amount of coins delegated + divided by the current + + exchange rate. Voting power can be calculated as total + bonded shares + + multiplied by exchange rate. + total_pool_stake: type: string format: uint64 - description: |- - delegator_count is the total number of individual - delegator addresses for that user. + title: >- + total_pool_stake returns the amount the validator has in + total + + staked in all his pools pools: type: array items: @@ -6429,10 +6959,10 @@ paths: title: |- total_funds of the pool. If the pool runs out of funds no more bundles will be produced - total_delegation: + total_stake: type: string format: uint64 - title: total_delegation of the pool + title: total_stake of the pool status: description: |- status of the pool if pool is able @@ -6482,60 +7012,152 @@ paths: to pay for gas fees - title: |- - PoolMembership shows in which pool the staker - is participating - description: |- - pools is a list of all pools the staker is currently - participating, i.e. allowed to vote and upload data. - title: >- - FullStaker aggregates information from the staker and its - delegators - - as well as pending queue entries into one object. - - It contains almost all needed information for a convenient - usage - description: >- - QueryStakerResponse is the response type for the Query/Staker RPC - method. - default: - description: An unexpected error response. - schema: - type: object - properties: - code: - type: integer - format: int32 - message: - type: string - details: - type: array - items: - type: object - properties: - '@type': - type: string - description: >- - A URL/resource name that uniquely identifies the type of - the serialized - - protocol buffer message. This string must contain at - least - - one "/" character. The last segment of the URL's path - must represent + commission: + type: string + title: >- + commission is the commission the validator has + chosen for - the fully qualified name of the type (as in + this specific pool + pending_commission_change: + description: >- + pending_commission_change shows if the staker plans - `path/google.protobuf.Duration`). The name should be in - a canonical form + to change its commission. Delegators will see a + warning in - (e.g., leading "." is not accepted). + the UI. A Commission change takes some time until + the commission is applied. Users have time to + redelegate + + if they not agree with the new commission. + type: object + properties: + commission: + type: string + title: |- + commission is the new commission that will + become active once the change-time is over + creation_date: + type: string + format: int64 + description: |- + creation_date is the UNIX-timestamp (in seconds) + of when the entry was created. + title: |- + CommissionChangeEntry shows when the old commission + of a staker will change to the new commission + stake_fraction: + type: string + title: >- + stake fraction is a percentage the validator has + chosen for + + this pool. It is the fraction of how much of his + total stake + + the validator wants to stake in this specific pool + pending_stake_fraction_change: + description: >- + pending_stake_fraction_change shows if the staker + plans + + to change its stake fraction. Delegators will see a + warning in + + the UI. A stake fraction change takes some time + until + + the stake fraction is applied. Users have time to + redelegate + + if they not agree with the new stake fraction. + type: object + properties: + stake_fraction: + type: string + title: >- + stake_fraction is the new stake_fraction that + will + + become active once the change-time is over + creation_date: + type: string + format: int64 + description: |- + creation_date is the UNIX-timestamp (in seconds) + of when the entry was created. + title: >- + StakeFractionChangeEntry shows when the old stake + fraction + + of a staker will change to the new stake fraction + pool_stake: + type: string + format: uint64 + title: >- + pool stake shows the actual amount the validator has + staked + + in this pool. It can be lower than the specified + stake fraction + + because of the max voting power limit + title: |- + PoolMembership shows in which pool the staker + is participating + description: |- + pools is a list of all pools the staker is currently + participating, i.e. allowed to vote and upload data. + title: >- + FullStaker aggregates information from the staker and its + delegators + + as well as pending queue entries into one object. + + It contains almost all needed information for a convenient + usage + description: >- + QueryStakerResponse is the response type for the Query/Staker RPC + method. + default: + description: An unexpected error response. + schema: + type: object + properties: + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + '@type': + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). - In practice, teams usually precompile into the binary - all types that they + + In practice, teams usually precompile into the binary + all types that they expect it to use in the context of Any. However, for URLs which use the @@ -6716,183 +7338,296 @@ paths: address: type: string title: address of the staker - metadata: - description: metadata as logo, moniker, etc. + validator: type: object properties: - commission: - type: string - title: >- - commission is the percentage of the rewards that - will - - get transferred to the staker before the remaining - - rewards are split across all delegators - moniker: - type: string - title: |- - moniker is a human-readable name for displaying - the staker in the UI - website: - type: string - title: website is a https-link to the website of the staker - identity: - type: string - title: identity from keybase.io - security_contact: - type: string - description: security_contact ... - details: + operator_address: type: string - description: details ... - pending_commission_change: description: >- - pending_commission_change shows if the staker plans - - to change its commission. Delegators will see a - warning in - - the UI. A Commission change takes some time until - - the commission is applied. Users have time to - redelegate - - if they not agree with the new commission. + operator_address defines the address of the + validator's operator; bech encoded in JSON. + consensus_pubkey: + description: >- + consensus_pubkey is the consensus public key of the + validator, as a Protobuf Any. type: object properties: - commission: - type: string - title: |- - commission is the new commission that will - become active once the change-time is over - creation_date: + '@type': type: string - format: int64 - description: |- - creation_date is the UNIX-timestamp (in seconds) - of when the entry was created. - title: |- - CommissionChangeEntry shows when the old commission - of a staker will change to the new commission - commission_rewards: - type: array - items: - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination and an - amount. + description: >- + A URL/resource name that uniquely identifies the + type of the serialized + protocol buffer message. This string must + contain at least - NOTE: The amount field is an Int which implements - the custom method + one "/" character. The last segment of the URL's + path must represent - signatures required by gogoproto. - title: >- - commission_rewards are the rewards through - commission and storage cost - title: StakerMetadata contains static information for a staker - self_delegation: - type: string - format: uint64 - title: amount the staker has delegated to himself - self_delegation_unbonding: - type: string - format: uint64 - description: >- - unbonding_amount is the amount the staker is currently - unbonding + the fully qualified name of the type (as in - from the self-delegation. + `path/google.protobuf.Duration`). The name + should be in a canonical form - This amount can be larger than `amount` when the staker + (e.g., leading "." is not accepted). - got slashed during unbonding. However, at the end of - the unbonding period this amount is double checked with - the + In practice, teams usually precompile into the + binary all types that they - remaining amount. - total_delegation: - type: string - format: uint64 - title: |- - total_delegation returns the sum of all $KYVE users - have delegated to this staker - delegator_count: - type: string - format: uint64 - description: |- - delegator_count is the total number of individual - delegator addresses for that user. - pools: - type: array - items: - type: object - properties: - pool: - title: pool contains useful information about the pool - type: object - properties: - id: - type: string - format: uint64 - title: id is the ID of the pool - name: - type: string - title: name of the pool - runtime: - type: string - description: |- - runtime for the protocol nodes - like evm, bitcoin, etc. - logo: - type: string - title: logo of the pool - inflation_share_weight: - type: string - title: >- - inflation_share_weight is the base payout for - each bundle reward - upload_interval: - type: string - format: uint64 - title: >- - upload_interval is the interval bundles get - created - total_funds: - type: array - items: - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination and - an amount. + expect it to use in the context of Any. However, + for URLs which use the + scheme `http`, `https`, or no scheme, one can + optionally set up a type - NOTE: The amount field is an Int which - implements the custom method + server that maps type URLs to message + definitions as follows: - signatures required by gogoproto. - title: |- - total_funds of the pool. If the pool runs - out of funds no more bundles will be produced - total_delegation: - type: string - format: uint64 - title: total_delegation of the pool - status: - description: |- - status of the pool if pool is able + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup + results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently + available in the official + + protobuf release, and it is not used for type + URLs beginning with + + type.googleapis.com. As of May 2023, there are + no widely used type server + + implementations and no plans to implement one. + + + Schemes other than `http`, `https` (or the empty + scheme) might be + + used with implementation specific semantics. + additionalProperties: {} + jailed: + type: boolean + description: >- + jailed defined whether the validator has been jailed + from bonded status or not. + status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). + type: string + enum: + - BOND_STATUS_UNSPECIFIED + - BOND_STATUS_UNBONDED + - BOND_STATUS_UNBONDING + - BOND_STATUS_BONDED + default: BOND_STATUS_UNSPECIFIED + tokens: + type: string + description: >- + tokens define the delegated tokens (incl. + self-delegation). + delegator_shares: + type: string + description: >- + delegator_shares defines total shares issued to a + validator's delegators. + description: + description: >- + description defines the description terms for the + validator. + type: object + properties: + moniker: + type: string + description: >- + moniker defines a human-readable name for the + validator. + identity: + type: string + description: >- + identity defines an optional identity signature + (ex. UPort or Keybase). + website: + type: string + description: website defines an optional website link. + security_contact: + type: string + description: >- + security_contact defines an optional email for + security contact. + details: + type: string + description: details define other optional details. + unbonding_height: + type: string + format: int64 + description: >- + unbonding_height defines, if unbonding, the height + at which this validator has begun unbonding. + unbonding_time: + type: string + format: date-time + description: >- + unbonding_time defines, if unbonding, the min time + for the validator to complete unbonding. + commission: + description: commission defines the commission parameters. + type: object + properties: + commission_rates: + description: >- + commission_rates defines the initial commission + rates to be used for creating a validator. + type: object + properties: + rate: + type: string + description: >- + rate is the commission rate charged to + delegators, as a fraction. + max_rate: + type: string + description: >- + max_rate defines the maximum commission rate + which validator can ever charge, as a + fraction. + max_change_rate: + type: string + description: >- + max_change_rate defines the maximum daily + increase of the validator commission, as a + fraction. + update_time: + type: string + format: date-time + description: >- + update_time is the last time the commission rate + was changed. + min_self_delegation: + type: string + description: >- + min_self_delegation is the validator's self declared + minimum self delegation. + + + Since: cosmos-sdk 0.46 + unbonding_on_hold_ref_count: + type: string + format: int64 + title: >- + strictly positive if this validator's unbonding has + been stopped by external modules + unbonding_ids: + type: array + items: + type: string + format: uint64 + title: >- + list of unbonding ids, each uniquely identifing an + unbonding of this validator + description: >- + Validator defines a validator, together with the total + amount of the + + Validator's bond shares and their exchange rate to + coins. Slashing results in + + a decrease in the exchange rate, allowing correct + calculation of future + + undelegations without iterating over delegators. When + coins are delegated to + + this validator, the validator is credited with a + delegation whose number of + + bond shares is based on the amount of coins delegated + divided by the current + + exchange rate. Voting power can be calculated as total + bonded shares + + multiplied by exchange rate. + total_pool_stake: + type: string + format: uint64 + title: >- + total_pool_stake returns the amount the validator has in + total + + staked in all his pools + pools: + type: array + items: + type: object + properties: + pool: + title: pool contains useful information about the pool + type: object + properties: + id: + type: string + format: uint64 + title: id is the ID of the pool + name: + type: string + title: name of the pool + runtime: + type: string + description: |- + runtime for the protocol nodes + like evm, bitcoin, etc. + logo: + type: string + title: logo of the pool + inflation_share_weight: + type: string + title: >- + inflation_share_weight is the base payout for + each bundle reward + upload_interval: + type: string + format: uint64 + title: >- + upload_interval is the interval bundles get + created + total_funds: + type: array + items: + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + Coin defines a token with a denomination and + an amount. + + + NOTE: The amount field is an Int which + implements the custom method + + signatures required by gogoproto. + title: |- + total_funds of the pool. If the pool runs + out of funds no more bundles will be produced + total_stake: + type: string + format: uint64 + title: total_stake of the pool + status: + description: |- + status of the pool if pool is able to produce bundles, etc. type: string enum: @@ -6939,6 +7674,105 @@ paths: funds to pay for gas fees + commission: + type: string + title: >- + commission is the commission the validator has + chosen for + + this specific pool + pending_commission_change: + description: >- + pending_commission_change shows if the staker + plans + + to change its commission. Delegators will see a + warning in + + the UI. A Commission change takes some time until + + the commission is applied. Users have time to + redelegate + + if they not agree with the new commission. + type: object + properties: + commission: + type: string + title: |- + commission is the new commission that will + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + CommissionChangeEntry shows when the old + commission + + of a staker will change to the new commission + stake_fraction: + type: string + title: >- + stake fraction is a percentage the validator has + chosen for + + this pool. It is the fraction of how much of his + total stake + + the validator wants to stake in this specific pool + pending_stake_fraction_change: + description: >- + pending_stake_fraction_change shows if the staker + plans + + to change its stake fraction. Delegators will see + a warning in + + the UI. A stake fraction change takes some time + until + + the stake fraction is applied. Users have time to + redelegate + + if they not agree with the new stake fraction. + type: object + properties: + stake_fraction: + type: string + title: >- + stake_fraction is the new stake_fraction that + will + + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + StakeFractionChangeEntry shows when the old stake + fraction + + of a staker will change to the new stake fraction + pool_stake: + type: string + format: uint64 + title: >- + pool stake shows the actual amount the validator + has staked + + in this pool. It can be lower than the specified + stake fraction + + because of the max voting power limit title: |- PoolMembership shows in which pool the staker is participating @@ -7270,132 +8104,237 @@ paths: address: type: string title: address of the staker - metadata: - description: metadata as logo, moniker, etc. + validator: type: object properties: - commission: + operator_address: type: string - title: >- - commission is the percentage of the rewards that - will + description: >- + operator_address defines the address of the + validator's operator; bech encoded in JSON. + consensus_pubkey: + description: >- + consensus_pubkey is the consensus public key of + the validator, as a Protobuf Any. + type: object + properties: + '@type': + type: string + description: >- + A URL/resource name that uniquely identifies + the type of the serialized - get transferred to the staker before the - remaining + protocol buffer message. This string must + contain at least - rewards are split across all delegators - moniker: + one "/" character. The last segment of the + URL's path must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name + should be in a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into + the binary all types that they + + expect it to use in the context of Any. + However, for URLs which use the + + scheme `http`, `https`, or no scheme, one + can optionally set up a type + + server that maps type URLs to message + definitions as follows: + + + * If no scheme is provided, `https` is + assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup + results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently + available in the official + + protobuf release, and it is not used for + type URLs beginning with + + type.googleapis.com. As of May 2023, there + are no widely used type server + + implementations and no plans to implement + one. + + + Schemes other than `http`, `https` (or the + empty scheme) might be + + used with implementation specific semantics. + additionalProperties: {} + jailed: + type: boolean + description: >- + jailed defined whether the validator has been + jailed from bonded status or not. + status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). type: string - title: |- - moniker is a human-readable name for displaying - the staker in the UI - website: + enum: + - BOND_STATUS_UNSPECIFIED + - BOND_STATUS_UNBONDED + - BOND_STATUS_UNBONDING + - BOND_STATUS_BONDED + default: BOND_STATUS_UNSPECIFIED + tokens: type: string - title: >- - website is a https-link to the website of the - staker - identity: + description: >- + tokens define the delegated tokens (incl. + self-delegation). + delegator_shares: type: string - title: identity from keybase.io - security_contact: + description: >- + delegator_shares defines total shares issued to + a validator's delegators. + description: + description: >- + description defines the description terms for + the validator. + type: object + properties: + moniker: + type: string + description: >- + moniker defines a human-readable name for + the validator. + identity: + type: string + description: >- + identity defines an optional identity + signature (ex. UPort or Keybase). + website: + type: string + description: website defines an optional website link. + security_contact: + type: string + description: >- + security_contact defines an optional email + for security contact. + details: + type: string + description: details define other optional details. + unbonding_height: type: string - description: security_contact ... - details: + format: int64 + description: >- + unbonding_height defines, if unbonding, the + height at which this validator has begun + unbonding. + unbonding_time: type: string - description: details ... - pending_commission_change: + format: date-time description: >- - pending_commission_change shows if the staker - plans - - to change its commission. Delegators will see a - warning in - - the UI. A Commission change takes some time - until - - the commission is applied. Users have time to - redelegate - - if they not agree with the new commission. + unbonding_time defines, if unbonding, the min + time for the validator to complete unbonding. + commission: + description: commission defines the commission parameters. type: object properties: - commission: - type: string - title: |- - commission is the new commission that will - become active once the change-time is over - creation_date: + commission_rates: + description: >- + commission_rates defines the initial + commission rates to be used for creating a + validator. + type: object + properties: + rate: + type: string + description: >- + rate is the commission rate charged to + delegators, as a fraction. + max_rate: + type: string + description: >- + max_rate defines the maximum commission + rate which validator can ever charge, as + a fraction. + max_change_rate: + type: string + description: >- + max_change_rate defines the maximum + daily increase of the validator + commission, as a fraction. + update_time: type: string - format: int64 + format: date-time description: >- - creation_date is the UNIX-timestamp (in - seconds) + update_time is the last time the commission + rate was changed. + min_self_delegation: + type: string + description: >- + min_self_delegation is the validator's self + declared minimum self delegation. - of when the entry was created. - title: >- - CommissionChangeEntry shows when the old - commission - of a staker will change to the new commission - commission_rewards: + Since: cosmos-sdk 0.46 + unbonding_on_hold_ref_count: + type: string + format: int64 + title: >- + strictly positive if this validator's unbonding + has been stopped by external modules + unbonding_ids: type: array items: - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination and - an amount. - - - NOTE: The amount field is an Int which - implements the custom method - - signatures required by gogoproto. + type: string + format: uint64 title: >- - commission_rewards are the rewards through - commission and storage cost - title: >- - StakerMetadata contains static information for a - staker - self_delegation: - type: string - format: uint64 - title: amount the staker has delegated to himself - self_delegation_unbonding: - type: string - format: uint64 + list of unbonding ids, each uniquely identifing + an unbonding of this validator description: >- - unbonding_amount is the amount the staker is - currently unbonding + Validator defines a validator, together with the + total amount of the - from the self-delegation. + Validator's bond shares and their exchange rate to + coins. Slashing results in - This amount can be larger than `amount` when the - staker + a decrease in the exchange rate, allowing correct + calculation of future - got slashed during unbonding. However, at the end of + undelegations without iterating over delegators. + When coins are delegated to - the unbonding period this amount is double checked - with the + this validator, the validator is credited with a + delegation whose number of - remaining amount. - total_delegation: - type: string - format: uint64 - title: |- - total_delegation returns the sum of all $KYVE users - have delegated to this staker - delegator_count: + bond shares is based on the amount of coins + delegated divided by the current + + exchange rate. Voting power can be calculated as + total bonded shares + + multiplied by exchange rate. + total_pool_stake: type: string format: uint64 - description: |- - delegator_count is the total number of individual - delegator addresses for that user. + title: >- + total_pool_stake returns the amount the validator + has in total + + staked in all his pools pools: type: array items: @@ -7456,10 +8395,10 @@ paths: out of funds no more bundles will be produced - total_delegation: + total_stake: type: string format: uint64 - title: total_delegation of the pool + title: total_stake of the pool status: description: |- status of the pool if pool is able @@ -7514,6 +8453,108 @@ paths: funds to pay for gas fees + commission: + type: string + title: >- + commission is the commission the validator has + chosen for + + this specific pool + pending_commission_change: + description: >- + pending_commission_change shows if the staker + plans + + to change its commission. Delegators will see + a warning in + + the UI. A Commission change takes some time + until + + the commission is applied. Users have time to + redelegate + + if they not agree with the new commission. + type: object + properties: + commission: + type: string + title: |- + commission is the new commission that will + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + CommissionChangeEntry shows when the old + commission + + of a staker will change to the new commission + stake_fraction: + type: string + title: >- + stake fraction is a percentage the validator + has chosen for + + this pool. It is the fraction of how much of + his total stake + + the validator wants to stake in this specific + pool + pending_stake_fraction_change: + description: >- + pending_stake_fraction_change shows if the + staker plans + + to change its stake fraction. Delegators will + see a warning in + + the UI. A stake fraction change takes some + time until + + the stake fraction is applied. Users have time + to redelegate + + if they not agree with the new stake fraction. + type: object + properties: + stake_fraction: + type: string + title: >- + stake_fraction is the new stake_fraction + that will + + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + StakeFractionChangeEntry shows when the old + stake fraction + + of a staker will change to the new stake + fraction + pool_stake: + type: string + format: uint64 + title: >- + pool stake shows the actual amount the + validator has staked + + in this pool. It can be lower than the + specified stake fraction + + because of the max voting power limit title: |- PoolMembership shows in which pool the staker is participating @@ -7775,136 +8816,249 @@ paths: StakersByPool queries for all stakers and sorted them first by number of pools participating and - then by delegation - operationId: StakersByPoolCount - responses: - '200': - description: A successful response. - schema: - type: object - properties: - stakers: - type: array - items: - type: object - properties: - address: - type: string - title: address of the staker - metadata: - description: metadata as logo, moniker, etc. - type: object - properties: - commission: - type: string - title: >- - commission is the percentage of the rewards that - will + then by delegation + operationId: StakersByPoolCount + responses: + '200': + description: A successful response. + schema: + type: object + properties: + stakers: + type: array + items: + type: object + properties: + address: + type: string + title: address of the staker + validator: + type: object + properties: + operator_address: + type: string + description: >- + operator_address defines the address of the + validator's operator; bech encoded in JSON. + consensus_pubkey: + description: >- + consensus_pubkey is the consensus public key of the + validator, as a Protobuf Any. + type: object + properties: + '@type': + type: string + description: >- + A URL/resource name that uniquely identifies the + type of the serialized + + protocol buffer message. This string must + contain at least + + one "/" character. The last segment of the URL's + path must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name + should be in a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the + binary all types that they + + expect it to use in the context of Any. However, + for URLs which use the + + scheme `http`, `https`, or no scheme, one can + optionally set up a type + + server that maps type URLs to message + definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup + results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently + available in the official + + protobuf release, and it is not used for type + URLs beginning with + + type.googleapis.com. As of May 2023, there are + no widely used type server + + implementations and no plans to implement one. - get transferred to the staker before the remaining - rewards are split across all delegators - moniker: + Schemes other than `http`, `https` (or the empty + scheme) might be + + used with implementation specific semantics. + additionalProperties: {} + jailed: + type: boolean + description: >- + jailed defined whether the validator has been jailed + from bonded status or not. + status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). type: string - title: |- - moniker is a human-readable name for displaying - the staker in the UI - website: + enum: + - BOND_STATUS_UNSPECIFIED + - BOND_STATUS_UNBONDED + - BOND_STATUS_UNBONDING + - BOND_STATUS_BONDED + default: BOND_STATUS_UNSPECIFIED + tokens: type: string - title: website is a https-link to the website of the staker - identity: + description: >- + tokens define the delegated tokens (incl. + self-delegation). + delegator_shares: type: string - title: identity from keybase.io - security_contact: + description: >- + delegator_shares defines total shares issued to a + validator's delegators. + description: + description: >- + description defines the description terms for the + validator. + type: object + properties: + moniker: + type: string + description: >- + moniker defines a human-readable name for the + validator. + identity: + type: string + description: >- + identity defines an optional identity signature + (ex. UPort or Keybase). + website: + type: string + description: website defines an optional website link. + security_contact: + type: string + description: >- + security_contact defines an optional email for + security contact. + details: + type: string + description: details define other optional details. + unbonding_height: type: string - description: security_contact ... - details: + format: int64 + description: >- + unbonding_height defines, if unbonding, the height + at which this validator has begun unbonding. + unbonding_time: type: string - description: details ... - pending_commission_change: + format: date-time description: >- - pending_commission_change shows if the staker plans - - to change its commission. Delegators will see a - warning in - - the UI. A Commission change takes some time until - - the commission is applied. Users have time to - redelegate - - if they not agree with the new commission. + unbonding_time defines, if unbonding, the min time + for the validator to complete unbonding. + commission: + description: commission defines the commission parameters. type: object properties: - commission: - type: string - title: |- - commission is the new commission that will - become active once the change-time is over - creation_date: + commission_rates: + description: >- + commission_rates defines the initial commission + rates to be used for creating a validator. + type: object + properties: + rate: + type: string + description: >- + rate is the commission rate charged to + delegators, as a fraction. + max_rate: + type: string + description: >- + max_rate defines the maximum commission rate + which validator can ever charge, as a + fraction. + max_change_rate: + type: string + description: >- + max_change_rate defines the maximum daily + increase of the validator commission, as a + fraction. + update_time: type: string - format: int64 - description: |- - creation_date is the UNIX-timestamp (in seconds) - of when the entry was created. - title: |- - CommissionChangeEntry shows when the old commission - of a staker will change to the new commission - commission_rewards: - type: array - items: - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination and an - amount. - + format: date-time + description: >- + update_time is the last time the commission rate + was changed. + min_self_delegation: + type: string + description: >- + min_self_delegation is the validator's self declared + minimum self delegation. - NOTE: The amount field is an Int which implements - the custom method - signatures required by gogoproto. + Since: cosmos-sdk 0.46 + unbonding_on_hold_ref_count: + type: string + format: int64 title: >- - commission_rewards are the rewards through - commission and storage cost - title: StakerMetadata contains static information for a staker - self_delegation: - type: string - format: uint64 - title: amount the staker has delegated to himself - self_delegation_unbonding: - type: string - format: uint64 + strictly positive if this validator's unbonding has + been stopped by external modules + unbonding_ids: + type: array + items: + type: string + format: uint64 + title: >- + list of unbonding ids, each uniquely identifing an + unbonding of this validator description: >- - unbonding_amount is the amount the staker is currently - unbonding + Validator defines a validator, together with the total + amount of the + + Validator's bond shares and their exchange rate to + coins. Slashing results in + + a decrease in the exchange rate, allowing correct + calculation of future - from the self-delegation. + undelegations without iterating over delegators. When + coins are delegated to - This amount can be larger than `amount` when the staker + this validator, the validator is credited with a + delegation whose number of - got slashed during unbonding. However, at the end of + bond shares is based on the amount of coins delegated + divided by the current - the unbonding period this amount is double checked with - the + exchange rate. Voting power can be calculated as total + bonded shares - remaining amount. - total_delegation: - type: string - format: uint64 - title: |- - total_delegation returns the sum of all $KYVE users - have delegated to this staker - delegator_count: + multiplied by exchange rate. + total_pool_stake: type: string format: uint64 - description: |- - delegator_count is the total number of individual - delegator addresses for that user. + title: >- + total_pool_stake returns the amount the validator has in + total + + staked in all his pools pools: type: array items: @@ -7961,10 +9115,10 @@ paths: title: |- total_funds of the pool. If the pool runs out of funds no more bundles will be produced - total_delegation: + total_stake: type: string format: uint64 - title: total_delegation of the pool + title: total_stake of the pool status: description: |- status of the pool if pool is able @@ -8014,6 +9168,105 @@ paths: funds to pay for gas fees + commission: + type: string + title: >- + commission is the commission the validator has + chosen for + + this specific pool + pending_commission_change: + description: >- + pending_commission_change shows if the staker + plans + + to change its commission. Delegators will see a + warning in + + the UI. A Commission change takes some time until + + the commission is applied. Users have time to + redelegate + + if they not agree with the new commission. + type: object + properties: + commission: + type: string + title: |- + commission is the new commission that will + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + CommissionChangeEntry shows when the old + commission + + of a staker will change to the new commission + stake_fraction: + type: string + title: >- + stake fraction is a percentage the validator has + chosen for + + this pool. It is the fraction of how much of his + total stake + + the validator wants to stake in this specific pool + pending_stake_fraction_change: + description: >- + pending_stake_fraction_change shows if the staker + plans + + to change its stake fraction. Delegators will see + a warning in + + the UI. A stake fraction change takes some time + until + + the stake fraction is applied. Users have time to + redelegate + + if they not agree with the new stake fraction. + type: object + properties: + stake_fraction: + type: string + title: >- + stake_fraction is the new stake_fraction that + will + + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) + + of when the entry was created. + title: >- + StakeFractionChangeEntry shows when the old stake + fraction + + of a staker will change to the new stake fraction + pool_stake: + type: string + format: uint64 + title: >- + pool stake shows the actual amount the validator + has staked + + in this pool. It can be lower than the specified + stake fraction + + because of the max voting power limit title: |- PoolMembership shows in which pool the staker is participating diff --git a/go.mod b/go.mod index 0655627d..f1a0156a 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,6 @@ require ( github.com/cosmos/gogoproto v1.4.12 github.com/cosmos/ibc-go/modules/capability v1.0.0 github.com/cosmos/ibc-go/v8 v8.3.1 - github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.4 github.com/golangci/golangci-lint v1.52.0 github.com/gorilla/mux v1.8.1 @@ -162,6 +161,7 @@ require ( github.com/gofrs/flock v0.8.1 // indirect github.com/gofrs/uuid/v5 v5.0.0 // indirect github.com/gogo/googleapis v1.4.1 // indirect + github.com/gogo/protobuf v1.3.3 // indirect github.com/golang/glog v1.2.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect diff --git a/proto/kyve/query/v1beta1/query.proto b/proto/kyve/query/v1beta1/query.proto index 18a0dd2b..a812a0b2 100644 --- a/proto/kyve/query/v1beta1/query.proto +++ b/proto/kyve/query/v1beta1/query.proto @@ -6,6 +6,7 @@ import "amino/amino.proto"; import "cosmos/base/v1beta1/coin.proto"; import "gogoproto/gogo.proto"; import "kyve/pool/v1beta1/pool.proto"; +import "cosmos/staking/v1beta1/staking.proto"; option go_package = "github.com/KYVENetwork/chain/x/query/types"; @@ -57,8 +58,8 @@ message BasicPool { (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" ]; - // total_delegation of the pool - uint64 total_delegation = 8; + // total_stake of the pool + uint64 total_stake = 8; // status of the pool if pool is able // to produce bundles, etc. @@ -72,80 +73,38 @@ message FullStaker { // address of the staker string address = 1; - // metadata as logo, moniker, etc. - StakerMetadata metadata = 2; + cosmos.staking.v1beta1.Validator validator = 2; - // amount the staker has delegated to himself - uint64 self_delegation = 3; - - // unbonding_amount is the amount the staker is currently unbonding - // from the self-delegation. - // This amount can be larger than `amount` when the staker - // got slashed during unbonding. However, at the end of - // the unbonding period this amount is double checked with the - // remaining amount. - uint64 self_delegation_unbonding = 4; - - // total_delegation returns the sum of all $KYVE users - // have delegated to this staker - uint64 total_delegation = 5; - - // delegator_count is the total number of individual - // delegator addresses for that user. - uint64 delegator_count = 6; + // total_pool_stake returns the amount the validator has in total + // staked in all his pools + uint64 total_pool_stake = 3; // pools is a list of all pools the staker is currently // participating, i.e. allowed to vote and upload data. - repeated PoolMembership pools = 7; + repeated PoolMembership pools = 4; } -// StakerMetadata contains static information for a staker -message StakerMetadata { - // commission is the percentage of the rewards that will - // get transferred to the staker before the remaining - // rewards are split across all delegators +// CommissionChangeEntry shows when the old commission +// of a staker will change to the new commission +message CommissionChangeEntry { + // commission is the new commission that will + // become active once the change-time is over string commission = 1 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false ]; - // moniker is a human-readable name for displaying - // the staker in the UI - string moniker = 2; - - // website is a https-link to the website of the staker - string website = 3; - - // identity from keybase.io - string identity = 4; - - // security_contact ... - string security_contact = 5; - - // details ... - string details = 6; - - // pending_commission_change shows if the staker plans - // to change its commission. Delegators will see a warning in - // the UI. A Commission change takes some time until - // the commission is applied. Users have time to redelegate - // if they not agree with the new commission. - CommissionChangeEntry pending_commission_change = 7; - - // commission_rewards are the rewards through commission and storage cost - repeated cosmos.base.v1beta1.Coin commission_rewards = 8 [ - (gogoproto.nullable) = false, - (amino.dont_omitempty) = true, - (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" - ]; + // creation_date is the UNIX-timestamp (in seconds) + // of when the entry was created. + int64 creation_date = 2; } -// CommissionChangeEntry shows when the old commission -// of a staker will change to the new commission -message CommissionChangeEntry { - // commission is the new commission that will +// StakeFractionChangeEntry shows when the old stake fraction +// of a staker will change to the new stake fraction +message StakeFractionChangeEntry { + // stake_fraction is the new stake_fraction that will // become active once the change-time is over - string commission = 1 [ + string stake_fraction = 1 [ (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", (gogoproto.nullable) = false ]; @@ -181,4 +140,38 @@ message PoolMembership { // whether or not the valaccount needs additional funds to // pay for gas fees uint64 balance = 5; + + // commission is the commission the validator has chosen for + // this specific pool + string commission = 6 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + + // pending_commission_change shows if the staker plans + // to change its commission. Delegators will see a warning in + // the UI. A Commission change takes some time until + // the commission is applied. Users have time to redelegate + // if they not agree with the new commission. + CommissionChangeEntry pending_commission_change = 7; + + // stake fraction is a percentage the validator has chosen for + // this pool. It is the fraction of how much of his total stake + // the validator wants to stake in this specific pool + string stake_fraction = 8 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + + // pending_stake_fraction_change shows if the staker plans + // to change its stake fraction. Delegators will see a warning in + // the UI. A stake fraction change takes some time until + // the stake fraction is applied. Users have time to redelegate + // if they not agree with the new stake fraction. + StakeFractionChangeEntry pending_stake_fraction_change = 9; + + // pool stake shows the actual amount the validator has staked + // in this pool. It can be lower than the specified stake fraction + // because of the max voting power limit + uint64 pool_stake = 10; } diff --git a/x/query/keeper/grpc_account_funded.go b/x/query/keeper/grpc_account_funded.go index 6c562cf5..fe9c04b0 100644 --- a/x/query/keeper/grpc_account_funded.go +++ b/x/query/keeper/grpc_account_funded.go @@ -35,7 +35,7 @@ func (k Keeper) AccountFundedList(goCtx context.Context, req *types.QueryAccount InflationShareWeight: pool.InflationShareWeight, UploadInterval: pool.UploadInterval, TotalFunds: k.fundersKeeper.GetTotalActiveFunding(ctx, pool.Id), - TotalDelegation: k.delegationKeeper.GetDelegationOfPool(ctx, pool.Id), + TotalStake: k.delegationKeeper.GetDelegationOfPool(ctx, pool.Id), Status: k.GetPoolStatus(ctx, &pool), }, }) diff --git a/x/query/keeper/grpc_query_staker.go b/x/query/keeper/grpc_query_staker.go index 7dd1fe11..ddfc323c 100644 --- a/x/query/keeper/grpc_query_staker.go +++ b/x/query/keeper/grpc_query_staker.go @@ -26,7 +26,7 @@ func (k Keeper) Stakers(c context.Context, req *types.QueryStakersRequest) (*typ fullStaker := k.GetFullStaker(ctx, address) searchAddress := strings.ToLower(fullStaker.Address) - searchMoniker := strings.ToLower(fullStaker.Metadata.Moniker) + searchMoniker := strings.ToLower(fullStaker.Validator.GetMoniker()) if strings.Contains(searchAddress, req.Search) || strings.Contains(searchMoniker, req.Search) { if accumulate { @@ -41,7 +41,7 @@ func (k Keeper) Stakers(c context.Context, req *types.QueryStakersRequest) (*typ var pageRes *query.PageResponse var err error - pageRes, err = k.stakerKeeper.GetPaginatedStakersByDelegation(ctx, req.Pagination, accumulator) + pageRes, err = k.stakerKeeper.GetPaginatedStakersByPoolStake(ctx, req.Pagination, accumulator) if err != nil { return nil, err diff --git a/x/query/keeper/helper.go b/x/query/keeper/helper.go index 364183c5..0105ff2f 100644 --- a/x/query/keeper/helper.go +++ b/x/query/keeper/helper.go @@ -8,28 +8,38 @@ import ( ) func (k Keeper) GetFullStaker(ctx sdk.Context, stakerAddress string) *types.FullStaker { - staker, _ := k.stakerKeeper.GetValidator(ctx, stakerAddress) - - stakerMetadata := types.StakerMetadata{ - Commission: staker.Commission.Rate, - Moniker: staker.GetMoniker(), - Website: staker.Description.Website, - Identity: staker.Description.Identity, - SecurityContact: staker.Description.SecurityContact, - Details: staker.Description.GetDetails(), - PendingCommissionChange: nil, - CommissionRewards: sdk.NewCoins(), - } + validator, _ := k.stakerKeeper.GetValidator(ctx, stakerAddress) var poolMemberships []*types.PoolMembership + totalPoolStake := uint64(0) for _, valaccount := range k.stakerKeeper.GetValaccountsFromStaker(ctx, stakerAddress) { - pool, _ := k.poolKeeper.GetPool(ctx, valaccount.PoolId) accountValaddress, _ := sdk.AccAddressFromBech32(valaccount.Valaddress) balanceValaccount := k.bankKeeper.GetBalance(ctx, accountValaddress, globalTypes.Denom).Amount.Uint64() + commissionChange, found := k.stakerKeeper.GetCommissionChangeEntryByIndex2(ctx, stakerAddress, valaccount.PoolId) + var commissionChangeEntry *types.CommissionChangeEntry = nil + if found { + commissionChangeEntry = &types.CommissionChangeEntry{ + Commission: commissionChange.Commission, + CreationDate: commissionChange.CreationDate, + } + } + + stakeFractionChange, found := k.stakerKeeper.GetStakeFractionChangeEntryByIndex2(ctx, stakerAddress, valaccount.PoolId) + var stakeFractionChangeEntry *types.StakeFractionChangeEntry = nil + if found { + stakeFractionChangeEntry = &types.StakeFractionChangeEntry{ + StakeFraction: stakeFractionChange.StakeFraction, + CreationDate: stakeFractionChange.CreationDate, + } + } + + poolStake := k.stakerKeeper.GetValidatorPoolStake(ctx, stakerAddress, pool.Id) + totalPoolStake += poolStake + poolMemberships = append( poolMemberships, &types.PoolMembership{ Pool: &types.BasicPool{ @@ -40,29 +50,27 @@ func (k Keeper) GetFullStaker(ctx sdk.Context, stakerAddress string) *types.Full InflationShareWeight: pool.InflationShareWeight, UploadInterval: pool.UploadInterval, TotalFunds: k.fundersKeeper.GetTotalActiveFunding(ctx, pool.Id), - TotalDelegation: k.stakerKeeper.GetTotalStakeOfPool(ctx, pool.Id), + TotalStake: k.stakerKeeper.GetTotalStakeOfPool(ctx, pool.Id), Status: k.GetPoolStatus(ctx, &pool), }, - Points: valaccount.Points, - IsLeaving: valaccount.IsLeaving, - Valaddress: valaccount.Valaddress, - Balance: balanceValaccount, + Points: valaccount.Points, + IsLeaving: valaccount.IsLeaving, + Valaddress: valaccount.Valaddress, + Balance: balanceValaccount, + Commission: valaccount.Commission, + PendingCommissionChange: commissionChangeEntry, + StakeFraction: valaccount.StakeFraction, + PendingStakeFractionChange: stakeFractionChangeEntry, + PoolStake: poolStake, }, ) } - // Iterate all UnbondingDelegation entries to get total delegation unbonding amount - selfDelegationUnbonding := uint64(0) - // TODO rework query spec - return &types.FullStaker{ - Address: stakerAddress, - Metadata: &stakerMetadata, - SelfDelegation: uint64(0), // TODO rework query spec - SelfDelegationUnbonding: selfDelegationUnbonding, - TotalDelegation: staker.Tokens.Uint64(), - DelegatorCount: 0, // TODO rework query spec - Pools: poolMemberships, + Address: stakerAddress, + Validator: &validator, + TotalPoolStake: totalPoolStake, + Pools: poolMemberships, } } diff --git a/x/query/types/query.pb.go b/x/query/types/query.pb.go index d1e5a6c1..4e07f51c 100644 --- a/x/query/types/query.pb.go +++ b/x/query/types/query.pb.go @@ -10,6 +10,7 @@ import ( github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + types2 "github.com/cosmos/cosmos-sdk/x/staking/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" @@ -47,8 +48,8 @@ type BasicPool struct { // total_funds of the pool. If the pool runs // out of funds no more bundles will be produced TotalFunds github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,7,rep,name=total_funds,json=totalFunds,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"total_funds"` - // total_delegation of the pool - TotalDelegation uint64 `protobuf:"varint,8,opt,name=total_delegation,json=totalDelegation,proto3" json:"total_delegation,omitempty"` + // total_stake of the pool + TotalStake uint64 `protobuf:"varint,8,opt,name=total_stake,json=totalStake,proto3" json:"total_stake,omitempty"` // status of the pool if pool is able // to produce bundles, etc. Status types1.PoolStatus `protobuf:"varint,9,opt,name=status,proto3,enum=kyve.pool.v1beta1.PoolStatus" json:"status,omitempty"` @@ -129,9 +130,9 @@ func (m *BasicPool) GetTotalFunds() github_com_cosmos_cosmos_sdk_types.Coins { return nil } -func (m *BasicPool) GetTotalDelegation() uint64 { +func (m *BasicPool) GetTotalStake() uint64 { if m != nil { - return m.TotalDelegation + return m.TotalStake } return 0 } @@ -148,27 +149,14 @@ func (m *BasicPool) GetStatus() types1.PoolStatus { // It contains almost all needed information for a convenient usage type FullStaker struct { // address of the staker - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - // metadata as logo, moniker, etc. - Metadata *StakerMetadata `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"` - // amount the staker has delegated to himself - SelfDelegation uint64 `protobuf:"varint,3,opt,name=self_delegation,json=selfDelegation,proto3" json:"self_delegation,omitempty"` - // unbonding_amount is the amount the staker is currently unbonding - // from the self-delegation. - // This amount can be larger than `amount` when the staker - // got slashed during unbonding. However, at the end of - // the unbonding period this amount is double checked with the - // remaining amount. - SelfDelegationUnbonding uint64 `protobuf:"varint,4,opt,name=self_delegation_unbonding,json=selfDelegationUnbonding,proto3" json:"self_delegation_unbonding,omitempty"` - // total_delegation returns the sum of all $KYVE users - // have delegated to this staker - TotalDelegation uint64 `protobuf:"varint,5,opt,name=total_delegation,json=totalDelegation,proto3" json:"total_delegation,omitempty"` - // delegator_count is the total number of individual - // delegator addresses for that user. - DelegatorCount uint64 `protobuf:"varint,6,opt,name=delegator_count,json=delegatorCount,proto3" json:"delegator_count,omitempty"` + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Validator *types2.Validator `protobuf:"bytes,2,opt,name=validator,proto3" json:"validator,omitempty"` + // total_pool_stake returns the amount the validator has in total + // staked in all his pools + TotalPoolStake uint64 `protobuf:"varint,3,opt,name=total_pool_stake,json=totalPoolStake,proto3" json:"total_pool_stake,omitempty"` // pools is a list of all pools the staker is currently // participating, i.e. allowed to vote and upload data. - Pools []*PoolMembership `protobuf:"bytes,7,rep,name=pools,proto3" json:"pools,omitempty"` + Pools []*PoolMembership `protobuf:"bytes,4,rep,name=pools,proto3" json:"pools,omitempty"` } func (m *FullStaker) Reset() { *m = FullStaker{} } @@ -211,37 +199,16 @@ func (m *FullStaker) GetAddress() string { return "" } -func (m *FullStaker) GetMetadata() *StakerMetadata { +func (m *FullStaker) GetValidator() *types2.Validator { if m != nil { - return m.Metadata + return m.Validator } return nil } -func (m *FullStaker) GetSelfDelegation() uint64 { +func (m *FullStaker) GetTotalPoolStake() uint64 { if m != nil { - return m.SelfDelegation - } - return 0 -} - -func (m *FullStaker) GetSelfDelegationUnbonding() uint64 { - if m != nil { - return m.SelfDelegationUnbonding - } - return 0 -} - -func (m *FullStaker) GetTotalDelegation() uint64 { - if m != nil { - return m.TotalDelegation - } - return 0 -} - -func (m *FullStaker) GetDelegatorCount() uint64 { - if m != nil { - return m.DelegatorCount + return m.TotalPoolStake } return 0 } @@ -253,45 +220,29 @@ func (m *FullStaker) GetPools() []*PoolMembership { return nil } -// StakerMetadata contains static information for a staker -type StakerMetadata struct { - // commission is the percentage of the rewards that will - // get transferred to the staker before the remaining - // rewards are split across all delegators +// CommissionChangeEntry shows when the old commission +// of a staker will change to the new commission +type CommissionChangeEntry struct { + // commission is the new commission that will + // become active once the change-time is over Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,1,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` - // moniker is a human-readable name for displaying - // the staker in the UI - Moniker string `protobuf:"bytes,2,opt,name=moniker,proto3" json:"moniker,omitempty"` - // website is a https-link to the website of the staker - Website string `protobuf:"bytes,3,opt,name=website,proto3" json:"website,omitempty"` - // identity from keybase.io - Identity string `protobuf:"bytes,4,opt,name=identity,proto3" json:"identity,omitempty"` - // security_contact ... - SecurityContact string `protobuf:"bytes,5,opt,name=security_contact,json=securityContact,proto3" json:"security_contact,omitempty"` - // details ... - Details string `protobuf:"bytes,6,opt,name=details,proto3" json:"details,omitempty"` - // pending_commission_change shows if the staker plans - // to change its commission. Delegators will see a warning in - // the UI. A Commission change takes some time until - // the commission is applied. Users have time to redelegate - // if they not agree with the new commission. - PendingCommissionChange *CommissionChangeEntry `protobuf:"bytes,7,opt,name=pending_commission_change,json=pendingCommissionChange,proto3" json:"pending_commission_change,omitempty"` - // commission_rewards are the rewards through commission and storage cost - CommissionRewards github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,8,rep,name=commission_rewards,json=commissionRewards,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"commission_rewards"` + // creation_date is the UNIX-timestamp (in seconds) + // of when the entry was created. + CreationDate int64 `protobuf:"varint,2,opt,name=creation_date,json=creationDate,proto3" json:"creation_date,omitempty"` } -func (m *StakerMetadata) Reset() { *m = StakerMetadata{} } -func (m *StakerMetadata) String() string { return proto.CompactTextString(m) } -func (*StakerMetadata) ProtoMessage() {} -func (*StakerMetadata) Descriptor() ([]byte, []int) { +func (m *CommissionChangeEntry) Reset() { *m = CommissionChangeEntry{} } +func (m *CommissionChangeEntry) String() string { return proto.CompactTextString(m) } +func (*CommissionChangeEntry) ProtoMessage() {} +func (*CommissionChangeEntry) Descriptor() ([]byte, []int) { return fileDescriptor_6b41255feae93a15, []int{2} } -func (m *StakerMetadata) XXX_Unmarshal(b []byte) error { +func (m *CommissionChangeEntry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *StakerMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *CommissionChangeEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_StakerMetadata.Marshal(b, m, deterministic) + return xxx_messageInfo_CommissionChangeEntry.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -301,90 +252,48 @@ func (m *StakerMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, erro return b[:n], nil } } -func (m *StakerMetadata) XXX_Merge(src proto.Message) { - xxx_messageInfo_StakerMetadata.Merge(m, src) +func (m *CommissionChangeEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommissionChangeEntry.Merge(m, src) } -func (m *StakerMetadata) XXX_Size() int { +func (m *CommissionChangeEntry) XXX_Size() int { return m.Size() } -func (m *StakerMetadata) XXX_DiscardUnknown() { - xxx_messageInfo_StakerMetadata.DiscardUnknown(m) -} - -var xxx_messageInfo_StakerMetadata proto.InternalMessageInfo - -func (m *StakerMetadata) GetMoniker() string { - if m != nil { - return m.Moniker - } - return "" -} - -func (m *StakerMetadata) GetWebsite() string { - if m != nil { - return m.Website - } - return "" -} - -func (m *StakerMetadata) GetIdentity() string { - if m != nil { - return m.Identity - } - return "" -} - -func (m *StakerMetadata) GetSecurityContact() string { - if m != nil { - return m.SecurityContact - } - return "" -} - -func (m *StakerMetadata) GetDetails() string { - if m != nil { - return m.Details - } - return "" +func (m *CommissionChangeEntry) XXX_DiscardUnknown() { + xxx_messageInfo_CommissionChangeEntry.DiscardUnknown(m) } -func (m *StakerMetadata) GetPendingCommissionChange() *CommissionChangeEntry { - if m != nil { - return m.PendingCommissionChange - } - return nil -} +var xxx_messageInfo_CommissionChangeEntry proto.InternalMessageInfo -func (m *StakerMetadata) GetCommissionRewards() github_com_cosmos_cosmos_sdk_types.Coins { +func (m *CommissionChangeEntry) GetCreationDate() int64 { if m != nil { - return m.CommissionRewards + return m.CreationDate } - return nil + return 0 } -// CommissionChangeEntry shows when the old commission -// of a staker will change to the new commission -type CommissionChangeEntry struct { - // commission is the new commission that will +// StakeFractionChangeEntry shows when the old stake fraction +// of a staker will change to the new stake fraction +type StakeFractionChangeEntry struct { + // stake_fraction is the new stake_fraction that will // become active once the change-time is over - Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,1,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` + StakeFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,1,opt,name=stake_fraction,json=stakeFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"stake_fraction"` // creation_date is the UNIX-timestamp (in seconds) // of when the entry was created. CreationDate int64 `protobuf:"varint,2,opt,name=creation_date,json=creationDate,proto3" json:"creation_date,omitempty"` } -func (m *CommissionChangeEntry) Reset() { *m = CommissionChangeEntry{} } -func (m *CommissionChangeEntry) String() string { return proto.CompactTextString(m) } -func (*CommissionChangeEntry) ProtoMessage() {} -func (*CommissionChangeEntry) Descriptor() ([]byte, []int) { +func (m *StakeFractionChangeEntry) Reset() { *m = StakeFractionChangeEntry{} } +func (m *StakeFractionChangeEntry) String() string { return proto.CompactTextString(m) } +func (*StakeFractionChangeEntry) ProtoMessage() {} +func (*StakeFractionChangeEntry) Descriptor() ([]byte, []int) { return fileDescriptor_6b41255feae93a15, []int{3} } -func (m *CommissionChangeEntry) XXX_Unmarshal(b []byte) error { +func (m *StakeFractionChangeEntry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *CommissionChangeEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *StakeFractionChangeEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_CommissionChangeEntry.Marshal(b, m, deterministic) + return xxx_messageInfo_StakeFractionChangeEntry.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -394,19 +303,19 @@ func (m *CommissionChangeEntry) XXX_Marshal(b []byte, deterministic bool) ([]byt return b[:n], nil } } -func (m *CommissionChangeEntry) XXX_Merge(src proto.Message) { - xxx_messageInfo_CommissionChangeEntry.Merge(m, src) +func (m *StakeFractionChangeEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_StakeFractionChangeEntry.Merge(m, src) } -func (m *CommissionChangeEntry) XXX_Size() int { +func (m *StakeFractionChangeEntry) XXX_Size() int { return m.Size() } -func (m *CommissionChangeEntry) XXX_DiscardUnknown() { - xxx_messageInfo_CommissionChangeEntry.DiscardUnknown(m) +func (m *StakeFractionChangeEntry) XXX_DiscardUnknown() { + xxx_messageInfo_StakeFractionChangeEntry.DiscardUnknown(m) } -var xxx_messageInfo_CommissionChangeEntry proto.InternalMessageInfo +var xxx_messageInfo_StakeFractionChangeEntry proto.InternalMessageInfo -func (m *CommissionChangeEntry) GetCreationDate() int64 { +func (m *StakeFractionChangeEntry) GetCreationDate() int64 { if m != nil { return m.CreationDate } @@ -435,6 +344,29 @@ type PoolMembership struct { // whether or not the valaccount needs additional funds to // pay for gas fees Balance uint64 `protobuf:"varint,5,opt,name=balance,proto3" json:"balance,omitempty"` + // commission is the commission the validator has chosen for + // this specific pool + Commission cosmossdk_io_math.LegacyDec `protobuf:"bytes,6,opt,name=commission,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"commission"` + // pending_commission_change shows if the staker plans + // to change its commission. Delegators will see a warning in + // the UI. A Commission change takes some time until + // the commission is applied. Users have time to redelegate + // if they not agree with the new commission. + PendingCommissionChange *CommissionChangeEntry `protobuf:"bytes,7,opt,name=pending_commission_change,json=pendingCommissionChange,proto3" json:"pending_commission_change,omitempty"` + // stake fraction is a percentage the validator has chosen for + // this pool. It is the fraction of how much of his total stake + // the validator wants to stake in this specific pool + StakeFraction cosmossdk_io_math.LegacyDec `protobuf:"bytes,8,opt,name=stake_fraction,json=stakeFraction,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"stake_fraction"` + // pending_stake_fraction_change shows if the staker plans + // to change its stake fraction. Delegators will see a warning in + // the UI. A stake fraction change takes some time until + // the stake fraction is applied. Users have time to redelegate + // if they not agree with the new stake fraction. + PendingStakeFractionChange *StakeFractionChangeEntry `protobuf:"bytes,9,opt,name=pending_stake_fraction_change,json=pendingStakeFractionChange,proto3" json:"pending_stake_fraction_change,omitempty"` + // pool stake shows the actual amount the validator has staked + // in this pool. It can be lower than the specified stake fraction + // because of the max voting power limit + PoolStake uint64 `protobuf:"varint,10,opt,name=pool_stake,json=poolStake,proto3" json:"pool_stake,omitempty"` } func (m *PoolMembership) Reset() { *m = PoolMembership{} } @@ -505,73 +437,91 @@ func (m *PoolMembership) GetBalance() uint64 { return 0 } +func (m *PoolMembership) GetPendingCommissionChange() *CommissionChangeEntry { + if m != nil { + return m.PendingCommissionChange + } + return nil +} + +func (m *PoolMembership) GetPendingStakeFractionChange() *StakeFractionChangeEntry { + if m != nil { + return m.PendingStakeFractionChange + } + return nil +} + +func (m *PoolMembership) GetPoolStake() uint64 { + if m != nil { + return m.PoolStake + } + return 0 +} + func init() { proto.RegisterType((*BasicPool)(nil), "kyve.query.v1beta1.BasicPool") proto.RegisterType((*FullStaker)(nil), "kyve.query.v1beta1.FullStaker") - proto.RegisterType((*StakerMetadata)(nil), "kyve.query.v1beta1.StakerMetadata") proto.RegisterType((*CommissionChangeEntry)(nil), "kyve.query.v1beta1.CommissionChangeEntry") + proto.RegisterType((*StakeFractionChangeEntry)(nil), "kyve.query.v1beta1.StakeFractionChangeEntry") proto.RegisterType((*PoolMembership)(nil), "kyve.query.v1beta1.PoolMembership") } func init() { proto.RegisterFile("kyve/query/v1beta1/query.proto", fileDescriptor_6b41255feae93a15) } var fileDescriptor_6b41255feae93a15 = []byte{ - // 871 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xcf, 0xc6, 0x4e, 0x62, 0x4f, 0xc0, 0xa1, 0xa3, 0xd2, 0x6e, 0x02, 0xdd, 0x44, 0xee, 0xa1, - 0x6e, 0x25, 0x76, 0x95, 0xa0, 0x4a, 0x88, 0x03, 0x87, 0x38, 0xad, 0x84, 0x68, 0x11, 0x9a, 0x0a, - 0x50, 0xb9, 0xac, 0x66, 0x77, 0x5f, 0xd6, 0x23, 0xef, 0xce, 0xb8, 0x3b, 0xb3, 0x0e, 0x3e, 0x21, - 0xbe, 0x01, 0x1f, 0x03, 0x71, 0xe2, 0x80, 0xf8, 0x0c, 0x3d, 0x56, 0x9c, 0x80, 0x43, 0x41, 0xc9, - 0x81, 0xaf, 0x81, 0xe6, 0xcf, 0x6e, 0xed, 0xe2, 0x03, 0x07, 0xb8, 0xd8, 0xf3, 0x7e, 0xef, 0xef, - 0xfc, 0xde, 0x7b, 0xb3, 0x28, 0x98, 0x2e, 0xe6, 0x10, 0x3d, 0xab, 0xa1, 0x5a, 0x44, 0xf3, 0xe3, - 0x04, 0x14, 0x3d, 0xb6, 0x52, 0x38, 0xab, 0x84, 0x12, 0x18, 0x6b, 0x7d, 0x68, 0x11, 0xa7, 0x3f, - 0xb8, 0x46, 0x4b, 0xc6, 0x45, 0x64, 0x7e, 0xad, 0xd9, 0x41, 0x90, 0x0a, 0x59, 0x0a, 0x19, 0x25, - 0x54, 0x42, 0x1b, 0x27, 0x15, 0x8c, 0x3b, 0xfd, 0xf5, 0x5c, 0xe4, 0xc2, 0x1c, 0x23, 0x7d, 0x72, - 0xe8, 0xbb, 0x26, 0xf9, 0x4c, 0x88, 0xa2, 0xf5, 0xd1, 0x82, 0xd5, 0x0e, 0x7f, 0xee, 0xa0, 0xfe, - 0x29, 0x95, 0x2c, 0xfd, 0x4c, 0x88, 0x02, 0x0f, 0xd0, 0x26, 0xcb, 0x7c, 0xef, 0xc8, 0x1b, 0x75, - 0xc9, 0x26, 0xcb, 0x30, 0x46, 0x5d, 0x4e, 0x4b, 0xf0, 0x37, 0x8f, 0xbc, 0x51, 0x9f, 0x98, 0x33, - 0xf6, 0xd1, 0x4e, 0x55, 0x73, 0xc5, 0x4a, 0xf0, 0x3b, 0x06, 0x6e, 0x44, 0x6d, 0x5d, 0x88, 0x5c, - 0xf8, 0x5d, 0x6b, 0xad, 0xcf, 0xf8, 0x29, 0xba, 0xc1, 0xf8, 0x79, 0x41, 0x15, 0x13, 0x3c, 0x96, - 0x13, 0x5a, 0x41, 0x7c, 0x01, 0x2c, 0x9f, 0x28, 0x7f, 0x4b, 0x5b, 0x9d, 0xde, 0x7e, 0xfe, 0xf2, - 0x70, 0xe3, 0xf7, 0x97, 0x87, 0xef, 0xd8, 0xbb, 0xc9, 0x6c, 0x1a, 0x32, 0x11, 0x95, 0x54, 0x4d, - 0xc2, 0x47, 0x90, 0xd3, 0x74, 0x71, 0x06, 0x29, 0xb9, 0xde, 0x86, 0x78, 0xa2, 0x23, 0x7c, 0x69, - 0x02, 0xe0, 0x3b, 0x68, 0xaf, 0x9e, 0x15, 0x82, 0x66, 0x31, 0xe3, 0x0a, 0xaa, 0x39, 0x2d, 0xfc, - 0x6d, 0x53, 0xf9, 0xc0, 0xc2, 0x1f, 0x3b, 0x14, 0x3f, 0x43, 0xbb, 0x4a, 0x28, 0x5a, 0xc4, 0xe7, - 0x35, 0xcf, 0xa4, 0xbf, 0x73, 0xd4, 0x19, 0xed, 0x9e, 0xec, 0x87, 0x36, 0x63, 0xa8, 0xd9, 0x6c, - 0x58, 0x0f, 0xc7, 0x82, 0xf1, 0xd3, 0xfb, 0xba, 0xa6, 0x1f, 0xfe, 0x38, 0x1c, 0xe5, 0x4c, 0x4d, - 0xea, 0x24, 0x4c, 0x45, 0x19, 0x39, 0xea, 0xed, 0xdf, 0x7b, 0x32, 0x9b, 0x46, 0x6a, 0x31, 0x03, - 0x69, 0x1c, 0xe4, 0xf7, 0x7f, 0xfd, 0x78, 0xcf, 0x23, 0xc8, 0x24, 0x79, 0xa8, 0x73, 0xe0, 0xbb, - 0xe8, 0x2d, 0x9b, 0x32, 0x83, 0x02, 0x72, 0x53, 0xba, 0xdf, 0x33, 0xc5, 0xed, 0x19, 0xfc, 0xac, - 0x85, 0xf1, 0x7d, 0xb4, 0x2d, 0x15, 0x55, 0xb5, 0xf4, 0xfb, 0x47, 0xde, 0x68, 0x70, 0x72, 0x2b, - 0x34, 0xd3, 0x60, 0x7a, 0xd4, 0x94, 0xa5, 0x9b, 0xf3, 0xc4, 0x18, 0x11, 0x67, 0x3c, 0xfc, 0x6d, - 0x13, 0xa1, 0x87, 0x75, 0xa1, 0xe1, 0x29, 0x54, 0xba, 0x2b, 0x34, 0xcb, 0x2a, 0x90, 0xd2, 0xb4, - 0xaf, 0x4f, 0x1a, 0x11, 0x7f, 0x84, 0x7a, 0x25, 0x28, 0x9a, 0x51, 0x45, 0x4d, 0x1f, 0x77, 0x4f, - 0x86, 0xe1, 0x3f, 0xe7, 0x2d, 0xb4, 0x71, 0x1e, 0x3b, 0x4b, 0xd2, 0xfa, 0x68, 0x9a, 0x25, 0x14, - 0xe7, 0xcb, 0x37, 0xe9, 0x58, 0x9a, 0x35, 0xbc, 0x74, 0x91, 0x0f, 0xd1, 0xfe, 0x6b, 0x86, 0x71, - 0xcd, 0x13, 0xc1, 0x33, 0xc6, 0x73, 0x33, 0x13, 0x5d, 0x72, 0x73, 0xd5, 0xe5, 0xf3, 0x46, 0xbd, - 0x96, 0xaf, 0xad, 0xf5, 0x7c, 0xdd, 0x41, 0x7b, 0xce, 0x48, 0x54, 0x71, 0x2a, 0x6a, 0xae, 0x9a, - 0xb6, 0xb7, 0xf0, 0x58, 0xa3, 0xf8, 0x03, 0xb4, 0xa5, 0x49, 0x6c, 0x1a, 0xbe, 0xf6, 0xd6, 0x9a, - 0xd8, 0xc7, 0x50, 0x26, 0x50, 0xc9, 0x09, 0x9b, 0x11, 0xeb, 0x30, 0xfc, 0xa5, 0x83, 0x06, 0xab, - 0x7c, 0xe0, 0x31, 0x42, 0xa9, 0x28, 0x4b, 0x26, 0xa5, 0x2e, 0xcd, 0xfb, 0xf7, 0xb3, 0xbb, 0xe4, - 0xa6, 0x9b, 0x54, 0x0a, 0xce, 0xa6, 0x50, 0xb9, 0x8d, 0x6a, 0x44, 0xad, 0xb9, 0x80, 0x44, 0x32, - 0xd5, 0x2e, 0x95, 0x13, 0xf1, 0x01, 0xea, 0xb1, 0x0c, 0xb8, 0x62, 0x6a, 0xe1, 0x16, 0xab, 0x95, - 0x35, 0x6b, 0x12, 0xd2, 0xba, 0x62, 0x6a, 0x11, 0xa7, 0x82, 0x2b, 0x9a, 0xba, 0xb5, 0x22, 0x7b, - 0x0d, 0x3e, 0xb6, 0xb0, 0x4e, 0x90, 0x81, 0xa2, 0xac, 0x90, 0x86, 0xad, 0x3e, 0x69, 0x44, 0x0c, - 0x68, 0x7f, 0x06, 0xa6, 0x0b, 0xf1, 0xab, 0x52, 0xe3, 0x74, 0x42, 0x79, 0x0e, 0xfe, 0x8e, 0x19, - 0x98, 0xbb, 0xeb, 0xa8, 0x1b, 0xb7, 0xc6, 0x63, 0x63, 0xfb, 0x80, 0xab, 0x6a, 0x41, 0x6e, 0xba, - 0x58, 0xaf, 0x6b, 0xf1, 0x37, 0x08, 0x2f, 0x85, 0xaf, 0xe0, 0x82, 0x56, 0x99, 0xf4, 0x7b, 0xff, - 0xd3, 0x2e, 0x5e, 0x7b, 0x95, 0x8b, 0xd8, 0x54, 0xc3, 0x6f, 0x3d, 0xf4, 0xf6, 0xda, 0x9a, 0xff, - 0x9b, 0xde, 0xde, 0x46, 0x6f, 0xa6, 0x15, 0xd8, 0xb1, 0xcf, 0xa8, 0xb2, 0x6f, 0x66, 0x87, 0xbc, - 0xd1, 0x80, 0x67, 0x54, 0xc1, 0xf0, 0x27, 0x0f, 0x0d, 0x56, 0x47, 0x0e, 0x1f, 0xa3, 0xae, 0x1e, - 0x3a, 0x93, 0x76, 0xb7, 0x59, 0xfe, 0x55, 0xa6, 0xdb, 0xf7, 0x99, 0x18, 0x53, 0x7c, 0x03, 0x6d, - 0xcf, 0x04, 0xe3, 0x4a, 0x9a, 0x1c, 0x5d, 0xe2, 0x24, 0x7c, 0x0b, 0x21, 0x26, 0xe3, 0x02, 0xe8, - 0x5c, 0x6f, 0x9c, 0x9e, 0xa3, 0x1e, 0xe9, 0x33, 0xf9, 0xc8, 0x02, 0x38, 0x40, 0x68, 0x4e, 0x8b, - 0xe6, 0x95, 0xb0, 0xb3, 0xb4, 0x84, 0xe8, 0x11, 0x49, 0x68, 0x41, 0x79, 0x0a, 0x6e, 0xf5, 0x1a, - 0xf1, 0xf4, 0xec, 0xf9, 0x65, 0xe0, 0xbd, 0xb8, 0x0c, 0xbc, 0x3f, 0x2f, 0x03, 0xef, 0xbb, 0xab, - 0x60, 0xe3, 0xc5, 0x55, 0xb0, 0xf1, 0xeb, 0x55, 0xb0, 0xf1, 0xd5, 0xbd, 0xa5, 0xb6, 0x7c, 0xf2, - 0xf4, 0x8b, 0x07, 0x9f, 0x82, 0xba, 0x10, 0xd5, 0x34, 0x4a, 0x27, 0x94, 0xf1, 0xe8, 0x6b, 0xf7, - 0xcd, 0x33, 0xed, 0x49, 0xb6, 0xcd, 0x17, 0xe7, 0xfd, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xea, - 0xce, 0x18, 0xb8, 0x0e, 0x07, 0x00, 0x00, + // 825 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0x4f, 0x6f, 0xe3, 0x44, + 0x14, 0x8f, 0x1b, 0x6f, 0x5a, 0x4f, 0xd8, 0x00, 0xa3, 0x65, 0xf1, 0x16, 0xea, 0x84, 0x2c, 0x12, + 0x61, 0x05, 0xb6, 0x5a, 0xb4, 0x12, 0x37, 0xa4, 0xa4, 0x5b, 0x09, 0x58, 0x10, 0x72, 0xa5, 0x45, + 0xcb, 0xc5, 0x9a, 0xd8, 0x53, 0x67, 0x14, 0x7b, 0xc6, 0xf5, 0x4c, 0x52, 0x72, 0xe4, 0xcc, 0x85, + 0x8f, 0x81, 0x10, 0x07, 0x3e, 0x00, 0x1f, 0xa0, 0x12, 0x97, 0x1e, 0x11, 0x87, 0x82, 0xda, 0x03, + 0x5f, 0x03, 0xcd, 0xbf, 0x34, 0x2d, 0x41, 0x2a, 0xbd, 0xb4, 0xf3, 0xde, 0xfb, 0xcd, 0x7b, 0xbf, + 0xf7, 0x7e, 0x6f, 0x62, 0x10, 0x4c, 0x17, 0x73, 0x1c, 0x1d, 0xcf, 0x70, 0xbd, 0x88, 0xe6, 0xbb, + 0x63, 0x2c, 0xd0, 0xae, 0xb6, 0xc2, 0xaa, 0x66, 0x82, 0x41, 0x28, 0xe3, 0xa1, 0xf6, 0x98, 0xf8, + 0xf6, 0xeb, 0xa8, 0x24, 0x94, 0x45, 0xea, 0xaf, 0x86, 0x6d, 0x07, 0x29, 0xe3, 0x25, 0xe3, 0xd1, + 0x18, 0x71, 0xbc, 0xcc, 0x93, 0x32, 0x42, 0x4d, 0xfc, 0x41, 0xce, 0x72, 0xa6, 0x8e, 0x91, 0x3c, + 0x19, 0xef, 0xdb, 0xaa, 0x78, 0xc5, 0x58, 0xb1, 0xbc, 0x23, 0x0d, 0x13, 0x7d, 0xd7, 0xe4, 0xe4, + 0x02, 0x4d, 0x09, 0xcd, 0x97, 0x10, 0x63, 0x6b, 0x54, 0xff, 0xe7, 0x26, 0xf0, 0x86, 0x88, 0x93, + 0xf4, 0x2b, 0xc6, 0x0a, 0xd8, 0x01, 0x1b, 0x24, 0xf3, 0x9d, 0x9e, 0x33, 0x70, 0xe3, 0x0d, 0x92, + 0x41, 0x08, 0x5c, 0x8a, 0x4a, 0xec, 0x6f, 0xf4, 0x9c, 0x81, 0x17, 0xab, 0x33, 0xf4, 0xc1, 0x66, + 0x3d, 0xa3, 0x82, 0x94, 0xd8, 0x6f, 0x2a, 0xb7, 0x35, 0x25, 0xba, 0x60, 0x39, 0xf3, 0x5d, 0x8d, + 0x96, 0x67, 0xf8, 0x12, 0x3c, 0x24, 0xf4, 0xa8, 0x40, 0x82, 0x30, 0x9a, 0xf0, 0x09, 0xaa, 0x71, + 0x72, 0x82, 0x49, 0x3e, 0x11, 0xfe, 0x3d, 0x89, 0x1a, 0x3e, 0x3e, 0x3d, 0xef, 0x36, 0xfe, 0x38, + 0xef, 0xbe, 0xa5, 0xd9, 0xf2, 0x6c, 0x1a, 0x12, 0x16, 0x95, 0x48, 0x4c, 0xc2, 0xe7, 0x38, 0x47, + 0xe9, 0x62, 0x1f, 0xa7, 0xf1, 0x83, 0x65, 0x8a, 0x43, 0x99, 0xe1, 0x6b, 0x95, 0x00, 0xbe, 0x07, + 0x5e, 0x9d, 0x55, 0x05, 0x43, 0x59, 0x42, 0xa8, 0xc0, 0xf5, 0x1c, 0x15, 0x7e, 0x4b, 0x31, 0xef, + 0x68, 0xf7, 0xa7, 0xc6, 0x0b, 0x8f, 0x41, 0x5b, 0x30, 0x81, 0x8a, 0xe4, 0x68, 0x46, 0x33, 0xee, + 0x6f, 0xf6, 0x9a, 0x83, 0xf6, 0xde, 0xa3, 0x50, 0x57, 0x0c, 0xe5, 0xcc, 0xad, 0x36, 0xe1, 0x88, + 0x11, 0x3a, 0x7c, 0x2a, 0x39, 0xfd, 0xf4, 0x67, 0x77, 0x90, 0x13, 0x31, 0x99, 0x8d, 0xc3, 0x94, + 0x95, 0x91, 0x19, 0xa6, 0xfe, 0xf7, 0x21, 0xcf, 0xa6, 0x91, 0x58, 0x54, 0x98, 0xab, 0x0b, 0xfc, + 0xc7, 0xbf, 0x7f, 0x79, 0xe2, 0xc4, 0x40, 0x15, 0x39, 0x90, 0x35, 0x60, 0xd7, 0x96, 0x94, 0xd3, + 0xc6, 0xfe, 0x96, 0xe2, 0xa5, 0x01, 0x87, 0xd2, 0x03, 0x9f, 0x82, 0x16, 0x17, 0x48, 0xcc, 0xb8, + 0xef, 0xf5, 0x9c, 0x41, 0x67, 0x6f, 0x27, 0x54, 0x9b, 0xa2, 0xf4, 0xb3, 0x64, 0xa4, 0x24, 0x87, + 0x0a, 0x14, 0x1b, 0x70, 0xff, 0x37, 0x07, 0x80, 0x83, 0x59, 0xa1, 0x93, 0xd4, 0x52, 0x0b, 0x94, + 0x65, 0x35, 0xe6, 0x5c, 0x89, 0xe6, 0xc5, 0xd6, 0x84, 0x9f, 0x00, 0x6f, 0x8e, 0x0a, 0x92, 0x21, + 0xc1, 0x6a, 0x25, 0x5f, 0x7b, 0xef, 0x1d, 0xdb, 0xb1, 0xdd, 0x00, 0x5b, 0xe7, 0x85, 0x05, 0xc6, + 0x57, 0x77, 0xe0, 0x00, 0xbc, 0xa6, 0x3b, 0x90, 0x94, 0x4c, 0x1b, 0x4d, 0x3d, 0x5e, 0xe5, 0x37, + 0xe4, 0xa6, 0x18, 0x7e, 0x0c, 0xee, 0x49, 0x0c, 0xf7, 0x5d, 0x35, 0xd8, 0x7e, 0xf8, 0xef, 0x9d, + 0x57, 0xad, 0x7c, 0x81, 0xcb, 0x31, 0xae, 0xf9, 0x84, 0x54, 0xb1, 0xbe, 0xd0, 0xff, 0xce, 0x01, + 0x6f, 0x8c, 0x58, 0x59, 0x12, 0xce, 0x09, 0xa3, 0xa3, 0x09, 0xa2, 0x39, 0x7e, 0x46, 0x45, 0xbd, + 0x80, 0x23, 0x00, 0xd2, 0x65, 0x40, 0xf7, 0x76, 0xbb, 0x55, 0x59, 0xb9, 0x06, 0x1f, 0x83, 0xfb, + 0x69, 0x8d, 0xf5, 0xea, 0x65, 0x48, 0xe8, 0x35, 0x6e, 0xc6, 0xaf, 0x58, 0xe7, 0x3e, 0x12, 0xb8, + 0xff, 0xbd, 0x03, 0x7c, 0xd5, 0xc7, 0x41, 0x8d, 0x52, 0x71, 0x83, 0xc6, 0x67, 0xa0, 0xa3, 0x3a, + 0x4f, 0x8e, 0x4c, 0xf0, 0xff, 0x50, 0xb9, 0xcf, 0x57, 0xd3, 0xde, 0x8e, 0xcd, 0xaf, 0x2e, 0xe8, + 0x5c, 0x9f, 0x15, 0xdc, 0x05, 0xae, 0x9c, 0x96, 0xaa, 0xdc, 0xb6, 0x7b, 0x72, 0x7d, 0xba, 0xcb, + 0x07, 0x1c, 0x2b, 0x28, 0x7c, 0x08, 0x5a, 0x15, 0x23, 0x54, 0x70, 0x55, 0xc3, 0x8d, 0x8d, 0x05, + 0x77, 0x00, 0x20, 0x3c, 0x29, 0x30, 0x9a, 0x13, 0x9a, 0x2b, 0x35, 0xb7, 0x62, 0x8f, 0xf0, 0xe7, + 0xda, 0x01, 0x03, 0x00, 0xe6, 0xa8, 0xb0, 0x0b, 0xa5, 0x5f, 0xf1, 0x8a, 0x47, 0x6e, 0xdb, 0x18, + 0x15, 0x88, 0xa6, 0x58, 0x3d, 0x5e, 0x37, 0xb6, 0xe6, 0x0d, 0xb9, 0x5a, 0x77, 0x93, 0x0b, 0x83, + 0x47, 0x15, 0xa6, 0x19, 0xa1, 0x79, 0x72, 0xe5, 0x4d, 0x52, 0x25, 0x87, 0xbf, 0xa9, 0xba, 0x7f, + 0x7f, 0x5d, 0xf7, 0x6b, 0x37, 0x28, 0x7e, 0xd3, 0xe4, 0xba, 0x19, 0x5d, 0xa3, 0xe9, 0xd6, 0x9d, + 0x35, 0x65, 0x60, 0xc7, 0x52, 0xbe, 0x9e, 0xd3, 0xd2, 0xf6, 0x14, 0xed, 0x0f, 0xd6, 0xd1, 0xfe, + 0xaf, 0xa5, 0x8b, 0xb7, 0x4d, 0xca, 0x35, 0x00, 0xa9, 0xe0, 0xca, 0x7b, 0x04, 0x4a, 0x05, 0xaf, + 0xb2, 0x4f, 0x71, 0xb8, 0x7f, 0x7a, 0x11, 0x38, 0x67, 0x17, 0x81, 0xf3, 0xd7, 0x45, 0xe0, 0xfc, + 0x70, 0x19, 0x34, 0xce, 0x2e, 0x83, 0xc6, 0xef, 0x97, 0x41, 0xe3, 0x9b, 0x27, 0x2b, 0xbf, 0x65, + 0x9f, 0xbf, 0x7c, 0xf1, 0xec, 0x4b, 0x2c, 0x4e, 0x58, 0x3d, 0x8d, 0xd2, 0x09, 0x22, 0x34, 0xfa, + 0xd6, 0x7c, 0xc2, 0xd4, 0x6f, 0xda, 0xb8, 0xa5, 0x3e, 0x0d, 0x1f, 0xfd, 0x13, 0x00, 0x00, 0xff, + 0xff, 0x4a, 0xf4, 0x98, 0x6f, 0xdd, 0x06, 0x00, 0x00, } func (m *BasicPool) Marshal() (dAtA []byte, err error) { @@ -599,8 +549,8 @@ func (m *BasicPool) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x48 } - if m.TotalDelegation != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.TotalDelegation)) + if m.TotalStake != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.TotalStake)) i-- dAtA[i] = 0x40 } @@ -693,32 +643,17 @@ func (m *FullStaker) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintQuery(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x3a + dAtA[i] = 0x22 } } - if m.DelegatorCount != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.DelegatorCount)) - i-- - dAtA[i] = 0x30 - } - if m.TotalDelegation != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.TotalDelegation)) - i-- - dAtA[i] = 0x28 - } - if m.SelfDelegationUnbonding != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.SelfDelegationUnbonding)) - i-- - dAtA[i] = 0x20 - } - if m.SelfDelegation != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.SelfDelegation)) + if m.TotalPoolStake != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.TotalPoolStake)) i-- dAtA[i] = 0x18 } - if m.Metadata != nil { + if m.Validator != nil { { - size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -738,7 +673,7 @@ func (m *FullStaker) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *StakerMetadata) Marshal() (dAtA []byte, err error) { +func (m *CommissionChangeEntry) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -748,76 +683,20 @@ func (m *StakerMetadata) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *StakerMetadata) MarshalTo(dAtA []byte) (int, error) { +func (m *CommissionChangeEntry) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *StakerMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *CommissionChangeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.CommissionRewards) > 0 { - for iNdEx := len(m.CommissionRewards) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.CommissionRewards[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x42 - } - } - if m.PendingCommissionChange != nil { - { - size, err := m.PendingCommissionChange.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x3a - } - if len(m.Details) > 0 { - i -= len(m.Details) - copy(dAtA[i:], m.Details) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Details))) - i-- - dAtA[i] = 0x32 - } - if len(m.SecurityContact) > 0 { - i -= len(m.SecurityContact) - copy(dAtA[i:], m.SecurityContact) - i = encodeVarintQuery(dAtA, i, uint64(len(m.SecurityContact))) - i-- - dAtA[i] = 0x2a - } - if len(m.Identity) > 0 { - i -= len(m.Identity) - copy(dAtA[i:], m.Identity) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Identity))) - i-- - dAtA[i] = 0x22 - } - if len(m.Website) > 0 { - i -= len(m.Website) - copy(dAtA[i:], m.Website) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Website))) - i-- - dAtA[i] = 0x1a - } - if len(m.Moniker) > 0 { - i -= len(m.Moniker) - copy(dAtA[i:], m.Moniker) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Moniker))) + if m.CreationDate != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CreationDate)) i-- - dAtA[i] = 0x12 + dAtA[i] = 0x10 } { size := m.Commission.Size() @@ -832,7 +711,7 @@ func (m *StakerMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *CommissionChangeEntry) Marshal() (dAtA []byte, err error) { +func (m *StakeFractionChangeEntry) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -842,12 +721,12 @@ func (m *CommissionChangeEntry) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *CommissionChangeEntry) MarshalTo(dAtA []byte) (int, error) { +func (m *StakeFractionChangeEntry) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *CommissionChangeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *StakeFractionChangeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -858,9 +737,9 @@ func (m *CommissionChangeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x10 } { - size := m.Commission.Size() + size := m.StakeFraction.Size() i -= size - if _, err := m.Commission.MarshalTo(dAtA[i:]); err != nil { + if _, err := m.StakeFraction.MarshalTo(dAtA[i:]); err != nil { return 0, err } i = encodeVarintQuery(dAtA, i, uint64(size)) @@ -890,6 +769,55 @@ func (m *PoolMembership) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.PoolStake != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PoolStake)) + i-- + dAtA[i] = 0x50 + } + if m.PendingStakeFractionChange != nil { + { + size, err := m.PendingStakeFractionChange.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + { + size := m.StakeFraction.Size() + i -= size + if _, err := m.StakeFraction.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + if m.PendingCommissionChange != nil { + { + size, err := m.PendingCommissionChange.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + { + size := m.Commission.Size() + i -= size + if _, err := m.Commission.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 if m.Balance != 0 { i = encodeVarintQuery(dAtA, i, uint64(m.Balance)) i-- @@ -975,8 +903,8 @@ func (m *BasicPool) Size() (n int) { n += 1 + l + sovQuery(uint64(l)) } } - if m.TotalDelegation != 0 { - n += 1 + sovQuery(uint64(m.TotalDelegation)) + if m.TotalStake != 0 { + n += 1 + sovQuery(uint64(m.TotalStake)) } if m.Status != 0 { n += 1 + sovQuery(uint64(m.Status)) @@ -994,21 +922,12 @@ func (m *FullStaker) Size() (n int) { if l > 0 { n += 1 + l + sovQuery(uint64(l)) } - if m.Metadata != nil { - l = m.Metadata.Size() + if m.Validator != nil { + l = m.Validator.Size() n += 1 + l + sovQuery(uint64(l)) } - if m.SelfDelegation != 0 { - n += 1 + sovQuery(uint64(m.SelfDelegation)) - } - if m.SelfDelegationUnbonding != 0 { - n += 1 + sovQuery(uint64(m.SelfDelegationUnbonding)) - } - if m.TotalDelegation != 0 { - n += 1 + sovQuery(uint64(m.TotalDelegation)) - } - if m.DelegatorCount != 0 { - n += 1 + sovQuery(uint64(m.DelegatorCount)) + if m.TotalPoolStake != 0 { + n += 1 + sovQuery(uint64(m.TotalPoolStake)) } if len(m.Pools) > 0 { for _, e := range m.Pools { @@ -1019,7 +938,7 @@ func (m *FullStaker) Size() (n int) { return n } -func (m *StakerMetadata) Size() (n int) { +func (m *CommissionChangeEntry) Size() (n int) { if m == nil { return 0 } @@ -1027,46 +946,19 @@ func (m *StakerMetadata) Size() (n int) { _ = l l = m.Commission.Size() n += 1 + l + sovQuery(uint64(l)) - l = len(m.Moniker) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Website) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Identity) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.SecurityContact) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Details) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.PendingCommissionChange != nil { - l = m.PendingCommissionChange.Size() - n += 1 + l + sovQuery(uint64(l)) - } - if len(m.CommissionRewards) > 0 { - for _, e := range m.CommissionRewards { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } + if m.CreationDate != 0 { + n += 1 + sovQuery(uint64(m.CreationDate)) } return n } -func (m *CommissionChangeEntry) Size() (n int) { +func (m *StakeFractionChangeEntry) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = m.Commission.Size() + l = m.StakeFraction.Size() n += 1 + l + sovQuery(uint64(l)) if m.CreationDate != 0 { n += 1 + sovQuery(uint64(m.CreationDate)) @@ -1097,6 +989,21 @@ func (m *PoolMembership) Size() (n int) { if m.Balance != 0 { n += 1 + sovQuery(uint64(m.Balance)) } + l = m.Commission.Size() + n += 1 + l + sovQuery(uint64(l)) + if m.PendingCommissionChange != nil { + l = m.PendingCommissionChange.Size() + n += 1 + l + sovQuery(uint64(l)) + } + l = m.StakeFraction.Size() + n += 1 + l + sovQuery(uint64(l)) + if m.PendingStakeFractionChange != nil { + l = m.PendingStakeFractionChange.Size() + n += 1 + l + sovQuery(uint64(l)) + } + if m.PoolStake != 0 { + n += 1 + sovQuery(uint64(m.PoolStake)) + } return n } @@ -1339,9 +1246,9 @@ func (m *BasicPool) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 8: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TotalDelegation", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field TotalStake", wireType) } - m.TotalDelegation = 0 + m.TotalStake = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1351,7 +1258,7 @@ func (m *BasicPool) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.TotalDelegation |= uint64(b&0x7F) << shift + m.TotalStake |= uint64(b&0x7F) << shift if b < 0x80 { break } @@ -1459,7 +1366,7 @@ func (m *FullStaker) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1486,18 +1393,18 @@ func (m *FullStaker) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Metadata == nil { - m.Metadata = &StakerMetadata{} + if m.Validator == nil { + m.Validator = &types2.Validator{} } - if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex case 3: if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field SelfDelegation", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field TotalPoolStake", wireType) } - m.SelfDelegation = 0 + m.TotalPoolStake = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1507,16 +1414,16 @@ func (m *FullStaker) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.SelfDelegation |= uint64(b&0x7F) << shift + m.TotalPoolStake |= uint64(b&0x7F) << shift if b < 0x80 { break } } case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field SelfDelegationUnbonding", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pools", wireType) } - m.SelfDelegationUnbonding = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1526,64 +1433,7 @@ func (m *FullStaker) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.SelfDelegationUnbonding |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TotalDelegation", wireType) - } - m.TotalDelegation = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.TotalDelegation |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DelegatorCount", wireType) - } - m.DelegatorCount = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.DelegatorCount |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pools", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } @@ -1624,7 +1474,7 @@ func (m *FullStaker) Unmarshal(dAtA []byte) error { } return nil } -func (m *StakerMetadata) Unmarshal(dAtA []byte) error { +func (m *CommissionChangeEntry) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1647,10 +1497,10 @@ func (m *StakerMetadata) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: StakerMetadata: wiretype end group for non-group") + return fmt.Errorf("proto: CommissionChangeEntry: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: StakerMetadata: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CommissionChangeEntry: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1688,206 +1538,10 @@ func (m *StakerMetadata) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Moniker", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - 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 ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Moniker = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Website", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - 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 ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Website = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Identity", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - 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 ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Identity = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SecurityContact", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - 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 ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SecurityContact = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Details", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - 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 ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Details = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PendingCommissionChange", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.PendingCommissionChange == nil { - m.PendingCommissionChange = &CommissionChangeEntry{} - } - if err := m.PendingCommissionChange.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CommissionRewards", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CreationDate", wireType) } - var msglen int + m.CreationDate = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1897,26 +1551,11 @@ func (m *StakerMetadata) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + m.CreationDate |= int64(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.CommissionRewards = append(m.CommissionRewards, types.Coin{}) - if err := m.CommissionRewards[len(m.CommissionRewards)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -1938,7 +1577,7 @@ func (m *StakerMetadata) Unmarshal(dAtA []byte) error { } return nil } -func (m *CommissionChangeEntry) Unmarshal(dAtA []byte) error { +func (m *StakeFractionChangeEntry) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1961,15 +1600,15 @@ func (m *CommissionChangeEntry) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: CommissionChangeEntry: wiretype end group for non-group") + return fmt.Errorf("proto: StakeFractionChangeEntry: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: CommissionChangeEntry: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: StakeFractionChangeEntry: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Commission", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field StakeFraction", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1997,7 +1636,7 @@ func (m *CommissionChangeEntry) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Commission.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.StakeFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2196,6 +1835,165 @@ func (m *PoolMembership) Unmarshal(dAtA []byte) error { break } } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commission", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Commission.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PendingCommissionChange", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PendingCommissionChange == nil { + m.PendingCommissionChange = &CommissionChangeEntry{} + } + if err := m.PendingCommissionChange.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeFraction", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + 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 ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StakeFraction.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PendingStakeFractionChange", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PendingStakeFractionChange == nil { + m.PendingStakeFractionChange = &StakeFractionChangeEntry{} + } + if err := m.PendingStakeFractionChange.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolStake", wireType) + } + m.PoolStake = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolStake |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 0a8e02f0..d84a821b 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -2,6 +2,8 @@ package keeper import ( "context" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "sort" "cosmossdk.io/errors" @@ -44,18 +46,25 @@ func (k Keeper) GetAllStakerAddressesOfPool(ctx sdk.Context, poolId uint64) (sta return stakers } -func (k Keeper) GetPaginatedStakersByDelegation(ctx sdk.Context, pagination *query.PageRequest, accumulator func(staker string, accumulate bool) bool) (*query.PageResponse, error) { +func (k Keeper) GetPaginatedStakersByPoolStake(ctx sdk.Context, pagination *query.PageRequest, accumulator func(validator string, accumulate bool) bool) (*query.PageResponse, error) { validators, err := k.stakingKeeper.GetBondedValidatorsByPower(ctx) if err != nil { return nil, err } + // TODO: sort by pool stake + addresses := make([]string, 0) + for _, validator := range validators { - accumulator(util.MustAccountAddressFromValAddress(validator.OperatorAddress), true) + addresses = append(addresses, util.MustAccountAddressFromValAddress(validator.OperatorAddress)) + } + + pageRes, err := arrayPaginationAccumulator(addresses, pagination, accumulator) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) } - res := query.PageResponse{} - return &res, nil + return pageRes, nil } // AssertValaccountAuthorized checks if the given `valaddress` is allowed to vote in pool diff --git a/x/stakers/keeper/getters_staker.go b/x/stakers/keeper/getters_staker.go index ffa270e9..1ff6ba1a 100644 --- a/x/stakers/keeper/getters_staker.go +++ b/x/stakers/keeper/getters_staker.go @@ -2,6 +2,7 @@ package keeper import ( "encoding/binary" + "fmt" "cosmossdk.io/math" @@ -245,3 +246,33 @@ func (k Keeper) getAllActiveStakers(ctx sdk.Context) (list []string) { return } + +// arrayPaginationAccumulator helps to parse the query.PageRequest for an array +// instead of a KV-Store. +func arrayPaginationAccumulator(slice []string, pagination *query.PageRequest, accumulator func(address string, accumulate bool) bool) (*query.PageResponse, error) { + if pagination != nil && pagination.Key != nil { + return nil, fmt.Errorf("key pagination not supported") + } + + page, limit, err := query.ParsePagination(pagination) + if err != nil { + return nil, err + } + + count := 0 + minIndex := (page - 1) * limit + maxIndex := (page) * limit + + for i := 0; i < len(slice); i++ { + if accumulator(slice[i], count >= minIndex && count < maxIndex) { + count++ + } + } + + pageRes := &query.PageResponse{ + NextKey: nil, + Total: uint64(count), + } + + return pageRes, nil +} From 48445cdb472694ec2df3f93737cc061702492814 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Wed, 18 Dec 2024 15:07:59 +0100 Subject: [PATCH 15/24] chore: added staker_by_pool query --- docs/static/openapi.yml | 779 +++++++++---------- proto/kyve/query/v1beta1/stakers.proto | 12 +- x/query/keeper/grpc_query_stakers_by_pool.go | 21 +- x/query/types/stakers.pb.go | 347 ++------- 4 files changed, 424 insertions(+), 735 deletions(-) diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 368410fe..16e3e215 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -8097,515 +8097,458 @@ paths: items: type: object properties: - staker: - description: staker ... + address: + type: string + title: address of the staker + validator: type: object properties: - address: + operator_address: type: string - title: address of the staker - validator: + description: >- + operator_address defines the address of the + validator's operator; bech encoded in JSON. + consensus_pubkey: + description: >- + consensus_pubkey is the consensus public key of the + validator, as a Protobuf Any. type: object properties: - operator_address: + '@type': type: string description: >- - operator_address defines the address of the - validator's operator; bech encoded in JSON. - consensus_pubkey: - description: >- - consensus_pubkey is the consensus public key of - the validator, as a Protobuf Any. - type: object - properties: - '@type': - type: string - description: >- - A URL/resource name that uniquely identifies - the type of the serialized + A URL/resource name that uniquely identifies the + type of the serialized - protocol buffer message. This string must - contain at least + protocol buffer message. This string must + contain at least - one "/" character. The last segment of the - URL's path must represent + one "/" character. The last segment of the URL's + path must represent - the fully qualified name of the type (as in + the fully qualified name of the type (as in - `path/google.protobuf.Duration`). The name - should be in a canonical form + `path/google.protobuf.Duration`). The name + should be in a canonical form - (e.g., leading "." is not accepted). + (e.g., leading "." is not accepted). - In practice, teams usually precompile into - the binary all types that they + In practice, teams usually precompile into the + binary all types that they - expect it to use in the context of Any. - However, for URLs which use the + expect it to use in the context of Any. However, + for URLs which use the - scheme `http`, `https`, or no scheme, one - can optionally set up a type + scheme `http`, `https`, or no scheme, one can + optionally set up a type - server that maps type URLs to message - definitions as follows: + server that maps type URLs to message + definitions as follows: - * If no scheme is provided, `https` is - assumed. + * If no scheme is provided, `https` is assumed. - * An HTTP GET on the URL must yield a - [google.protobuf.Type][] - value in binary format, or produce an error. - * Applications are allowed to cache lookup - results based on the - URL, or have them precompiled into a binary to avoid any - lookup. Therefore, binary compatibility needs to be preserved - on changes to types. (Use versioned type names to manage - breaking changes.) + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup + results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) - Note: this functionality is not currently - available in the official + Note: this functionality is not currently + available in the official - protobuf release, and it is not used for - type URLs beginning with + protobuf release, and it is not used for type + URLs beginning with - type.googleapis.com. As of May 2023, there - are no widely used type server + type.googleapis.com. As of May 2023, there are + no widely used type server - implementations and no plans to implement - one. + implementations and no plans to implement one. - Schemes other than `http`, `https` (or the - empty scheme) might be + Schemes other than `http`, `https` (or the empty + scheme) might be - used with implementation specific semantics. - additionalProperties: {} - jailed: - type: boolean + used with implementation specific semantics. + additionalProperties: {} + jailed: + type: boolean + description: >- + jailed defined whether the validator has been jailed + from bonded status or not. + status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). + type: string + enum: + - BOND_STATUS_UNSPECIFIED + - BOND_STATUS_UNBONDED + - BOND_STATUS_UNBONDING + - BOND_STATUS_BONDED + default: BOND_STATUS_UNSPECIFIED + tokens: + type: string + description: >- + tokens define the delegated tokens (incl. + self-delegation). + delegator_shares: + type: string + description: >- + delegator_shares defines total shares issued to a + validator's delegators. + description: + description: >- + description defines the description terms for the + validator. + type: object + properties: + moniker: + type: string description: >- - jailed defined whether the validator has been - jailed from bonded status or not. - status: + moniker defines a human-readable name for the + validator. + identity: + type: string description: >- - status is the validator status - (bonded/unbonding/unbonded). + identity defines an optional identity signature + (ex. UPort or Keybase). + website: type: string - enum: - - BOND_STATUS_UNSPECIFIED - - BOND_STATUS_UNBONDED - - BOND_STATUS_UNBONDING - - BOND_STATUS_BONDED - default: BOND_STATUS_UNSPECIFIED - tokens: + description: website defines an optional website link. + security_contact: type: string description: >- - tokens define the delegated tokens (incl. - self-delegation). - delegator_shares: + security_contact defines an optional email for + security contact. + details: type: string + description: details define other optional details. + unbonding_height: + type: string + format: int64 + description: >- + unbonding_height defines, if unbonding, the height + at which this validator has begun unbonding. + unbonding_time: + type: string + format: date-time + description: >- + unbonding_time defines, if unbonding, the min time + for the validator to complete unbonding. + commission: + description: commission defines the commission parameters. + type: object + properties: + commission_rates: description: >- - delegator_shares defines total shares issued to - a validator's delegators. - description: - description: >- - description defines the description terms for - the validator. + commission_rates defines the initial commission + rates to be used for creating a validator. type: object properties: - moniker: + rate: type: string description: >- - moniker defines a human-readable name for - the validator. - identity: + rate is the commission rate charged to + delegators, as a fraction. + max_rate: type: string description: >- - identity defines an optional identity - signature (ex. UPort or Keybase). - website: - type: string - description: website defines an optional website link. - security_contact: + max_rate defines the maximum commission rate + which validator can ever charge, as a + fraction. + max_change_rate: type: string description: >- - security_contact defines an optional email - for security contact. - details: - type: string - description: details define other optional details. - unbonding_height: - type: string - format: int64 - description: >- - unbonding_height defines, if unbonding, the - height at which this validator has begun - unbonding. - unbonding_time: + max_change_rate defines the maximum daily + increase of the validator commission, as a + fraction. + update_time: type: string format: date-time description: >- - unbonding_time defines, if unbonding, the min - time for the validator to complete unbonding. - commission: - description: commission defines the commission parameters. - type: object - properties: - commission_rates: - description: >- - commission_rates defines the initial - commission rates to be used for creating a - validator. - type: object - properties: - rate: - type: string - description: >- - rate is the commission rate charged to - delegators, as a fraction. - max_rate: - type: string - description: >- - max_rate defines the maximum commission - rate which validator can ever charge, as - a fraction. - max_change_rate: - type: string - description: >- - max_change_rate defines the maximum - daily increase of the validator - commission, as a fraction. - update_time: - type: string - format: date-time - description: >- - update_time is the last time the commission - rate was changed. - min_self_delegation: - type: string - description: >- - min_self_delegation is the validator's self - declared minimum self delegation. + update_time is the last time the commission rate + was changed. + min_self_delegation: + type: string + description: >- + min_self_delegation is the validator's self declared + minimum self delegation. - Since: cosmos-sdk 0.46 - unbonding_on_hold_ref_count: - type: string - format: int64 - title: >- - strictly positive if this validator's unbonding - has been stopped by external modules - unbonding_ids: - type: array - items: - type: string - format: uint64 - title: >- - list of unbonding ids, each uniquely identifing - an unbonding of this validator - description: >- - Validator defines a validator, together with the - total amount of the + Since: cosmos-sdk 0.46 + unbonding_on_hold_ref_count: + type: string + format: int64 + title: >- + strictly positive if this validator's unbonding has + been stopped by external modules + unbonding_ids: + type: array + items: + type: string + format: uint64 + title: >- + list of unbonding ids, each uniquely identifing an + unbonding of this validator + description: >- + Validator defines a validator, together with the total + amount of the - Validator's bond shares and their exchange rate to - coins. Slashing results in + Validator's bond shares and their exchange rate to + coins. Slashing results in - a decrease in the exchange rate, allowing correct - calculation of future + a decrease in the exchange rate, allowing correct + calculation of future - undelegations without iterating over delegators. - When coins are delegated to + undelegations without iterating over delegators. When + coins are delegated to - this validator, the validator is credited with a - delegation whose number of + this validator, the validator is credited with a + delegation whose number of - bond shares is based on the amount of coins - delegated divided by the current + bond shares is based on the amount of coins delegated + divided by the current - exchange rate. Voting power can be calculated as - total bonded shares + exchange rate. Voting power can be calculated as total + bonded shares - multiplied by exchange rate. - total_pool_stake: - type: string - format: uint64 - title: >- - total_pool_stake returns the amount the validator - has in total + multiplied by exchange rate. + total_pool_stake: + type: string + format: uint64 + title: >- + total_pool_stake returns the amount the validator has in + total - staked in all his pools - pools: - type: array - items: + staked in all his pools + pools: + type: array + items: + type: object + properties: + pool: + title: pool contains useful information about the pool type: object properties: - pool: - title: >- - pool contains useful information about the - pool - type: object - properties: - id: - type: string - format: uint64 - title: id is the ID of the pool - name: - type: string - title: name of the pool - runtime: - type: string - description: |- - runtime for the protocol nodes - like evm, bitcoin, etc. - logo: - type: string - title: logo of the pool - inflation_share_weight: - type: string - title: >- - inflation_share_weight is the base payout - for each bundle reward - upload_interval: - type: string - format: uint64 - title: >- - upload_interval is the interval bundles - get created - total_funds: - type: array - items: - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination - and an amount. - - - NOTE: The amount field is an Int which - implements the custom method - - signatures required by gogoproto. - title: >- - total_funds of the pool. If the pool runs - - out of funds no more bundles will be - produced - total_stake: - type: string - format: uint64 - title: total_stake of the pool - status: - description: |- - status of the pool if pool is able - to produce bundles, etc. - type: string - enum: - - POOL_STATUS_UNSPECIFIED - - POOL_STATUS_ACTIVE - - POOL_STATUS_DISABLED - - POOL_STATUS_NO_FUNDS - - POOL_STATUS_NOT_ENOUGH_DELEGATION - - POOL_STATUS_UPGRADING - - POOL_STATUS_VOTING_POWER_TOO_HIGH - - POOL_STATUS_END_KEY_REACHED - default: POOL_STATUS_UNSPECIFIED - points: + id: type: string format: uint64 + title: id is the ID of the pool + name: + type: string + title: name of the pool + runtime: + type: string description: |- - points indicates if the staker is inactive - If the staker misses a vote, a point is added. - After 5 points the staker is removed from - the stakers set. - is_leaving: - type: boolean + runtime for the protocol nodes + like evm, bitcoin, etc. + logo: + type: string + title: logo of the pool + inflation_share_weight: + type: string title: >- - is_leaving indicates if a user has scheduled a - - a PoolLeave entry. After the leave-time is - over - - the staker will no longer participate in that - pool - valaddress: + inflation_share_weight is the base payout for + each bundle reward + upload_interval: type: string - description: >- - Valaddress is the address which is authorized - to vote + format: uint64 + title: >- + upload_interval is the interval bundles get + created + total_funds: + type: array + items: + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + Coin defines a token with a denomination and + an amount. - and submit bundles. If the server gets - compromised - the staker can just change the valaddress. - balance: + NOTE: The amount field is an Int which + implements the custom method + + signatures required by gogoproto. + title: |- + total_funds of the pool. If the pool runs + out of funds no more bundles will be produced + total_stake: type: string format: uint64 - title: >- - balance is the valaddress account balance and - indicates + title: total_stake of the pool + status: + description: |- + status of the pool if pool is able + to produce bundles, etc. + type: string + enum: + - POOL_STATUS_UNSPECIFIED + - POOL_STATUS_ACTIVE + - POOL_STATUS_DISABLED + - POOL_STATUS_NO_FUNDS + - POOL_STATUS_NOT_ENOUGH_DELEGATION + - POOL_STATUS_UPGRADING + - POOL_STATUS_VOTING_POWER_TOO_HIGH + - POOL_STATUS_END_KEY_REACHED + default: POOL_STATUS_UNSPECIFIED + points: + type: string + format: uint64 + description: |- + points indicates if the staker is inactive + If the staker misses a vote, a point is added. + After 5 points the staker is removed from + the stakers set. + is_leaving: + type: boolean + title: |- + is_leaving indicates if a user has scheduled a + a PoolLeave entry. After the leave-time is over + the staker will no longer participate in that pool + valaddress: + type: string + description: >- + Valaddress is the address which is authorized to + vote - whether or not the valaccount needs additional - funds to + and submit bundles. If the server gets compromised - pay for gas fees - commission: - type: string - title: >- - commission is the commission the validator has - chosen for + the staker can just change the valaddress. + balance: + type: string + format: uint64 + title: >- + balance is the valaddress account balance and + indicates - this specific pool - pending_commission_change: - description: >- - pending_commission_change shows if the staker - plans + whether or not the valaccount needs additional + funds to - to change its commission. Delegators will see - a warning in + pay for gas fees + commission: + type: string + title: >- + commission is the commission the validator has + chosen for - the UI. A Commission change takes some time - until + this specific pool + pending_commission_change: + description: >- + pending_commission_change shows if the staker + plans - the commission is applied. Users have time to - redelegate + to change its commission. Delegators will see a + warning in - if they not agree with the new commission. - type: object - properties: - commission: - type: string - title: |- - commission is the new commission that will - become active once the change-time is over - creation_date: - type: string - format: int64 - description: >- - creation_date is the UNIX-timestamp (in - seconds) + the UI. A Commission change takes some time until - of when the entry was created. - title: >- - CommissionChangeEntry shows when the old - commission + the commission is applied. Users have time to + redelegate - of a staker will change to the new commission - stake_fraction: + if they not agree with the new commission. + type: object + properties: + commission: type: string - title: >- - stake fraction is a percentage the validator - has chosen for + title: |- + commission is the new commission that will + become active once the change-time is over + creation_date: + type: string + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) - this pool. It is the fraction of how much of - his total stake + of when the entry was created. + title: >- + CommissionChangeEntry shows when the old + commission - the validator wants to stake in this specific - pool - pending_stake_fraction_change: - description: >- - pending_stake_fraction_change shows if the - staker plans + of a staker will change to the new commission + stake_fraction: + type: string + title: >- + stake fraction is a percentage the validator has + chosen for - to change its stake fraction. Delegators will - see a warning in + this pool. It is the fraction of how much of his + total stake - the UI. A stake fraction change takes some - time until + the validator wants to stake in this specific pool + pending_stake_fraction_change: + description: >- + pending_stake_fraction_change shows if the staker + plans - the stake fraction is applied. Users have time - to redelegate + to change its stake fraction. Delegators will see + a warning in - if they not agree with the new stake fraction. - type: object - properties: - stake_fraction: - type: string - title: >- - stake_fraction is the new stake_fraction - that will + the UI. A stake fraction change takes some time + until - become active once the change-time is over - creation_date: - type: string - format: int64 - description: >- - creation_date is the UNIX-timestamp (in - seconds) + the stake fraction is applied. Users have time to + redelegate - of when the entry was created. + if they not agree with the new stake fraction. + type: object + properties: + stake_fraction: + type: string title: >- - StakeFractionChangeEntry shows when the old - stake fraction + stake_fraction is the new stake_fraction that + will - of a staker will change to the new stake - fraction - pool_stake: + become active once the change-time is over + creation_date: type: string - format: uint64 - title: >- - pool stake shows the actual amount the - validator has staked + format: int64 + description: >- + creation_date is the UNIX-timestamp (in + seconds) - in this pool. It can be lower than the - specified stake fraction + of when the entry was created. + title: >- + StakeFractionChangeEntry shows when the old stake + fraction - because of the max voting power limit - title: |- - PoolMembership shows in which pool the staker - is participating - description: |- - pools is a list of all pools the staker is currently - participating, i.e. allowed to vote and upload data. - title: >- - FullStaker aggregates information from the staker and - its delegators + of a staker will change to the new stake fraction + pool_stake: + type: string + format: uint64 + title: >- + pool stake shows the actual amount the validator + has staked - as well as pending queue entries into one object. + in this pool. It can be lower than the specified + stake fraction - It contains almost all needed information for a - convenient usage - valaccount: - description: valaccount ... - type: object - properties: - pool_id: - type: string - format: uint64 - description: |- - pool_id defines the pool in which the address - is allowed to vote in. - staker: - type: string - description: staker is the address the valaccount is voting for. - valaddress: - type: string - title: |- - valaddress is the account stored on the protocol - node which votes for the staker in the given pool - points: - type: string - format: uint64 - description: |- - When a node is inactive (does not vote at all) - A point is added, after a certain amount of points - is reached the node gets kicked out. - is_leaving: - type: boolean - description: >- - isLeaving indicates if a staker is leaving the given - pool. - commission: - type: string - description: commission ... - stake_fraction: - type: string - description: stake_fraction ... - description: StakerPoolResponse ... + because of the max voting power limit + title: |- + PoolMembership shows in which pool the staker + is participating + description: |- + pools is a list of all pools the staker is currently + participating, i.e. allowed to vote and upload data. + title: >- + FullStaker aggregates information from the staker and its + delegators + + as well as pending queue entries into one object. + + It contains almost all needed information for a convenient + usage description: stakers ... description: >- QueryStakersByPoolResponse is the response type for the diff --git a/proto/kyve/query/v1beta1/stakers.proto b/proto/kyve/query/v1beta1/stakers.proto index 7bcfd3d5..8a86e5f8 100644 --- a/proto/kyve/query/v1beta1/stakers.proto +++ b/proto/kyve/query/v1beta1/stakers.proto @@ -99,19 +99,11 @@ message QueryStakersByPoolRequest { // QueryStakersByPoolResponse is the response type for the Query/Staker RPC method. message QueryStakersByPoolResponse { // stakers ... - repeated StakerPoolResponse stakers = 1 [(gogoproto.nullable) = false]; -} - -// StakerPoolResponse ... -message StakerPoolResponse { - // staker ... - FullStaker staker = 1; - // valaccount ... - kyve.stakers.v1beta1.Valaccount valaccount = 2; + repeated FullStaker stakers = 1 [(gogoproto.nullable) = false]; } // ========================= -// stakers_by_pool/{pool_id} +// stakers_by_pool_count // ========================= // QueryStakersByPoolCountRequest ... diff --git a/x/query/keeper/grpc_query_stakers_by_pool.go b/x/query/keeper/grpc_query_stakers_by_pool.go index 7d5d7199..14299655 100644 --- a/x/query/keeper/grpc_query_stakers_by_pool.go +++ b/x/query/keeper/grpc_query_stakers_by_pool.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "sort" "github.com/KYVENetwork/chain/x/query/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -15,24 +16,22 @@ func (k Keeper) StakersByPool(c context.Context, req *types.QueryStakersByPoolRe return nil, status.Error(codes.InvalidArgument, "invalid request") } - data := make([]types.StakerPoolResponse, 0) - ctx := sdk.UnwrapSDKContext(c) - _, found := k.poolKeeper.GetPool(ctx, req.PoolId) - if !found { + if _, found := k.poolKeeper.GetPool(ctx, req.PoolId); !found { return nil, sdkerrors.ErrKeyNotFound } + stakers := make([]types.FullStaker, 0) + valaccounts := k.stakerKeeper.GetAllValaccountsOfPool(ctx, req.PoolId) for _, valaccount := range valaccounts { - if _, exist := k.stakerKeeper.GetValidator(ctx, valaccount.Staker); exist { - data = append(data, types.StakerPoolResponse{ - Staker: k.GetFullStaker(ctx, valaccount.Staker), - Valaccount: valaccount, - }) - } + stakers = append(stakers, *k.GetFullStaker(ctx, valaccount.Staker)) } - return &types.QueryStakersByPoolResponse{Stakers: data}, nil + sort.Slice(stakers, func(i, j int) bool { + return k.stakerKeeper.GetValidatorPoolStake(ctx, stakers[i].Address, req.PoolId) > k.stakerKeeper.GetValidatorPoolStake(ctx, stakers[j].Address, req.PoolId) + }) + + return &types.QueryStakersByPoolResponse{Stakers: stakers}, nil } diff --git a/x/query/types/stakers.pb.go b/x/query/types/stakers.pb.go index 86d0d02d..4f1a0789 100644 --- a/x/query/types/stakers.pb.go +++ b/x/query/types/stakers.pb.go @@ -6,7 +6,7 @@ package types import ( context "context" fmt "fmt" - types "github.com/KYVENetwork/chain/x/stakers/types" + _ "github.com/KYVENetwork/chain/x/stakers/types" query "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" @@ -323,7 +323,7 @@ func (m *QueryStakersByPoolRequest) GetPoolId() uint64 { // QueryStakersByPoolResponse is the response type for the Query/Staker RPC method. type QueryStakersByPoolResponse struct { // stakers ... - Stakers []StakerPoolResponse `protobuf:"bytes,1,rep,name=stakers,proto3" json:"stakers"` + Stakers []FullStaker `protobuf:"bytes,1,rep,name=stakers,proto3" json:"stakers"` } func (m *QueryStakersByPoolResponse) Reset() { *m = QueryStakersByPoolResponse{} } @@ -359,68 +359,13 @@ func (m *QueryStakersByPoolResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QueryStakersByPoolResponse proto.InternalMessageInfo -func (m *QueryStakersByPoolResponse) GetStakers() []StakerPoolResponse { +func (m *QueryStakersByPoolResponse) GetStakers() []FullStaker { if m != nil { return m.Stakers } return nil } -// StakerPoolResponse ... -type StakerPoolResponse struct { - // staker ... - Staker *FullStaker `protobuf:"bytes,1,opt,name=staker,proto3" json:"staker,omitempty"` - // valaccount ... - Valaccount *types.Valaccount `protobuf:"bytes,2,opt,name=valaccount,proto3" json:"valaccount,omitempty"` -} - -func (m *StakerPoolResponse) Reset() { *m = StakerPoolResponse{} } -func (m *StakerPoolResponse) String() string { return proto.CompactTextString(m) } -func (*StakerPoolResponse) ProtoMessage() {} -func (*StakerPoolResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6aa31a681566da33, []int{6} -} -func (m *StakerPoolResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *StakerPoolResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_StakerPoolResponse.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 *StakerPoolResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_StakerPoolResponse.Merge(m, src) -} -func (m *StakerPoolResponse) XXX_Size() int { - return m.Size() -} -func (m *StakerPoolResponse) XXX_DiscardUnknown() { - xxx_messageInfo_StakerPoolResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_StakerPoolResponse proto.InternalMessageInfo - -func (m *StakerPoolResponse) GetStaker() *FullStaker { - if m != nil { - return m.Staker - } - return nil -} - -func (m *StakerPoolResponse) GetValaccount() *types.Valaccount { - if m != nil { - return m.Valaccount - } - return nil -} - // QueryStakersByPoolCountRequest ... type QueryStakersByPoolCountRequest struct { // pagination defines an optional pagination for the request. @@ -431,7 +376,7 @@ func (m *QueryStakersByPoolCountRequest) Reset() { *m = QueryStakersByPo func (m *QueryStakersByPoolCountRequest) String() string { return proto.CompactTextString(m) } func (*QueryStakersByPoolCountRequest) ProtoMessage() {} func (*QueryStakersByPoolCountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_6aa31a681566da33, []int{7} + return fileDescriptor_6aa31a681566da33, []int{6} } func (m *QueryStakersByPoolCountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -479,7 +424,7 @@ func (m *QueryStakersByPoolCountResponse) Reset() { *m = QueryStakersByP func (m *QueryStakersByPoolCountResponse) String() string { return proto.CompactTextString(m) } func (*QueryStakersByPoolCountResponse) ProtoMessage() {} func (*QueryStakersByPoolCountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_6aa31a681566da33, []int{8} + return fileDescriptor_6aa31a681566da33, []int{7} } func (m *QueryStakersByPoolCountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -530,7 +475,6 @@ func init() { proto.RegisterType((*QueryStakerResponse)(nil), "kyve.query.v1beta1.QueryStakerResponse") proto.RegisterType((*QueryStakersByPoolRequest)(nil), "kyve.query.v1beta1.QueryStakersByPoolRequest") proto.RegisterType((*QueryStakersByPoolResponse)(nil), "kyve.query.v1beta1.QueryStakersByPoolResponse") - proto.RegisterType((*StakerPoolResponse)(nil), "kyve.query.v1beta1.StakerPoolResponse") proto.RegisterType((*QueryStakersByPoolCountRequest)(nil), "kyve.query.v1beta1.QueryStakersByPoolCountRequest") proto.RegisterType((*QueryStakersByPoolCountResponse)(nil), "kyve.query.v1beta1.QueryStakersByPoolCountResponse") } @@ -538,54 +482,51 @@ func init() { func init() { proto.RegisterFile("kyve/query/v1beta1/stakers.proto", fileDescriptor_6aa31a681566da33) } var fileDescriptor_6aa31a681566da33 = []byte{ - // 739 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0x4f, 0x4f, 0x13, 0x4d, - 0x1c, 0xee, 0x94, 0xa6, 0x0d, 0x03, 0xef, 0x1b, 0x32, 0x2f, 0xe1, 0x2d, 0xab, 0x2c, 0xcd, 0x6a, - 0x4a, 0x45, 0xd9, 0x09, 0x45, 0x8d, 0x07, 0x63, 0xe4, 0x4f, 0x6b, 0x1a, 0x12, 0x82, 0xdb, 0x42, - 0xa2, 0x97, 0x66, 0xda, 0x4e, 0xb6, 0x9b, 0x96, 0x9d, 0xb2, 0xb3, 0x45, 0x1b, 0xc2, 0x41, 0x2f, - 0x7a, 0x32, 0x26, 0x7e, 0x00, 0x0f, 0xc6, 0x8b, 0x17, 0xfd, 0x18, 0x1c, 0x49, 0xbc, 0x78, 0x32, - 0x06, 0xfc, 0x0e, 0x5e, 0x4d, 0x67, 0x67, 0x71, 0x17, 0x5a, 0x5b, 0x12, 0x0f, 0xde, 0x66, 0x76, - 0x9e, 0x67, 0x7e, 0xcf, 0xf3, 0xcc, 0xfc, 0x66, 0x61, 0xaa, 0xd1, 0xd9, 0xa3, 0x78, 0xb7, 0x4d, - 0x9d, 0x0e, 0xde, 0x5b, 0xac, 0x50, 0x97, 0x2c, 0x62, 0xee, 0x92, 0x06, 0x75, 0xb8, 0xde, 0x72, - 0x98, 0xcb, 0x10, 0xea, 0x22, 0x74, 0x81, 0xd0, 0x25, 0x42, 0x99, 0xaf, 0x32, 0xbe, 0xc3, 0x38, - 0xae, 0x10, 0x7e, 0x96, 0xdc, 0x22, 0xa6, 0x65, 0x13, 0xd7, 0x62, 0xb6, 0xc7, 0x57, 0x26, 0x4d, - 0x66, 0x32, 0x31, 0xc4, 0xdd, 0x91, 0xfc, 0x7a, 0xd9, 0x64, 0xcc, 0x6c, 0x52, 0x4c, 0x5a, 0x16, - 0x26, 0xb6, 0xcd, 0x5c, 0x41, 0x91, 0x35, 0x15, 0xb5, 0x87, 0x2a, 0x4f, 0x81, 0xb7, 0xae, 0x89, - 0x75, 0xa9, 0xb3, 0xb7, 0x6e, 0xed, 0x23, 0x80, 0xff, 0x3d, 0xec, 0x72, 0x8a, 0xde, 0x67, 0x83, - 0xee, 0xb6, 0x29, 0x77, 0x51, 0x1e, 0xc2, 0x5f, 0x1a, 0x93, 0x20, 0x05, 0x32, 0x63, 0xd9, 0xb4, - 0xee, 0x19, 0xd2, 0xbb, 0x86, 0xc2, 0x5e, 0xf5, 0x4d, 0x62, 0x52, 0xc9, 0x35, 0x02, 0x4c, 0x74, - 0x07, 0xc6, 0xb9, 0x4b, 0xdc, 0x36, 0x4f, 0x46, 0x53, 0x20, 0xf3, 0x6f, 0x36, 0xa5, 0x9f, 0x0f, - 0x4a, 0xf7, 0x6a, 0x17, 0x05, 0xce, 0x90, 0x78, 0x34, 0x05, 0xe3, 0x9c, 0x12, 0xa7, 0x5a, 0x4f, - 0x8e, 0xa4, 0x40, 0x66, 0xd4, 0x90, 0x33, 0xed, 0x2d, 0x80, 0x93, 0x61, 0xc5, 0xbc, 0xc5, 0x6c, - 0x4e, 0xd1, 0x3d, 0x98, 0x90, 0xde, 0x92, 0x20, 0x35, 0x92, 0x19, 0xcb, 0xaa, 0xbd, 0x6a, 0xe5, - 0xdb, 0xcd, 0xa6, 0xc7, 0x5c, 0x89, 0x1d, 0x7e, 0x9d, 0x8d, 0x18, 0x3e, 0x09, 0x3d, 0x08, 0x59, - 0x8e, 0x0a, 0xcb, 0x73, 0x03, 0x2d, 0x7b, 0xc5, 0x83, 0x9e, 0x35, 0x1d, 0xa2, 0x80, 0x40, 0x3f, - 0xd1, 0x24, 0x4c, 0x90, 0x5a, 0xcd, 0xa1, 0x9c, 0x8b, 0x38, 0x47, 0x0d, 0x7f, 0xaa, 0x15, 0x43, - 0x47, 0x70, 0xea, 0xe7, 0xae, 0x88, 0xae, 0x41, 0x1d, 0x19, 0xff, 0x70, 0x76, 0x24, 0x47, 0xbb, - 0x09, 0xa7, 0x83, 0x29, 0xad, 0x74, 0x36, 0x19, 0x6b, 0xfa, 0x5a, 0xfe, 0x87, 0x89, 0x16, 0x63, - 0xcd, 0xb2, 0x55, 0x13, 0x7b, 0xc7, 0x8c, 0x78, 0x77, 0x5a, 0xa8, 0x69, 0x35, 0xa8, 0xf4, 0x62, - 0x49, 0x45, 0xf9, 0xb3, 0x09, 0xa7, 0xfb, 0x9f, 0x66, 0x90, 0x78, 0x26, 0x69, 0xed, 0x15, 0x80, - 0xe8, 0x3c, 0x0a, 0xdd, 0xbe, 0x98, 0x61, 0xdf, 0x2a, 0xba, 0x0f, 0xe1, 0x1e, 0x69, 0x92, 0x6a, - 0x95, 0xb5, 0x6d, 0x57, 0x1e, 0x9c, 0xbc, 0x67, 0xfe, 0x65, 0xf7, 0xd9, 0xdb, 0xa7, 0x38, 0x23, - 0xc0, 0xd1, 0xea, 0x50, 0x3d, 0x6f, 0x7b, 0x55, 0xc0, 0xfe, 0x6c, 0x3f, 0x68, 0x1f, 0x00, 0x9c, - 0xed, 0x5b, 0xea, 0x2f, 0xbb, 0xc8, 0xf3, 0x16, 0x1c, 0x0f, 0xb6, 0x26, 0x9a, 0x81, 0xd3, 0xc5, - 0xd2, 0xf2, 0x7a, 0xce, 0x28, 0x17, 0x4b, 0xcb, 0xa5, 0xad, 0x62, 0x79, 0x6b, 0xa3, 0xb8, 0x99, - 0x5b, 0x2d, 0xe4, 0x0b, 0xb9, 0xb5, 0x89, 0x08, 0x4a, 0xc2, 0xc9, 0xf0, 0xf2, 0xf2, 0x6a, 0xa9, - 0xb0, 0x9d, 0x9b, 0x00, 0x48, 0x81, 0x53, 0xe1, 0x95, 0xc2, 0x86, 0x5c, 0x8b, 0x2a, 0xb1, 0x97, - 0xef, 0xd4, 0x48, 0xf6, 0x47, 0x0c, 0x8e, 0x07, 0x73, 0x41, 0xcf, 0x00, 0x4c, 0xf8, 0xe3, 0xb9, - 0x5e, 0xfe, 0x7b, 0xbc, 0x5a, 0x4a, 0x66, 0x30, 0xd0, 0xb3, 0xa9, 0x5d, 0x79, 0xfe, 0xf9, 0xfb, - 0x9b, 0xe8, 0x0c, 0xba, 0x84, 0xfb, 0x3f, 0xed, 0xe8, 0x05, 0x80, 0x71, 0x8f, 0x88, 0xd2, 0x03, - 0x76, 0xf6, 0x15, 0xcc, 0x0d, 0xc4, 0x49, 0x01, 0x37, 0x84, 0x80, 0x34, 0xba, 0xda, 0x5f, 0x00, - 0xde, 0x97, 0x2f, 0xc4, 0x01, 0x7a, 0x0f, 0xe0, 0x3f, 0xa1, 0x1b, 0x83, 0x16, 0x06, 0x59, 0x0d, - 0x75, 0xbc, 0xa2, 0x0f, 0x0b, 0x97, 0xf2, 0x6e, 0x09, 0x79, 0x18, 0x2d, 0xfc, 0x26, 0x9f, 0x72, - 0xa5, 0x53, 0xee, 0xbe, 0x1b, 0x78, 0x5f, 0x3e, 0x26, 0x07, 0xe8, 0xd3, 0x69, 0x67, 0x07, 0x6f, - 0x36, 0xca, 0x0e, 0x57, 0x3d, 0xd8, 0x71, 0xca, 0xd2, 0x85, 0x38, 0x52, 0xf6, 0xa2, 0x90, 0x7d, - 0x1d, 0x5d, 0x1b, 0x42, 0x76, 0x59, 0xf4, 0xfe, 0xca, 0xda, 0xe1, 0xb1, 0x0a, 0x8e, 0x8e, 0x55, - 0xf0, 0xed, 0x58, 0x05, 0xaf, 0x4f, 0xd4, 0xc8, 0xd1, 0x89, 0x1a, 0xf9, 0x72, 0xa2, 0x46, 0x1e, - 0xcf, 0x9b, 0x96, 0x5b, 0x6f, 0x57, 0xf4, 0x2a, 0xdb, 0xc1, 0xeb, 0x8f, 0xb6, 0x73, 0x1b, 0xd4, - 0x7d, 0xc2, 0x9c, 0x06, 0xae, 0xd6, 0x89, 0x65, 0xe3, 0xa7, 0x72, 0x77, 0xb7, 0xd3, 0xa2, 0xbc, - 0x12, 0x17, 0xbf, 0xd3, 0xa5, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x68, 0x64, 0xf5, 0xe3, 0x2a, - 0x08, 0x00, 0x00, + // 691 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x95, 0xcf, 0x6b, 0x13, 0x41, + 0x14, 0xc7, 0x33, 0x69, 0x48, 0xe8, 0xb4, 0x4a, 0x19, 0x4b, 0x4d, 0x57, 0xbb, 0x0d, 0xab, 0xb4, + 0xb1, 0xda, 0x1d, 0x9a, 0x2a, 0x78, 0x10, 0xa1, 0x3f, 0x52, 0x09, 0x85, 0x52, 0x77, 0xd3, 0x82, + 0x22, 0x84, 0x4d, 0x32, 0x6c, 0x96, 0xa4, 0x3b, 0xe9, 0xce, 0xa4, 0x1a, 0x4a, 0x0f, 0x7a, 0xd1, + 0xa3, 0xe0, 0x1f, 0xe0, 0x41, 0xbc, 0x78, 0xd1, 0x3f, 0xa3, 0xc7, 0x82, 0x17, 0x4f, 0x22, 0xad, + 0xff, 0x83, 0x57, 0xd9, 0xd9, 0x89, 0xee, 0xda, 0xad, 0x89, 0xd0, 0x83, 0xb7, 0x99, 0x7d, 0xef, + 0x3b, 0xef, 0xf3, 0x7d, 0x99, 0x37, 0x81, 0xb9, 0x66, 0x77, 0x8f, 0xe0, 0xdd, 0x0e, 0xf1, 0xba, + 0x78, 0x6f, 0xa1, 0x4a, 0xb8, 0xb5, 0x80, 0x19, 0xb7, 0x9a, 0xc4, 0x63, 0x7a, 0xdb, 0xa3, 0x9c, + 0x22, 0xe4, 0x67, 0xe8, 0x22, 0x43, 0x97, 0x19, 0xca, 0x5c, 0x8d, 0xb2, 0x1d, 0xca, 0x70, 0xd5, + 0x62, 0x7f, 0x8a, 0xdb, 0x96, 0xed, 0xb8, 0x16, 0x77, 0xa8, 0x1b, 0xe8, 0x95, 0x71, 0x9b, 0xda, + 0x54, 0x2c, 0xb1, 0xbf, 0x92, 0x5f, 0xaf, 0xda, 0x94, 0xda, 0x2d, 0x82, 0xad, 0xb6, 0x83, 0x2d, + 0xd7, 0xa5, 0x5c, 0x48, 0x64, 0x4d, 0x45, 0x8d, 0xa1, 0x0a, 0x08, 0x82, 0xb8, 0x26, 0xe2, 0x92, + 0x33, 0x9e, 0x5b, 0xfb, 0x08, 0xe0, 0xa5, 0x87, 0xbe, 0xc6, 0x0c, 0x3e, 0x1b, 0x64, 0xb7, 0x43, + 0x18, 0x47, 0x6b, 0x10, 0xfe, 0x66, 0xcc, 0x82, 0x1c, 0xc8, 0x8f, 0x14, 0x66, 0xf4, 0xc0, 0x90, + 0xee, 0x1b, 0x8a, 0x7a, 0xd5, 0x37, 0x2d, 0x9b, 0x48, 0xad, 0x11, 0x52, 0xa2, 0xbb, 0x30, 0xcd, + 0xb8, 0xc5, 0x3b, 0x2c, 0x9b, 0xcc, 0x81, 0xfc, 0xc5, 0x42, 0x4e, 0x3f, 0xdd, 0x28, 0x3d, 0xa8, + 0x6d, 0x8a, 0x3c, 0x43, 0xe6, 0xa3, 0x09, 0x98, 0x66, 0xc4, 0xf2, 0x6a, 0x8d, 0xec, 0x50, 0x0e, + 0xe4, 0x87, 0x0d, 0xb9, 0xd3, 0xde, 0x02, 0x38, 0x1e, 0x25, 0x66, 0x6d, 0xea, 0x32, 0x82, 0xee, + 0xc3, 0x8c, 0xf4, 0x96, 0x05, 0xb9, 0xa1, 0xfc, 0x48, 0x41, 0x8d, 0xab, 0xb5, 0xd6, 0x69, 0xb5, + 0x02, 0xe5, 0x72, 0xea, 0xf0, 0xeb, 0x74, 0xc2, 0xe8, 0x89, 0xd0, 0x83, 0x88, 0xe5, 0xa4, 0xb0, + 0x3c, 0xdb, 0xd7, 0x72, 0x50, 0x3c, 0xec, 0x59, 0xd3, 0x21, 0x0a, 0x01, 0xf6, 0x3a, 0x9a, 0x85, + 0x19, 0xab, 0x5e, 0xf7, 0x08, 0x63, 0xa2, 0x9d, 0xc3, 0x46, 0x6f, 0xab, 0x99, 0x91, 0x9f, 0xe0, + 0x97, 0x9f, 0x7b, 0xa2, 0x75, 0x4d, 0xe2, 0xc9, 0xf6, 0x0f, 0x66, 0x47, 0x6a, 0xb4, 0xdb, 0x70, + 0x32, 0xdc, 0xa5, 0xe5, 0xee, 0x26, 0xa5, 0xad, 0x1e, 0xcb, 0x65, 0x98, 0x69, 0x53, 0xda, 0xaa, + 0x38, 0x75, 0x71, 0x76, 0xca, 0x48, 0xfb, 0xdb, 0x52, 0x5d, 0x7b, 0x02, 0x95, 0x38, 0xd5, 0xf9, + 0x74, 0x58, 0x6b, 0x40, 0xf5, 0xf4, 0xe9, 0x2b, 0xb4, 0xe3, 0xf2, 0x73, 0xbe, 0x76, 0xda, 0x07, + 0x00, 0xa7, 0xcf, 0x2c, 0xf5, 0x9f, 0xdd, 0x97, 0x39, 0x07, 0x8e, 0x86, 0x27, 0x00, 0x4d, 0xc1, + 0x49, 0xb3, 0xbc, 0xb4, 0x5e, 0x34, 0x2a, 0x66, 0x79, 0xa9, 0xbc, 0x65, 0x56, 0xb6, 0x36, 0xcc, + 0xcd, 0xe2, 0x4a, 0x69, 0xad, 0x54, 0x5c, 0x1d, 0x4b, 0xa0, 0x2c, 0x1c, 0x8f, 0x86, 0x97, 0x56, + 0xca, 0xa5, 0xed, 0xe2, 0x18, 0x40, 0x0a, 0x9c, 0x88, 0x46, 0x4a, 0x1b, 0x32, 0x96, 0x54, 0x52, + 0xaf, 0xde, 0xa9, 0x89, 0xc2, 0x8f, 0x14, 0x1c, 0x0d, 0xf7, 0x05, 0x3d, 0x07, 0x30, 0xd3, 0x5b, + 0xcf, 0xc6, 0xf9, 0x8f, 0x79, 0x1c, 0x94, 0x7c, 0xff, 0xc4, 0xc0, 0xa6, 0x76, 0xed, 0xc5, 0xe7, + 0xef, 0x6f, 0x92, 0x53, 0xe8, 0x0a, 0x3e, 0xfb, 0x05, 0x45, 0x2f, 0x01, 0x4c, 0x07, 0x42, 0x34, + 0xd3, 0xe7, 0xe4, 0x1e, 0xc1, 0x6c, 0xdf, 0x3c, 0x09, 0x70, 0x4b, 0x00, 0xcc, 0xa0, 0xeb, 0x67, + 0x03, 0xe0, 0x7d, 0x39, 0x88, 0x07, 0xe8, 0x3d, 0x80, 0x17, 0x22, 0x37, 0x06, 0xcd, 0xf7, 0xb3, + 0x1a, 0x19, 0x2c, 0x45, 0x1f, 0x34, 0x5d, 0xe2, 0xdd, 0x11, 0x78, 0x18, 0xcd, 0xff, 0xa5, 0x3f, + 0x95, 0x6a, 0xb7, 0xe2, 0x8f, 0x27, 0xde, 0x97, 0x33, 0x7b, 0x80, 0x3e, 0x01, 0x88, 0x4e, 0xdf, + 0x6c, 0x54, 0x18, 0xac, 0x7a, 0x78, 0xe2, 0x94, 0xc5, 0x7f, 0xd2, 0x48, 0xec, 0x05, 0x81, 0x7d, + 0x13, 0xdd, 0x18, 0x00, 0xbb, 0x52, 0xf3, 0xa5, 0xcb, 0xab, 0x87, 0xc7, 0x2a, 0x38, 0x3a, 0x56, + 0xc1, 0xb7, 0x63, 0x15, 0xbc, 0x3e, 0x51, 0x13, 0x47, 0x27, 0x6a, 0xe2, 0xcb, 0x89, 0x9a, 0x78, + 0x3c, 0x67, 0x3b, 0xbc, 0xd1, 0xa9, 0xea, 0x35, 0xba, 0x83, 0xd7, 0x1f, 0x6d, 0x17, 0x37, 0x08, + 0x7f, 0x4a, 0xbd, 0x26, 0xae, 0x35, 0x2c, 0xc7, 0xc5, 0xcf, 0xe4, 0xe9, 0xbc, 0xdb, 0x26, 0xac, + 0x9a, 0x16, 0xff, 0x5a, 0x8b, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xcf, 0x3c, 0x86, 0x13, 0x91, + 0x07, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1011,53 +952,6 @@ func (m *QueryStakersByPoolResponse) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } -func (m *StakerPoolResponse) 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 *StakerPoolResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *StakerPoolResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Valaccount != nil { - { - size, err := m.Valaccount.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintStakers(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if m.Staker != nil { - { - size, err := m.Staker.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintStakers(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func (m *QueryStakersByPoolCountRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1243,23 +1137,6 @@ func (m *QueryStakersByPoolResponse) Size() (n int) { return n } -func (m *StakerPoolResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Staker != nil { - l = m.Staker.Size() - n += 1 + l + sovStakers(uint64(l)) - } - if m.Valaccount != nil { - l = m.Valaccount.Size() - n += 1 + l + sovStakers(uint64(l)) - } - return n -} - func (m *QueryStakersByPoolCountRequest) Size() (n int) { if m == nil { return 0 @@ -1847,7 +1724,7 @@ func (m *QueryStakersByPoolResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Stakers = append(m.Stakers, StakerPoolResponse{}) + m.Stakers = append(m.Stakers, FullStaker{}) if err := m.Stakers[len(m.Stakers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1873,128 +1750,6 @@ func (m *QueryStakersByPoolResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *StakerPoolResponse) 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 ErrIntOverflowStakers - } - 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: StakerPoolResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: StakerPoolResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Staker", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowStakers - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthStakers - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthStakers - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Staker == nil { - m.Staker = &FullStaker{} - } - if err := m.Staker.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Valaccount", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowStakers - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthStakers - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthStakers - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Valaccount == nil { - m.Valaccount = &types.Valaccount{} - } - if err := m.Valaccount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipStakers(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthStakers - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *QueryStakersByPoolCountRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 From 405b806338c7a329fc9686114a00c1d21929e498 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Wed, 18 Dec 2024 15:24:41 +0100 Subject: [PATCH 16/24] chore: sorty by pool stake --- .../grpc_query_stakers_by_pool_count.go | 25 ++++++++++-- x/stakers/keeper/exported_functions.go | 40 ++++++++++++++++++- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/x/query/keeper/grpc_query_stakers_by_pool_count.go b/x/query/keeper/grpc_query_stakers_by_pool_count.go index 3fc2de68..bf8ab95d 100644 --- a/x/query/keeper/grpc_query_stakers_by_pool_count.go +++ b/x/query/keeper/grpc_query_stakers_by_pool_count.go @@ -2,8 +2,9 @@ package keeper import ( "context" - "github.com/KYVENetwork/chain/x/query/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -13,7 +14,25 @@ func (k Keeper) StakersByPoolCount(c context.Context, req *types.QueryStakersByP return nil, status.Error(codes.InvalidArgument, "invalid request") } - // ToDo no - op + ctx := sdk.UnwrapSDKContext(c) + + data := make([]types.FullStaker, 0) + + accumulator := func(address string, accumulate bool) bool { + if accumulate { + data = append(data, *k.GetFullStaker(ctx, address)) + } + return true + } + + var pageRes *query.PageResponse + var err error + + pageRes, err = k.stakerKeeper.GetPaginatedStakersByPoolCount(ctx, req.Pagination, accumulator) + + if err != nil { + return nil, err + } - return &types.QueryStakersByPoolCountResponse{}, nil + return &types.QueryStakersByPoolCountResponse{Stakers: data, Pagination: pageRes}, nil } diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index d84a821b..27ac2d1f 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -52,13 +52,41 @@ func (k Keeper) GetPaginatedStakersByPoolStake(ctx sdk.Context, pagination *quer return nil, err } - // TODO: sort by pool stake addresses := make([]string, 0) for _, validator := range validators { addresses = append(addresses, util.MustAccountAddressFromValAddress(validator.OperatorAddress)) } + // TODO: is this too expensive? + sort.Slice(addresses, func(i, j int) bool { + return k.GetValidatorTotalPoolStake(ctx, addresses[i]) > k.GetValidatorTotalPoolStake(ctx, addresses[j]) + }) + + pageRes, err := arrayPaginationAccumulator(addresses, pagination, accumulator) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return pageRes, nil +} + +func (k Keeper) GetPaginatedStakersByPoolCount(ctx sdk.Context, pagination *query.PageRequest, accumulator func(validator string, accumulate bool) bool) (*query.PageResponse, error) { + validators, err := k.stakingKeeper.GetBondedValidatorsByPower(ctx) + if err != nil { + return nil, err + } + + addresses := make([]string, 0) + + for _, validator := range validators { + addresses = append(addresses, util.MustAccountAddressFromValAddress(validator.OperatorAddress)) + } + + sort.Slice(addresses, func(i, j int) bool { + return len(k.GetValaccountsFromStaker(ctx, addresses[i])) > len(k.GetValaccountsFromStaker(ctx, addresses[j])) + }) + pageRes, err := arrayPaginationAccumulator(addresses, pagination, accumulator) if err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -138,6 +166,16 @@ func (k Keeper) GetValidatorPoolStake(ctx sdk.Context, staker string, poolId uin return k.GetValidatorPoolStakes(ctx, poolId, staker)[staker] } +// GetValidatorTotalPoolStake returns the total stake the validator has combined in every pool +func (k Keeper) GetValidatorTotalPoolStake(ctx sdk.Context, staker string) (totalStake uint64) { + valaccounts := k.GetValaccountsFromStaker(ctx, staker) + for _, valaccount := range valaccounts { + totalStake += k.GetValidatorPoolStake(ctx, valaccount.Staker, valaccount.PoolId) + } + + return +} + // GetValidatorPoolStakes returns a map for all pool validators with their effective stake. Effective stake // is the actual amount which determines the validator's voting power and is the actual amount at risk for // slashing. The effective stake can be lower (never higher) than the specified stake by the validators by From 513fadd1dadb333e16505b83ee28710cb9d4f7bf Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Wed, 18 Dec 2024 16:30:55 +0100 Subject: [PATCH 17/24] chore: added staker status --- docs/static/openapi.yml | 12 ++- proto/kyve/query/v1beta1/stakers.proto | 12 ++- x/query/keeper/grpc_query_staker.go | 2 +- x/query/types/stakers.pb.go | 118 ++++++++++++++----------- x/stakers/keeper/exported_functions.go | 31 +++++-- 5 files changed, 107 insertions(+), 68 deletions(-) diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 16e3e215..8b31768f 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -8063,15 +8063,19 @@ paths: status looks whether a staker is participating in pools or not - STAKER_STATUS_UNSPECIFIED: STAKER_STATUS_UNSPECIFIED ... - - STAKER_STATUS_ACTIVE: STAKER_STATUS_ACTIVE ... - - STAKER_STATUS_INACTIVE: STAKER_STATUS_INACTIVE ... + - STAKER_STATUS_PROTOCOL_ACTIVE: STAKER_STATUS_PROTOCOL_ACTIVE ... + - STAKER_STATUS_PROTOCOL_INACTIVE: STAKER_STATUS_PROTOCOL_INACTIVE ... + - STAKER_STATUS_CHAIN_ACTIVE: STAKER_STATUS_CHAIN_ACTIVE ... + - STAKER_STATUS_CHAIN_INACTIVE: STAKER_STATUS_CHAIN_INACTIVE ... in: query required: false type: string enum: - STAKER_STATUS_UNSPECIFIED - - STAKER_STATUS_ACTIVE - - STAKER_STATUS_INACTIVE + - STAKER_STATUS_PROTOCOL_ACTIVE + - STAKER_STATUS_PROTOCOL_INACTIVE + - STAKER_STATUS_CHAIN_ACTIVE + - STAKER_STATUS_CHAIN_INACTIVE default: STAKER_STATUS_UNSPECIFIED - name: search description: search searches for moniker OR address diff --git a/proto/kyve/query/v1beta1/stakers.proto b/proto/kyve/query/v1beta1/stakers.proto index 8a86e5f8..9bb2142d 100644 --- a/proto/kyve/query/v1beta1/stakers.proto +++ b/proto/kyve/query/v1beta1/stakers.proto @@ -56,10 +56,14 @@ enum StakerStatus { // STAKER_STATUS_UNSPECIFIED ... STAKER_STATUS_UNSPECIFIED = 0; - // STAKER_STATUS_ACTIVE ... - STAKER_STATUS_ACTIVE = 1; - // STAKER_STATUS_INACTIVE ... - STAKER_STATUS_INACTIVE = 2; + // STAKER_STATUS_PROTOCOL_ACTIVE ... + STAKER_STATUS_PROTOCOL_ACTIVE = 1; + // STAKER_STATUS_PROTOCOL_INACTIVE ... + STAKER_STATUS_PROTOCOL_INACTIVE = 2; + // STAKER_STATUS_CHAIN_ACTIVE ... + STAKER_STATUS_CHAIN_ACTIVE = 3; + // STAKER_STATUS_CHAIN_INACTIVE ... + STAKER_STATUS_CHAIN_INACTIVE = 4; } // QueryStakersResponse is the response type for the Query/Stakers RPC method. diff --git a/x/query/keeper/grpc_query_staker.go b/x/query/keeper/grpc_query_staker.go index ddfc323c..a72689ca 100644 --- a/x/query/keeper/grpc_query_staker.go +++ b/x/query/keeper/grpc_query_staker.go @@ -41,7 +41,7 @@ func (k Keeper) Stakers(c context.Context, req *types.QueryStakersRequest) (*typ var pageRes *query.PageResponse var err error - pageRes, err = k.stakerKeeper.GetPaginatedStakersByPoolStake(ctx, req.Pagination, accumulator) + pageRes, err = k.stakerKeeper.GetPaginatedStakersByPoolStake(ctx, req.Pagination, req.Status, accumulator) if err != nil { return nil, err diff --git a/x/query/types/stakers.pb.go b/x/query/types/stakers.pb.go index 4f1a0789..3a8b99db 100644 --- a/x/query/types/stakers.pb.go +++ b/x/query/types/stakers.pb.go @@ -37,22 +37,30 @@ type StakerStatus int32 const ( // STAKER_STATUS_UNSPECIFIED ... STAKER_STATUS_UNSPECIFIED StakerStatus = 0 - // STAKER_STATUS_ACTIVE ... - STAKER_STATUS_ACTIVE StakerStatus = 1 - // STAKER_STATUS_INACTIVE ... - STAKER_STATUS_INACTIVE StakerStatus = 2 + // STAKER_STATUS_PROTOCOL_ACTIVE ... + STAKER_STATUS_PROTOCOL_ACTIVE StakerStatus = 1 + // STAKER_STATUS_PROTOCOL_INACTIVE ... + STAKER_STATUS_PROTOCOL_INACTIVE StakerStatus = 2 + // STAKER_STATUS_CHAIN_ACTIVE ... + STAKER_STATUS_CHAIN_ACTIVE StakerStatus = 3 + // STAKER_STATUS_CHAIN_INACTIVE ... + STAKER_STATUS_CHAIN_INACTIVE StakerStatus = 4 ) var StakerStatus_name = map[int32]string{ 0: "STAKER_STATUS_UNSPECIFIED", - 1: "STAKER_STATUS_ACTIVE", - 2: "STAKER_STATUS_INACTIVE", + 1: "STAKER_STATUS_PROTOCOL_ACTIVE", + 2: "STAKER_STATUS_PROTOCOL_INACTIVE", + 3: "STAKER_STATUS_CHAIN_ACTIVE", + 4: "STAKER_STATUS_CHAIN_INACTIVE", } var StakerStatus_value = map[string]int32{ - "STAKER_STATUS_UNSPECIFIED": 0, - "STAKER_STATUS_ACTIVE": 1, - "STAKER_STATUS_INACTIVE": 2, + "STAKER_STATUS_UNSPECIFIED": 0, + "STAKER_STATUS_PROTOCOL_ACTIVE": 1, + "STAKER_STATUS_PROTOCOL_INACTIVE": 2, + "STAKER_STATUS_CHAIN_ACTIVE": 3, + "STAKER_STATUS_CHAIN_INACTIVE": 4, } func (x StakerStatus) String() string { @@ -482,51 +490,53 @@ func init() { func init() { proto.RegisterFile("kyve/query/v1beta1/stakers.proto", fileDescriptor_6aa31a681566da33) } var fileDescriptor_6aa31a681566da33 = []byte{ - // 691 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x95, 0xcf, 0x6b, 0x13, 0x41, - 0x14, 0xc7, 0x33, 0x69, 0x48, 0xe8, 0xb4, 0x4a, 0x19, 0x4b, 0x4d, 0x57, 0xbb, 0x0d, 0xab, 0xb4, - 0xb1, 0xda, 0x1d, 0x9a, 0x2a, 0x78, 0x10, 0xa1, 0x3f, 0x52, 0x09, 0x85, 0x52, 0x77, 0xd3, 0x82, - 0x22, 0x84, 0x4d, 0x32, 0x6c, 0x96, 0xa4, 0x3b, 0xe9, 0xce, 0xa4, 0x1a, 0x4a, 0x0f, 0x7a, 0xd1, - 0xa3, 0xe0, 0x1f, 0xe0, 0x41, 0xbc, 0x78, 0xd1, 0x3f, 0xa3, 0xc7, 0x82, 0x17, 0x4f, 0x22, 0xad, - 0xff, 0x83, 0x57, 0xd9, 0xd9, 0x89, 0xee, 0xda, 0xad, 0x89, 0xd0, 0x83, 0xb7, 0x99, 0x7d, 0xef, - 0x3b, 0xef, 0xf3, 0x7d, 0x99, 0x37, 0x81, 0xb9, 0x66, 0x77, 0x8f, 0xe0, 0xdd, 0x0e, 0xf1, 0xba, - 0x78, 0x6f, 0xa1, 0x4a, 0xb8, 0xb5, 0x80, 0x19, 0xb7, 0x9a, 0xc4, 0x63, 0x7a, 0xdb, 0xa3, 0x9c, - 0x22, 0xe4, 0x67, 0xe8, 0x22, 0x43, 0x97, 0x19, 0xca, 0x5c, 0x8d, 0xb2, 0x1d, 0xca, 0x70, 0xd5, - 0x62, 0x7f, 0x8a, 0xdb, 0x96, 0xed, 0xb8, 0x16, 0x77, 0xa8, 0x1b, 0xe8, 0x95, 0x71, 0x9b, 0xda, - 0x54, 0x2c, 0xb1, 0xbf, 0x92, 0x5f, 0xaf, 0xda, 0x94, 0xda, 0x2d, 0x82, 0xad, 0xb6, 0x83, 0x2d, - 0xd7, 0xa5, 0x5c, 0x48, 0x64, 0x4d, 0x45, 0x8d, 0xa1, 0x0a, 0x08, 0x82, 0xb8, 0x26, 0xe2, 0x92, - 0x33, 0x9e, 0x5b, 0xfb, 0x08, 0xe0, 0xa5, 0x87, 0xbe, 0xc6, 0x0c, 0x3e, 0x1b, 0x64, 0xb7, 0x43, - 0x18, 0x47, 0x6b, 0x10, 0xfe, 0x66, 0xcc, 0x82, 0x1c, 0xc8, 0x8f, 0x14, 0x66, 0xf4, 0xc0, 0x90, - 0xee, 0x1b, 0x8a, 0x7a, 0xd5, 0x37, 0x2d, 0x9b, 0x48, 0xad, 0x11, 0x52, 0xa2, 0xbb, 0x30, 0xcd, - 0xb8, 0xc5, 0x3b, 0x2c, 0x9b, 0xcc, 0x81, 0xfc, 0xc5, 0x42, 0x4e, 0x3f, 0xdd, 0x28, 0x3d, 0xa8, - 0x6d, 0x8a, 0x3c, 0x43, 0xe6, 0xa3, 0x09, 0x98, 0x66, 0xc4, 0xf2, 0x6a, 0x8d, 0xec, 0x50, 0x0e, - 0xe4, 0x87, 0x0d, 0xb9, 0xd3, 0xde, 0x02, 0x38, 0x1e, 0x25, 0x66, 0x6d, 0xea, 0x32, 0x82, 0xee, - 0xc3, 0x8c, 0xf4, 0x96, 0x05, 0xb9, 0xa1, 0xfc, 0x48, 0x41, 0x8d, 0xab, 0xb5, 0xd6, 0x69, 0xb5, - 0x02, 0xe5, 0x72, 0xea, 0xf0, 0xeb, 0x74, 0xc2, 0xe8, 0x89, 0xd0, 0x83, 0x88, 0xe5, 0xa4, 0xb0, - 0x3c, 0xdb, 0xd7, 0x72, 0x50, 0x3c, 0xec, 0x59, 0xd3, 0x21, 0x0a, 0x01, 0xf6, 0x3a, 0x9a, 0x85, - 0x19, 0xab, 0x5e, 0xf7, 0x08, 0x63, 0xa2, 0x9d, 0xc3, 0x46, 0x6f, 0xab, 0x99, 0x91, 0x9f, 0xe0, - 0x97, 0x9f, 0x7b, 0xa2, 0x75, 0x4d, 0xe2, 0xc9, 0xf6, 0x0f, 0x66, 0x47, 0x6a, 0xb4, 0xdb, 0x70, - 0x32, 0xdc, 0xa5, 0xe5, 0xee, 0x26, 0xa5, 0xad, 0x1e, 0xcb, 0x65, 0x98, 0x69, 0x53, 0xda, 0xaa, - 0x38, 0x75, 0x71, 0x76, 0xca, 0x48, 0xfb, 0xdb, 0x52, 0x5d, 0x7b, 0x02, 0x95, 0x38, 0xd5, 0xf9, - 0x74, 0x58, 0x6b, 0x40, 0xf5, 0xf4, 0xe9, 0x2b, 0xb4, 0xe3, 0xf2, 0x73, 0xbe, 0x76, 0xda, 0x07, - 0x00, 0xa7, 0xcf, 0x2c, 0xf5, 0x9f, 0xdd, 0x97, 0x39, 0x07, 0x8e, 0x86, 0x27, 0x00, 0x4d, 0xc1, - 0x49, 0xb3, 0xbc, 0xb4, 0x5e, 0x34, 0x2a, 0x66, 0x79, 0xa9, 0xbc, 0x65, 0x56, 0xb6, 0x36, 0xcc, - 0xcd, 0xe2, 0x4a, 0x69, 0xad, 0x54, 0x5c, 0x1d, 0x4b, 0xa0, 0x2c, 0x1c, 0x8f, 0x86, 0x97, 0x56, - 0xca, 0xa5, 0xed, 0xe2, 0x18, 0x40, 0x0a, 0x9c, 0x88, 0x46, 0x4a, 0x1b, 0x32, 0x96, 0x54, 0x52, - 0xaf, 0xde, 0xa9, 0x89, 0xc2, 0x8f, 0x14, 0x1c, 0x0d, 0xf7, 0x05, 0x3d, 0x07, 0x30, 0xd3, 0x5b, - 0xcf, 0xc6, 0xf9, 0x8f, 0x79, 0x1c, 0x94, 0x7c, 0xff, 0xc4, 0xc0, 0xa6, 0x76, 0xed, 0xc5, 0xe7, - 0xef, 0x6f, 0x92, 0x53, 0xe8, 0x0a, 0x3e, 0xfb, 0x05, 0x45, 0x2f, 0x01, 0x4c, 0x07, 0x42, 0x34, - 0xd3, 0xe7, 0xe4, 0x1e, 0xc1, 0x6c, 0xdf, 0x3c, 0x09, 0x70, 0x4b, 0x00, 0xcc, 0xa0, 0xeb, 0x67, - 0x03, 0xe0, 0x7d, 0x39, 0x88, 0x07, 0xe8, 0x3d, 0x80, 0x17, 0x22, 0x37, 0x06, 0xcd, 0xf7, 0xb3, - 0x1a, 0x19, 0x2c, 0x45, 0x1f, 0x34, 0x5d, 0xe2, 0xdd, 0x11, 0x78, 0x18, 0xcd, 0xff, 0xa5, 0x3f, - 0x95, 0x6a, 0xb7, 0xe2, 0x8f, 0x27, 0xde, 0x97, 0x33, 0x7b, 0x80, 0x3e, 0x01, 0x88, 0x4e, 0xdf, - 0x6c, 0x54, 0x18, 0xac, 0x7a, 0x78, 0xe2, 0x94, 0xc5, 0x7f, 0xd2, 0x48, 0xec, 0x05, 0x81, 0x7d, - 0x13, 0xdd, 0x18, 0x00, 0xbb, 0x52, 0xf3, 0xa5, 0xcb, 0xab, 0x87, 0xc7, 0x2a, 0x38, 0x3a, 0x56, - 0xc1, 0xb7, 0x63, 0x15, 0xbc, 0x3e, 0x51, 0x13, 0x47, 0x27, 0x6a, 0xe2, 0xcb, 0x89, 0x9a, 0x78, - 0x3c, 0x67, 0x3b, 0xbc, 0xd1, 0xa9, 0xea, 0x35, 0xba, 0x83, 0xd7, 0x1f, 0x6d, 0x17, 0x37, 0x08, - 0x7f, 0x4a, 0xbd, 0x26, 0xae, 0x35, 0x2c, 0xc7, 0xc5, 0xcf, 0xe4, 0xe9, 0xbc, 0xdb, 0x26, 0xac, - 0x9a, 0x16, 0xff, 0x5a, 0x8b, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xcf, 0x3c, 0x86, 0x13, 0x91, - 0x07, 0x00, 0x00, + // 725 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0x41, 0x4f, 0x13, 0x4d, + 0x18, 0xee, 0x94, 0xa6, 0x0d, 0x03, 0xdf, 0x17, 0x32, 0x1f, 0xf9, 0x2c, 0x2b, 0x2c, 0x75, 0x31, + 0x50, 0x51, 0x76, 0x42, 0xd1, 0xc4, 0x83, 0x31, 0x29, 0xa5, 0x68, 0x83, 0x29, 0x75, 0x5b, 0x48, + 0x34, 0x26, 0x9b, 0x6d, 0x3b, 0xd9, 0x36, 0x2d, 0x3b, 0x65, 0x67, 0x8b, 0x36, 0x84, 0x83, 0x5e, + 0xf4, 0x68, 0xe2, 0x0f, 0xf0, 0x60, 0xbc, 0x78, 0xd1, 0x3f, 0xe0, 0x9d, 0x23, 0x89, 0x17, 0x4f, + 0xc6, 0x80, 0xff, 0xc1, 0xab, 0xd9, 0xdd, 0x59, 0xdc, 0x95, 0xad, 0xad, 0x09, 0x07, 0x6f, 0x33, + 0x3b, 0xcf, 0xf3, 0xbe, 0xcf, 0xf3, 0x74, 0xde, 0x29, 0x4c, 0xb5, 0x7a, 0x7b, 0x04, 0xef, 0x76, + 0x89, 0xd9, 0xc3, 0x7b, 0xcb, 0x55, 0x62, 0x69, 0xcb, 0x98, 0x59, 0x5a, 0x8b, 0x98, 0x4c, 0xee, + 0x98, 0xd4, 0xa2, 0x08, 0xd9, 0x08, 0xd9, 0x41, 0xc8, 0x1c, 0x21, 0x2c, 0xd6, 0x28, 0xdb, 0xa1, + 0x0c, 0x57, 0x35, 0xf6, 0x2b, 0xb9, 0xa3, 0xe9, 0x4d, 0x43, 0xb3, 0x9a, 0xd4, 0x70, 0xf9, 0xc2, + 0xa4, 0x4e, 0x75, 0xea, 0x2c, 0xb1, 0xbd, 0xe2, 0x5f, 0xa7, 0x75, 0x4a, 0xf5, 0x36, 0xc1, 0x5a, + 0xa7, 0x89, 0x35, 0xc3, 0xa0, 0x96, 0x43, 0xe1, 0x3d, 0x05, 0x31, 0x44, 0x95, 0xab, 0xc0, 0x3d, + 0x97, 0x9c, 0x73, 0xae, 0x33, 0x5c, 0xb7, 0xf4, 0x1e, 0xc0, 0xff, 0xee, 0xdb, 0x9c, 0xb2, 0xfb, + 0x59, 0x21, 0xbb, 0x5d, 0xc2, 0x2c, 0xb4, 0x0e, 0xe1, 0x4f, 0x8d, 0x49, 0x90, 0x02, 0xe9, 0xb1, + 0xcc, 0xbc, 0xec, 0x1a, 0x92, 0x6d, 0x43, 0x41, 0xaf, 0x72, 0x49, 0xd3, 0x09, 0xe7, 0x2a, 0x3e, + 0x26, 0xba, 0x09, 0xe3, 0xcc, 0xd2, 0xac, 0x2e, 0x4b, 0x46, 0x53, 0x20, 0xfd, 0x6f, 0x26, 0x25, + 0x9f, 0x0d, 0x4a, 0x76, 0x7b, 0x97, 0x1d, 0x9c, 0xc2, 0xf1, 0xe8, 0x7f, 0x18, 0x67, 0x44, 0x33, + 0x6b, 0x8d, 0xe4, 0x48, 0x0a, 0xa4, 0x47, 0x15, 0xbe, 0x93, 0x5e, 0x03, 0x38, 0x19, 0x54, 0xcc, + 0x3a, 0xd4, 0x60, 0x04, 0xdd, 0x86, 0x09, 0xee, 0x2d, 0x09, 0x52, 0x23, 0xe9, 0xb1, 0x8c, 0x18, + 0xd6, 0x6b, 0xbd, 0xdb, 0x6e, 0xbb, 0xcc, 0xd5, 0xd8, 0xe1, 0x97, 0xd9, 0x88, 0xe2, 0x91, 0xd0, + 0x9d, 0x80, 0xe5, 0xa8, 0x63, 0x79, 0x61, 0xa0, 0x65, 0xb7, 0xb9, 0xdf, 0xb3, 0x24, 0x43, 0xe4, + 0x13, 0xe8, 0x25, 0x9a, 0x84, 0x09, 0xad, 0x5e, 0x37, 0x09, 0x63, 0x4e, 0x9c, 0xa3, 0x8a, 0xb7, + 0x95, 0xca, 0x81, 0x9f, 0xe0, 0xd4, 0xcf, 0x2d, 0x27, 0xba, 0x16, 0x31, 0x79, 0xfc, 0xc3, 0xd9, + 0xe1, 0x1c, 0xe9, 0x3a, 0x9c, 0xf2, 0xa7, 0xb4, 0xda, 0x2b, 0x51, 0xda, 0xf6, 0xb4, 0x5c, 0x80, + 0x89, 0x0e, 0xa5, 0x6d, 0xb5, 0x59, 0x77, 0x6a, 0xc7, 0x94, 0xb8, 0xbd, 0x2d, 0xd4, 0xa5, 0x47, + 0x50, 0x08, 0x63, 0x9d, 0x4f, 0xc2, 0x52, 0x03, 0x8a, 0x67, 0xab, 0xe7, 0x68, 0xd7, 0xb0, 0xce, + 0xf9, 0xda, 0x49, 0xef, 0x00, 0x9c, 0xed, 0xdb, 0xea, 0x2f, 0xbb, 0x2f, 0x8b, 0x1f, 0x01, 0x1c, + 0xf7, 0x8f, 0x00, 0x9a, 0x81, 0x53, 0xe5, 0x4a, 0x76, 0x23, 0xaf, 0xa8, 0xe5, 0x4a, 0xb6, 0xb2, + 0x55, 0x56, 0xb7, 0x8a, 0xe5, 0x52, 0x3e, 0x57, 0x58, 0x2f, 0xe4, 0xd7, 0x26, 0x22, 0xe8, 0x12, + 0x9c, 0x09, 0x1e, 0x97, 0x94, 0xcd, 0xca, 0x66, 0x6e, 0xf3, 0x9e, 0x9a, 0xcd, 0x55, 0x0a, 0xdb, + 0xf9, 0x09, 0x80, 0xe6, 0xe0, 0x6c, 0x1f, 0x48, 0xa1, 0xc8, 0x41, 0x51, 0x24, 0x42, 0x21, 0x08, + 0xca, 0xdd, 0xcd, 0x16, 0x8a, 0x5e, 0x91, 0x11, 0x94, 0x82, 0xd3, 0x61, 0xe7, 0xa7, 0x15, 0x62, + 0x42, 0xec, 0xc5, 0x1b, 0x31, 0x92, 0xf9, 0x1e, 0x83, 0xe3, 0xfe, 0xb0, 0xd1, 0x53, 0x00, 0x13, + 0xde, 0x7a, 0x21, 0x2c, 0xd4, 0x90, 0x17, 0x47, 0x48, 0x0f, 0x06, 0xba, 0xd9, 0x49, 0x73, 0xcf, + 0x3e, 0x7d, 0x7b, 0x15, 0x9d, 0x41, 0x17, 0x71, 0xff, 0x67, 0x19, 0x3d, 0x07, 0x30, 0xee, 0x12, + 0xd1, 0xfc, 0x80, 0xca, 0x9e, 0x82, 0x85, 0x81, 0x38, 0x2e, 0xe0, 0x9a, 0x23, 0x60, 0x1e, 0x5d, + 0xee, 0x2f, 0x00, 0xef, 0xf3, 0xe9, 0x3e, 0x40, 0x6f, 0x01, 0xfc, 0x27, 0x70, 0x0d, 0xd1, 0xd2, + 0x20, 0xab, 0x81, 0x69, 0x15, 0xe4, 0x61, 0xe1, 0x5c, 0xde, 0x0d, 0x47, 0x1e, 0x46, 0x4b, 0xbf, + 0xc9, 0x47, 0xad, 0xf6, 0x54, 0x7b, 0xe6, 0xf1, 0x3e, 0x7f, 0x08, 0x0e, 0xd0, 0x07, 0x00, 0xd1, + 0xd9, 0x71, 0x41, 0x99, 0xe1, 0xba, 0xfb, 0xc7, 0x58, 0x58, 0xf9, 0x23, 0x0e, 0x97, 0xbd, 0xec, + 0xc8, 0xbe, 0x8a, 0xae, 0x0c, 0x21, 0x5b, 0xad, 0xd9, 0xd4, 0xd5, 0xb5, 0xc3, 0x63, 0x11, 0x1c, + 0x1d, 0x8b, 0xe0, 0xeb, 0xb1, 0x08, 0x5e, 0x9e, 0x88, 0x91, 0xa3, 0x13, 0x31, 0xf2, 0xf9, 0x44, + 0x8c, 0x3c, 0x5c, 0xd4, 0x9b, 0x56, 0xa3, 0x5b, 0x95, 0x6b, 0x74, 0x07, 0x6f, 0x3c, 0xd8, 0xce, + 0x17, 0x89, 0xf5, 0x98, 0x9a, 0x2d, 0x5c, 0x6b, 0x68, 0x4d, 0x03, 0x3f, 0xe1, 0xd5, 0xad, 0x5e, + 0x87, 0xb0, 0x6a, 0xdc, 0xf9, 0x2b, 0x5c, 0xf9, 0x11, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x55, 0x4c, + 0xd2, 0xe6, 0x07, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 27ac2d1f..90b9c3e2 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -2,6 +2,7 @@ package keeper import ( "context" + querytypes "github.com/KYVENetwork/chain/x/query/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "sort" @@ -46,7 +47,7 @@ func (k Keeper) GetAllStakerAddressesOfPool(ctx sdk.Context, poolId uint64) (sta return stakers } -func (k Keeper) GetPaginatedStakersByPoolStake(ctx sdk.Context, pagination *query.PageRequest, accumulator func(validator string, accumulate bool) bool) (*query.PageResponse, error) { +func (k Keeper) GetPaginatedStakersByPoolStake(ctx sdk.Context, pagination *query.PageRequest, stakerStatus querytypes.StakerStatus, accumulator func(validator string, accumulate bool) bool) (*query.PageResponse, error) { validators, err := k.stakingKeeper.GetBondedValidatorsByPower(ctx) if err != nil { return nil, err @@ -55,13 +56,33 @@ func (k Keeper) GetPaginatedStakersByPoolStake(ctx sdk.Context, pagination *quer addresses := make([]string, 0) for _, validator := range validators { - addresses = append(addresses, util.MustAccountAddressFromValAddress(validator.OperatorAddress)) + address := util.MustAccountAddressFromValAddress(validator.OperatorAddress) + + if stakerStatus == querytypes.STAKER_STATUS_PROTOCOL_ACTIVE && len(k.GetValaccountsFromStaker(ctx, address)) == 0 { + continue + } + + if stakerStatus == querytypes.STAKER_STATUS_PROTOCOL_INACTIVE && len(k.GetValaccountsFromStaker(ctx, address)) > 0 { + continue + } + + if stakerStatus == querytypes.STAKER_STATUS_CHAIN_ACTIVE && !validator.IsBonded() { + continue + } + + if stakerStatus == querytypes.STAKER_STATUS_CHAIN_INACTIVE && validator.IsBonded() { + continue + } + + addresses = append(addresses, address) } // TODO: is this too expensive? - sort.Slice(addresses, func(i, j int) bool { - return k.GetValidatorTotalPoolStake(ctx, addresses[i]) > k.GetValidatorTotalPoolStake(ctx, addresses[j]) - }) + if stakerStatus == querytypes.STAKER_STATUS_UNSPECIFIED || stakerStatus == querytypes.STAKER_STATUS_PROTOCOL_ACTIVE { + sort.Slice(addresses, func(i, j int) bool { + return k.GetValidatorTotalPoolStake(ctx, addresses[i]) > k.GetValidatorTotalPoolStake(ctx, addresses[j]) + }) + } pageRes, err := arrayPaginationAccumulator(addresses, pagination, accumulator) if err != nil { From 7a8151044f9b4472118cec578576e569d83a6b0e Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Wed, 18 Dec 2024 16:51:01 +0100 Subject: [PATCH 18/24] fix: make all --- proto/kyve/query/v1beta1/query.proto | 2 +- proto/kyve/query/v1beta1/stakers.proto | 1 - testutil/integration/checks.go | 16 ++-- .../grpc_query_stakers_by_pool_count.go | 1 + x/query/types/query.pb.go | 86 +++++++++--------- x/query/types/stakers.pb.go | 90 +++++++++---------- x/stakers/keeper/exported_functions.go | 3 +- 7 files changed, 99 insertions(+), 100 deletions(-) diff --git a/proto/kyve/query/v1beta1/query.proto b/proto/kyve/query/v1beta1/query.proto index a812a0b2..dc35d847 100644 --- a/proto/kyve/query/v1beta1/query.proto +++ b/proto/kyve/query/v1beta1/query.proto @@ -4,9 +4,9 @@ package kyve.query.v1beta1; import "amino/amino.proto"; import "cosmos/base/v1beta1/coin.proto"; +import "cosmos/staking/v1beta1/staking.proto"; import "gogoproto/gogo.proto"; import "kyve/pool/v1beta1/pool.proto"; -import "cosmos/staking/v1beta1/staking.proto"; option go_package = "github.com/KYVENetwork/chain/x/query/types"; diff --git a/proto/kyve/query/v1beta1/stakers.proto b/proto/kyve/query/v1beta1/stakers.proto index 9bb2142d..876752c9 100644 --- a/proto/kyve/query/v1beta1/stakers.proto +++ b/proto/kyve/query/v1beta1/stakers.proto @@ -6,7 +6,6 @@ import "cosmos/base/query/v1beta1/pagination.proto"; import "gogoproto/gogo.proto"; import "google/api/annotations.proto"; import "kyve/query/v1beta1/query.proto"; -import "kyve/stakers/v1beta1/stakers.proto"; option go_package = "github.com/KYVENetwork/chain/x/query/types"; diff --git a/testutil/integration/checks.go b/testutil/integration/checks.go index b76c5fdf..287907de 100644 --- a/testutil/integration/checks.go +++ b/testutil/integration/checks.go @@ -2,6 +2,7 @@ package integration import ( "fmt" + "sort" "time" "github.com/KYVENetwork/chain/util" @@ -123,19 +124,18 @@ func (suite *KeeperTestSuite) VerifyPoolQueries() { // test stakers by pool valaccounts := suite.App().StakersKeeper.GetAllValaccountsOfPool(suite.Ctx(), poolsState[i].Id) - stakersByPoolState := make([]querytypes.StakerPoolResponse, 0) + stakersByPoolState := make([]querytypes.FullStaker, 0) for _, valaccount := range valaccounts { - _, stakerFound := suite.App().StakersKeeper.GetValidator(suite.Ctx(), valaccount.Staker) - - if stakerFound { - stakersByPoolState = append(stakersByPoolState, querytypes.StakerPoolResponse{ - Staker: suite.App().QueryKeeper.GetFullStaker(suite.Ctx(), valaccount.Staker), - Valaccount: valaccount, - }) + if _, stakerFound := suite.App().StakersKeeper.GetValidator(suite.Ctx(), valaccount.Staker); stakerFound { + stakersByPoolState = append(stakersByPoolState, *suite.App().QueryKeeper.GetFullStaker(suite.Ctx(), valaccount.Staker)) } } + sort.Slice(stakersByPoolState, func(a, b int) bool { + return suite.App().StakersKeeper.GetValidatorPoolStake(suite.Ctx(), stakersByPoolState[a].Address, poolsState[i].Id) > suite.App().StakersKeeper.GetValidatorPoolStake(suite.Ctx(), stakersByPoolState[b].Address, poolsState[i].Id) + }) + stakersByPoolQuery, stakersByPoolQueryErr := suite.App().QueryKeeper.StakersByPool(suite.Ctx(), &querytypes.QueryStakersByPoolRequest{ PoolId: poolsState[i].Id, }) diff --git a/x/query/keeper/grpc_query_stakers_by_pool_count.go b/x/query/keeper/grpc_query_stakers_by_pool_count.go index bf8ab95d..868fbe1a 100644 --- a/x/query/keeper/grpc_query_stakers_by_pool_count.go +++ b/x/query/keeper/grpc_query_stakers_by_pool_count.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "github.com/KYVENetwork/chain/x/query/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" diff --git a/x/query/types/query.pb.go b/x/query/types/query.pb.go index 4e07f51c..40a905af 100644 --- a/x/query/types/query.pb.go +++ b/x/query/types/query.pb.go @@ -479,49 +479,49 @@ var fileDescriptor_6b41255feae93a15 = []byte{ 0xf7, 0x7e, 0x6f, 0x62, 0x10, 0x4c, 0x17, 0x73, 0x1c, 0x1d, 0xcf, 0x70, 0xbd, 0x88, 0xe6, 0xbb, 0x63, 0x2c, 0xd0, 0xae, 0xb6, 0xc2, 0xaa, 0x66, 0x82, 0x41, 0x28, 0xe3, 0xa1, 0xf6, 0x98, 0xf8, 0xf6, 0xeb, 0xa8, 0x24, 0x94, 0x45, 0xea, 0xaf, 0x86, 0x6d, 0x07, 0x29, 0xe3, 0x25, 0xe3, 0xd1, - 0x18, 0x71, 0xbc, 0xcc, 0x93, 0x32, 0x42, 0x4d, 0xfc, 0x41, 0xce, 0x72, 0xa6, 0x8e, 0x91, 0x3c, - 0x19, 0xef, 0xdb, 0xaa, 0x78, 0xc5, 0x58, 0xb1, 0xbc, 0x23, 0x0d, 0x13, 0x7d, 0xd7, 0xe4, 0xe4, - 0x02, 0x4d, 0x09, 0xcd, 0x97, 0x10, 0x63, 0x6b, 0x54, 0xff, 0xe7, 0x26, 0xf0, 0x86, 0x88, 0x93, - 0xf4, 0x2b, 0xc6, 0x0a, 0xd8, 0x01, 0x1b, 0x24, 0xf3, 0x9d, 0x9e, 0x33, 0x70, 0xe3, 0x0d, 0x92, - 0x41, 0x08, 0x5c, 0x8a, 0x4a, 0xec, 0x6f, 0xf4, 0x9c, 0x81, 0x17, 0xab, 0x33, 0xf4, 0xc1, 0x66, - 0x3d, 0xa3, 0x82, 0x94, 0xd8, 0x6f, 0x2a, 0xb7, 0x35, 0x25, 0xba, 0x60, 0x39, 0xf3, 0x5d, 0x8d, - 0x96, 0x67, 0xf8, 0x12, 0x3c, 0x24, 0xf4, 0xa8, 0x40, 0x82, 0x30, 0x9a, 0xf0, 0x09, 0xaa, 0x71, - 0x72, 0x82, 0x49, 0x3e, 0x11, 0xfe, 0x3d, 0x89, 0x1a, 0x3e, 0x3e, 0x3d, 0xef, 0x36, 0xfe, 0x38, - 0xef, 0xbe, 0xa5, 0xd9, 0xf2, 0x6c, 0x1a, 0x12, 0x16, 0x95, 0x48, 0x4c, 0xc2, 0xe7, 0x38, 0x47, - 0xe9, 0x62, 0x1f, 0xa7, 0xf1, 0x83, 0x65, 0x8a, 0x43, 0x99, 0xe1, 0x6b, 0x95, 0x00, 0xbe, 0x07, - 0x5e, 0x9d, 0x55, 0x05, 0x43, 0x59, 0x42, 0xa8, 0xc0, 0xf5, 0x1c, 0x15, 0x7e, 0x4b, 0x31, 0xef, - 0x68, 0xf7, 0xa7, 0xc6, 0x0b, 0x8f, 0x41, 0x5b, 0x30, 0x81, 0x8a, 0xe4, 0x68, 0x46, 0x33, 0xee, - 0x6f, 0xf6, 0x9a, 0x83, 0xf6, 0xde, 0xa3, 0x50, 0x57, 0x0c, 0xe5, 0xcc, 0xad, 0x36, 0xe1, 0x88, - 0x11, 0x3a, 0x7c, 0x2a, 0x39, 0xfd, 0xf4, 0x67, 0x77, 0x90, 0x13, 0x31, 0x99, 0x8d, 0xc3, 0x94, - 0x95, 0x91, 0x19, 0xa6, 0xfe, 0xf7, 0x21, 0xcf, 0xa6, 0x91, 0x58, 0x54, 0x98, 0xab, 0x0b, 0xfc, - 0xc7, 0xbf, 0x7f, 0x79, 0xe2, 0xc4, 0x40, 0x15, 0x39, 0x90, 0x35, 0x60, 0xd7, 0x96, 0x94, 0xd3, - 0xc6, 0xfe, 0x96, 0xe2, 0xa5, 0x01, 0x87, 0xd2, 0x03, 0x9f, 0x82, 0x16, 0x17, 0x48, 0xcc, 0xb8, - 0xef, 0xf5, 0x9c, 0x41, 0x67, 0x6f, 0x27, 0x54, 0x9b, 0xa2, 0xf4, 0xb3, 0x64, 0xa4, 0x24, 0x87, - 0x0a, 0x14, 0x1b, 0x70, 0xff, 0x37, 0x07, 0x80, 0x83, 0x59, 0xa1, 0x93, 0xd4, 0x52, 0x0b, 0x94, - 0x65, 0x35, 0xe6, 0x5c, 0x89, 0xe6, 0xc5, 0xd6, 0x84, 0x9f, 0x00, 0x6f, 0x8e, 0x0a, 0x92, 0x21, - 0xc1, 0x6a, 0x25, 0x5f, 0x7b, 0xef, 0x1d, 0xdb, 0xb1, 0xdd, 0x00, 0x5b, 0xe7, 0x85, 0x05, 0xc6, - 0x57, 0x77, 0xe0, 0x00, 0xbc, 0xa6, 0x3b, 0x90, 0x94, 0x4c, 0x1b, 0x4d, 0x3d, 0x5e, 0xe5, 0x37, - 0xe4, 0xa6, 0x18, 0x7e, 0x0c, 0xee, 0x49, 0x0c, 0xf7, 0x5d, 0x35, 0xd8, 0x7e, 0xf8, 0xef, 0x9d, - 0x57, 0xad, 0x7c, 0x81, 0xcb, 0x31, 0xae, 0xf9, 0x84, 0x54, 0xb1, 0xbe, 0xd0, 0xff, 0xce, 0x01, - 0x6f, 0x8c, 0x58, 0x59, 0x12, 0xce, 0x09, 0xa3, 0xa3, 0x09, 0xa2, 0x39, 0x7e, 0x46, 0x45, 0xbd, - 0x80, 0x23, 0x00, 0xd2, 0x65, 0x40, 0xf7, 0x76, 0xbb, 0x55, 0x59, 0xb9, 0x06, 0x1f, 0x83, 0xfb, - 0x69, 0x8d, 0xf5, 0xea, 0x65, 0x48, 0xe8, 0x35, 0x6e, 0xc6, 0xaf, 0x58, 0xe7, 0x3e, 0x12, 0xb8, - 0xff, 0xbd, 0x03, 0x7c, 0xd5, 0xc7, 0x41, 0x8d, 0x52, 0x71, 0x83, 0xc6, 0x67, 0xa0, 0xa3, 0x3a, - 0x4f, 0x8e, 0x4c, 0xf0, 0xff, 0x50, 0xb9, 0xcf, 0x57, 0xd3, 0xde, 0x8e, 0xcd, 0xaf, 0x2e, 0xe8, - 0x5c, 0x9f, 0x15, 0xdc, 0x05, 0xae, 0x9c, 0x96, 0xaa, 0xdc, 0xb6, 0x7b, 0x72, 0x7d, 0xba, 0xcb, - 0x07, 0x1c, 0x2b, 0x28, 0x7c, 0x08, 0x5a, 0x15, 0x23, 0x54, 0x70, 0x55, 0xc3, 0x8d, 0x8d, 0x05, - 0x77, 0x00, 0x20, 0x3c, 0x29, 0x30, 0x9a, 0x13, 0x9a, 0x2b, 0x35, 0xb7, 0x62, 0x8f, 0xf0, 0xe7, - 0xda, 0x01, 0x03, 0x00, 0xe6, 0xa8, 0xb0, 0x0b, 0xa5, 0x5f, 0xf1, 0x8a, 0x47, 0x6e, 0xdb, 0x18, - 0x15, 0x88, 0xa6, 0x58, 0x3d, 0x5e, 0x37, 0xb6, 0xe6, 0x0d, 0xb9, 0x5a, 0x77, 0x93, 0x0b, 0x83, - 0x47, 0x15, 0xa6, 0x19, 0xa1, 0x79, 0x72, 0xe5, 0x4d, 0x52, 0x25, 0x87, 0xbf, 0xa9, 0xba, 0x7f, - 0x7f, 0x5d, 0xf7, 0x6b, 0x37, 0x28, 0x7e, 0xd3, 0xe4, 0xba, 0x19, 0x5d, 0xa3, 0xe9, 0xd6, 0x9d, - 0x35, 0x65, 0x60, 0xc7, 0x52, 0xbe, 0x9e, 0xd3, 0xd2, 0xf6, 0x14, 0xed, 0x0f, 0xd6, 0xd1, 0xfe, - 0xaf, 0xa5, 0x8b, 0xb7, 0x4d, 0xca, 0x35, 0x00, 0xa9, 0xe0, 0xca, 0x7b, 0x04, 0x4a, 0x05, 0xaf, - 0xb2, 0x4f, 0x71, 0xb8, 0x7f, 0x7a, 0x11, 0x38, 0x67, 0x17, 0x81, 0xf3, 0xd7, 0x45, 0xe0, 0xfc, - 0x70, 0x19, 0x34, 0xce, 0x2e, 0x83, 0xc6, 0xef, 0x97, 0x41, 0xe3, 0x9b, 0x27, 0x2b, 0xbf, 0x65, - 0x9f, 0xbf, 0x7c, 0xf1, 0xec, 0x4b, 0x2c, 0x4e, 0x58, 0x3d, 0x8d, 0xd2, 0x09, 0x22, 0x34, 0xfa, - 0xd6, 0x7c, 0xc2, 0xd4, 0x6f, 0xda, 0xb8, 0xa5, 0x3e, 0x0d, 0x1f, 0xfd, 0x13, 0x00, 0x00, 0xff, - 0xff, 0x4a, 0xf4, 0x98, 0x6f, 0xdd, 0x06, 0x00, 0x00, + 0x18, 0x71, 0xbc, 0xcc, 0x93, 0x32, 0x42, 0x4d, 0xfc, 0x5d, 0x13, 0xe7, 0x02, 0x4d, 0x09, 0xcd, + 0x97, 0x10, 0x63, 0x1b, 0xd4, 0x83, 0x9c, 0xe5, 0x4c, 0x1d, 0x23, 0x79, 0x32, 0xde, 0xb7, 0x15, + 0xc5, 0x8a, 0xb1, 0x62, 0x79, 0x4d, 0x1a, 0x3a, 0xda, 0xff, 0xb9, 0x09, 0xbc, 0x21, 0xe2, 0x24, + 0xfd, 0x8a, 0xb1, 0x02, 0x76, 0xc0, 0x06, 0xc9, 0x7c, 0xa7, 0xe7, 0x0c, 0xdc, 0x78, 0x83, 0x64, + 0x10, 0x02, 0x97, 0xa2, 0x12, 0xfb, 0x1b, 0x3d, 0x67, 0xe0, 0xc5, 0xea, 0x0c, 0x7d, 0xb0, 0x59, + 0xcf, 0xa8, 0x20, 0x25, 0xf6, 0x9b, 0xca, 0x6d, 0x4d, 0x89, 0x2e, 0x58, 0xce, 0x7c, 0x57, 0xa3, + 0xe5, 0x19, 0xbe, 0x04, 0x0f, 0x09, 0x3d, 0x2a, 0x90, 0x20, 0x8c, 0x26, 0x7c, 0x82, 0x6a, 0x9c, + 0x9c, 0x60, 0x92, 0x4f, 0x84, 0x7f, 0x4f, 0xa2, 0x86, 0x8f, 0x4f, 0xcf, 0xbb, 0x8d, 0x3f, 0xce, + 0xbb, 0x6f, 0xe9, 0x0e, 0x79, 0x36, 0x0d, 0x09, 0x8b, 0x4a, 0x24, 0x26, 0xe1, 0x73, 0x9c, 0xa3, + 0x74, 0xb1, 0x8f, 0xd3, 0xf8, 0xc1, 0x32, 0xc5, 0xa1, 0xcc, 0xf0, 0xb5, 0x4a, 0x00, 0xdf, 0x03, + 0xaf, 0xce, 0xaa, 0x82, 0xa1, 0x2c, 0x21, 0x54, 0xe0, 0x7a, 0x8e, 0x0a, 0xbf, 0xa5, 0x98, 0x77, + 0xb4, 0xfb, 0x53, 0xe3, 0x85, 0xc7, 0xa0, 0x2d, 0x98, 0x40, 0x45, 0x72, 0x34, 0xa3, 0x19, 0xf7, + 0x37, 0x7b, 0xcd, 0x41, 0x7b, 0xef, 0x51, 0xa8, 0x2b, 0x86, 0x72, 0xe6, 0x56, 0x9b, 0x70, 0xc4, + 0x08, 0x1d, 0x3e, 0x95, 0x9c, 0x7e, 0xfa, 0xb3, 0x3b, 0xc8, 0x89, 0x98, 0xcc, 0xc6, 0x61, 0xca, + 0xca, 0xc8, 0x08, 0xa0, 0xff, 0x7d, 0xc8, 0xb3, 0x69, 0x24, 0x16, 0x15, 0xe6, 0xea, 0x02, 0xff, + 0xf1, 0xef, 0x5f, 0x9e, 0x38, 0x31, 0x50, 0x45, 0x0e, 0x64, 0x0d, 0xd8, 0xb5, 0x25, 0xa5, 0x42, + 0xd8, 0xdf, 0x52, 0xbc, 0x34, 0xe0, 0x50, 0x7a, 0xe0, 0x53, 0xd0, 0xe2, 0x02, 0x89, 0x19, 0xf7, + 0xbd, 0x9e, 0x33, 0xe8, 0xec, 0xed, 0x84, 0x6a, 0x53, 0x94, 0x32, 0x96, 0x8c, 0x94, 0xe4, 0x50, + 0x81, 0x62, 0x03, 0xee, 0xff, 0xe6, 0x00, 0x70, 0x30, 0x2b, 0x74, 0x92, 0x5a, 0x6a, 0x81, 0xb2, + 0xac, 0xc6, 0x9c, 0x2b, 0xd1, 0xbc, 0xd8, 0x9a, 0xf0, 0x13, 0xe0, 0xcd, 0x51, 0x41, 0x32, 0x24, + 0x58, 0xad, 0xe4, 0x6b, 0xef, 0xbd, 0x63, 0x3b, 0xb6, 0x5b, 0x63, 0xeb, 0xbc, 0xb0, 0xc0, 0xf8, + 0xea, 0x0e, 0x1c, 0x80, 0xd7, 0x74, 0x07, 0x92, 0x92, 0x69, 0xa3, 0xa9, 0xc7, 0xab, 0xfc, 0x86, + 0xdc, 0x14, 0xc3, 0x8f, 0xc1, 0x3d, 0x89, 0xe1, 0xbe, 0xab, 0x06, 0xdb, 0x0f, 0xff, 0xbd, 0xf3, + 0xaa, 0x95, 0x2f, 0x70, 0x39, 0xc6, 0x35, 0x9f, 0x90, 0x2a, 0xd6, 0x17, 0xfa, 0xdf, 0x39, 0xe0, + 0x8d, 0x11, 0x2b, 0x4b, 0xc2, 0x39, 0x61, 0x74, 0x34, 0x41, 0x34, 0xc7, 0xcf, 0xa8, 0xa8, 0x17, + 0x70, 0x04, 0x40, 0xba, 0x0c, 0xe8, 0xde, 0x6e, 0xb7, 0x2a, 0x2b, 0xd7, 0xe0, 0x63, 0x70, 0x3f, + 0xad, 0xb1, 0x5e, 0xbd, 0x0c, 0x09, 0xbd, 0xc6, 0xcd, 0xf8, 0x15, 0xeb, 0xdc, 0x47, 0x02, 0xf7, + 0xbf, 0x77, 0x80, 0xaf, 0xfa, 0x38, 0xa8, 0x51, 0x2a, 0x6e, 0xd0, 0xf8, 0x0c, 0x74, 0x54, 0xe7, + 0xc9, 0x91, 0x09, 0xfe, 0x1f, 0x2a, 0xf7, 0xf9, 0x6a, 0xda, 0xdb, 0xb1, 0xf9, 0xd5, 0x05, 0x9d, + 0xeb, 0xb3, 0x82, 0xbb, 0xc0, 0x95, 0xd3, 0x52, 0x95, 0xdb, 0x76, 0x4f, 0xae, 0x4f, 0x77, 0xf9, + 0x80, 0x63, 0x05, 0x85, 0x0f, 0x41, 0xab, 0x62, 0x84, 0x0a, 0xae, 0x6a, 0xb8, 0xb1, 0xb1, 0xe0, + 0x0e, 0x00, 0x84, 0x27, 0x05, 0x46, 0x73, 0x42, 0x73, 0xa5, 0xe6, 0x56, 0xec, 0x11, 0xfe, 0x5c, + 0x3b, 0x60, 0x00, 0xc0, 0x1c, 0x15, 0x76, 0xa1, 0xf4, 0x2b, 0x5e, 0xf1, 0xc8, 0x6d, 0x1b, 0xa3, + 0x02, 0xd1, 0x14, 0xab, 0xc7, 0xeb, 0xc6, 0xd6, 0xbc, 0x21, 0x57, 0xeb, 0x6e, 0x72, 0x61, 0xf0, + 0xa8, 0xc2, 0x34, 0x23, 0x34, 0x4f, 0xae, 0xbc, 0x49, 0xaa, 0xe4, 0xf0, 0x37, 0x55, 0xf7, 0xef, + 0xaf, 0xeb, 0x7e, 0xed, 0x06, 0xc5, 0x6f, 0x9a, 0x5c, 0x37, 0xa3, 0x6b, 0x34, 0xdd, 0xba, 0xb3, + 0xa6, 0x0c, 0xec, 0x58, 0xca, 0xd7, 0x73, 0x5a, 0xda, 0x9e, 0xa2, 0xfd, 0xc1, 0x3a, 0xda, 0xff, + 0xb5, 0x74, 0xf1, 0xb6, 0x49, 0xb9, 0x06, 0x20, 0x15, 0x5c, 0x79, 0x8f, 0x40, 0xa9, 0xe0, 0x55, + 0xf6, 0x29, 0x0e, 0xf7, 0x4f, 0x2f, 0x02, 0xe7, 0xec, 0x22, 0x70, 0xfe, 0xba, 0x08, 0x9c, 0x1f, + 0x2e, 0x83, 0xc6, 0xd9, 0x65, 0xd0, 0xf8, 0xfd, 0x32, 0x68, 0x7c, 0xf3, 0x64, 0xe5, 0xb7, 0xec, + 0xf3, 0x97, 0x2f, 0x9e, 0x7d, 0x89, 0xc5, 0x09, 0xab, 0xa7, 0x51, 0x3a, 0x41, 0x84, 0x46, 0xdf, + 0x9a, 0x4f, 0x98, 0xfa, 0x4d, 0x1b, 0xb7, 0xd4, 0xa7, 0xe1, 0xa3, 0x7f, 0x02, 0x00, 0x00, 0xff, + 0xff, 0x32, 0x03, 0xb7, 0x13, 0xdd, 0x06, 0x00, 0x00, } func (m *BasicPool) Marshal() (dAtA []byte, err error) { diff --git a/x/query/types/stakers.pb.go b/x/query/types/stakers.pb.go index 3a8b99db..77c2c5ee 100644 --- a/x/query/types/stakers.pb.go +++ b/x/query/types/stakers.pb.go @@ -6,7 +6,6 @@ package types import ( context "context" fmt "fmt" - _ "github.com/KYVENetwork/chain/x/stakers/types" query "github.com/cosmos/cosmos-sdk/types/query" _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" @@ -490,53 +489,52 @@ func init() { func init() { proto.RegisterFile("kyve/query/v1beta1/stakers.proto", fileDescriptor_6aa31a681566da33) } var fileDescriptor_6aa31a681566da33 = []byte{ - // 725 bytes of a gzipped FileDescriptorProto + // 719 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0x41, 0x4f, 0x13, 0x4d, 0x18, 0xee, 0x94, 0xa6, 0x0d, 0x03, 0xdf, 0x17, 0x32, 0x1f, 0xf9, 0x2c, 0x2b, 0x2c, 0x75, 0x31, - 0x50, 0x51, 0x76, 0x42, 0xd1, 0xc4, 0x83, 0x31, 0x29, 0xa5, 0x68, 0x83, 0x29, 0x75, 0x5b, 0x48, - 0x34, 0x26, 0x9b, 0x6d, 0x3b, 0xd9, 0x36, 0x2d, 0x3b, 0x65, 0x67, 0x8b, 0x36, 0x84, 0x83, 0x5e, - 0xf4, 0x68, 0xe2, 0x0f, 0xf0, 0x60, 0xbc, 0x78, 0xd1, 0x3f, 0xe0, 0x9d, 0x23, 0x89, 0x17, 0x4f, - 0xc6, 0x80, 0xff, 0xc1, 0xab, 0xd9, 0xdd, 0x59, 0xdc, 0x95, 0xad, 0xad, 0x09, 0x07, 0x6f, 0x33, - 0x3b, 0xcf, 0xf3, 0xbe, 0xcf, 0xf3, 0x74, 0xde, 0x29, 0x4c, 0xb5, 0x7a, 0x7b, 0x04, 0xef, 0x76, - 0x89, 0xd9, 0xc3, 0x7b, 0xcb, 0x55, 0x62, 0x69, 0xcb, 0x98, 0x59, 0x5a, 0x8b, 0x98, 0x4c, 0xee, - 0x98, 0xd4, 0xa2, 0x08, 0xd9, 0x08, 0xd9, 0x41, 0xc8, 0x1c, 0x21, 0x2c, 0xd6, 0x28, 0xdb, 0xa1, - 0x0c, 0x57, 0x35, 0xf6, 0x2b, 0xb9, 0xa3, 0xe9, 0x4d, 0x43, 0xb3, 0x9a, 0xd4, 0x70, 0xf9, 0xc2, - 0xa4, 0x4e, 0x75, 0xea, 0x2c, 0xb1, 0xbd, 0xe2, 0x5f, 0xa7, 0x75, 0x4a, 0xf5, 0x36, 0xc1, 0x5a, - 0xa7, 0x89, 0x35, 0xc3, 0xa0, 0x96, 0x43, 0xe1, 0x3d, 0x05, 0x31, 0x44, 0x95, 0xab, 0xc0, 0x3d, - 0x97, 0x9c, 0x73, 0xae, 0x33, 0x5c, 0xb7, 0xf4, 0x1e, 0xc0, 0xff, 0xee, 0xdb, 0x9c, 0xb2, 0xfb, - 0x59, 0x21, 0xbb, 0x5d, 0xc2, 0x2c, 0xb4, 0x0e, 0xe1, 0x4f, 0x8d, 0x49, 0x90, 0x02, 0xe9, 0xb1, - 0xcc, 0xbc, 0xec, 0x1a, 0x92, 0x6d, 0x43, 0x41, 0xaf, 0x72, 0x49, 0xd3, 0x09, 0xe7, 0x2a, 0x3e, - 0x26, 0xba, 0x09, 0xe3, 0xcc, 0xd2, 0xac, 0x2e, 0x4b, 0x46, 0x53, 0x20, 0xfd, 0x6f, 0x26, 0x25, - 0x9f, 0x0d, 0x4a, 0x76, 0x7b, 0x97, 0x1d, 0x9c, 0xc2, 0xf1, 0xe8, 0x7f, 0x18, 0x67, 0x44, 0x33, - 0x6b, 0x8d, 0xe4, 0x48, 0x0a, 0xa4, 0x47, 0x15, 0xbe, 0x93, 0x5e, 0x03, 0x38, 0x19, 0x54, 0xcc, - 0x3a, 0xd4, 0x60, 0x04, 0xdd, 0x86, 0x09, 0xee, 0x2d, 0x09, 0x52, 0x23, 0xe9, 0xb1, 0x8c, 0x18, - 0xd6, 0x6b, 0xbd, 0xdb, 0x6e, 0xbb, 0xcc, 0xd5, 0xd8, 0xe1, 0x97, 0xd9, 0x88, 0xe2, 0x91, 0xd0, - 0x9d, 0x80, 0xe5, 0xa8, 0x63, 0x79, 0x61, 0xa0, 0x65, 0xb7, 0xb9, 0xdf, 0xb3, 0x24, 0x43, 0xe4, - 0x13, 0xe8, 0x25, 0x9a, 0x84, 0x09, 0xad, 0x5e, 0x37, 0x09, 0x63, 0x4e, 0x9c, 0xa3, 0x8a, 0xb7, - 0x95, 0xca, 0x81, 0x9f, 0xe0, 0xd4, 0xcf, 0x2d, 0x27, 0xba, 0x16, 0x31, 0x79, 0xfc, 0xc3, 0xd9, - 0xe1, 0x1c, 0xe9, 0x3a, 0x9c, 0xf2, 0xa7, 0xb4, 0xda, 0x2b, 0x51, 0xda, 0xf6, 0xb4, 0x5c, 0x80, - 0x89, 0x0e, 0xa5, 0x6d, 0xb5, 0x59, 0x77, 0x6a, 0xc7, 0x94, 0xb8, 0xbd, 0x2d, 0xd4, 0xa5, 0x47, - 0x50, 0x08, 0x63, 0x9d, 0x4f, 0xc2, 0x52, 0x03, 0x8a, 0x67, 0xab, 0xe7, 0x68, 0xd7, 0xb0, 0xce, - 0xf9, 0xda, 0x49, 0xef, 0x00, 0x9c, 0xed, 0xdb, 0xea, 0x2f, 0xbb, 0x2f, 0x8b, 0x1f, 0x01, 0x1c, - 0xf7, 0x8f, 0x00, 0x9a, 0x81, 0x53, 0xe5, 0x4a, 0x76, 0x23, 0xaf, 0xa8, 0xe5, 0x4a, 0xb6, 0xb2, - 0x55, 0x56, 0xb7, 0x8a, 0xe5, 0x52, 0x3e, 0x57, 0x58, 0x2f, 0xe4, 0xd7, 0x26, 0x22, 0xe8, 0x12, - 0x9c, 0x09, 0x1e, 0x97, 0x94, 0xcd, 0xca, 0x66, 0x6e, 0xf3, 0x9e, 0x9a, 0xcd, 0x55, 0x0a, 0xdb, - 0xf9, 0x09, 0x80, 0xe6, 0xe0, 0x6c, 0x1f, 0x48, 0xa1, 0xc8, 0x41, 0x51, 0x24, 0x42, 0x21, 0x08, - 0xca, 0xdd, 0xcd, 0x16, 0x8a, 0x5e, 0x91, 0x11, 0x94, 0x82, 0xd3, 0x61, 0xe7, 0xa7, 0x15, 0x62, - 0x42, 0xec, 0xc5, 0x1b, 0x31, 0x92, 0xf9, 0x1e, 0x83, 0xe3, 0xfe, 0xb0, 0xd1, 0x53, 0x00, 0x13, - 0xde, 0x7a, 0x21, 0x2c, 0xd4, 0x90, 0x17, 0x47, 0x48, 0x0f, 0x06, 0xba, 0xd9, 0x49, 0x73, 0xcf, - 0x3e, 0x7d, 0x7b, 0x15, 0x9d, 0x41, 0x17, 0x71, 0xff, 0x67, 0x19, 0x3d, 0x07, 0x30, 0xee, 0x12, - 0xd1, 0xfc, 0x80, 0xca, 0x9e, 0x82, 0x85, 0x81, 0x38, 0x2e, 0xe0, 0x9a, 0x23, 0x60, 0x1e, 0x5d, - 0xee, 0x2f, 0x00, 0xef, 0xf3, 0xe9, 0x3e, 0x40, 0x6f, 0x01, 0xfc, 0x27, 0x70, 0x0d, 0xd1, 0xd2, - 0x20, 0xab, 0x81, 0x69, 0x15, 0xe4, 0x61, 0xe1, 0x5c, 0xde, 0x0d, 0x47, 0x1e, 0x46, 0x4b, 0xbf, - 0xc9, 0x47, 0xad, 0xf6, 0x54, 0x7b, 0xe6, 0xf1, 0x3e, 0x7f, 0x08, 0x0e, 0xd0, 0x07, 0x00, 0xd1, - 0xd9, 0x71, 0x41, 0x99, 0xe1, 0xba, 0xfb, 0xc7, 0x58, 0x58, 0xf9, 0x23, 0x0e, 0x97, 0xbd, 0xec, - 0xc8, 0xbe, 0x8a, 0xae, 0x0c, 0x21, 0x5b, 0xad, 0xd9, 0xd4, 0xd5, 0xb5, 0xc3, 0x63, 0x11, 0x1c, - 0x1d, 0x8b, 0xe0, 0xeb, 0xb1, 0x08, 0x5e, 0x9e, 0x88, 0x91, 0xa3, 0x13, 0x31, 0xf2, 0xf9, 0x44, - 0x8c, 0x3c, 0x5c, 0xd4, 0x9b, 0x56, 0xa3, 0x5b, 0x95, 0x6b, 0x74, 0x07, 0x6f, 0x3c, 0xd8, 0xce, - 0x17, 0x89, 0xf5, 0x98, 0x9a, 0x2d, 0x5c, 0x6b, 0x68, 0x4d, 0x03, 0x3f, 0xe1, 0xd5, 0xad, 0x5e, - 0x87, 0xb0, 0x6a, 0xdc, 0xf9, 0x2b, 0x5c, 0xf9, 0x11, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x55, 0x4c, - 0xd2, 0xe6, 0x07, 0x00, 0x00, + 0x50, 0x51, 0x76, 0x42, 0xd1, 0xc4, 0x83, 0x31, 0x29, 0xa5, 0x68, 0x83, 0x29, 0x75, 0xb7, 0x90, + 0x68, 0x4c, 0x36, 0xdb, 0x76, 0xb2, 0x6d, 0x5a, 0x76, 0xca, 0xce, 0x16, 0x6d, 0x08, 0x07, 0xbd, + 0xe8, 0xd1, 0xc4, 0x1f, 0xe0, 0xc1, 0x78, 0xf1, 0xa2, 0x7f, 0xc0, 0x3b, 0x47, 0x12, 0x2f, 0x9e, + 0x8c, 0x01, 0xff, 0x83, 0x57, 0xb3, 0xbb, 0xb3, 0xb8, 0x2b, 0xad, 0xad, 0x09, 0x07, 0x6f, 0x33, + 0x9d, 0xe7, 0x79, 0xdf, 0xe7, 0x79, 0x3a, 0xef, 0x2c, 0x4c, 0x35, 0xbb, 0x7b, 0x04, 0xef, 0x76, + 0x88, 0xd5, 0xc5, 0x7b, 0xcb, 0x15, 0x62, 0xeb, 0xcb, 0x98, 0xd9, 0x7a, 0x93, 0x58, 0x4c, 0x6e, + 0x5b, 0xd4, 0xa6, 0x08, 0x39, 0x08, 0xd9, 0x45, 0xc8, 0x1c, 0x21, 0x2c, 0x56, 0x29, 0xdb, 0xa1, + 0x0c, 0x57, 0x74, 0xf6, 0x2b, 0xb9, 0xad, 0x1b, 0x0d, 0x53, 0xb7, 0x1b, 0xd4, 0xf4, 0xf8, 0xc2, + 0xa4, 0x41, 0x0d, 0xea, 0x2e, 0xb1, 0xb3, 0xe2, 0xbf, 0x4e, 0x1b, 0x94, 0x1a, 0x2d, 0x82, 0xf5, + 0x76, 0x03, 0xeb, 0xa6, 0x49, 0x6d, 0x97, 0xc2, 0x7b, 0x0a, 0x62, 0x0f, 0x55, 0x9e, 0x02, 0xf7, + 0x5c, 0x7a, 0x0f, 0xe0, 0x7f, 0xf7, 0x9d, 0xbd, 0xea, 0x49, 0x55, 0xc8, 0x6e, 0x87, 0x30, 0x1b, + 0xad, 0x43, 0xf8, 0xb3, 0x7f, 0x12, 0xa4, 0x40, 0x7a, 0x2c, 0x33, 0x2f, 0x7b, 0x62, 0x65, 0x47, + 0x6c, 0xd8, 0x87, 0x5c, 0xd2, 0x0d, 0xc2, 0xb9, 0x4a, 0x80, 0x89, 0x6e, 0xc2, 0x38, 0xb3, 0x75, + 0xbb, 0xc3, 0x92, 0xd1, 0x14, 0x48, 0xff, 0x9b, 0x49, 0xc9, 0x67, 0x43, 0x90, 0xbd, 0xde, 0xaa, + 0x8b, 0x53, 0x38, 0x1e, 0xfd, 0x0f, 0xe3, 0x8c, 0xe8, 0x56, 0xb5, 0x9e, 0x1c, 0x49, 0x81, 0xf4, + 0xa8, 0xc2, 0x77, 0xd2, 0x6b, 0x00, 0x27, 0xc3, 0x8a, 0x59, 0x9b, 0x9a, 0x8c, 0xa0, 0xdb, 0x30, + 0xc1, 0xf3, 0x4e, 0x82, 0xd4, 0x48, 0x7a, 0x2c, 0x23, 0xf6, 0xea, 0xb5, 0xde, 0x69, 0xb5, 0x3c, + 0xe6, 0x6a, 0xec, 0xf0, 0xcb, 0x6c, 0x44, 0xf1, 0x49, 0xe8, 0x4e, 0xc8, 0x72, 0xd4, 0xb5, 0xbc, + 0x30, 0xd0, 0xb2, 0xd7, 0x3c, 0xe8, 0x59, 0x92, 0x21, 0x0a, 0x08, 0xf4, 0x13, 0x4d, 0xc2, 0x84, + 0x5e, 0xab, 0x59, 0x84, 0x31, 0x37, 0xce, 0x51, 0xc5, 0xdf, 0x4a, 0x6a, 0xe8, 0x2f, 0x38, 0xf5, + 0x73, 0xcb, 0x8d, 0xae, 0x49, 0x2c, 0x1e, 0xff, 0x70, 0x76, 0x38, 0x47, 0xba, 0x0e, 0xa7, 0x82, + 0x29, 0xad, 0x76, 0x4b, 0x94, 0xb6, 0x7c, 0x2d, 0x17, 0x60, 0xa2, 0x4d, 0x69, 0x4b, 0x6b, 0xd4, + 0xdc, 0xda, 0x31, 0x25, 0xee, 0x6c, 0x0b, 0x35, 0xe9, 0x11, 0x14, 0x7a, 0xb1, 0xce, 0x27, 0x61, + 0xa9, 0x0e, 0xc5, 0xb3, 0xd5, 0x73, 0xb4, 0x63, 0xda, 0xe7, 0x7c, 0xed, 0xa4, 0x77, 0x00, 0xce, + 0xf6, 0x6d, 0xf5, 0x97, 0xdd, 0x97, 0xc5, 0x8f, 0x00, 0x8e, 0x07, 0x47, 0x00, 0xcd, 0xc0, 0x29, + 0xb5, 0x9c, 0xdd, 0xc8, 0x2b, 0x9a, 0x5a, 0xce, 0x96, 0xb7, 0x54, 0x6d, 0xab, 0xa8, 0x96, 0xf2, + 0xb9, 0xc2, 0x7a, 0x21, 0xbf, 0x36, 0x11, 0x41, 0x97, 0xe0, 0x4c, 0xf8, 0xb8, 0xa4, 0x6c, 0x96, + 0x37, 0x73, 0x9b, 0xf7, 0xb4, 0x6c, 0xae, 0x5c, 0xd8, 0xce, 0x4f, 0x00, 0x34, 0x07, 0x67, 0xfb, + 0x40, 0x0a, 0x45, 0x0e, 0x8a, 0x22, 0x11, 0x0a, 0x61, 0x50, 0xee, 0x6e, 0xb6, 0x50, 0xf4, 0x8b, + 0x8c, 0xa0, 0x14, 0x9c, 0xee, 0x75, 0x7e, 0x5a, 0x21, 0x26, 0xc4, 0x5e, 0xbc, 0x11, 0x23, 0x99, + 0xef, 0x31, 0x38, 0x1e, 0x0c, 0x1b, 0x3d, 0x05, 0x30, 0xe1, 0xaf, 0x17, 0x7a, 0x85, 0xda, 0xe3, + 0xc5, 0x11, 0xd2, 0x83, 0x81, 0x5e, 0x76, 0xd2, 0xdc, 0xb3, 0x4f, 0xdf, 0x5e, 0x45, 0x67, 0xd0, + 0x45, 0xdc, 0xff, 0xc9, 0x45, 0xcf, 0x01, 0x8c, 0x7b, 0x44, 0x34, 0x3f, 0xa0, 0xb2, 0xaf, 0x60, + 0x61, 0x20, 0x8e, 0x0b, 0xb8, 0xe6, 0x0a, 0x98, 0x47, 0x97, 0xfb, 0x0b, 0xc0, 0xfb, 0x7c, 0xba, + 0x0f, 0xd0, 0x5b, 0x00, 0xff, 0x09, 0x5d, 0x43, 0xb4, 0x34, 0xc8, 0x6a, 0x68, 0x5a, 0x05, 0x79, + 0x58, 0x38, 0x97, 0x77, 0xc3, 0x95, 0x87, 0xd1, 0xd2, 0x6f, 0xf2, 0xd1, 0x2a, 0x5d, 0xcd, 0x99, + 0x79, 0xbc, 0xcf, 0x1f, 0x82, 0x03, 0xf4, 0x01, 0x40, 0x74, 0x76, 0x5c, 0x50, 0x66, 0xb8, 0xee, + 0xc1, 0x31, 0x16, 0x56, 0xfe, 0x88, 0xc3, 0x65, 0x2f, 0xbb, 0xb2, 0xaf, 0xa2, 0x2b, 0x43, 0xc8, + 0xd6, 0xaa, 0x0e, 0x75, 0x75, 0xed, 0xf0, 0x58, 0x04, 0x47, 0xc7, 0x22, 0xf8, 0x7a, 0x2c, 0x82, + 0x97, 0x27, 0x62, 0xe4, 0xe8, 0x44, 0x8c, 0x7c, 0x3e, 0x11, 0x23, 0x0f, 0x17, 0x8d, 0x86, 0x5d, + 0xef, 0x54, 0xe4, 0x2a, 0xdd, 0xc1, 0x1b, 0x0f, 0xb6, 0xf3, 0x45, 0x62, 0x3f, 0xa6, 0x56, 0x13, + 0x57, 0xeb, 0x7a, 0xc3, 0xc4, 0x4f, 0x78, 0x75, 0xbb, 0xdb, 0x26, 0xac, 0x12, 0x77, 0x3f, 0x85, + 0x2b, 0x3f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xce, 0x3c, 0x81, 0x37, 0xc2, 0x07, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 90b9c3e2..8be1c708 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -2,10 +2,11 @@ package keeper import ( "context" + "sort" + querytypes "github.com/KYVENetwork/chain/x/query/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "sort" "cosmossdk.io/errors" "cosmossdk.io/math" From 08de954c3072dad2634c38313a88f13a8cab78e4 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 20 Dec 2024 10:20:38 +0100 Subject: [PATCH 19/24] chore: implemented setter method for max pool stake --- testutil/integration/helpers.go | 6 +++++ .../keeper_suite_invalid_bundles_test.go | 4 +--- .../keeper/keeper_suite_valid_bundles_test.go | 4 +--- x/bundles/keeper/logic_bundles_test.go | 8 ++----- ...ic_end_block_handle_upload_timeout_test.go | 4 +--- x/bundles/keeper/logic_round_robin_test.go | 8 ++----- .../keeper_suite_effective_stake_test.go | 24 +++++-------------- x/stakers/keeper/msg_server_join_pool_test.go | 4 +--- .../keeper/msg_server_leave_pool_test.go | 4 +--- .../msg_server_update_stake_fraction_test.go | 4 +--- 10 files changed, 22 insertions(+), 48 deletions(-) diff --git a/testutil/integration/helpers.go b/testutil/integration/helpers.go index 40db2fdb..afe0ab59 100644 --- a/testutil/integration/helpers.go +++ b/testutil/integration/helpers.go @@ -86,3 +86,9 @@ func (suite *KeeperTestSuite) GetNextUploader() (nextStaker string, nextValaddre return } + +func (suite *KeeperTestSuite) SetMaxVotingPower(maxVotingPower string) { + params := suite.App().PoolKeeper.GetParams(suite.Ctx()) + params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr(maxVotingPower) + suite.App().PoolKeeper.SetParams(suite.Ctx(), params) +} diff --git a/x/bundles/keeper/keeper_suite_invalid_bundles_test.go b/x/bundles/keeper/keeper_suite_invalid_bundles_test.go index d6b270d0..64827c21 100644 --- a/x/bundles/keeper/keeper_suite_invalid_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_invalid_bundles_test.go @@ -64,9 +64,7 @@ var _ = Describe("invalid bundles", Ordered, func() { } s.RunTxPoolSuccess(msg) - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("1") s.RunTxFundersSuccess(&funderstypes.MsgCreateFunder{ Creator: i.ALICE, diff --git a/x/bundles/keeper/keeper_suite_valid_bundles_test.go b/x/bundles/keeper/keeper_suite_valid_bundles_test.go index addc5630..69804fec 100644 --- a/x/bundles/keeper/keeper_suite_valid_bundles_test.go +++ b/x/bundles/keeper/keeper_suite_valid_bundles_test.go @@ -966,9 +966,7 @@ var _ = Describe("valid bundles", Ordered, func() { It("Produce a valid bundle with multiple validators and foreign delegation although some voted invalid with maximum voting power", func() { // ARRANGE - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.4") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("0.4") s.CreateValidator(i.STAKER_2, "Staker-2", int64(100*i.KYVE)) diff --git a/x/bundles/keeper/logic_bundles_test.go b/x/bundles/keeper/logic_bundles_test.go index 9d3a0885..e527a3ba 100644 --- a/x/bundles/keeper/logic_bundles_test.go +++ b/x/bundles/keeper/logic_bundles_test.go @@ -307,9 +307,7 @@ var _ = Describe("logic_bundles.go", Ordered, func() { It("Assert pool can run while voting power of one node exceeds 40%", func() { // ARRANGE - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.4") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("0.4") msg := &pooltypes.MsgCreatePool{ Authority: gov, @@ -371,9 +369,7 @@ var _ = Describe("logic_bundles.go", Ordered, func() { It("Assert pool can run with a single staker while voting power is 100%", func() { // ARRANGE - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("1") msg := &pooltypes.MsgCreatePool{ Authority: gov, diff --git a/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go b/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go index bdb04f90..847aa16d 100644 --- a/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go +++ b/x/bundles/keeper/logic_end_block_handle_upload_timeout_test.go @@ -289,9 +289,7 @@ var _ = Describe("logic_end_block_handle_upload_timeout.go", Ordered, func() { PoolId: 0, }) - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.2") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("0.2") // ACT s.CommitAfterSeconds(1) diff --git a/x/bundles/keeper/logic_round_robin_test.go b/x/bundles/keeper/logic_round_robin_test.go index bd5229c8..2cb3c442 100644 --- a/x/bundles/keeper/logic_round_robin_test.go +++ b/x/bundles/keeper/logic_round_robin_test.go @@ -101,9 +101,7 @@ var _ = Describe("logic_round_robin.go", Ordered, func() { } s.App().PoolKeeper.SetPool(s.Ctx(), pool) - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("1") }) AfterEach(func() { @@ -269,9 +267,7 @@ var _ = Describe("logic_round_robin.go", Ordered, func() { It("Frequency analysis with maximum voting power cap", func() { // ARRANGE - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.5") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("0.5") // NOTE that dummy with index 2 has more than 50% voting power, so his effective stake // will be lower diff --git a/x/stakers/keeper/keeper_suite_effective_stake_test.go b/x/stakers/keeper/keeper_suite_effective_stake_test.go index 991b7d41..8322cbe3 100644 --- a/x/stakers/keeper/keeper_suite_effective_stake_test.go +++ b/x/stakers/keeper/keeper_suite_effective_stake_test.go @@ -50,9 +50,7 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { } s.RunTxPoolSuccess(msg) - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.5") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("0.5") }) AfterEach(func() { @@ -147,9 +145,7 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { It("Test effective stake with multiple validators above the max pool voting power", func() { // ARRANGE - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.35") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("0.35") s.CreateValidator(i.STAKER_0, "Staker-0", int64(600*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ @@ -193,9 +189,7 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { It("Test effective stake with fewer validators than required to undercut the max pool voting power", func() { // ARRANGE - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.2") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("0.2") s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ @@ -315,9 +309,7 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { It("Test effective stake with 0% as max pool stake", func() { // ARRANGE - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("0") s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ @@ -357,9 +349,7 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { It("Test effective stake with 100% as max pool stake", func() { // ARRANGE - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("1") s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ @@ -467,9 +457,7 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { It("Test effective stake with multiple validators above the max pool voting power due to stake fractions", func() { // ARRANGE - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("0.35") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("0.35") s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ diff --git a/x/stakers/keeper/msg_server_join_pool_test.go b/x/stakers/keeper/msg_server_join_pool_test.go index 92f7ffbd..e5998dff 100644 --- a/x/stakers/keeper/msg_server_join_pool_test.go +++ b/x/stakers/keeper/msg_server_join_pool_test.go @@ -71,9 +71,7 @@ var _ = Describe("msg_server_join_pool.go", Ordered, func() { } s.RunTxPoolSuccess(msg) - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("1") s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) diff --git a/x/stakers/keeper/msg_server_leave_pool_test.go b/x/stakers/keeper/msg_server_leave_pool_test.go index ca33d3e5..045fdc7c 100644 --- a/x/stakers/keeper/msg_server_leave_pool_test.go +++ b/x/stakers/keeper/msg_server_leave_pool_test.go @@ -43,9 +43,7 @@ var _ = Describe("msg_server_leave_pool.go", Ordered, func() { // create staker s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("1") // join pool s.RunTxStakersSuccess(&stakerstypes.MsgJoinPool{ diff --git a/x/stakers/keeper/msg_server_update_stake_fraction_test.go b/x/stakers/keeper/msg_server_update_stake_fraction_test.go index afb76ea5..9e266a33 100644 --- a/x/stakers/keeper/msg_server_update_stake_fraction_test.go +++ b/x/stakers/keeper/msg_server_update_stake_fraction_test.go @@ -50,9 +50,7 @@ var _ = Describe("msg_server_update_stake_fraction.go", Ordered, func() { } s.RunTxPoolSuccess(msg) - params := s.App().PoolKeeper.GetParams(s.Ctx()) - params.MaxVotingPowerPerPool = math.LegacyMustNewDecFromStr("1") - s.App().PoolKeeper.SetParams(s.Ctx(), params) + s.SetMaxVotingPower("1") s.CreateValidator(i.STAKER_0, "Staker-0", int64(100*i.KYVE)) From 117440d8d867d7dcedbb8ab60c865362fa811a83 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 20 Dec 2024 10:27:28 +0100 Subject: [PATCH 20/24] chore: use new total stake method --- x/query/keeper/grpc_account_funded.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/query/keeper/grpc_account_funded.go b/x/query/keeper/grpc_account_funded.go index fe9c04b0..d2ad75e9 100644 --- a/x/query/keeper/grpc_account_funded.go +++ b/x/query/keeper/grpc_account_funded.go @@ -35,7 +35,7 @@ func (k Keeper) AccountFundedList(goCtx context.Context, req *types.QueryAccount InflationShareWeight: pool.InflationShareWeight, UploadInterval: pool.UploadInterval, TotalFunds: k.fundersKeeper.GetTotalActiveFunding(ctx, pool.Id), - TotalStake: k.delegationKeeper.GetDelegationOfPool(ctx, pool.Id), + TotalStake: k.stakerKeeper.GetTotalStakeOfPool(ctx, pool.Id), Status: k.GetPoolStatus(ctx, &pool), }, }) From 1e3c45760015c007f64ebcffa705bc9fa7609428 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 20 Dec 2024 14:53:54 +0100 Subject: [PATCH 21/24] chore: added missing changes --- x/stakers/keeper/exported_functions.go | 26 ++++++++++++++++--- .../keeper_suite_effective_stake_test.go | 18 ++++++------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 322b8be6..659c626b 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -77,7 +77,6 @@ func (k Keeper) GetPaginatedStakersByPoolStake(ctx sdk.Context, pagination *quer addresses = append(addresses, address) } - // TODO: is this too expensive? if stakerStatus == querytypes.STAKER_STATUS_UNSPECIFIED || stakerStatus == querytypes.STAKER_STATUS_PROTOCOL_ACTIVE { sort.Slice(addresses, func(i, j int) bool { return k.GetValidatorTotalPoolStake(ctx, addresses[i]) > k.GetValidatorTotalPoolStake(ctx, addresses[j]) @@ -261,7 +260,7 @@ func (k Keeper) GetValidatorPoolStakes(ctx sdk.Context, poolId uint64, mustInclu totalStakeRemainder := totalStake // sort descending based on stake - sort.Slice(validators, func(i, j int) bool { + sort.SliceStable(validators, func(i, j int) bool { return validators[i].Stake > validators[j].Stake }) @@ -270,6 +269,8 @@ func (k Keeper) GetValidatorPoolStakes(ctx sdk.Context, poolId uint64, mustInclu return stakes } + var lastCutoffIndex int + for i, validator := range validators { // check if the validator has a higher stake than allowed by the max voting power if math.LegacyNewDec(int64(stakes[validator.Address])).GT(maxVotingPower.MulInt64(totalStake)) { @@ -288,9 +289,20 @@ func (k Keeper) GetValidatorPoolStakes(ctx sdk.Context, poolId uint64, mustInclu stakes[v.Address] += uint64(math.LegacyNewDec(int64(v.Stake)).QuoInt64(totalStakeRemainder).MulInt64(cutoffAmount).TruncateInt64()) } } + + lastCutoffIndex = i + } else { + // if we reach the first validator who is below the max voting power we know that the remaining + // ones will be also below it + break } } + // if no amounts got cut off we can return already + if totalStakeRemainder == totalStake { + return stakes + } + // after we have redistributed all cutoff amounts so that no validator exceeds the maximum voting power // based on their remaining effective stake we now scale the stakes to get the true effective staking amount. // This is because while the top validators who got their voting power reduced the lower validators have actually @@ -309,8 +321,14 @@ func (k Keeper) GetValidatorPoolStakes(ctx sdk.Context, poolId uint64, mustInclu } // scale all effective stakes down to scale factor - for _, validator := range validators { - stakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(stakes[validator.Address])).RoundInt64()) + for i, validator := range validators { + // for all validators who got cut off we always round down to ensure that their voting power actually + // stays below the max voting power + if i <= lastCutoffIndex { + stakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(stakes[validator.Address])).TruncateInt64()) + } else { + stakes[validator.Address] = uint64(scaleFactor.MulInt64(int64(stakes[validator.Address])).Ceil().TruncateInt64()) + } } // the result is a map which contains the effective stake for every validator in a pool. The effective stake diff --git a/x/stakers/keeper/keeper_suite_effective_stake_test.go b/x/stakers/keeper/keeper_suite_effective_stake_test.go index 8322cbe3..4fdc412c 100644 --- a/x/stakers/keeper/keeper_suite_effective_stake_test.go +++ b/x/stakers/keeper/keeper_suite_effective_stake_test.go @@ -137,10 +137,10 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(200*i.KYVE - 1)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(400*i.KYVE - 1)) }) It("Test effective stake with multiple validators above the max pool voting power", func() { @@ -262,11 +262,11 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { // ASSERT Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) - Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100*i.KYVE - 1)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(0 * i.KYVE)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(200*i.KYVE - 1)) }) It("Test effective stake with all validators having zero delegation", func() { @@ -449,10 +449,10 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(200 * i.KYVE)) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(200*i.KYVE - 1)) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(100 * i.KYVE)) - Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(400 * i.KYVE)) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(400*i.KYVE - 1)) }) It("Test effective stake with multiple validators above the max pool voting power due to stake fractions", func() { @@ -492,11 +492,11 @@ var _ = Describe("keeper_suite_effective_stake_test.go", Ordered, func() { // ASSERT Expect(s.App().StakersKeeper.IsVotingPowerTooHigh(s.Ctx(), 0)).To(BeFalse()) - Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(uint64(23333333334))) - Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(uint64(23333333334))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_0, 0)).To(Equal(uint64(23333333333))) + Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_1, 0)).To(Equal(uint64(23333333333))) Expect(s.App().StakersKeeper.GetValidatorPoolStake(s.Ctx(), i.STAKER_2, 0)).To(Equal(20 * i.KYVE)) - Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(uint64(66666666668))) + Expect(s.App().StakersKeeper.GetTotalStakeOfPool(s.Ctx(), 0)).To(Equal(uint64(66666666666))) }) It("Test effective stake with some validators having zero delegation due to stake fractions", func() { From 87df706181a85caf0f709d1bf1fbfd6d003cf7db Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 20 Dec 2024 14:57:41 +0100 Subject: [PATCH 22/24] chore: improved staker sorting --- x/query/keeper/grpc_query_stakers_by_pool.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x/query/keeper/grpc_query_stakers_by_pool.go b/x/query/keeper/grpc_query_stakers_by_pool.go index 14299655..d62aa750 100644 --- a/x/query/keeper/grpc_query_stakers_by_pool.go +++ b/x/query/keeper/grpc_query_stakers_by_pool.go @@ -29,8 +29,10 @@ func (k Keeper) StakersByPool(c context.Context, req *types.QueryStakersByPoolRe stakers = append(stakers, *k.GetFullStaker(ctx, valaccount.Staker)) } - sort.Slice(stakers, func(i, j int) bool { - return k.stakerKeeper.GetValidatorPoolStake(ctx, stakers[i].Address, req.PoolId) > k.stakerKeeper.GetValidatorPoolStake(ctx, stakers[j].Address, req.PoolId) + stakes := k.stakerKeeper.GetValidatorPoolStakes(ctx, req.PoolId) + + sort.SliceStable(stakers, func(i, j int) bool { + return stakes[stakers[i].Address] > stakes[stakers[j].Address] }) return &types.QueryStakersByPoolResponse{Stakers: stakers}, nil From bbdd2f61e9f0ee68afe4ffde258387c771679537 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 20 Dec 2024 14:59:32 +0100 Subject: [PATCH 23/24] chore: added comment --- x/stakers/keeper/exported_functions.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/stakers/keeper/exported_functions.go b/x/stakers/keeper/exported_functions.go index 659c626b..ded6c72f 100644 --- a/x/stakers/keeper/exported_functions.go +++ b/x/stakers/keeper/exported_functions.go @@ -78,6 +78,7 @@ func (k Keeper) GetPaginatedStakersByPoolStake(ctx sdk.Context, pagination *quer } if stakerStatus == querytypes.STAKER_STATUS_UNSPECIFIED || stakerStatus == querytypes.STAKER_STATUS_PROTOCOL_ACTIVE { + // TODO: consider optimization sort.Slice(addresses, func(i, j int) bool { return k.GetValidatorTotalPoolStake(ctx, addresses[i]) > k.GetValidatorTotalPoolStake(ctx, addresses[j]) }) From 68c40f4b960f03d502ee2d41a3ca3e5f0d9f7cb5 Mon Sep 17 00:00:00 2001 From: Troy Kessler Date: Fri, 20 Dec 2024 15:19:53 +0100 Subject: [PATCH 24/24] chore: fixed tests --- testutil/integration/checks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testutil/integration/checks.go b/testutil/integration/checks.go index 287907de..a2ac0a4b 100644 --- a/testutil/integration/checks.go +++ b/testutil/integration/checks.go @@ -132,7 +132,7 @@ func (suite *KeeperTestSuite) VerifyPoolQueries() { } } - sort.Slice(stakersByPoolState, func(a, b int) bool { + sort.SliceStable(stakersByPoolState, func(a, b int) bool { return suite.App().StakersKeeper.GetValidatorPoolStake(suite.Ctx(), stakersByPoolState[a].Address, poolsState[i].Id) > suite.App().StakersKeeper.GetValidatorPoolStake(suite.Ctx(), stakersByPoolState[b].Address, poolsState[i].Id) })