Merge PR #2236: Distr-PR-5 Implement Distribution
This commit is contained in:
commit
2803830c7e
|
@ -16,6 +16,7 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
|
@ -43,6 +44,8 @@ type GaiaApp struct {
|
|||
keyStake *sdk.KVStoreKey
|
||||
tkeyStake *sdk.TransientStoreKey
|
||||
keySlashing *sdk.KVStoreKey
|
||||
keyDistr *sdk.KVStoreKey
|
||||
tkeyDistr *sdk.TransientStoreKey
|
||||
keyGov *sdk.KVStoreKey
|
||||
keyFeeCollection *sdk.KVStoreKey
|
||||
keyParams *sdk.KVStoreKey
|
||||
|
@ -54,6 +57,7 @@ type GaiaApp struct {
|
|||
bankKeeper bank.Keeper
|
||||
stakeKeeper stake.Keeper
|
||||
slashingKeeper slashing.Keeper
|
||||
distrKeeper distr.Keeper
|
||||
govKeeper gov.Keeper
|
||||
paramsKeeper params.Keeper
|
||||
}
|
||||
|
@ -72,6 +76,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
keyAccount: sdk.NewKVStoreKey("acc"),
|
||||
keyStake: sdk.NewKVStoreKey("stake"),
|
||||
tkeyStake: sdk.NewTransientStoreKey("transient_stake"),
|
||||
keyDistr: sdk.NewKVStoreKey("distr"),
|
||||
tkeyDistr: sdk.NewTransientStoreKey("transient_distr"),
|
||||
keySlashing: sdk.NewKVStoreKey("slashing"),
|
||||
keyGov: sdk.NewKVStoreKey("gov"),
|
||||
keyFeeCollection: sdk.NewKVStoreKey("fee"),
|
||||
|
@ -88,30 +94,33 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
|
||||
// add handlers
|
||||
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
|
||||
|
||||
app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(
|
||||
app.cdc,
|
||||
app.keyFeeCollection,
|
||||
)
|
||||
app.paramsKeeper = params.NewKeeper(
|
||||
app.cdc,
|
||||
app.keyParams, app.tkeyParams,
|
||||
)
|
||||
|
||||
app.stakeKeeper = stake.NewKeeper(
|
||||
app.cdc,
|
||||
app.keyStake, app.tkeyStake,
|
||||
app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace),
|
||||
app.RegisterCodespace(stake.DefaultCodespace),
|
||||
)
|
||||
|
||||
app.distrKeeper = distr.NewKeeper(
|
||||
app.cdc,
|
||||
app.keyDistr,
|
||||
app.paramsKeeper.Subspace(distr.DefaultParamspace),
|
||||
app.bankKeeper, app.stakeKeeper, app.feeCollectionKeeper,
|
||||
app.RegisterCodespace(stake.DefaultCodespace),
|
||||
)
|
||||
app.slashingKeeper = slashing.NewKeeper(
|
||||
app.cdc,
|
||||
app.keySlashing,
|
||||
app.stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace),
|
||||
app.RegisterCodespace(slashing.DefaultCodespace),
|
||||
)
|
||||
|
||||
app.stakeKeeper = app.stakeKeeper.WithHooks(
|
||||
app.slashingKeeper.Hooks(),
|
||||
)
|
||||
|
||||
app.govKeeper = gov.NewKeeper(
|
||||
app.cdc,
|
||||
app.keyGov,
|
||||
|
@ -119,15 +128,15 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
app.RegisterCodespace(gov.DefaultCodespace),
|
||||
)
|
||||
|
||||
app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(
|
||||
app.cdc,
|
||||
app.keyFeeCollection,
|
||||
)
|
||||
// register the staking hooks
|
||||
app.stakeKeeper = app.stakeKeeper.WithHooks(
|
||||
NewHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()))
|
||||
|
||||
// register message routes
|
||||
app.Router().
|
||||
AddRoute("bank", bank.NewHandler(app.bankKeeper)).
|
||||
AddRoute("stake", stake.NewHandler(app.stakeKeeper)).
|
||||
AddRoute("distr", distr.NewHandler(app.distrKeeper)).
|
||||
AddRoute("slashing", slashing.NewHandler(app.slashingKeeper)).
|
||||
AddRoute("gov", gov.NewHandler(app.govKeeper))
|
||||
|
||||
|
@ -138,11 +147,12 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
|
|||
// initialize BaseApp
|
||||
app.SetInitChainer(app.initChainer)
|
||||
app.SetBeginBlocker(app.BeginBlocker)
|
||||
app.SetEndBlocker(app.EndBlocker)
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
|
||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake,
|
||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake, app.keyDistr,
|
||||
app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
|
||||
app.MountStoresTransient(app.tkeyParams, app.tkeyStake)
|
||||
app.MountStoresTransient(app.tkeyParams, app.tkeyStake, app.tkeyDistr)
|
||||
app.SetEndBlocker(app.EndBlocker)
|
||||
|
||||
err := app.LoadLatestVersion(app.keyMain)
|
||||
if err != nil {
|
||||
cmn.Exit(err.Error())
|
||||
|
@ -156,6 +166,7 @@ func MakeCodec() *codec.Codec {
|
|||
var cdc = codec.New()
|
||||
bank.RegisterCodec(cdc)
|
||||
stake.RegisterCodec(cdc)
|
||||
distr.RegisterCodec(cdc)
|
||||
slashing.RegisterCodec(cdc)
|
||||
gov.RegisterCodec(cdc)
|
||||
auth.RegisterCodec(cdc)
|
||||
|
@ -168,6 +179,9 @@ func MakeCodec() *codec.Codec {
|
|||
func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||
tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper)
|
||||
|
||||
// distribute rewards from previous block
|
||||
distr.BeginBlocker(ctx, req, app.distrKeeper)
|
||||
|
||||
return abci.ResponseBeginBlock{
|
||||
Tags: tags.ToKVPairs(),
|
||||
}
|
||||
|
@ -176,10 +190,13 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab
|
|||
// application updates every end block
|
||||
// nolint: unparam
|
||||
func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
|
||||
tags := gov.EndBlocker(ctx, app.govKeeper)
|
||||
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
|
||||
|
||||
// Add these new validators to the addr -> pubkey map.
|
||||
app.slashingKeeper.AddValidators(ctx, validatorUpdates)
|
||||
|
||||
return abci.ResponseEndBlock{
|
||||
ValidatorUpdates: validatorUpdates,
|
||||
Tags: tags,
|
||||
|
@ -208,18 +225,17 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
|
|||
// load the initial stake information
|
||||
validators, err := stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
|
||||
if err != nil {
|
||||
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
|
||||
// return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
panic(err) // TODO find a way to do this w/o panics
|
||||
}
|
||||
|
||||
// load the address to pubkey map
|
||||
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
|
||||
|
||||
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
|
||||
distr.InitGenesis(ctx, app.distrKeeper, genesisState.DistrData)
|
||||
err = GaiaValidateGenesisState(genesisState)
|
||||
if err != nil {
|
||||
// TODO find a way to do this w/o panics
|
||||
panic(err)
|
||||
panic(err) // TODO find a way to do this w/o panics
|
||||
}
|
||||
|
||||
return abci.ResponseInitChain{
|
||||
|
@ -243,6 +259,7 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val
|
|||
genState := GenesisState{
|
||||
Accounts: accounts,
|
||||
StakeData: stake.WriteGenesis(ctx, app.stakeKeeper),
|
||||
DistrData: distr.WriteGenesis(ctx, app.distrKeeper),
|
||||
GovData: gov.WriteGenesis(ctx, app.govKeeper),
|
||||
}
|
||||
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
|
||||
|
@ -252,3 +269,43 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val
|
|||
validators = stake.WriteValidators(ctx, app.stakeKeeper)
|
||||
return appState, validators, nil
|
||||
}
|
||||
|
||||
//______________________________________________________________________________________________
|
||||
|
||||
// Combined Staking Hooks
|
||||
type Hooks struct {
|
||||
dh distr.Hooks
|
||||
sh slashing.Hooks
|
||||
}
|
||||
|
||||
func NewHooks(dh distr.Hooks, sh slashing.Hooks) Hooks {
|
||||
return Hooks{dh, sh}
|
||||
}
|
||||
|
||||
var _ sdk.StakingHooks = Hooks{}
|
||||
|
||||
// nolint
|
||||
func (h Hooks) OnValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) {
|
||||
h.dh.OnValidatorCreated(ctx, addr)
|
||||
}
|
||||
func (h Hooks) OnValidatorCommissionChange(ctx sdk.Context, addr sdk.ValAddress) {
|
||||
h.dh.OnValidatorCommissionChange(ctx, addr)
|
||||
}
|
||||
func (h Hooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) {
|
||||
h.dh.OnValidatorRemoved(ctx, addr)
|
||||
}
|
||||
func (h Hooks) OnValidatorBonded(ctx sdk.Context, addr sdk.ConsAddress) {
|
||||
h.sh.OnValidatorBonded(ctx, addr)
|
||||
}
|
||||
func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, addr sdk.ConsAddress) {
|
||||
h.sh.OnValidatorBeginUnbonding(ctx, addr)
|
||||
}
|
||||
func (h Hooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||
h.dh.OnDelegationCreated(ctx, delAddr, valAddr)
|
||||
}
|
||||
func (h Hooks) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||
h.dh.OnDelegationSharesModified(ctx, delAddr, valAddr)
|
||||
}
|
||||
func (h Hooks) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||
h.dh.OnDelegationRemoved(ctx, delAddr, valAddr)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -24,6 +25,7 @@ func setGenesis(gapp *GaiaApp, accs ...*auth.BaseAccount) error {
|
|||
genesisState := GenesisState{
|
||||
Accounts: genaccs,
|
||||
StakeData: stake.DefaultGenesisState(),
|
||||
DistrData: distr.DefaultGenesisState(),
|
||||
SlashingData: slashing.DefaultGenesisState(),
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/server/config"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
|
@ -34,6 +35,7 @@ var (
|
|||
type GenesisState struct {
|
||||
Accounts []GenesisAccount `json:"accounts"`
|
||||
StakeData stake.GenesisState `json:"stake"`
|
||||
DistrData distr.GenesisState `json:"distr"`
|
||||
GovData gov.GenesisState `json:"gov"`
|
||||
SlashingData slashing.GenesisState `json:"slashing"`
|
||||
}
|
||||
|
@ -196,6 +198,7 @@ func GaiaAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (genesisStat
|
|||
genesisState = GenesisState{
|
||||
Accounts: genaccs,
|
||||
StakeData: stakeData,
|
||||
DistrData: distr.DefaultGenesisState(),
|
||||
GovData: gov.DefaultGenesisState(),
|
||||
SlashingData: slashingData,
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation"
|
||||
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
|
||||
|
@ -60,13 +61,18 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
|||
slashingGenesis := slashing.DefaultGenesisState()
|
||||
var validators []stake.Validator
|
||||
var delegations []stake.Delegation
|
||||
|
||||
// XXX Try different numbers of initially bonded validators
|
||||
numInitiallyBonded := int64(50)
|
||||
valAddrs := make([]sdk.ValAddress, numInitiallyBonded)
|
||||
for i := 0; i < int(numInitiallyBonded); i++ {
|
||||
validator := stake.NewValidator(sdk.ValAddress(accs[i].Address), accs[i].PubKey, stake.Description{})
|
||||
valAddr := sdk.ValAddress(accs[i].Address)
|
||||
valAddrs[i] = valAddr
|
||||
|
||||
validator := stake.NewValidator(valAddr, accs[i].PubKey, stake.Description{})
|
||||
validator.Tokens = sdk.NewDec(100)
|
||||
validator.DelegatorShares = sdk.NewDec(100)
|
||||
delegation := stake.Delegation{accs[i].Address, sdk.ValAddress(accs[i].Address), sdk.NewDec(100), 0}
|
||||
delegation := stake.Delegation{accs[i].Address, valAddr, sdk.NewDec(100), 0}
|
||||
validators = append(validators, validator)
|
||||
delegations = append(delegations, delegation)
|
||||
}
|
||||
|
@ -76,9 +82,11 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
|||
// No inflation, for now
|
||||
stakeGenesis.Params.InflationMax = sdk.NewDec(0)
|
||||
stakeGenesis.Params.InflationMin = sdk.NewDec(0)
|
||||
|
||||
genesis := GenesisState{
|
||||
Accounts: genesisAccounts,
|
||||
StakeData: stakeGenesis,
|
||||
DistrData: distr.DefaultGenesisWithValidators(valAddrs),
|
||||
SlashingData: slashingGenesis,
|
||||
GovData: govGenesis,
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
|
@ -72,6 +73,7 @@ func NewTestGaiaAppGenState(
|
|||
return GenesisState{
|
||||
Accounts: genAccs,
|
||||
StakeData: stakeData,
|
||||
DistrData: distr.DefaultGenesisState(),
|
||||
SlashingData: slashing.DefaultGenesisState(),
|
||||
GovData: gov.DefaultGenesisState(),
|
||||
}, nil
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
|
@ -10,18 +14,17 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/client/lcd"
|
||||
"github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
distrcmd "github.com/cosmos/cosmos-sdk/x/distribution/client/cli"
|
||||
govcmd "github.com/cosmos/cosmos-sdk/x/gov/client/cli"
|
||||
slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli"
|
||||
stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli"
|
||||
|
||||
_ "github.com/cosmos/cosmos-sdk/client/lcd/statik"
|
||||
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||
"github.com/spf13/viper"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -101,11 +104,13 @@ func main() {
|
|||
stakecmd.GetCmdCreateValidator(cdc),
|
||||
stakecmd.GetCmdEditValidator(cdc),
|
||||
stakecmd.GetCmdDelegate(cdc),
|
||||
govcmd.GetCmdDeposit(cdc),
|
||||
stakecmd.GetCmdRedelegate(storeStake, cdc),
|
||||
stakecmd.GetCmdUnbond(storeStake, cdc),
|
||||
distrcmd.GetCmdWithdrawRewards(cdc),
|
||||
distrcmd.GetCmdSetWithdrawAddr(cdc),
|
||||
govcmd.GetCmdDeposit(cdc),
|
||||
bankcmd.SendTxCmd(cdc),
|
||||
govcmd.GetCmdSubmitProposal(cdc),
|
||||
stakecmd.GetCmdUnbond(storeStake, cdc),
|
||||
slashingcmd.GetCmdUnjail(cdc),
|
||||
govcmd.GetCmdVote(cdc),
|
||||
)...)
|
||||
|
|
|
@ -15,7 +15,7 @@ pool which validator holds individually
|
|||
(`ValidatorDistribution.ProvisionsRewardPool`).
|
||||
|
||||
```
|
||||
func AllocateFees(feesCollected sdk.Coins, global Global, proposer ValidatorDistribution,
|
||||
func AllocateFees(feesCollected sdk.Coins, feePool FeePool, proposer ValidatorDistribution,
|
||||
sumPowerPrecommitValidators, totalBondedTokens, communityTax,
|
||||
proposerCommissionRate sdk.Dec)
|
||||
|
||||
|
@ -28,13 +28,11 @@ func AllocateFees(feesCollected sdk.Coins, global Global, proposer ValidatorDist
|
|||
proposer.Pool += proposerReward - commission
|
||||
|
||||
communityFunding = feesCollectedDec * communityTax
|
||||
global.CommunityFund += communityFunding
|
||||
feePool.CommunityFund += communityFunding
|
||||
|
||||
poolReceived = feesCollectedDec - proposerReward - communityFunding
|
||||
global.Pool += poolReceived
|
||||
global.EverReceivedPool += poolReceived
|
||||
global.LastReceivedPool = poolReceived
|
||||
feePool.Pool += poolReceived
|
||||
|
||||
SetValidatorDistribution(proposer)
|
||||
SetGlobal(global)
|
||||
SetFeePool(feePool)
|
||||
```
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
The pool of a new delegator bond will be 0 for the height at which the bond was
|
||||
added, or the withdrawal has taken place. This is achieved by setting
|
||||
`DelegatorDistInfo.WithdrawalHeight` to the height of the triggering transaction.
|
||||
`DelegationDistInfo.WithdrawalHeight` to the height of the triggering transaction.
|
||||
|
||||
## Commission rate change
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ to independently and lazily withdraw their rewards.
|
|||
|
||||
As a part of the lazy computations, each delegator holds an accumulation term
|
||||
specific to each validator which is used to estimate what their approximate
|
||||
fair portion of tokens held in the global pool is owed to them.
|
||||
fair portion of tokens held in the global fee pool is owed to them.
|
||||
|
||||
```
|
||||
entitlement = delegator-accumulation / all-delegators-accumulation
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
## State
|
||||
|
||||
### Global
|
||||
### FeePool
|
||||
|
||||
All globally tracked parameters for distribution are stored within
|
||||
`Global`. Rewards are collected and added to the reward pool and
|
||||
`FeePool`. Rewards are collected and added to the reward pool and
|
||||
distributed to validators/delegators from here.
|
||||
|
||||
Note that the reward pool holds decimal coins (`DecCoins`) to allow
|
||||
|
@ -11,7 +11,7 @@ for fractions of coins to be received from operations like inflation.
|
|||
When coins are distributed from the pool they are truncated back to
|
||||
`sdk.Coins` which are non-decimal.
|
||||
|
||||
- Global: `0x00 -> amino(global)`
|
||||
- FeePool: `0x00 -> amino(FeePool)`
|
||||
|
||||
```golang
|
||||
// coins with decimal
|
||||
|
@ -22,7 +22,7 @@ type DecCoin struct {
|
|||
Denom string
|
||||
}
|
||||
|
||||
type Global struct {
|
||||
type FeePool struct {
|
||||
TotalValAccumUpdateHeight int64 // last height which the total validator accum was updated
|
||||
TotalValAccum sdk.Dec // total valdator accum held by validators
|
||||
Pool DecCoins // funds for all validators which have yet to be withdrawn
|
||||
|
@ -42,7 +42,7 @@ Validator distribution information for the relevant validator is updated each ti
|
|||
|
||||
```golang
|
||||
type ValidatorDistInfo struct {
|
||||
GlobalWithdrawalHeight int64 // last height this validator withdrew from the global pool
|
||||
FeePoolWithdrawalHeight int64 // last height this validator withdrew from the global fee pool
|
||||
Pool DecCoins // rewards owed to delegators, commission has already been charged (includes proposer reward)
|
||||
PoolCommission DecCoins // commission collected by this validator (pending withdrawal)
|
||||
|
||||
|
@ -59,10 +59,10 @@ properties change (aka bonded tokens etc.) its properties will remain constant
|
|||
and the delegator's _accumulation_ factor can be calculated passively knowing
|
||||
only the height of the last withdrawal and its current properties.
|
||||
|
||||
- DelegatorDistInfo: ` 0x02 | DelegatorAddr | ValOperatorAddr -> amino(delegatorDist)`
|
||||
- DelegationDistInfo: ` 0x02 | DelegatorAddr | ValOperatorAddr -> amino(delegatorDist)`
|
||||
|
||||
```golang
|
||||
type DelegatorDistInfo struct {
|
||||
type DelegationDistInfo struct {
|
||||
WithdrawalHeight int64 // last time this delegation withdrew rewards
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
# Transactions
|
||||
|
||||
## TxWithdrawDelegationRewardsAll
|
||||
## MsgWithdrawDelegationRewardsAll
|
||||
|
||||
When a delegator wishes to withdraw their rewards it must send
|
||||
`TxWithdrawDelegationRewardsAll`. Note that parts of this transaction logic are also
|
||||
`MsgWithdrawDelegationRewardsAll`. Note that parts of this transaction logic are also
|
||||
triggered each with any change in individual delegations, such as an unbond,
|
||||
redelegation, or delegation of additional tokens to a specific validator.
|
||||
|
||||
```golang
|
||||
type TxWithdrawDelegationRewardsAll struct {
|
||||
delegatorAddr sdk.AccAddress
|
||||
withdrawAddr sdk.AccAddress // address to make the withdrawal to
|
||||
type MsgWithdrawDelegationRewardsAll struct {
|
||||
DelegatorAddr sdk.AccAddress
|
||||
}
|
||||
|
||||
func WithdrawDelegationRewardsAll(delegatorAddr, withdrawAddr sdk.AccAddress)
|
||||
|
@ -26,31 +25,30 @@ func GetDelegatorRewardsAll(delegatorAddr sdk.AccAddress, height int64) DecCoins
|
|||
// collect all entitled rewards
|
||||
withdraw = 0
|
||||
pool = stake.GetPool()
|
||||
global = GetGlobal()
|
||||
feePool = GetFeePool()
|
||||
for delegation = range delegations
|
||||
delInfo = GetDelegationDistInfo(delegation.DelegatorAddr,
|
||||
delegation.ValidatorAddr)
|
||||
valInfo = GetValidatorDistInfo(delegation.ValidatorAddr)
|
||||
validator = GetValidator(delegation.ValidatorAddr)
|
||||
|
||||
global, diWithdraw = delInfo.WithdrawRewards(global, valInfo, height, pool.BondedTokens,
|
||||
feePool, diWithdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens,
|
||||
validator.Tokens, validator.DelegatorShares, validator.Commission)
|
||||
withdraw += diWithdraw
|
||||
|
||||
SetGlobal(global)
|
||||
SetFeePool(feePool)
|
||||
return withdraw
|
||||
```
|
||||
|
||||
## TxWithdrawDelegationReward
|
||||
## MsgWithdrawDelegationReward
|
||||
|
||||
under special circumstances a delegator may wish to withdraw rewards from only
|
||||
a single validator.
|
||||
|
||||
```golang
|
||||
type TxWithdrawDelegationReward struct {
|
||||
delegatorAddr sdk.AccAddress
|
||||
validatorAddr sdk.AccAddress
|
||||
withdrawAddr sdk.AccAddress // address to make the withdrawal to
|
||||
type MsgWithdrawDelegationReward struct {
|
||||
DelegatorAddr sdk.AccAddress
|
||||
ValidatorAddr sdk.ValAddress
|
||||
}
|
||||
|
||||
func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.AccAddress)
|
||||
|
@ -58,39 +56,38 @@ func WithdrawDelegationReward(delegatorAddr, validatorAddr, withdrawAddr sdk.Acc
|
|||
|
||||
// get all distribution scenarios
|
||||
pool = stake.GetPool()
|
||||
global = GetGlobal()
|
||||
feePool = GetFeePool()
|
||||
delInfo = GetDelegationDistInfo(delegatorAddr,
|
||||
validatorAddr)
|
||||
valInfo = GetValidatorDistInfo(validatorAddr)
|
||||
validator = GetValidator(validatorAddr)
|
||||
|
||||
global, withdraw = delInfo.WithdrawRewards(global, valInfo, height, pool.BondedTokens,
|
||||
feePool, withdraw = delInfo.WithdrawRewards(feePool, valInfo, height, pool.BondedTokens,
|
||||
validator.Tokens, validator.DelegatorShares, validator.Commission)
|
||||
|
||||
SetGlobal(global)
|
||||
SetFeePool(feePool)
|
||||
AddCoins(withdrawAddr, withdraw.TruncateDecimal())
|
||||
```
|
||||
|
||||
|
||||
## TxWithdrawValidatorRewardsAll
|
||||
## MsgWithdrawValidatorRewardsAll
|
||||
|
||||
When a validator wishes to withdraw their rewards it must send
|
||||
`TxWithdrawValidatorRewardsAll`. Note that parts of this transaction logic are also
|
||||
`MsgWithdrawValidatorRewardsAll`. Note that parts of this transaction logic are also
|
||||
triggered each with any change in individual delegations, such as an unbond,
|
||||
redelegation, or delegation of additional tokens to a specific validator. This
|
||||
transaction withdraws the validators commission fee, as well as any rewards
|
||||
earning on their self-delegation.
|
||||
|
||||
```
|
||||
type TxWithdrawValidatorRewardsAll struct {
|
||||
operatorAddr sdk.AccAddress // validator address to withdraw from
|
||||
withdrawAddr sdk.AccAddress // address to make the withdrawal to
|
||||
type MsgWithdrawValidatorRewardsAll struct {
|
||||
OperatorAddr sdk.ValAddress // validator address to withdraw from
|
||||
}
|
||||
|
||||
func WithdrawValidatorRewardsAll(operatorAddr, withdrawAddr sdk.AccAddress)
|
||||
|
||||
height = GetHeight()
|
||||
global = GetGlobal()
|
||||
feePool = GetFeePool()
|
||||
pool = GetPool()
|
||||
ValInfo = GetValidatorDistInfo(delegation.ValidatorAddr)
|
||||
validator = GetValidator(delegation.ValidatorAddr)
|
||||
|
@ -99,10 +96,10 @@ func WithdrawValidatorRewardsAll(operatorAddr, withdrawAddr sdk.AccAddress)
|
|||
withdraw = GetDelegatorRewardsAll(validator.OperatorAddr, height)
|
||||
|
||||
// withdrawal validator commission rewards
|
||||
global, commission = valInfo.WithdrawCommission(global, valInfo, height, pool.BondedTokens,
|
||||
feePool, commission = valInfo.WithdrawCommission(feePool, valInfo, height, pool.BondedTokens,
|
||||
validator.Tokens, validator.Commission)
|
||||
withdraw += commission
|
||||
SetGlobal(global)
|
||||
SetFeePool(feePool)
|
||||
|
||||
AddCoins(withdrawAddr, withdraw.TruncateDecimal())
|
||||
```
|
||||
|
@ -117,7 +114,7 @@ block. The accum is always additive to the existing accum. This term is to be
|
|||
updated each time rewards are withdrawn from the system.
|
||||
|
||||
```
|
||||
func (g Global) UpdateTotalValAccum(height int64, totalBondedTokens Dec) Global
|
||||
func (g FeePool) UpdateTotalValAccum(height int64, totalBondedTokens Dec) FeePool
|
||||
blocks = height - g.TotalValAccumUpdateHeight
|
||||
g.TotalValAccum += totalDelShares * blocks
|
||||
g.TotalValAccumUpdateHeight = height
|
||||
|
@ -140,7 +137,7 @@ func (vi ValidatorDistInfo) UpdateTotalDelAccum(height int64, totalDelShares Dec
|
|||
return vi
|
||||
```
|
||||
|
||||
### Global pool to validator pool
|
||||
### FeePool pool to validator pool
|
||||
|
||||
Every time a validator or delegator executes a withdrawal or the validator is
|
||||
the proposer and receives new tokens, the relevant validator must move tokens
|
||||
|
@ -148,14 +145,14 @@ from the passive global pool to their own pool. It is at this point that the
|
|||
commission is withdrawn
|
||||
|
||||
```
|
||||
func (vi ValidatorDistInfo) TakeAccum(g Global, height int64, totalBonded, vdTokens, commissionRate Dec) (
|
||||
vi ValidatorDistInfo, g Global)
|
||||
func (vi ValidatorDistInfo) TakeFeePoolRewards(g FeePool, height int64, totalBonded, vdTokens, commissionRate Dec) (
|
||||
vi ValidatorDistInfo, g FeePool)
|
||||
|
||||
g.UpdateTotalValAccum(height, totalBondedShares)
|
||||
|
||||
// update the validators pool
|
||||
blocks = height - vi.GlobalWithdrawalHeight
|
||||
vi.GlobalWithdrawalHeight = height
|
||||
blocks = height - vi.FeePoolWithdrawalHeight
|
||||
vi.FeePoolWithdrawalHeight = height
|
||||
accum = blocks * vdTokens
|
||||
withdrawalTokens := g.Pool * accum / g.TotalValAccum
|
||||
commission := withdrawalTokens * commissionRate
|
||||
|
@ -175,12 +172,12 @@ For delegations (including validator's self-delegation) all rewards from reward
|
|||
pool have already had the validator's commission taken away.
|
||||
|
||||
```
|
||||
func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo,
|
||||
func (di DelegationDistInfo) WithdrawRewards(g FeePool, vi ValidatorDistInfo,
|
||||
height int64, totalBonded, vdTokens, totalDelShares, commissionRate Dec) (
|
||||
di DelegatorDistInfo, g Global, withdrawn DecCoins)
|
||||
di DelegationDistInfo, g FeePool, withdrawn DecCoins)
|
||||
|
||||
vi.UpdateTotalDelAccum(height, totalDelShares)
|
||||
g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate)
|
||||
g = vi.TakeFeePoolRewards(g, height, totalBonded, vdTokens, commissionRate)
|
||||
|
||||
blocks = height - di.WithdrawalHeight
|
||||
di.WithdrawalHeight = height
|
||||
|
@ -200,11 +197,11 @@ func (di DelegatorDistInfo) WithdrawRewards(g Global, vi ValidatorDistInfo,
|
|||
Commission is calculated each time rewards enter into the validator.
|
||||
|
||||
```
|
||||
func (vi ValidatorDistInfo) WithdrawCommission(g Global, height int64,
|
||||
func (vi ValidatorDistInfo) WithdrawCommission(g FeePool, height int64,
|
||||
totalBonded, vdTokens, commissionRate Dec) (
|
||||
vi ValidatorDistInfo, g Global, withdrawn DecCoins)
|
||||
vi ValidatorDistInfo, g FeePool, withdrawn DecCoins)
|
||||
|
||||
g = vi.TakeAccum(g, height, totalBonded, vdTokens, commissionRate)
|
||||
g = vi.TakeFeePoolRewards(g, height, totalBonded, vdTokens, commissionRate)
|
||||
|
||||
withdrawalTokens := vi.PoolCommission
|
||||
vi.PoolCommission = 0
|
||||
|
|
|
@ -48,6 +48,11 @@ func (v Validator) GetDelegatorShares() sdk.Dec {
|
|||
return sdk.ZeroDec()
|
||||
}
|
||||
|
||||
// Implements sdk.Validator
|
||||
func (v Validator) GetCommission() sdk.Dec {
|
||||
return sdk.ZeroDec()
|
||||
}
|
||||
|
||||
// Implements sdk.Validator
|
||||
func (v Validator) GetJailed() bool {
|
||||
return false
|
||||
|
|
|
@ -187,6 +187,12 @@ func (c Context) WithBlockTime(newTime time.Time) Context {
|
|||
return c.WithBlockHeader(newHeader)
|
||||
}
|
||||
|
||||
func (c Context) WithProposer(addr ConsAddress) Context {
|
||||
newHeader := c.BlockHeader()
|
||||
newHeader.ProposerAddress = addr.Bytes()
|
||||
return c.WithBlockHeader(newHeader)
|
||||
}
|
||||
|
||||
func (c Context) WithBlockHeight(height int64) Context {
|
||||
newHeader := c.BlockHeader()
|
||||
newHeader.Height = height
|
||||
|
|
|
@ -241,6 +241,12 @@ func (d Dec) Quo(d2 Dec) Dec {
|
|||
return Dec{chopped}
|
||||
}
|
||||
|
||||
// quotient
|
||||
func (d Dec) QuoInt(i Int) Dec {
|
||||
mul := new(big.Int).Quo(d.Int, i.i)
|
||||
return Dec{mul}
|
||||
}
|
||||
|
||||
func (d Dec) String() string {
|
||||
str := d.ToLeftPaddedWithDecimals(Precision)
|
||||
placement := len(str) - Precision
|
||||
|
@ -462,6 +468,6 @@ func MaxDec(d1, d2 Dec) Dec {
|
|||
}
|
||||
|
||||
// intended to be used with require/assert: require.True(DecEq(...))
|
||||
func DecEq(t *testing.T, exp, got Dec) (*testing.T, bool, string, Dec, Dec) {
|
||||
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp, got
|
||||
func DecEq(t *testing.T, exp, got Dec) (*testing.T, bool, string, string, string) {
|
||||
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp.String(), got.String()
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package types
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"math/big"
|
||||
"math/rand"
|
||||
|
@ -525,3 +526,10 @@ func (i *Uint) UnmarshalJSON(bz []byte) error {
|
|||
}
|
||||
return unmarshalJSON(i.i, bz)
|
||||
}
|
||||
|
||||
//__________________________________________________________________________
|
||||
|
||||
// intended to be used with require/assert: require.True(IntEq(...))
|
||||
func IntEq(t *testing.T, exp, got Int) (*testing.T, bool, string, string, string) {
|
||||
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp.String(), got.String()
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ type Validator interface {
|
|||
GetConsAddr() ConsAddress // validation consensus address
|
||||
GetPower() Dec // validation power
|
||||
GetTokens() Dec // validation tokens
|
||||
GetCommission() Dec // validator commission rate
|
||||
GetDelegatorShares() Dec // Total out standing delegator shares
|
||||
GetBondHeight() int64 // height in which the validator became active
|
||||
}
|
||||
|
|
|
@ -302,6 +302,3 @@ func getSignBytesList(chainID string, stdTx StdTx, stdSigs []StdSignature) (sign
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BurnFeeHandler burns all fees (decreasing total supply)
|
||||
func BurnFeeHandler(_ sdk.Context, _ sdk.Tx, _ sdk.Coins) {}
|
||||
|
|
|
@ -20,7 +20,6 @@ type FeeCollectionKeeper struct {
|
|||
cdc *codec.Codec
|
||||
}
|
||||
|
||||
// NewFeeKeeper returns a new FeeKeeper
|
||||
func NewFeeCollectionKeeper(cdc *codec.Codec, key sdk.StoreKey) FeeCollectionKeeper {
|
||||
return FeeCollectionKeeper{
|
||||
key: key,
|
||||
|
@ -28,7 +27,7 @@ func NewFeeCollectionKeeper(cdc *codec.Codec, key sdk.StoreKey) FeeCollectionKee
|
|||
}
|
||||
}
|
||||
|
||||
// Adds to Collected Fee Pool
|
||||
// retrieves the collected fee pool
|
||||
func (fck FeeCollectionKeeper) GetCollectedFees(ctx sdk.Context) sdk.Coins {
|
||||
store := ctx.KVStore(fck.key)
|
||||
bz := store.Get(collectedFeesKey)
|
||||
|
@ -41,14 +40,12 @@ func (fck FeeCollectionKeeper) GetCollectedFees(ctx sdk.Context) sdk.Coins {
|
|||
return *feePool
|
||||
}
|
||||
|
||||
// Sets to Collected Fee Pool
|
||||
func (fck FeeCollectionKeeper) setCollectedFees(ctx sdk.Context, coins sdk.Coins) {
|
||||
bz := fck.cdc.MustMarshalBinary(coins)
|
||||
store := ctx.KVStore(fck.key)
|
||||
store.Set(collectedFeesKey, bz)
|
||||
}
|
||||
|
||||
// Adds to Collected Fee Pool
|
||||
func (fck FeeCollectionKeeper) addCollectedFees(ctx sdk.Context, coins sdk.Coins) sdk.Coins {
|
||||
newCoins := fck.GetCollectedFees(ctx).Plus(coins)
|
||||
fck.setCollectedFees(ctx, newCoins)
|
||||
|
@ -56,7 +53,7 @@ func (fck FeeCollectionKeeper) addCollectedFees(ctx sdk.Context, coins sdk.Coins
|
|||
return newCoins
|
||||
}
|
||||
|
||||
// Clears the collected Fee Pool
|
||||
// clear the fee pool
|
||||
func (fck FeeCollectionKeeper) ClearCollectedFees(ctx sdk.Context) {
|
||||
fck.setCollectedFees(ctx, sdk.Coins{})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package distribution
|
||||
|
||||
import (
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
)
|
||||
|
||||
// set the proposer for determining distribution during endblock
|
||||
func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) {
|
||||
|
||||
if ctx.BlockHeight() > 1 {
|
||||
previousPercentPrecommitVotes := getPreviousPercentPrecommitVotes(req)
|
||||
previousProposer := k.GetPreviousProposerConsAddr(ctx)
|
||||
k.AllocateFees(ctx, previousPercentPrecommitVotes, previousProposer)
|
||||
}
|
||||
|
||||
consAddr := sdk.ConsAddress(req.Header.ProposerAddress)
|
||||
k.SetPreviousProposerConsAddr(ctx, consAddr)
|
||||
}
|
||||
|
||||
// percent precommit votes for the previous block
|
||||
func getPreviousPercentPrecommitVotes(req abci.RequestBeginBlock) sdk.Dec {
|
||||
|
||||
// determine the total number of signed power
|
||||
totalPower, sumPrecommitPower := int64(0), int64(0)
|
||||
for _, voteInfo := range req.LastCommitInfo.GetVotes() {
|
||||
totalPower += voteInfo.Validator.Power
|
||||
if voteInfo.SignedLastBlock {
|
||||
sumPrecommitPower += voteInfo.Validator.Power
|
||||
}
|
||||
}
|
||||
|
||||
if totalPower == 0 {
|
||||
return sdk.ZeroDec()
|
||||
}
|
||||
return sdk.NewDec(sumPrecommitPower).Quo(sdk.NewDec(totalPower))
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// nolint
|
||||
package distribution
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/tags"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
type (
|
||||
Keeper = keeper.Keeper
|
||||
Hooks = keeper.Hooks
|
||||
|
||||
DelegatorWithdrawInfo = types.DelegatorWithdrawInfo
|
||||
DelegationDistInfo = types.DelegationDistInfo
|
||||
ValidatorDistInfo = types.ValidatorDistInfo
|
||||
TotalAccum = types.TotalAccum
|
||||
FeePool = types.FeePool
|
||||
|
||||
MsgSetWithdrawAddress = types.MsgSetWithdrawAddress
|
||||
MsgWithdrawDelegatorRewardsAll = types.MsgWithdrawDelegatorRewardsAll
|
||||
MsgWithdrawDelegatorReward = types.MsgWithdrawDelegatorReward
|
||||
MsgWithdrawValidatorRewardsAll = types.MsgWithdrawValidatorRewardsAll
|
||||
|
||||
GenesisState = types.GenesisState
|
||||
)
|
||||
|
||||
var (
|
||||
NewKeeper = keeper.NewKeeper
|
||||
|
||||
GetValidatorDistInfoKey = keeper.GetValidatorDistInfoKey
|
||||
GetDelegationDistInfoKey = keeper.GetDelegationDistInfoKey
|
||||
GetDelegationDistInfosKey = keeper.GetDelegationDistInfosKey
|
||||
GetDelegatorWithdrawAddrKey = keeper.GetDelegatorWithdrawAddrKey
|
||||
FeePoolKey = keeper.FeePoolKey
|
||||
ValidatorDistInfoKey = keeper.ValidatorDistInfoKey
|
||||
DelegationDistInfoKey = keeper.DelegationDistInfoKey
|
||||
DelegatorWithdrawInfoKey = keeper.DelegatorWithdrawInfoKey
|
||||
ProposerKey = keeper.ProposerKey
|
||||
DefaultParamspace = keeper.DefaultParamspace
|
||||
|
||||
InitialFeePool = types.InitialFeePool
|
||||
|
||||
NewGenesisState = types.NewGenesisState
|
||||
DefaultGenesisState = types.DefaultGenesisState
|
||||
DefaultGenesisWithValidators = types.DefaultGenesisWithValidators
|
||||
|
||||
RegisterCodec = types.RegisterCodec
|
||||
|
||||
NewMsgSetWithdrawAddress = types.NewMsgSetWithdrawAddress
|
||||
NewMsgWithdrawDelegatorRewardsAll = types.NewMsgWithdrawDelegatorRewardsAll
|
||||
NewMsgWithdrawDelegationReward = types.NewMsgWithdrawDelegatorReward
|
||||
NewMsgWithdrawValidatorRewardsAll = types.NewMsgWithdrawValidatorRewardsAll
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultCodespace = types.DefaultCodespace
|
||||
CodeInvalidInput = types.CodeInvalidInput
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNilDelegatorAddr = types.ErrNilDelegatorAddr
|
||||
ErrNilWithdrawAddr = types.ErrNilWithdrawAddr
|
||||
ErrNilValidatorAddr = types.ErrNilValidatorAddr
|
||||
)
|
||||
|
||||
var (
|
||||
ActionModifyWithdrawAddress = tags.ActionModifyWithdrawAddress
|
||||
ActionWithdrawDelegatorRewardsAll = tags.ActionWithdrawDelegatorRewardsAll
|
||||
ActionWithdrawDelegatorReward = tags.ActionWithdrawDelegatorReward
|
||||
ActionWithdrawValidatorRewardsAll = tags.ActionWithdrawValidatorRewardsAll
|
||||
|
||||
TagAction = tags.Action
|
||||
TagValidator = tags.Validator
|
||||
TagDelegator = tags.Delegator
|
||||
)
|
|
@ -0,0 +1,114 @@
|
|||
// nolint
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
"github.com/cosmos/cosmos-sdk/client/utils"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
var (
|
||||
flagOnlyFromValidator = "only-from-validator"
|
||||
flagIsValidator = "is-validator"
|
||||
)
|
||||
|
||||
// command to withdraw rewards
|
||||
func GetCmdWithdrawRewards(cdc *codec.Codec) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "withdraw-rewards",
|
||||
Short: "withdraw rewards for either: all-delegations, a delegation, or a validator",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
onlyFromVal := viper.GetString(flagOnlyFromValidator)
|
||||
isVal := viper.GetBool(flagIsValidator)
|
||||
|
||||
if onlyFromVal != "" && isVal {
|
||||
return fmt.Errorf("cannot use --%v, and --%v flags together",
|
||||
flagOnlyFromValidator, flagIsValidator)
|
||||
}
|
||||
|
||||
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
|
||||
cliCtx := context.NewCLIContext().
|
||||
WithCodec(cdc).
|
||||
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
|
||||
|
||||
var msg sdk.Msg
|
||||
switch {
|
||||
case isVal:
|
||||
addr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valAddr := sdk.ValAddress(addr.Bytes())
|
||||
msg = types.NewMsgWithdrawValidatorRewardsAll(valAddr)
|
||||
case onlyFromVal != "":
|
||||
delAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
valAddr, err := sdk.ValAddressFromBech32(onlyFromVal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg = types.NewMsgWithdrawDelegatorReward(delAddr, valAddr)
|
||||
default:
|
||||
delAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg = types.NewMsgWithdrawDelegatorRewardsAll(delAddr)
|
||||
}
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
cmd.Flags().String(flagOnlyFromValidator, "", "only withdraw from this validator address (in bech)")
|
||||
cmd.Flags().Bool(flagIsValidator, false, "also withdraw validator's commission")
|
||||
return cmd
|
||||
}
|
||||
|
||||
// GetCmdDelegate implements the delegate command.
|
||||
func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "set-withdraw-addr [withdraw-addr]",
|
||||
Short: "change the default withdraw address for rewards associated with an address",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
|
||||
cliCtx := context.NewCLIContext().
|
||||
WithCodec(cdc).
|
||||
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
|
||||
|
||||
delAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
withdrawAddr, err := sdk.AccAddressFromBech32(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := types.NewMsgSetWithdrawAddress(delAddr, withdrawAddr)
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package distribution
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
// InitGenesis sets distribution information for genesis
|
||||
func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) {
|
||||
keeper.SetFeePool(ctx, data.FeePool)
|
||||
keeper.SetCommunityTax(ctx, data.CommunityTax)
|
||||
keeper.SetBaseProposerReward(ctx, data.BaseProposerReward)
|
||||
keeper.SetBonusProposerReward(ctx, data.BonusProposerReward)
|
||||
|
||||
for _, vdi := range data.ValidatorDistInfos {
|
||||
keeper.SetValidatorDistInfo(ctx, vdi)
|
||||
}
|
||||
for _, ddi := range data.DelegationDistInfos {
|
||||
keeper.SetDelegationDistInfo(ctx, ddi)
|
||||
}
|
||||
for _, dw := range data.DelegatorWithdrawInfos {
|
||||
keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteGenesis returns a GenesisState for a given context and keeper. The
|
||||
// GenesisState will contain the pool, and validator/delegator distribution info's
|
||||
func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
|
||||
feePool := keeper.GetFeePool(ctx)
|
||||
communityTax := keeper.GetCommunityTax(ctx)
|
||||
baseProposerRewards := keeper.GetBaseProposerReward(ctx)
|
||||
bonusProposerRewards := keeper.GetBonusProposerReward(ctx)
|
||||
vdis := keeper.GetAllValidatorDistInfos(ctx)
|
||||
ddis := keeper.GetAllDelegationDistInfos(ctx)
|
||||
dwis := keeper.GetAllDelegatorWithdrawInfos(ctx)
|
||||
return NewGenesisState(feePool, communityTax, baseProposerRewards,
|
||||
bonusProposerRewards, vdis, ddis, dwis)
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package distribution
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/tags"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
func NewHandler(k keeper.Keeper) sdk.Handler {
|
||||
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
|
||||
// NOTE msg already has validate basic run
|
||||
switch msg := msg.(type) {
|
||||
case types.MsgSetWithdrawAddress:
|
||||
return handleMsgModifyWithdrawAddress(ctx, msg, k)
|
||||
case types.MsgWithdrawDelegatorRewardsAll:
|
||||
return handleMsgWithdrawDelegatorRewardsAll(ctx, msg, k)
|
||||
case types.MsgWithdrawDelegatorReward:
|
||||
return handleMsgWithdrawDelegatorReward(ctx, msg, k)
|
||||
case types.MsgWithdrawValidatorRewardsAll:
|
||||
return handleMsgWithdrawValidatorRewardsAll(ctx, msg, k)
|
||||
default:
|
||||
return sdk.ErrTxDecode("invalid message parse in distribution module").Result()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________________
|
||||
|
||||
// These functions assume everything has been authenticated,
|
||||
// now we just perform action and save
|
||||
|
||||
func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAddress, k keeper.Keeper) sdk.Result {
|
||||
|
||||
k.SetDelegatorWithdrawAddr(ctx, msg.DelegatorAddr, msg.WithdrawAddr)
|
||||
|
||||
tags := sdk.NewTags(
|
||||
tags.Action, tags.ActionModifyWithdrawAddress,
|
||||
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
||||
)
|
||||
return sdk.Result{
|
||||
Tags: tags,
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgWithdrawDelegatorRewardsAll(ctx sdk.Context, msg types.MsgWithdrawDelegatorRewardsAll, k keeper.Keeper) sdk.Result {
|
||||
|
||||
k.WithdrawDelegationRewardsAll(ctx, msg.DelegatorAddr)
|
||||
|
||||
tags := sdk.NewTags(
|
||||
tags.Action, tags.ActionWithdrawDelegatorRewardsAll,
|
||||
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
||||
)
|
||||
return sdk.Result{
|
||||
Tags: tags,
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDelegatorReward, k keeper.Keeper) sdk.Result {
|
||||
|
||||
k.WithdrawDelegationReward(ctx, msg.DelegatorAddr, msg.ValidatorAddr)
|
||||
|
||||
tags := sdk.NewTags(
|
||||
tags.Action, tags.ActionWithdrawDelegatorReward,
|
||||
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
||||
tags.Validator, []byte(msg.ValidatorAddr.String()),
|
||||
)
|
||||
return sdk.Result{
|
||||
Tags: tags,
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgWithdrawValidatorRewardsAll(ctx sdk.Context, msg types.MsgWithdrawValidatorRewardsAll, k keeper.Keeper) sdk.Result {
|
||||
|
||||
k.WithdrawValidatorRewardsAll(ctx, msg.ValidatorAddr)
|
||||
|
||||
tags := sdk.NewTags(
|
||||
tags.Action, tags.ActionWithdrawValidatorRewardsAll,
|
||||
tags.Validator, []byte(msg.ValidatorAddr.String()),
|
||||
)
|
||||
return sdk.Result{
|
||||
Tags: tags,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
// Allocate fees handles distribution of the collected fees
|
||||
func (k Keeper) AllocateFees(ctx sdk.Context, percentVotes sdk.Dec, proposer sdk.ConsAddress) {
|
||||
ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("allocation height: %v", ctx.BlockHeight()))
|
||||
|
||||
// get the proposer of this block
|
||||
proposerValidator := k.stakeKeeper.ValidatorByConsAddr(ctx, proposer)
|
||||
proposerDist := k.GetValidatorDistInfo(ctx, proposerValidator.GetOperator())
|
||||
|
||||
// get the fees which have been getting collected through all the
|
||||
// transactions in the block
|
||||
feesCollected := k.feeCollectionKeeper.GetCollectedFees(ctx)
|
||||
feesCollectedDec := types.NewDecCoins(feesCollected)
|
||||
|
||||
// allocated rewards to proposer
|
||||
baseProposerReward := k.GetBaseProposerReward(ctx)
|
||||
bonusProposerReward := k.GetBonusProposerReward(ctx)
|
||||
proposerMultiplier := baseProposerReward.Add(bonusProposerReward.Mul(percentVotes))
|
||||
proposerReward := feesCollectedDec.MulDec(proposerMultiplier)
|
||||
|
||||
// apply commission
|
||||
commission := proposerReward.MulDec(proposerValidator.GetCommission())
|
||||
remaining := proposerReward.Minus(commission)
|
||||
proposerDist.PoolCommission = proposerDist.PoolCommission.Plus(commission)
|
||||
proposerDist.Pool = proposerDist.Pool.Plus(remaining)
|
||||
|
||||
// allocate community funding
|
||||
communityTax := k.GetCommunityTax(ctx)
|
||||
communityFunding := feesCollectedDec.MulDec(communityTax)
|
||||
feePool := k.GetFeePool(ctx)
|
||||
feePool.CommunityPool = feePool.CommunityPool.Plus(communityFunding)
|
||||
|
||||
// set the global pool within the distribution module
|
||||
poolReceived := feesCollectedDec.Minus(proposerReward).Minus(communityFunding)
|
||||
feePool.Pool = feePool.Pool.Plus(poolReceived)
|
||||
|
||||
k.SetValidatorDistInfo(ctx, proposerDist)
|
||||
k.SetFeePool(ctx, feePool)
|
||||
|
||||
// clear the now distributed fees
|
||||
k.feeCollectionKeeper.ClearCollectedFees(ctx)
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAllocateFeesBasic(t *testing.T) {
|
||||
|
||||
// no community tax on inputs
|
||||
ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator
|
||||
totalPower := int64(10)
|
||||
totalPowerDec := sdk.NewDec(totalPower)
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidator(valOpAddr1, valConsPk1, totalPower)
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// verify everything has been set in staking correctly
|
||||
validator, found := sk.GetValidator(ctx, valOpAddr1)
|
||||
require.True(t, found)
|
||||
require.Equal(t, sdk.Bonded, validator.Status)
|
||||
assert.True(sdk.DecEq(t, totalPowerDec, validator.Tokens))
|
||||
assert.True(sdk.DecEq(t, totalPowerDec, validator.DelegatorShares))
|
||||
bondedTokens := sk.TotalPower(ctx)
|
||||
assert.True(sdk.DecEq(t, totalPowerDec, bondedTokens))
|
||||
|
||||
// initial fee pool should be empty
|
||||
feePool := keeper.GetFeePool(ctx)
|
||||
require.Nil(t, feePool.Pool)
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// verify that these fees have been received by the feePool
|
||||
percentProposer := sdk.NewDecWithPrec(5, 2)
|
||||
percentRemaining := sdk.OneDec().Sub(percentProposer)
|
||||
feePool = keeper.GetFeePool(ctx)
|
||||
expRes := sdk.NewDecFromInt(feeInputs).Mul(percentRemaining)
|
||||
require.Equal(t, 1, len(feePool.Pool))
|
||||
require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount))
|
||||
}
|
||||
|
||||
func TestAllocateFeesWithCommunityTax(t *testing.T) {
|
||||
communityTax := sdk.NewDecWithPrec(1, 2) //1%
|
||||
ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, communityTax)
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator
|
||||
totalPower := int64(10)
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidator(valOpAddr1, valConsPk1, totalPower)
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// verify that these fees have been received by the feePool
|
||||
feePool := keeper.GetFeePool(ctx)
|
||||
// 5% goes to proposer, 1% community tax
|
||||
percentProposer := sdk.NewDecWithPrec(5, 2)
|
||||
percentRemaining := sdk.OneDec().Sub(communityTax.Add(percentProposer))
|
||||
expRes := sdk.NewDecFromInt(feeInputs).Mul(percentRemaining)
|
||||
require.Equal(t, 1, len(feePool.Pool))
|
||||
require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount))
|
||||
}
|
||||
|
||||
func TestAllocateFeesWithPartialPrecommitPower(t *testing.T) {
|
||||
communityTax := sdk.NewDecWithPrec(1, 2)
|
||||
ctx, _, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, communityTax)
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator
|
||||
totalPower := int64(100)
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidator(valOpAddr1, valConsPk1, totalPower)
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
percentPrecommitVotes := sdk.NewDecWithPrec(25, 2)
|
||||
keeper.AllocateFees(ctx, percentPrecommitVotes, valConsAddr1)
|
||||
|
||||
// verify that these fees have been received by the feePool
|
||||
feePool := keeper.GetFeePool(ctx)
|
||||
// 1% + 4%*0.25 to proposer + 1% community tax = 97%
|
||||
percentProposer := sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(4, 2).Mul(percentPrecommitVotes))
|
||||
percentRemaining := sdk.OneDec().Sub(communityTax.Add(percentProposer))
|
||||
expRes := sdk.NewDecFromInt(feeInputs).Mul(percentRemaining)
|
||||
require.Equal(t, 1, len(feePool.Pool))
|
||||
require.True(sdk.DecEq(t, expRes, feePool.Pool[0].Amount))
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
// get the delegator distribution info
|
||||
func (k Keeper) GetDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
|
||||
valOperatorAddr sdk.ValAddress) (ddi types.DelegationDistInfo) {
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
b := store.Get(GetDelegationDistInfoKey(delAddr, valOperatorAddr))
|
||||
if b == nil {
|
||||
panic("Stored delegation-distribution info should not have been nil")
|
||||
}
|
||||
|
||||
k.cdc.MustUnmarshalBinary(b, &ddi)
|
||||
return
|
||||
}
|
||||
|
||||
// set the delegator distribution info
|
||||
func (k Keeper) SetDelegationDistInfo(ctx sdk.Context, ddi types.DelegationDistInfo) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
b := k.cdc.MustMarshalBinary(ddi)
|
||||
store.Set(GetDelegationDistInfoKey(ddi.DelegatorAddr, ddi.ValOperatorAddr), b)
|
||||
}
|
||||
|
||||
// remove a delegator distribution info
|
||||
func (k Keeper) RemoveDelegationDistInfo(ctx sdk.Context, delAddr sdk.AccAddress,
|
||||
valOperatorAddr sdk.ValAddress) {
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Delete(GetDelegationDistInfoKey(delAddr, valOperatorAddr))
|
||||
}
|
||||
|
||||
//___________________________________________________________________________________________
|
||||
|
||||
// get the delegator withdraw address, return the delegator address if not set
|
||||
func (k Keeper) GetDelegatorWithdrawAddr(ctx sdk.Context, delAddr sdk.AccAddress) sdk.AccAddress {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
b := store.Get(GetDelegatorWithdrawAddrKey(delAddr))
|
||||
if b == nil {
|
||||
return delAddr
|
||||
}
|
||||
return sdk.AccAddress(b)
|
||||
}
|
||||
|
||||
// set the delegator withdraw address
|
||||
func (k Keeper) SetDelegatorWithdrawAddr(ctx sdk.Context, delAddr, withdrawAddr sdk.AccAddress) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Set(GetDelegatorWithdrawAddrKey(delAddr), withdrawAddr.Bytes())
|
||||
}
|
||||
|
||||
// remove a delegator withdraw info
|
||||
func (k Keeper) RemoveDelegatorWithdrawAddr(ctx sdk.Context, delAddr, withdrawAddr sdk.AccAddress) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Delete(GetDelegatorWithdrawAddrKey(delAddr))
|
||||
}
|
||||
|
||||
//___________________________________________________________________________________________
|
||||
|
||||
// withdraw all the rewards for a single delegation
|
||||
func (k Keeper) WithdrawDelegationReward(ctx sdk.Context, delegatorAddr sdk.AccAddress,
|
||||
validatorAddr sdk.ValAddress) {
|
||||
|
||||
height := ctx.BlockHeight()
|
||||
bondedTokens := k.stakeKeeper.TotalPower(ctx)
|
||||
feePool := k.GetFeePool(ctx)
|
||||
delInfo := k.GetDelegationDistInfo(ctx, delegatorAddr, validatorAddr)
|
||||
valInfo := k.GetValidatorDistInfo(ctx, validatorAddr)
|
||||
validator := k.stakeKeeper.Validator(ctx, validatorAddr)
|
||||
delegation := k.stakeKeeper.Delegation(ctx, delegatorAddr, validatorAddr)
|
||||
|
||||
delInfo, valInfo, feePool, withdraw := delInfo.WithdrawRewards(feePool, valInfo, height, bondedTokens,
|
||||
validator.GetTokens(), validator.GetDelegatorShares(), delegation.GetShares(), validator.GetCommission())
|
||||
|
||||
k.SetFeePool(ctx, feePool)
|
||||
k.SetValidatorDistInfo(ctx, valInfo)
|
||||
k.SetDelegationDistInfo(ctx, delInfo)
|
||||
withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr)
|
||||
_, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
//___________________________________________________________________________________________
|
||||
|
||||
// return all rewards for all delegations of a delegator
|
||||
func (k Keeper) WithdrawDelegationRewardsAll(ctx sdk.Context, delegatorAddr sdk.AccAddress) {
|
||||
height := ctx.BlockHeight()
|
||||
withdraw := k.getDelegatorRewardsAll(ctx, delegatorAddr, height)
|
||||
withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, delegatorAddr)
|
||||
_, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// return all rewards for all delegations of a delegator
|
||||
func (k Keeper) getDelegatorRewardsAll(ctx sdk.Context, delAddr sdk.AccAddress, height int64) types.DecCoins {
|
||||
|
||||
withdraw := types.DecCoins{}
|
||||
bondedTokens := k.stakeKeeper.TotalPower(ctx)
|
||||
feePool := k.GetFeePool(ctx)
|
||||
|
||||
// iterate over all the delegations
|
||||
operationAtDelegation := func(_ int64, del sdk.Delegation) (stop bool) {
|
||||
valAddr := del.GetValidator()
|
||||
delInfo := k.GetDelegationDistInfo(ctx, delAddr, valAddr)
|
||||
valInfo := k.GetValidatorDistInfo(ctx, valAddr)
|
||||
validator := k.stakeKeeper.Validator(ctx, valAddr)
|
||||
delegation := k.stakeKeeper.Delegation(ctx, delAddr, valAddr)
|
||||
|
||||
delInfo, valInfo, feePool, diWithdraw := delInfo.WithdrawRewards(feePool, valInfo, height, bondedTokens,
|
||||
validator.GetTokens(), validator.GetDelegatorShares(), delegation.GetShares(), validator.GetCommission())
|
||||
withdraw = withdraw.Plus(diWithdraw)
|
||||
k.SetFeePool(ctx, feePool)
|
||||
k.SetValidatorDistInfo(ctx, valInfo)
|
||||
k.SetDelegationDistInfo(ctx, delInfo)
|
||||
return false
|
||||
}
|
||||
k.stakeKeeper.IterateDelegations(ctx, delAddr, operationAtDelegation)
|
||||
|
||||
k.SetFeePool(ctx, feePool)
|
||||
return withdraw
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestWithdrawDelegationRewardBasic(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidator(valOpAddr1, valConsPk1, 10)
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// delegate
|
||||
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(90), amt.Int64())
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw delegation
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
|
||||
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
|
||||
expRes := sdk.NewDec(90).Add(sdk.NewDec(100).Quo(sdk.NewDec(2))).TruncateInt() // 90 + 100 tokens * 10/20
|
||||
require.True(sdk.IntEq(t, expRes, amt))
|
||||
}
|
||||
|
||||
func TestWithdrawDelegationRewardWithCommission(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator with 10% commission
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr1, valConsPk1, 10, sdk.NewDecWithPrec(1, 1))
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// delegate
|
||||
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(90), amt.Int64())
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw delegation
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
|
||||
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
|
||||
expRes := sdk.NewDec(90).Add(sdk.NewDec(90).Quo(sdk.NewDec(2))).TruncateInt() // 90 + 100*90% tokens * 10/20
|
||||
require.True(sdk.IntEq(t, expRes, amt))
|
||||
}
|
||||
|
||||
func TestWithdrawDelegationRewardTwoDelegators(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator with 10% commission
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr1, valConsPk1, 10, sdk.NewDecWithPrec(1, 1))
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// delegate
|
||||
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(90), amt.Int64())
|
||||
|
||||
msgDelegate = stake.NewTestMsgDelegate(delAddr2, valOpAddr1, 20)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(80), amt.Int64())
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// delegator 1 withdraw delegation
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
|
||||
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
|
||||
expRes := sdk.NewDec(90).Add(sdk.NewDec(90).Quo(sdk.NewDec(4))).TruncateInt() // 90 + 100*90% tokens * 10/40
|
||||
require.True(sdk.IntEq(t, expRes, amt))
|
||||
}
|
||||
|
||||
// this test demonstrates how two delegators with the same power can end up
|
||||
// with different rewards in the end
|
||||
func TestWithdrawDelegationRewardTwoDelegatorsUneven(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator with no commission
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr1, valConsPk1, 10, sdk.ZeroDec())
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// delegate
|
||||
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(90), amt.Int64())
|
||||
|
||||
msgDelegate = stake.NewTestMsgDelegate(delAddr2, valOpAddr1, 10)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(90), amt.Int64())
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(90)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
|
||||
// delegator 1 withdraw delegation early, delegator 2 just keeps it's accum
|
||||
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
|
||||
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
|
||||
expRes1 := sdk.NewDec(90).Add(sdk.NewDec(90).Quo(sdk.NewDec(3))).TruncateInt() // 90 + 100 * 10/30
|
||||
require.True(sdk.IntEq(t, expRes1, amt))
|
||||
|
||||
// allocate 200 denom of fees
|
||||
feeInputs = sdk.NewInt(180)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
ctx = ctx.WithBlockHeight(2)
|
||||
|
||||
// delegator 2 now withdraws everything it's entitled to
|
||||
keeper.WithdrawDelegationReward(ctx, delAddr2, valOpAddr1)
|
||||
amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom)
|
||||
// existingTokens + (100+200 * (10/(20+30))
|
||||
withdrawnFromVal := sdk.NewDec(60 + 180).Mul(sdk.NewDec(2)).Quo(sdk.NewDec(5))
|
||||
expRes2 := sdk.NewDec(90).Add(withdrawnFromVal).TruncateInt()
|
||||
require.True(sdk.IntEq(t, expRes2, amt))
|
||||
|
||||
// finally delegator 1 withdraws the remainder of its reward
|
||||
keeper.WithdrawDelegationReward(ctx, delAddr1, valOpAddr1)
|
||||
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
|
||||
remainingInVal := sdk.NewDec(60 + 180).Sub(withdrawnFromVal)
|
||||
expRes3 := sdk.NewDecFromInt(expRes1).Add(remainingInVal.Mul(sdk.NewDec(1)).Quo(sdk.NewDec(3))).TruncateInt()
|
||||
require.True(sdk.IntEq(t, expRes3, amt))
|
||||
|
||||
// verify the final withdraw amounts are different
|
||||
require.True(t, expRes2.GT(expRes3))
|
||||
}
|
||||
|
||||
func TestWithdrawDelegationRewardsAll(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//make some validators with different commissions
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr1, valConsPk1, 10, sdk.NewDecWithPrec(1, 1))
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
|
||||
msgCreateValidator = stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr2, valConsPk2, 50, sdk.NewDecWithPrec(2, 1))
|
||||
got = stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
|
||||
msgCreateValidator = stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr3, valConsPk3, 40, sdk.NewDecWithPrec(3, 1))
|
||||
got = stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// delegate to all the validators
|
||||
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
|
||||
require.True(t, stakeHandler(ctx, msgDelegate).IsOK())
|
||||
msgDelegate = stake.NewTestMsgDelegate(delAddr1, valOpAddr2, 20)
|
||||
require.True(t, stakeHandler(ctx, msgDelegate).IsOK())
|
||||
msgDelegate = stake.NewTestMsgDelegate(delAddr1, valOpAddr3, 30)
|
||||
require.True(t, stakeHandler(ctx, msgDelegate).IsOK())
|
||||
|
||||
// 40 tokens left after delegating 60 of them
|
||||
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(40), amt.Int64())
|
||||
|
||||
// total power of each validator:
|
||||
// validator 1: 10 (self) + 10 (delegator) = 20
|
||||
// validator 2: 50 (self) + 20 (delegator) = 70
|
||||
// validator 3: 40 (self) + 30 (delegator) = 70
|
||||
// grand total: 160
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(1000)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw delegation
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
keeper.WithdrawDelegationRewardsAll(ctx, delAddr1)
|
||||
amt = accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
|
||||
// orig-amount + fees *(1-proposerReward)* (val1Portion * delegatorPotion * (1-val1Commission) ... etc)
|
||||
// + fees *(proposerReward) * (delegatorPotion * (1-val1Commission))
|
||||
// 40 + 1000 *(1- 0.95)* (20/160 * 10/20 * 0.9 + 70/160 * 20/70 * 0.8 + 70/160 * 30/70 * 0.7)
|
||||
// 40 + 1000 *( 0.05) * (10/20 * 0.9)
|
||||
feesInNonProposer := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(95, 2))
|
||||
feesInProposer := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(5, 2))
|
||||
feesInVal1 := feesInNonProposer.Mul(sdk.NewDec(10).Quo(sdk.NewDec(160))).Mul(sdk.NewDecWithPrec(9, 1))
|
||||
feesInVal2 := feesInNonProposer.Mul(sdk.NewDec(20).Quo(sdk.NewDec(160))).Mul(sdk.NewDecWithPrec(8, 1))
|
||||
feesInVal3 := feesInNonProposer.Mul(sdk.NewDec(30).Quo(sdk.NewDec(160))).Mul(sdk.NewDecWithPrec(7, 1))
|
||||
feesInVal1Proposer := feesInProposer.Mul(sdk.NewDec(10).Quo(sdk.NewDec(20))).Mul(sdk.NewDecWithPrec(9, 1))
|
||||
expRes := sdk.NewDec(40).Add(feesInVal1).Add(feesInVal2).Add(feesInVal3).Add(feesInVal1Proposer).TruncateInt()
|
||||
require.True(sdk.IntEq(t, expRes, amt))
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
// Get the set of all validator-distribution-info's with no limits, used during genesis dump
|
||||
func (k Keeper) GetAllValidatorDistInfos(ctx sdk.Context) (vdis []types.ValidatorDistInfo) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
iterator := sdk.KVStorePrefixIterator(store, ValidatorDistInfoKey)
|
||||
defer iterator.Close()
|
||||
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
var vdi types.ValidatorDistInfo
|
||||
k.cdc.MustUnmarshalBinary(iterator.Value(), &vdi)
|
||||
vdis = append(vdis, vdi)
|
||||
}
|
||||
return vdis
|
||||
}
|
||||
|
||||
// Get the set of all delegator-distribution-info's with no limits, used during genesis dump
|
||||
func (k Keeper) GetAllDelegationDistInfos(ctx sdk.Context) (ddis []types.DelegationDistInfo) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey)
|
||||
defer iterator.Close()
|
||||
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
var ddi types.DelegationDistInfo
|
||||
k.cdc.MustUnmarshalBinary(iterator.Value(), &ddi)
|
||||
ddis = append(ddis, ddi)
|
||||
}
|
||||
return ddis
|
||||
}
|
||||
|
||||
// Get the set of all delegator-withdraw addresses with no limits, used during genesis dump
|
||||
func (k Keeper) GetAllDelegatorWithdrawInfos(ctx sdk.Context) (dwis []types.DelegatorWithdrawInfo) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey)
|
||||
defer iterator.Close()
|
||||
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
dw := types.DelegatorWithdrawInfo{
|
||||
DelegatorAddr: sdk.AccAddress(iterator.Key()),
|
||||
WithdrawAddr: sdk.AccAddress(iterator.Value()),
|
||||
}
|
||||
dwis = append(dwis, dw)
|
||||
}
|
||||
return dwis
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
// Create a new validator distribution record
|
||||
func (k Keeper) onValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) {
|
||||
|
||||
height := ctx.BlockHeight()
|
||||
vdi := types.ValidatorDistInfo{
|
||||
OperatorAddr: addr,
|
||||
FeePoolWithdrawalHeight: height,
|
||||
Pool: types.DecCoins{},
|
||||
PoolCommission: types.DecCoins{},
|
||||
DelAccum: types.NewTotalAccum(height),
|
||||
}
|
||||
k.SetValidatorDistInfo(ctx, vdi)
|
||||
}
|
||||
|
||||
// Withdrawal all validator rewards
|
||||
func (k Keeper) onValidatorCommissionChange(ctx sdk.Context, addr sdk.ValAddress) {
|
||||
k.WithdrawValidatorRewardsAll(ctx, addr)
|
||||
}
|
||||
|
||||
// Withdrawal all validator distribution rewards and cleanup the distribution record
|
||||
func (k Keeper) onValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) {
|
||||
k.RemoveValidatorDistInfo(ctx, addr)
|
||||
}
|
||||
|
||||
//_________________________________________________________________________________________
|
||||
|
||||
// Create a new delegator distribution record
|
||||
func (k Keeper) onDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress,
|
||||
valAddr sdk.ValAddress) {
|
||||
|
||||
ddi := types.DelegationDistInfo{
|
||||
DelegatorAddr: delAddr,
|
||||
ValOperatorAddr: valAddr,
|
||||
WithdrawalHeight: ctx.BlockHeight(),
|
||||
}
|
||||
k.SetDelegationDistInfo(ctx, ddi)
|
||||
ctx.Logger().With("module", "x/distribution").Error(fmt.Sprintf("ddi created: %v", ddi))
|
||||
}
|
||||
|
||||
// Withdrawal all validator rewards
|
||||
func (k Keeper) onDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress,
|
||||
valAddr sdk.ValAddress) {
|
||||
|
||||
k.WithdrawDelegationReward(ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// Withdrawal all validator distribution rewards and cleanup the distribution record
|
||||
func (k Keeper) onDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress,
|
||||
valAddr sdk.ValAddress) {
|
||||
|
||||
k.RemoveDelegationDistInfo(ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
//_________________________________________________________________________________________
|
||||
|
||||
// Wrapper struct
|
||||
type Hooks struct {
|
||||
k Keeper
|
||||
}
|
||||
|
||||
var _ sdk.StakingHooks = Hooks{}
|
||||
|
||||
// New Validator Hooks
|
||||
func (k Keeper) Hooks() Hooks { return Hooks{k} }
|
||||
|
||||
// nolint
|
||||
func (h Hooks) OnValidatorCreated(ctx sdk.Context, addr sdk.ValAddress) {
|
||||
h.k.onValidatorCreated(ctx, addr)
|
||||
}
|
||||
func (h Hooks) OnValidatorCommissionChange(ctx sdk.Context, addr sdk.ValAddress) {
|
||||
h.k.onValidatorCommissionChange(ctx, addr)
|
||||
}
|
||||
func (h Hooks) OnValidatorRemoved(ctx sdk.Context, addr sdk.ValAddress) {
|
||||
h.k.onValidatorRemoved(ctx, addr)
|
||||
}
|
||||
func (h Hooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||
h.k.onDelegationCreated(ctx, delAddr, valAddr)
|
||||
}
|
||||
func (h Hooks) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||
h.k.onDelegationSharesModified(ctx, delAddr, valAddr)
|
||||
}
|
||||
func (h Hooks) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||
h.k.onDelegationRemoved(ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// nolint - unused hooks for interface
|
||||
func (h Hooks) OnValidatorBonded(ctx sdk.Context, addr sdk.ConsAddress) {}
|
||||
func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, addr sdk.ConsAddress) {}
|
|
@ -0,0 +1,129 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
)
|
||||
|
||||
// keeper of the stake store
|
||||
type Keeper struct {
|
||||
storeKey sdk.StoreKey
|
||||
cdc *codec.Codec
|
||||
paramSpace params.Subspace
|
||||
bankKeeper types.BankKeeper
|
||||
stakeKeeper types.StakeKeeper
|
||||
feeCollectionKeeper types.FeeCollectionKeeper
|
||||
|
||||
// codespace
|
||||
codespace sdk.CodespaceType
|
||||
}
|
||||
|
||||
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramSpace params.Subspace, ck types.BankKeeper,
|
||||
sk types.StakeKeeper, fck types.FeeCollectionKeeper, codespace sdk.CodespaceType) Keeper {
|
||||
|
||||
keeper := Keeper{
|
||||
storeKey: key,
|
||||
cdc: cdc,
|
||||
paramSpace: paramSpace.WithTypeTable(ParamTypeTable()),
|
||||
bankKeeper: ck,
|
||||
stakeKeeper: sk,
|
||||
feeCollectionKeeper: fck,
|
||||
codespace: codespace,
|
||||
}
|
||||
return keeper
|
||||
}
|
||||
|
||||
//______________________________________________________________________
|
||||
|
||||
// get the global fee pool distribution info
|
||||
func (k Keeper) GetFeePool(ctx sdk.Context) (feePool types.FeePool) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
b := store.Get(FeePoolKey)
|
||||
if b == nil {
|
||||
panic("Stored fee pool should not have been nil")
|
||||
}
|
||||
k.cdc.MustUnmarshalBinary(b, &feePool)
|
||||
return
|
||||
}
|
||||
|
||||
// set the global fee pool distribution info
|
||||
func (k Keeper) SetFeePool(ctx sdk.Context, feePool types.FeePool) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
b := k.cdc.MustMarshalBinary(feePool)
|
||||
store.Set(FeePoolKey, b)
|
||||
}
|
||||
|
||||
//______________________________________________________________________
|
||||
|
||||
// set the proposer public key for this block
|
||||
func (k Keeper) GetPreviousProposerConsAddr(ctx sdk.Context) (consAddr sdk.ConsAddress) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
b := store.Get(ProposerKey)
|
||||
if b == nil {
|
||||
panic("Previous proposer not set")
|
||||
}
|
||||
|
||||
k.cdc.MustUnmarshalBinary(b, &consAddr)
|
||||
return
|
||||
}
|
||||
|
||||
// get the proposer public key for this block
|
||||
func (k Keeper) SetPreviousProposerConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
b := k.cdc.MustMarshalBinary(consAddr)
|
||||
store.Set(ProposerKey, b)
|
||||
}
|
||||
|
||||
//______________________________________________________________________
|
||||
// PARAM STORE
|
||||
|
||||
// Type declaration for parameters
|
||||
func ParamTypeTable() params.TypeTable {
|
||||
return params.NewTypeTable(
|
||||
ParamStoreKeyCommunityTax, sdk.Dec{},
|
||||
ParamStoreKeyBaseProposerReward, sdk.Dec{},
|
||||
ParamStoreKeyBonusProposerReward, sdk.Dec{},
|
||||
)
|
||||
}
|
||||
|
||||
// Returns the current CommunityTax rate from the global param store
|
||||
// nolint: errcheck
|
||||
func (k Keeper) GetCommunityTax(ctx sdk.Context) sdk.Dec {
|
||||
var percent sdk.Dec
|
||||
k.paramSpace.Get(ctx, ParamStoreKeyCommunityTax, &percent)
|
||||
return percent
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
func (k Keeper) SetCommunityTax(ctx sdk.Context, percent sdk.Dec) {
|
||||
k.paramSpace.Set(ctx, ParamStoreKeyCommunityTax, &percent)
|
||||
}
|
||||
|
||||
// Returns the current BaseProposerReward rate from the global param store
|
||||
// nolint: errcheck
|
||||
func (k Keeper) GetBaseProposerReward(ctx sdk.Context) sdk.Dec {
|
||||
var percent sdk.Dec
|
||||
k.paramSpace.Get(ctx, ParamStoreKeyBaseProposerReward, &percent)
|
||||
return percent
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
func (k Keeper) SetBaseProposerReward(ctx sdk.Context, percent sdk.Dec) {
|
||||
k.paramSpace.Set(ctx, ParamStoreKeyBaseProposerReward, &percent)
|
||||
}
|
||||
|
||||
// Returns the current BaseProposerReward rate from the global param store
|
||||
// nolint: errcheck
|
||||
func (k Keeper) GetBonusProposerReward(ctx sdk.Context) sdk.Dec {
|
||||
var percent sdk.Dec
|
||||
k.paramSpace.Get(ctx, ParamStoreKeyBonusProposerReward, &percent)
|
||||
return percent
|
||||
}
|
||||
|
||||
// nolint: errcheck
|
||||
func (k Keeper) SetBonusProposerReward(ctx sdk.Context, percent sdk.Dec) {
|
||||
k.paramSpace.Set(ctx, ParamStoreKeyBonusProposerReward, &percent)
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSetGetPreviousProposerConsAddr(t *testing.T) {
|
||||
ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0)
|
||||
|
||||
keeper.SetPreviousProposerConsAddr(ctx, valConsAddr1)
|
||||
res := keeper.GetPreviousProposerConsAddr(ctx)
|
||||
require.True(t, res.Equals(valConsAddr1), "expected: %v got: %v", valConsAddr1.String(), res.String())
|
||||
}
|
||||
|
||||
func TestSetGetCommunityTax(t *testing.T) {
|
||||
ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0)
|
||||
|
||||
someDec := sdk.NewDec(333)
|
||||
keeper.SetCommunityTax(ctx, someDec)
|
||||
res := keeper.GetCommunityTax(ctx)
|
||||
require.True(sdk.DecEq(t, someDec, res))
|
||||
}
|
||||
|
||||
func TestSetGetFeePool(t *testing.T) {
|
||||
ctx, _, keeper, _, _ := CreateTestInputDefault(t, false, 0)
|
||||
|
||||
fp := types.InitialFeePool()
|
||||
fp.ValAccum.UpdateHeight = 777
|
||||
|
||||
keeper.SetFeePool(ctx, fp)
|
||||
res := keeper.GetFeePool(ctx)
|
||||
require.Equal(t, fp.ValAccum, res.ValAccum)
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// keys/key-prefixes
|
||||
var (
|
||||
FeePoolKey = []byte{0x00} // key for global distribution state
|
||||
ValidatorDistInfoKey = []byte{0x01} // prefix for each key to a validator distribution
|
||||
DelegationDistInfoKey = []byte{0x02} // prefix for each key to a delegation distribution
|
||||
DelegatorWithdrawInfoKey = []byte{0x03} // prefix for each key to a delegator withdraw info
|
||||
ProposerKey = []byte{0x04} // key for storing the proposer operator address
|
||||
|
||||
// params store
|
||||
ParamStoreKeyCommunityTax = []byte("community-tax")
|
||||
ParamStoreKeyBaseProposerReward = []byte("base-proposer-reward")
|
||||
ParamStoreKeyBonusProposerReward = []byte("bonus-proposer-reward")
|
||||
)
|
||||
|
||||
const (
|
||||
// default paramspace for params keeper
|
||||
DefaultParamspace = "distr"
|
||||
)
|
||||
|
||||
// gets the key for the validator distribution info from address
|
||||
// VALUE: distribution/types.ValidatorDistInfo
|
||||
func GetValidatorDistInfoKey(operatorAddr sdk.ValAddress) []byte {
|
||||
return append(ValidatorDistInfoKey, operatorAddr.Bytes()...)
|
||||
}
|
||||
|
||||
// gets the key for delegator distribution for a validator
|
||||
// VALUE: distribution/types.DelegationDistInfo
|
||||
func GetDelegationDistInfoKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
|
||||
return append(GetDelegationDistInfosKey(delAddr), valAddr.Bytes()...)
|
||||
}
|
||||
|
||||
// gets the prefix for a delegator's distributions across all validators
|
||||
func GetDelegationDistInfosKey(delAddr sdk.AccAddress) []byte {
|
||||
return append(DelegationDistInfoKey, delAddr.Bytes()...)
|
||||
}
|
||||
|
||||
// gets the prefix for a delegator's withdraw info
|
||||
func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte {
|
||||
return append(DelegatorWithdrawInfoKey, delAddr.Bytes()...)
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
var (
|
||||
delPk1 = ed25519.GenPrivKey().PubKey()
|
||||
delPk2 = ed25519.GenPrivKey().PubKey()
|
||||
delPk3 = ed25519.GenPrivKey().PubKey()
|
||||
delAddr1 = sdk.AccAddress(delPk1.Address())
|
||||
delAddr2 = sdk.AccAddress(delPk2.Address())
|
||||
delAddr3 = sdk.AccAddress(delPk3.Address())
|
||||
|
||||
valOpPk1 = ed25519.GenPrivKey().PubKey()
|
||||
valOpPk2 = ed25519.GenPrivKey().PubKey()
|
||||
valOpPk3 = ed25519.GenPrivKey().PubKey()
|
||||
valOpAddr1 = sdk.ValAddress(valOpPk1.Address())
|
||||
valOpAddr2 = sdk.ValAddress(valOpPk2.Address())
|
||||
valOpAddr3 = sdk.ValAddress(valOpPk3.Address())
|
||||
valAccAddr1 = sdk.AccAddress(valOpPk1.Address()) // generate acc addresses for these validator keys too
|
||||
valAccAddr2 = sdk.AccAddress(valOpPk2.Address())
|
||||
valAccAddr3 = sdk.AccAddress(valOpPk3.Address())
|
||||
|
||||
valConsPk1 = ed25519.GenPrivKey().PubKey()
|
||||
valConsPk2 = ed25519.GenPrivKey().PubKey()
|
||||
valConsPk3 = ed25519.GenPrivKey().PubKey()
|
||||
valConsAddr1 = sdk.ConsAddress(valConsPk1.Address())
|
||||
valConsAddr2 = sdk.ConsAddress(valConsPk2.Address())
|
||||
valConsAddr3 = sdk.ConsAddress(valConsPk3.Address())
|
||||
|
||||
addrs = []sdk.AccAddress{
|
||||
delAddr1, delAddr2, delAddr3,
|
||||
valAccAddr1, valAccAddr2, valAccAddr3,
|
||||
}
|
||||
|
||||
emptyDelAddr sdk.AccAddress
|
||||
emptyValAddr sdk.ValAddress
|
||||
emptyPubkey crypto.PubKey
|
||||
)
|
||||
|
||||
// create a codec used only for testing
|
||||
func MakeTestCodec() *codec.Codec {
|
||||
var cdc = codec.New()
|
||||
bank.RegisterCodec(cdc)
|
||||
stake.RegisterCodec(cdc)
|
||||
auth.RegisterCodec(cdc)
|
||||
sdk.RegisterCodec(cdc)
|
||||
codec.RegisterCrypto(cdc)
|
||||
|
||||
types.RegisterCodec(cdc) // distr
|
||||
return cdc
|
||||
}
|
||||
|
||||
// test input with default values
|
||||
func CreateTestInputDefault(t *testing.T, isCheckTx bool, initCoins int64) (
|
||||
sdk.Context, auth.AccountMapper, Keeper, stake.Keeper, DummyFeeCollectionKeeper) {
|
||||
|
||||
communityTax := sdk.NewDecWithPrec(2, 2)
|
||||
return CreateTestInputAdvanced(t, isCheckTx, initCoins, communityTax)
|
||||
}
|
||||
|
||||
// hogpodge of all sorts of input required for testing
|
||||
func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initCoins int64,
|
||||
communityTax sdk.Dec) (
|
||||
sdk.Context, auth.AccountMapper, Keeper, stake.Keeper, DummyFeeCollectionKeeper) {
|
||||
|
||||
keyDistr := sdk.NewKVStoreKey("distr")
|
||||
keyStake := sdk.NewKVStoreKey("stake")
|
||||
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
|
||||
keyAcc := sdk.NewKVStoreKey("acc")
|
||||
keyFeeCollection := sdk.NewKVStoreKey("fee")
|
||||
keyParams := sdk.NewKVStoreKey("params")
|
||||
tkeyParams := sdk.NewTransientStoreKey("transient_params")
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
ms := store.NewCommitMultiStore(db)
|
||||
|
||||
ms.MountStoreWithDB(keyDistr, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil)
|
||||
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keyFeeCollection, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db)
|
||||
|
||||
err := ms.LoadLatestVersion()
|
||||
require.Nil(t, err)
|
||||
|
||||
cdc := MakeTestCodec()
|
||||
pk := params.NewKeeper(cdc, keyParams, tkeyParams)
|
||||
|
||||
ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, log.NewNopLogger())
|
||||
accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount)
|
||||
ck := bank.NewBaseKeeper(accountMapper)
|
||||
sk := stake.NewKeeper(cdc, keyStake, tkeyStake, ck, pk.Subspace(stake.DefaultParamspace), stake.DefaultCodespace)
|
||||
sk.SetPool(ctx, stake.InitialPool())
|
||||
sk.SetParams(ctx, stake.DefaultParams())
|
||||
sk.InitIntraTxCounter(ctx)
|
||||
|
||||
// fill all the addresses with some coins, set the loose pool tokens simultaneously
|
||||
for _, addr := range addrs {
|
||||
pool := sk.GetPool(ctx)
|
||||
_, _, err := ck.AddCoins(ctx, addr, sdk.Coins{
|
||||
{sk.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)},
|
||||
})
|
||||
require.Nil(t, err)
|
||||
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(initCoins))
|
||||
sk.SetPool(ctx, pool)
|
||||
}
|
||||
|
||||
fck := DummyFeeCollectionKeeper{}
|
||||
keeper := NewKeeper(cdc, keyDistr, pk.Subspace(DefaultParamspace), ck, sk, fck, types.DefaultCodespace)
|
||||
|
||||
// set the distribution hooks on staking
|
||||
sk = sk.WithHooks(keeper.Hooks())
|
||||
|
||||
// set genesis items required for distribution
|
||||
keeper.SetFeePool(ctx, types.InitialFeePool())
|
||||
keeper.SetCommunityTax(ctx, communityTax)
|
||||
keeper.SetBaseProposerReward(ctx, sdk.NewDecWithPrec(1, 2))
|
||||
keeper.SetBonusProposerReward(ctx, sdk.NewDecWithPrec(4, 2))
|
||||
|
||||
return ctx, accountMapper, keeper, sk, fck
|
||||
}
|
||||
|
||||
//__________________________________________________________________________________
|
||||
// fee collection keeper used only for testing
|
||||
type DummyFeeCollectionKeeper struct{}
|
||||
|
||||
var heldFees sdk.Coins
|
||||
var _ types.FeeCollectionKeeper = DummyFeeCollectionKeeper{}
|
||||
|
||||
// nolint
|
||||
func (fck DummyFeeCollectionKeeper) GetCollectedFees(_ sdk.Context) sdk.Coins {
|
||||
return heldFees
|
||||
}
|
||||
func (fck DummyFeeCollectionKeeper) SetCollectedFees(in sdk.Coins) {
|
||||
heldFees = in
|
||||
}
|
||||
func (fck DummyFeeCollectionKeeper) ClearCollectedFees(_ sdk.Context) {
|
||||
heldFees = sdk.Coins{}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
// get the validator distribution info
|
||||
func (k Keeper) GetValidatorDistInfo(ctx sdk.Context,
|
||||
operatorAddr sdk.ValAddress) (vdi types.ValidatorDistInfo) {
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
b := store.Get(GetValidatorDistInfoKey(operatorAddr))
|
||||
if b == nil {
|
||||
panic("Stored validator-distribution info should not have been nil")
|
||||
}
|
||||
|
||||
k.cdc.MustUnmarshalBinary(b, &vdi)
|
||||
return
|
||||
}
|
||||
|
||||
// set the validator distribution info
|
||||
func (k Keeper) SetValidatorDistInfo(ctx sdk.Context, vdi types.ValidatorDistInfo) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
b := k.cdc.MustMarshalBinary(vdi)
|
||||
store.Set(GetValidatorDistInfoKey(vdi.OperatorAddr), b)
|
||||
}
|
||||
|
||||
// remove a validator distribution info
|
||||
func (k Keeper) RemoveValidatorDistInfo(ctx sdk.Context, valAddr sdk.ValAddress) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Delete(GetValidatorDistInfoKey(valAddr))
|
||||
}
|
||||
|
||||
// withdrawal all the validator rewards including the commission
|
||||
func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.ValAddress) {
|
||||
|
||||
// withdraw self-delegation
|
||||
height := ctx.BlockHeight()
|
||||
validator := k.stakeKeeper.Validator(ctx, operatorAddr)
|
||||
accAddr := sdk.AccAddress(operatorAddr.Bytes())
|
||||
withdraw := k.getDelegatorRewardsAll(ctx, accAddr, height)
|
||||
|
||||
// withdrawal validator commission rewards
|
||||
bondedTokens := k.stakeKeeper.TotalPower(ctx)
|
||||
valInfo := k.GetValidatorDistInfo(ctx, operatorAddr)
|
||||
feePool := k.GetFeePool(ctx)
|
||||
valInfo, feePool, commission := valInfo.WithdrawCommission(feePool, height, bondedTokens,
|
||||
validator.GetTokens(), validator.GetCommission())
|
||||
withdraw = withdraw.Plus(commission)
|
||||
k.SetValidatorDistInfo(ctx, valInfo)
|
||||
k.SetFeePool(ctx, feePool)
|
||||
|
||||
withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, accAddr)
|
||||
_, _, err := k.bankKeeper.AddCoins(ctx, withdrawAddr, withdraw.TruncateDecimal())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
package keeper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestWithdrawValidatorRewardsAllNoDelegator(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidator(valOpAddr1, valConsPk1, 10)
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw self-delegation reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
keeper.WithdrawValidatorRewardsAll(ctx, valOpAddr1)
|
||||
amt := accMapper.GetAccount(ctx, valAccAddr1).GetCoins().AmountOf(denom)
|
||||
expRes := sdk.NewDec(90).Add(sdk.NewDec(100)).TruncateInt()
|
||||
require.True(sdk.IntEq(t, expRes, amt))
|
||||
}
|
||||
|
||||
func TestWithdrawValidatorRewardsAllDelegatorNoCommission(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidator(valOpAddr1, valConsPk1, 10)
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// delegate
|
||||
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(90), amt.Int64())
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw self-delegation reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
keeper.WithdrawValidatorRewardsAll(ctx, valOpAddr1)
|
||||
amt = accMapper.GetAccount(ctx, valAccAddr1).GetCoins().AmountOf(denom)
|
||||
expRes := sdk.NewDec(90).Add(sdk.NewDec(100).Quo(sdk.NewDec(2))).TruncateInt() // 90 + 100 tokens * 10/20
|
||||
require.True(sdk.IntEq(t, expRes, amt))
|
||||
}
|
||||
|
||||
func TestWithdrawValidatorRewardsAllDelegatorWithCommission(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator
|
||||
commissionRate := sdk.NewDecWithPrec(1, 1)
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr1, valConsPk1, 10, commissionRate)
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// delegate
|
||||
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(90), amt.Int64())
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw validator reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
keeper.WithdrawValidatorRewardsAll(ctx, valOpAddr1)
|
||||
amt = accMapper.GetAccount(ctx, valAccAddr1).GetCoins().AmountOf(denom)
|
||||
commissionTaken := sdk.NewDec(100).Mul(commissionRate)
|
||||
afterCommission := sdk.NewDec(100).Sub(commissionTaken)
|
||||
selfDelegationReward := afterCommission.Quo(sdk.NewDec(2))
|
||||
expRes := sdk.NewDec(90).Add(commissionTaken).Add(selfDelegationReward).TruncateInt() // 90 + 100 tokens * 10/20
|
||||
require.True(sdk.IntEq(t, expRes, amt))
|
||||
}
|
||||
|
||||
func TestWithdrawValidatorRewardsAllMultipleValidator(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//make some validators with different commissions
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr1, valConsPk1, 10, sdk.NewDecWithPrec(1, 1))
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
|
||||
msgCreateValidator = stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr2, valConsPk2, 50, sdk.NewDecWithPrec(2, 1))
|
||||
got = stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
|
||||
msgCreateValidator = stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr3, valConsPk3, 40, sdk.NewDecWithPrec(3, 1))
|
||||
got = stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(1000)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw validator reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
keeper.WithdrawValidatorRewardsAll(ctx, valOpAddr1)
|
||||
amt := accMapper.GetAccount(ctx, valAccAddr1).GetCoins().AmountOf(denom)
|
||||
|
||||
feesInNonProposer := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(95, 2))
|
||||
feesInProposer := sdk.NewDecFromInt(feeInputs).Mul(sdk.NewDecWithPrec(5, 2))
|
||||
expRes := sdk.NewDec(90). // orig tokens (100 - 10)
|
||||
Add(feesInNonProposer.Quo(sdk.NewDec(10))). // validator 1 has 1/10 total power
|
||||
Add(feesInProposer).
|
||||
TruncateInt()
|
||||
require.True(sdk.IntEq(t, expRes, amt))
|
||||
}
|
||||
|
||||
func TestWithdrawValidatorRewardsAllMultipleDelegator(t *testing.T) {
|
||||
ctx, accMapper, keeper, sk, fck := CreateTestInputAdvanced(t, false, 100, sdk.ZeroDec())
|
||||
stakeHandler := stake.NewHandler(sk)
|
||||
denom := sk.GetParams(ctx).BondDenom
|
||||
|
||||
//first make a validator with 10% commission
|
||||
commissionRate := sdk.NewDecWithPrec(1, 1)
|
||||
msgCreateValidator := stake.NewTestMsgCreateValidatorWithCommission(
|
||||
valOpAddr1, valConsPk1, 10, sdk.NewDecWithPrec(1, 1))
|
||||
got := stakeHandler(ctx, msgCreateValidator)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
_ = sk.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
// delegate
|
||||
msgDelegate := stake.NewTestMsgDelegate(delAddr1, valOpAddr1, 10)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt := accMapper.GetAccount(ctx, delAddr1).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(90), amt.Int64())
|
||||
|
||||
msgDelegate = stake.NewTestMsgDelegate(delAddr2, valOpAddr1, 20)
|
||||
got = stakeHandler(ctx, msgDelegate)
|
||||
require.True(t, got.IsOK())
|
||||
amt = accMapper.GetAccount(ctx, delAddr2).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, int64(80), amt.Int64())
|
||||
|
||||
// allocate 100 denom of fees
|
||||
feeInputs := sdk.NewInt(100)
|
||||
fck.SetCollectedFees(sdk.Coins{sdk.NewCoin(denom, feeInputs)})
|
||||
require.Equal(t, feeInputs, fck.GetCollectedFees(ctx).AmountOf(denom))
|
||||
keeper.AllocateFees(ctx, sdk.OneDec(), valConsAddr1)
|
||||
|
||||
// withdraw validator reward
|
||||
ctx = ctx.WithBlockHeight(1)
|
||||
keeper.WithdrawValidatorRewardsAll(ctx, valOpAddr1)
|
||||
amt = accMapper.GetAccount(ctx, valAccAddr1).GetCoins().AmountOf(denom)
|
||||
|
||||
commissionTaken := sdk.NewDec(100).Mul(commissionRate)
|
||||
afterCommission := sdk.NewDec(100).Sub(commissionTaken)
|
||||
expRes := sdk.NewDec(90).
|
||||
Add(afterCommission.Quo(sdk.NewDec(4))).
|
||||
Add(commissionTaken).
|
||||
TruncateInt() // 90 + 100*90% tokens * 10/40
|
||||
require.True(sdk.IntEq(t, expRes, amt))
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// nolint
|
||||
package tags
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
var (
|
||||
ActionModifyWithdrawAddress = []byte("modify-withdraw-address")
|
||||
ActionWithdrawDelegatorRewardsAll = []byte("withdraw-delegator-rewards-all")
|
||||
ActionWithdrawDelegatorReward = []byte("withdraw-delegator-reward")
|
||||
ActionWithdrawValidatorRewardsAll = []byte("withdraw-validator-rewards-all")
|
||||
|
||||
Action = sdk.TagAction
|
||||
Validator = sdk.TagSrcValidator
|
||||
Delegator = sdk.TagDelegator
|
||||
)
|
|
@ -5,16 +5,16 @@ import (
|
|||
)
|
||||
|
||||
// distribution info for a delegation - used to determine entitled rewards
|
||||
type DelegatorDistInfo struct {
|
||||
type DelegationDistInfo struct {
|
||||
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
|
||||
ValOperatorAddr sdk.ValAddress `json:"val_operator_addr"`
|
||||
WithdrawalHeight int64 `json:"withdrawal_height"` // last time this delegation withdrew rewards
|
||||
}
|
||||
|
||||
func NewDelegatorDistInfo(delegatorAddr sdk.AccAddress, valOperatorAddr sdk.ValAddress,
|
||||
currentHeight int64) DelegatorDistInfo {
|
||||
func NewDelegationDistInfo(delegatorAddr sdk.AccAddress, valOperatorAddr sdk.ValAddress,
|
||||
currentHeight int64) DelegationDistInfo {
|
||||
|
||||
return DelegatorDistInfo{
|
||||
return DelegationDistInfo{
|
||||
DelegatorAddr: delegatorAddr,
|
||||
ValOperatorAddr: valOperatorAddr,
|
||||
WithdrawalHeight: currentHeight,
|
||||
|
@ -22,9 +22,9 @@ func NewDelegatorDistInfo(delegatorAddr sdk.AccAddress, valOperatorAddr sdk.ValA
|
|||
}
|
||||
|
||||
// withdraw rewards from delegator
|
||||
func (di DelegatorDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo,
|
||||
func (di DelegationDistInfo) WithdrawRewards(fp FeePool, vi ValidatorDistInfo,
|
||||
height int64, totalBonded, vdTokens, totalDelShares, delegatorShares,
|
||||
commissionRate sdk.Dec) (DelegatorDistInfo, ValidatorDistInfo, FeePool, DecCoins) {
|
||||
commissionRate sdk.Dec) (DelegationDistInfo, ValidatorDistInfo, FeePool, DecCoins) {
|
||||
|
||||
vi = vi.UpdateTotalDelAccum(height, totalDelShares)
|
||||
|
||||
|
|
|
@ -18,10 +18,10 @@ func TestWithdrawRewards(t *testing.T) {
|
|||
validatorDelShares := sdk.NewDec(10)
|
||||
totalBondedTokens := validatorTokens.Add(sdk.NewDec(90)) // validator-1 is 10% of total power
|
||||
|
||||
di1 := NewDelegatorDistInfo(delAddr1, valAddr1, height)
|
||||
di1 := NewDelegationDistInfo(delAddr1, valAddr1, height)
|
||||
di1Shares := sdk.NewDec(5) // this delegator has half the shares in the validator
|
||||
|
||||
di2 := NewDelegatorDistInfo(delAddr2, valAddr1, height)
|
||||
di2 := NewDelegationDistInfo(delAddr2, valAddr1, height)
|
||||
di2Shares := sdk.NewDec(5)
|
||||
|
||||
// simulate adding some stake for inflation
|
||||
|
|
|
@ -12,22 +12,56 @@ type DelegatorWithdrawInfo struct {
|
|||
// GenesisState - all distribution state that must be provided at genesis
|
||||
type GenesisState struct {
|
||||
FeePool FeePool `json:"fee_pool"`
|
||||
CommunityTax sdk.Dec `json:"community_tax"`
|
||||
BaseProposerReward sdk.Dec `json:"base_proposer_reward"`
|
||||
BonusProposerReward sdk.Dec `json:"bonus_proposer_reward"`
|
||||
ValidatorDistInfos []ValidatorDistInfo `json:"validator_dist_infos"`
|
||||
DelegatorDistInfos []DelegatorDistInfo `json:"delegator_dist_infos"`
|
||||
DelegationDistInfos []DelegationDistInfo `json:"delegator_dist_infos"`
|
||||
DelegatorWithdrawInfos []DelegatorWithdrawInfo `json:"delegator_withdraw_infos"`
|
||||
}
|
||||
|
||||
func NewGenesisState(feePool FeePool, vdis []ValidatorDistInfo, ddis []DelegatorDistInfo) GenesisState {
|
||||
func NewGenesisState(feePool FeePool, communityTax, baseProposerReward, bonusProposerReward sdk.Dec,
|
||||
vdis []ValidatorDistInfo, ddis []DelegationDistInfo, dwis []DelegatorWithdrawInfo) GenesisState {
|
||||
|
||||
return GenesisState{
|
||||
FeePool: feePool,
|
||||
ValidatorDistInfos: vdis,
|
||||
DelegatorDistInfos: ddis,
|
||||
FeePool: feePool,
|
||||
CommunityTax: communityTax,
|
||||
BaseProposerReward: baseProposerReward,
|
||||
BonusProposerReward: bonusProposerReward,
|
||||
ValidatorDistInfos: vdis,
|
||||
DelegationDistInfos: ddis,
|
||||
DelegatorWithdrawInfos: dwis,
|
||||
}
|
||||
}
|
||||
|
||||
// get raw genesis raw message for testing
|
||||
func DefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
FeePool: InitialFeePool(),
|
||||
FeePool: InitialFeePool(),
|
||||
CommunityTax: sdk.NewDecWithPrec(2, 2), // 2%
|
||||
BaseProposerReward: sdk.NewDecWithPrec(1, 2), // 1%
|
||||
BonusProposerReward: sdk.NewDecWithPrec(4, 2), // 4%
|
||||
}
|
||||
}
|
||||
|
||||
// default genesis utility function, initialize for starting validator set
|
||||
func DefaultGenesisWithValidators(valAddrs []sdk.ValAddress) GenesisState {
|
||||
|
||||
vdis := make([]ValidatorDistInfo, len(valAddrs))
|
||||
ddis := make([]DelegationDistInfo, len(valAddrs))
|
||||
|
||||
for i, valAddr := range valAddrs {
|
||||
vdis[i] = NewValidatorDistInfo(valAddr, 0)
|
||||
accAddr := sdk.AccAddress(valAddr)
|
||||
ddis[i] = NewDelegationDistInfo(accAddr, valAddr, 0)
|
||||
}
|
||||
|
||||
return GenesisState{
|
||||
FeePool: InitialFeePool(),
|
||||
CommunityTax: sdk.NewDecWithPrec(2, 2), // 2%
|
||||
BaseProposerReward: sdk.NewDecWithPrec(1, 2), // 1%
|
||||
BonusProposerReward: sdk.NewDecWithPrec(4, 2), // 4%
|
||||
ValidatorDistInfos: vdis,
|
||||
DelegationDistInfos: ddis,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@ var (
|
|||
valPk1 = ed25519.GenPrivKey().PubKey()
|
||||
valPk2 = ed25519.GenPrivKey().PubKey()
|
||||
valPk3 = ed25519.GenPrivKey().PubKey()
|
||||
valAddr1 = sdk.ValAddress(delPk1.Address())
|
||||
valAddr2 = sdk.ValAddress(delPk2.Address())
|
||||
valAddr3 = sdk.ValAddress(delPk3.Address())
|
||||
valAddr1 = sdk.ValAddress(valPk1.Address())
|
||||
valAddr2 = sdk.ValAddress(valPk2.Address())
|
||||
valAddr3 = sdk.ValAddress(valPk3.Address())
|
||||
emptyValAddr sdk.ValAddress
|
||||
|
||||
emptyPubkey crypto.PubKey
|
|
@ -15,6 +15,7 @@ import (
|
|||
"time"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
common "github.com/tendermint/tendermint/libs/common"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
|
@ -81,7 +82,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
|
|||
// Initially this is the same as the initial validator set
|
||||
nextValidators := validators
|
||||
|
||||
header := abci.Header{Height: 0, Time: timestamp}
|
||||
header := abci.Header{Height: 0, Time: timestamp, ProposerAddress: randomProposer(r, validators)}
|
||||
opCount := 0
|
||||
|
||||
// Setup code to catch SIGTERM's
|
||||
|
@ -150,6 +151,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
|
|||
res := app.EndBlock(abci.RequestEndBlock{})
|
||||
header.Height++
|
||||
header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second)
|
||||
header.ProposerAddress = randomProposer(r, validators)
|
||||
logWriter("EndBlock")
|
||||
|
||||
if testingMode {
|
||||
|
@ -318,6 +320,21 @@ func getKeys(validators map[string]mockValidator) []string {
|
|||
return keys
|
||||
}
|
||||
|
||||
// randomProposer picks a random proposer from the current validator set
|
||||
func randomProposer(r *rand.Rand, validators map[string]mockValidator) common.HexBytes {
|
||||
keys := getKeys(validators)
|
||||
if len(keys) == 0 {
|
||||
return nil
|
||||
}
|
||||
key := keys[r.Intn(len(keys))]
|
||||
proposer := validators[key].val
|
||||
pk, err := tmtypes.PB2TM.PubKey(proposer.PubKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return pk.Address()
|
||||
}
|
||||
|
||||
// RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction
|
||||
// nolint: unparam
|
||||
func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64,
|
||||
|
|
|
@ -16,7 +16,7 @@ func TestCannotUnjailUnlessJailed(t *testing.T) {
|
|||
slh := NewHandler(keeper)
|
||||
amtInt := int64(100)
|
||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
msg := newTestMsgCreateValidator(addr, val, amt)
|
||||
msg := NewTestMsgCreateValidator(addr, val, amt)
|
||||
got := stake.NewHandler(sk)(ctx, msg)
|
||||
require.True(t, got.IsOK())
|
||||
stake.EndBlocker(ctx, sk)
|
||||
|
@ -41,7 +41,7 @@ func TestJailedValidatorDelegations(t *testing.T) {
|
|||
valPubKey, bondAmount := pks[0], sdk.NewInt(amount)
|
||||
valAddr, consAddr := addrs[1], sdk.ConsAddress(addrs[0])
|
||||
|
||||
msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, bondAmount)
|
||||
msgCreateVal := NewTestMsgCreateValidator(valAddr, valPubKey, bondAmount)
|
||||
got := stake.NewHandler(stakeKeeper)(ctx, msgCreateVal)
|
||||
require.True(t, got.IsOK(), "expected create validator msg to be ok, got: %v", got)
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ func TestHandleDoubleSign(t *testing.T) {
|
|||
sk = sk.WithHooks(keeper.Hooks())
|
||||
amtInt := int64(100)
|
||||
operatorAddr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(operatorAddr, val, amt))
|
||||
got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(operatorAddr, val, amt))
|
||||
require.True(t, got.IsOK())
|
||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
keeper.AddValidators(ctx, validatorUpdates)
|
||||
|
@ -75,7 +75,7 @@ func TestSlashingPeriodCap(t *testing.T) {
|
|||
amtInt := int64(100)
|
||||
operatorAddr, amt := addrs[0], sdk.NewInt(amtInt)
|
||||
valConsPubKey, valConsAddr := pks[0], pks[0].Address()
|
||||
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(operatorAddr, valConsPubKey, amt))
|
||||
got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(operatorAddr, valConsPubKey, amt))
|
||||
require.True(t, got.IsOK())
|
||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
@ -142,7 +142,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
|||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
sh := stake.NewHandler(sk)
|
||||
slh := NewHandler(keeper)
|
||||
got := sh(ctx, newTestMsgCreateValidator(addr, val, amt))
|
||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
||||
require.True(t, got.IsOK())
|
||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
keeper.AddValidators(ctx, validatorUpdates)
|
||||
|
@ -294,7 +294,7 @@ func TestHandleNewValidator(t *testing.T) {
|
|||
ctx, ck, sk, _, keeper := createTestInput(t, keeperTestParams())
|
||||
addr, val, amt := addrs[0], pks[0], int64(100)
|
||||
sh := stake.NewHandler(sk)
|
||||
got := sh(ctx, newTestMsgCreateValidator(addr, val, sdk.NewInt(amt)))
|
||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, sdk.NewInt(amt)))
|
||||
require.True(t, got.IsOK())
|
||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
keeper.AddValidators(ctx, validatorUpdates)
|
||||
|
@ -332,7 +332,7 @@ func TestHandleAlreadyJailed(t *testing.T) {
|
|||
amtInt := int64(100)
|
||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||
sh := stake.NewHandler(sk)
|
||||
got := sh(ctx, newTestMsgCreateValidator(addr, val, amt))
|
||||
got := sh(ctx, NewTestMsgCreateValidator(addr, val, amt))
|
||||
require.True(t, got.IsOK())
|
||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
keeper.AddValidators(ctx, validatorUpdates)
|
||||
|
|
|
@ -111,7 +111,7 @@ func testAddr(addr string) sdk.AccAddress {
|
|||
return res
|
||||
}
|
||||
|
||||
func newTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt sdk.Int) stake.MsgCreateValidator {
|
||||
func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt sdk.Int) stake.MsgCreateValidator {
|
||||
commission := stake.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())
|
||||
return stake.MsgCreateValidator{
|
||||
Description: stake.Description{},
|
||||
|
|
|
@ -18,7 +18,7 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, sk Keeper) (tags
|
|||
tags = sdk.NewTags("height", heightBytes)
|
||||
|
||||
// Iterate over all the validators which *should* have signed this block
|
||||
// Store whether or not they have actually signed it and slash/unbond any
|
||||
// store whether or not they have actually signed it and slash/unbond any
|
||||
// which have missed too many blocks in a row (downtime slashing)
|
||||
for _, voteInfo := range req.LastCommitInfo.GetVotes() {
|
||||
sk.handleValidatorSignature(ctx, voteInfo.Validator.Address, voteInfo.Validator.Power, voteInfo.SignedLastBlock)
|
||||
|
|
|
@ -17,7 +17,7 @@ func TestBeginBlocker(t *testing.T) {
|
|||
addr, pk, amt := addrs[2], pks[2], sdk.NewInt(100)
|
||||
|
||||
// bond the validator
|
||||
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, pk, amt))
|
||||
got := stake.NewHandler(sk)(ctx, NewTestMsgCreateValidator(addr, pk, amt))
|
||||
require.True(t, got.IsOK())
|
||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||
keeper.AddValidators(ctx, validatorUpdates)
|
||||
|
|
|
@ -10,24 +10,6 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
)
|
||||
|
||||
var (
|
||||
priv1 = ed25519.GenPrivKey()
|
||||
addr1 = sdk.AccAddress(priv1.PubKey().Address())
|
||||
priv2 = ed25519.GenPrivKey()
|
||||
addr2 = sdk.AccAddress(priv2.PubKey().Address())
|
||||
addr3 = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address())
|
||||
priv4 = ed25519.GenPrivKey()
|
||||
addr4 = sdk.AccAddress(priv4.PubKey().Address())
|
||||
coins = sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(10))}
|
||||
fee = auth.NewStdFee(
|
||||
100000,
|
||||
sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(0))}...,
|
||||
)
|
||||
|
||||
commissionMsg = NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())
|
||||
)
|
||||
|
||||
// getMockApp returns an initialized mock application for this module.
|
||||
|
|
|
@ -42,10 +42,13 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [
|
|||
// Manually set indices for the first time
|
||||
keeper.SetValidatorByConsAddr(ctx, validator)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool)
|
||||
|
||||
keeper.OnValidatorCreated(ctx, validator.OperatorAddr)
|
||||
}
|
||||
|
||||
for _, bond := range data.Bonds {
|
||||
keeper.SetDelegation(ctx, bond)
|
||||
for _, delegation := range data.Bonds {
|
||||
keeper.SetDelegation(ctx, delegation)
|
||||
keeper.OnDelegationCreated(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr)
|
||||
}
|
||||
|
||||
res = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
|
|
@ -106,7 +106,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
|
|||
|
||||
validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description)
|
||||
commission := NewCommissionWithTime(
|
||||
msg.Commission.Rate, msg.Commission.MaxChangeRate,
|
||||
msg.Commission.Rate, msg.Commission.MaxRate,
|
||||
msg.Commission.MaxChangeRate, ctx.BlockHeader().Time,
|
||||
)
|
||||
validator, err := validator.SetInitialCommission(commission)
|
||||
|
|
|
@ -7,8 +7,6 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
keep "github.com/cosmos/cosmos-sdk/x/stake/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
|
@ -16,31 +14,6 @@ import (
|
|||
|
||||
//______________________________________________________________________
|
||||
|
||||
func newTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt int64) MsgCreateValidator {
|
||||
return types.NewMsgCreateValidator(
|
||||
address, pubKey, sdk.NewCoin("steak", sdk.NewInt(amt)), Description{}, commissionMsg,
|
||||
)
|
||||
}
|
||||
|
||||
func newTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt int64) MsgDelegate {
|
||||
return MsgDelegate{
|
||||
DelegatorAddr: delAddr,
|
||||
ValidatorAddr: valAddr,
|
||||
Delegation: sdk.NewCoin("steak", sdk.NewInt(amt)),
|
||||
}
|
||||
}
|
||||
|
||||
func newTestMsgCreateValidatorOnBehalfOf(delAddr sdk.AccAddress, valAddr sdk.ValAddress, valPubKey crypto.PubKey, amt int64) MsgCreateValidator {
|
||||
return MsgCreateValidator{
|
||||
Description: Description{},
|
||||
Commission: commissionMsg,
|
||||
DelegatorAddr: delAddr,
|
||||
ValidatorAddr: valAddr,
|
||||
PubKey: valPubKey,
|
||||
Delegation: sdk.NewCoin("steak", sdk.NewInt(amt)),
|
||||
}
|
||||
}
|
||||
|
||||
// retrieve params which are instant
|
||||
func setInstantUnbondPeriod(keeper keep.Keeper, ctx sdk.Context) types.Params {
|
||||
params := keeper.GetParams(ctx)
|
||||
|
@ -59,7 +32,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
|||
_ = setInstantUnbondPeriod(keeper, ctx)
|
||||
|
||||
// create validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||
|
||||
|
@ -83,7 +56,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
|||
require.True(t, keep.ValidatorByPowerIndexExists(ctx, keeper, power))
|
||||
|
||||
// create a second validator keep it bonded
|
||||
msgCreateValidator = newTestMsgCreateValidator(validatorAddr3, keep.PKs[2], int64(1000000))
|
||||
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], int64(1000000))
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||
|
||||
|
@ -146,7 +119,7 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
|
|||
addr1, addr2 := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1])
|
||||
pk1, pk2 := keep.PKs[0], keep.PKs[1]
|
||||
|
||||
msgCreateValidator1 := newTestMsgCreateValidator(addr1, pk1, 10)
|
||||
msgCreateValidator1 := NewTestMsgCreateValidator(addr1, pk1, 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator1, keeper)
|
||||
require.True(t, got.IsOK(), "%v", got)
|
||||
|
||||
|
@ -162,17 +135,17 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
|
|||
assert.Equal(t, Description{}, validator.Description)
|
||||
|
||||
// two validators can't have the same operator address
|
||||
msgCreateValidator2 := newTestMsgCreateValidator(addr1, pk2, 10)
|
||||
msgCreateValidator2 := NewTestMsgCreateValidator(addr1, pk2, 10)
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator2, keeper)
|
||||
require.False(t, got.IsOK(), "%v", got)
|
||||
|
||||
// two validators can't have the same pubkey
|
||||
msgCreateValidator3 := newTestMsgCreateValidator(addr2, pk1, 10)
|
||||
msgCreateValidator3 := NewTestMsgCreateValidator(addr2, pk1, 10)
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator3, keeper)
|
||||
require.False(t, got.IsOK(), "%v", got)
|
||||
|
||||
// must have different pubkey and operator
|
||||
msgCreateValidator4 := newTestMsgCreateValidator(addr2, pk2, 10)
|
||||
msgCreateValidator4 := NewTestMsgCreateValidator(addr2, pk2, 10)
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator4, keeper)
|
||||
require.True(t, got.IsOK(), "%v", got)
|
||||
|
||||
|
@ -197,7 +170,7 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) {
|
|||
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
||||
delegatorAddr := keep.Addrs[1]
|
||||
pk := keep.PKs[0]
|
||||
msgCreateValidatorOnBehalfOf := newTestMsgCreateValidatorOnBehalfOf(delegatorAddr, validatorAddr, pk, 10)
|
||||
msgCreateValidatorOnBehalfOf := NewTestMsgCreateValidatorOnBehalfOf(delegatorAddr, validatorAddr, pk, 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper)
|
||||
require.True(t, got.IsOK(), "%v", got)
|
||||
|
||||
|
@ -232,7 +205,7 @@ func TestLegacyValidatorDelegations(t *testing.T) {
|
|||
delAddr := keep.Addrs[1]
|
||||
|
||||
// create validator
|
||||
msgCreateVal := newTestMsgCreateValidator(valAddr, valConsPubKey, bondAmount)
|
||||
msgCreateVal := NewTestMsgCreateValidator(valAddr, valConsPubKey, bondAmount)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateVal, keeper)
|
||||
require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got)
|
||||
|
||||
|
@ -248,7 +221,7 @@ func TestLegacyValidatorDelegations(t *testing.T) {
|
|||
require.Equal(t, bondAmount, validator.BondedTokens().RoundInt64())
|
||||
|
||||
// delegate tokens to the validator
|
||||
msgDelegate := newTestMsgDelegate(delAddr, valAddr, bondAmount)
|
||||
msgDelegate := NewTestMsgDelegate(delAddr, valAddr, bondAmount)
|
||||
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got)
|
||||
|
||||
|
@ -283,12 +256,12 @@ func TestLegacyValidatorDelegations(t *testing.T) {
|
|||
require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt64())
|
||||
|
||||
// verify a delegator cannot create a new delegation to the now jailed validator
|
||||
msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount)
|
||||
msgDelegate = NewTestMsgDelegate(delAddr, valAddr, bondAmount)
|
||||
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.False(t, got.IsOK(), "expected delegation to not be ok, got %v", got)
|
||||
|
||||
// verify the validator can still self-delegate
|
||||
msgSelfDelegate := newTestMsgDelegate(sdk.AccAddress(valAddr), valAddr, bondAmount)
|
||||
msgSelfDelegate := NewTestMsgDelegate(sdk.AccAddress(valAddr), valAddr, bondAmount)
|
||||
got = handleMsgDelegate(ctx, msgSelfDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected delegation to not be ok, got %v", got)
|
||||
|
||||
|
@ -302,7 +275,7 @@ func TestLegacyValidatorDelegations(t *testing.T) {
|
|||
keeper.Unjail(ctx, valConsAddr)
|
||||
|
||||
// verify the validator can now accept delegations
|
||||
msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount)
|
||||
msgDelegate = NewTestMsgDelegate(delAddr, valAddr, bondAmount)
|
||||
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got)
|
||||
|
||||
|
@ -328,7 +301,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
|
|||
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
||||
|
||||
// first create validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], bondAmount)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], bondAmount)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got)
|
||||
|
||||
|
@ -354,7 +327,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
|
|||
require.Equal(t, bondAmount, pool.BondedTokens.RoundInt64())
|
||||
|
||||
// just send the same msgbond multiple times
|
||||
msgDelegate := newTestMsgDelegate(delegatorAddr, validatorAddr, bondAmount)
|
||||
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, bondAmount)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
ctx = ctx.WithBlockHeight(int64(i))
|
||||
|
@ -402,14 +375,14 @@ func TestIncrementsMsgUnbond(t *testing.T) {
|
|||
// create validator, delegate
|
||||
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
||||
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], initBond)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||
|
||||
// initial balance
|
||||
amt1 := accMapper.GetAccount(ctx, delegatorAddr).GetCoins().AmountOf(denom)
|
||||
|
||||
msgDelegate := newTestMsgDelegate(delegatorAddr, validatorAddr, initBond)
|
||||
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, initBond)
|
||||
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected delegation to be ok, got %v", got)
|
||||
|
||||
|
@ -505,7 +478,7 @@ func TestMultipleMsgCreateValidator(t *testing.T) {
|
|||
|
||||
// bond them all
|
||||
for i, validatorAddr := range validatorAddrs {
|
||||
msgCreateValidatorOnBehalfOf := newTestMsgCreateValidatorOnBehalfOf(delegatorAddrs[i], validatorAddr, keep.PKs[i], 10)
|
||||
msgCreateValidatorOnBehalfOf := NewTestMsgCreateValidatorOnBehalfOf(delegatorAddrs[i], validatorAddr, keep.PKs[i], 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper)
|
||||
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
||||
|
||||
|
@ -552,13 +525,13 @@ func TestMultipleMsgDelegate(t *testing.T) {
|
|||
_ = setInstantUnbondPeriod(keeper, ctx)
|
||||
|
||||
//first make a validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
|
||||
|
||||
// delegate multiple parties
|
||||
for i, delegatorAddr := range delegatorAddrs {
|
||||
msgDelegate := newTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||
got := handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
||||
|
||||
|
@ -590,12 +563,12 @@ func TestJailValidator(t *testing.T) {
|
|||
_ = setInstantUnbondPeriod(keeper, ctx)
|
||||
|
||||
// create the validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
// bond a delegator
|
||||
msgDelegate := newTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
||||
|
||||
|
@ -639,12 +612,12 @@ func TestValidatorQueue(t *testing.T) {
|
|||
keeper.SetParams(ctx, params)
|
||||
|
||||
// create the validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
// bond a delegator
|
||||
msgDelegate := newTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
||||
|
||||
|
@ -689,7 +662,7 @@ func TestUnbondingPeriod(t *testing.T) {
|
|||
keeper.SetParams(ctx, params)
|
||||
|
||||
// create the validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
|
@ -727,12 +700,12 @@ func TestUnbondingFromUnbondingValidator(t *testing.T) {
|
|||
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
||||
|
||||
// create the validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
// bond a delegator
|
||||
msgDelegate := newTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||
msgDelegate := NewTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
||||
|
||||
|
@ -774,7 +747,7 @@ func TestRedelegationPeriod(t *testing.T) {
|
|||
keeper.SetParams(ctx, params)
|
||||
|
||||
// create the validators
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
|
||||
// initial balance
|
||||
amt1 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins().AmountOf(denom)
|
||||
|
@ -786,7 +759,7 @@ func TestRedelegationPeriod(t *testing.T) {
|
|||
amt2 := AccMapper.GetAccount(ctx, sdk.AccAddress(validatorAddr)).GetCoins().AmountOf(denom)
|
||||
require.Equal(t, amt1.Sub(sdk.NewInt(10)).Int64(), amt2.Int64(), "expected coins to be subtracted")
|
||||
|
||||
msgCreateValidator = newTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 10)
|
||||
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 10)
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
|
@ -833,15 +806,15 @@ func TestTransitiveRedelegation(t *testing.T) {
|
|||
keeper.SetParams(ctx, params)
|
||||
|
||||
// create the validators
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
msgCreateValidator = newTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 10)
|
||||
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 10)
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
msgCreateValidator = newTestMsgCreateValidator(validatorAddr3, keep.PKs[2], 10)
|
||||
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], 10)
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
|
@ -918,21 +891,21 @@ func TestUnbondingWhenExcessValidators(t *testing.T) {
|
|||
keeper.SetParams(ctx, params)
|
||||
|
||||
// add three validators
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr1, keep.PKs[0], 50)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(validatorAddr1, keep.PKs[0], 50)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
// apply TM updates
|
||||
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
require.Equal(t, 1, len(keeper.GetValidatorsBonded(ctx)))
|
||||
|
||||
msgCreateValidator = newTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 30)
|
||||
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 30)
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
// apply TM updates
|
||||
keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx)))
|
||||
|
||||
msgCreateValidator = newTestMsgCreateValidator(validatorAddr3, keep.PKs[2], 10)
|
||||
msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], 10)
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
// apply TM updates
|
||||
|
@ -962,16 +935,16 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
|||
valA, valB, del := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]), keep.Addrs[2]
|
||||
consAddr0 := sdk.ConsAddress(keep.PKs[0].Address())
|
||||
|
||||
msgCreateValidator := newTestMsgCreateValidator(valA, keep.PKs[0], 10)
|
||||
msgCreateValidator := NewTestMsgCreateValidator(valA, keep.PKs[0], 10)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
msgCreateValidator = newTestMsgCreateValidator(valB, keep.PKs[1], 10)
|
||||
msgCreateValidator = NewTestMsgCreateValidator(valB, keep.PKs[1], 10)
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||
|
||||
// delegate 10 stake
|
||||
msgDelegate := newTestMsgDelegate(del, valA, 10)
|
||||
msgDelegate := NewTestMsgDelegate(del, valA, 10)
|
||||
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||
require.True(t, got.IsOK(), "expected no error on runMsgDelegate")
|
||||
|
||||
|
|
|
@ -380,8 +380,6 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co
|
|||
func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress,
|
||||
shares sdk.Dec) (amount sdk.Dec, err sdk.Error) {
|
||||
|
||||
k.OnDelegationSharesModified(ctx, delAddr, valAddr)
|
||||
|
||||
// check if delegation has any shares in it unbond
|
||||
delegation, found := k.GetDelegation(ctx, delAddr, valAddr)
|
||||
if !found {
|
||||
|
@ -389,6 +387,8 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA
|
|||
return
|
||||
}
|
||||
|
||||
k.OnDelegationSharesModified(ctx, delAddr, valAddr)
|
||||
|
||||
// retrieve the amount to remove
|
||||
if delegation.Shares.LT(shares) {
|
||||
err = types.ErrNotEnoughDelegationShares(k.Codespace(), delegation.Shares.String())
|
||||
|
@ -430,7 +430,6 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA
|
|||
k.RemoveValidator(ctx, validator.OperatorAddr)
|
||||
}
|
||||
|
||||
k.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr)
|
||||
return amount, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,9 @@ func TestDelegation(t *testing.T) {
|
|||
}
|
||||
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[2] = testingUpdateValidator(keeper, ctx, validators[2])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[2] = TestingUpdateValidator(keeper, ctx, validators[2])
|
||||
|
||||
// first add a validators[0] to delegate too
|
||||
|
||||
|
@ -184,7 +184,7 @@ func TestUnbondDelegation(t *testing.T) {
|
|||
validator, pool, issuedShares := validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
|
||||
pool = keeper.GetPool(ctx)
|
||||
require.Equal(t, int64(10), pool.BondedTokens.RoundInt64())
|
||||
|
@ -226,7 +226,7 @@ func TestUndelegateSelfDelegation(t *testing.T) {
|
|||
validator, pool, issuedShares := validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
selfDelegation := types.Delegation{
|
||||
DelegatorAddr: sdk.AccAddress(addrVals[0].Bytes()),
|
||||
|
@ -240,7 +240,7 @@ func TestUndelegateSelfDelegation(t *testing.T) {
|
|||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
delegation := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
|
@ -274,7 +274,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) {
|
|||
validator, pool, issuedShares := validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
selfDelegation := types.Delegation{
|
||||
DelegatorAddr: sdk.AccAddress(addrVals[0].Bytes()),
|
||||
|
@ -288,7 +288,7 @@ func TestUndelegateFromUnbondingValidator(t *testing.T) {
|
|||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
delegation := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
|
@ -350,7 +350,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
|
|||
validator, pool, issuedShares := validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
|
||||
selfDelegation := types.Delegation{
|
||||
|
@ -365,7 +365,7 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
|
|||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
delegation := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
|
@ -512,7 +512,7 @@ func TestRedelegateSelfDelegation(t *testing.T) {
|
|||
validator, pool, issuedShares := validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
|
||||
selfDelegation := types.Delegation{
|
||||
|
@ -528,14 +528,14 @@ func TestRedelegateSelfDelegation(t *testing.T) {
|
|||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
pool.BondedTokens = pool.BondedTokens.Add(sdk.NewDec(10))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator2 = testingUpdateValidator(keeper, ctx, validator2)
|
||||
validator2 = TestingUpdateValidator(keeper, ctx, validator2)
|
||||
require.Equal(t, sdk.Bonded, validator2.Status)
|
||||
|
||||
// create a second delegation to this validator
|
||||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
delegation := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
|
@ -569,7 +569,7 @@ func TestRedelegateFromUnbondingValidator(t *testing.T) {
|
|||
validator, pool, issuedShares := validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
|
||||
selfDelegation := types.Delegation{
|
||||
|
@ -584,7 +584,7 @@ func TestRedelegateFromUnbondingValidator(t *testing.T) {
|
|||
validator, pool, issuedShares = validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
delegation := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
|
@ -599,7 +599,7 @@ func TestRedelegateFromUnbondingValidator(t *testing.T) {
|
|||
validator2, pool, issuedShares = validator2.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator2 = testingUpdateValidator(keeper, ctx, validator2)
|
||||
validator2 = TestingUpdateValidator(keeper, ctx, validator2)
|
||||
|
||||
header := ctx.BlockHeader()
|
||||
blockHeight := int64(10)
|
||||
|
@ -653,7 +653,7 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) {
|
|||
validator, pool, issuedShares := validator.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
|
||||
selfDelegation := types.Delegation{
|
||||
|
@ -669,7 +669,7 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) {
|
|||
validator.BondIntraTxCounter = 1
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
pool = keeper.GetPool(ctx)
|
||||
delegation := types.Delegation{
|
||||
DelegatorAddr: addrDels[0],
|
||||
|
@ -684,7 +684,7 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) {
|
|||
validator2, pool, issuedShares = validator2.AddTokensFromDel(pool, sdk.NewInt(10))
|
||||
require.Equal(t, int64(10), issuedShares.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator2 = testingUpdateValidator(keeper, ctx, validator2)
|
||||
validator2 = TestingUpdateValidator(keeper, ctx, validator2)
|
||||
require.Equal(t, sdk.Bonded, validator2.Status)
|
||||
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
|
|
|
@ -29,7 +29,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) {
|
|||
validator.BondIntraTxCounter = int16(i)
|
||||
pool.BondedTokens = pool.BondedTokens.Add(sdk.NewDec(amt))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
keeper.SetValidatorByConsAddr(ctx, validator)
|
||||
}
|
||||
pool = keeper.GetPool(ctx)
|
||||
|
|
|
@ -211,7 +211,8 @@ func ValidatorByPowerIndexExists(ctx sdk.Context, keeper Keeper, power []byte) b
|
|||
return store.Has(power)
|
||||
}
|
||||
|
||||
func testingUpdateValidator(keeper Keeper, ctx sdk.Context, validator types.Validator) types.Validator {
|
||||
// update validator for testing
|
||||
func TestingUpdateValidator(keeper Keeper, ctx sdk.Context, validator types.Validator) types.Validator {
|
||||
pool := keeper.GetPool(ctx)
|
||||
keeper.SetValidator(ctx, validator)
|
||||
keeper.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||
|
|
|
@ -84,7 +84,7 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
|||
require.Equal(t, sdk.Unbonded, validator.Status)
|
||||
require.Equal(t, int64(100), validator.Tokens.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
testingUpdateValidator(keeper, ctx, validator)
|
||||
TestingUpdateValidator(keeper, ctx, validator)
|
||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
|
||||
|
@ -98,7 +98,7 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
|||
validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewDec(2)))
|
||||
require.Equal(t, int64(50), burned.RoundInt64())
|
||||
keeper.SetPool(ctx, pool) // update the pool
|
||||
testingUpdateValidator(keeper, ctx, validator) // update the validator, possibly kicking it out
|
||||
TestingUpdateValidator(keeper, ctx, validator) // update the validator, possibly kicking it out
|
||||
require.False(t, validatorByPowerIndexExists(keeper, ctx, power))
|
||||
|
||||
pool = keeper.GetPool(ctx)
|
||||
|
@ -135,7 +135,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) {
|
|||
val, pool, _ = val.AddTokensFromDel(pool, sdk.NewInt(int64((i+1)*10)))
|
||||
|
||||
keeper.SetPool(ctx, pool)
|
||||
val = testingUpdateValidator(keeper, ctx, val)
|
||||
val = TestingUpdateValidator(keeper, ctx, val)
|
||||
validators[i] = val
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) {
|
|||
keeper.DeleteValidatorByPowerIndex(ctx, nextCliffVal, pool)
|
||||
nextCliffVal, pool, _ = nextCliffVal.RemoveDelShares(pool, sdk.NewDec(21))
|
||||
keeper.SetPool(ctx, pool)
|
||||
nextCliffVal = testingUpdateValidator(keeper, ctx, nextCliffVal)
|
||||
nextCliffVal = TestingUpdateValidator(keeper, ctx, nextCliffVal)
|
||||
|
||||
expectedValStatus := map[int]sdk.BondStatus{
|
||||
9: sdk.Bonded, 8: sdk.Bonded, 7: sdk.Bonded, 5: sdk.Bonded, 4: sdk.Bonded,
|
||||
|
@ -178,7 +178,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) {
|
|||
require.Equal(t, int64(100), validator.Tokens.RoundInt64())
|
||||
keeper.SetPool(ctx, pool)
|
||||
keeper.SetValidatorByConsAddr(ctx, validator)
|
||||
validator = testingUpdateValidator(keeper, ctx, validator)
|
||||
validator = TestingUpdateValidator(keeper, ctx, validator)
|
||||
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
|
||||
|
||||
// slash the validator by 100%
|
||||
|
@ -223,7 +223,7 @@ func TestValidatorBasics(t *testing.T) {
|
|||
assert.True(sdk.DecEq(t, sdk.ZeroDec(), pool.BondedTokens))
|
||||
|
||||
// set and retrieve a record
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
keeper.SetValidatorByConsAddr(ctx, validators[0])
|
||||
resVal, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
|
@ -250,7 +250,7 @@ func TestValidatorBasics(t *testing.T) {
|
|||
validators[0].Status = sdk.Bonded
|
||||
validators[0].Tokens = sdk.NewDec(10)
|
||||
validators[0].DelegatorShares = sdk.NewDec(10)
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
resVal, found = keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
assert.True(ValEq(t, validators[0], resVal))
|
||||
|
@ -260,8 +260,8 @@ func TestValidatorBasics(t *testing.T) {
|
|||
assert.True(ValEq(t, validators[0], resVals[0]))
|
||||
|
||||
// add other validators
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[2] = testingUpdateValidator(keeper, ctx, validators[2])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[2] = TestingUpdateValidator(keeper, ctx, validators[2])
|
||||
resVal, found = keeper.GetValidator(ctx, addrVals[1])
|
||||
require.True(t, found)
|
||||
assert.True(ValEq(t, validators[1], resVal))
|
||||
|
@ -294,7 +294,7 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
|||
validators[i].Status = sdk.Bonded
|
||||
validators[i].Tokens = sdk.NewDec(amt)
|
||||
validators[i].DelegatorShares = sdk.NewDec(amt)
|
||||
testingUpdateValidator(keeper, ctx, validators[i])
|
||||
TestingUpdateValidator(keeper, ctx, validators[i])
|
||||
}
|
||||
|
||||
// first make sure everything made it in to the gotValidator group
|
||||
|
@ -313,14 +313,14 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
|||
|
||||
// test a basic increase in voting power
|
||||
validators[3].Tokens = sdk.NewDec(500)
|
||||
testingUpdateValidator(keeper, ctx, validators[3])
|
||||
TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
|
||||
// test a decrease in voting power
|
||||
validators[3].Tokens = sdk.NewDec(300)
|
||||
testingUpdateValidator(keeper, ctx, validators[3])
|
||||
TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
|
@ -329,7 +329,7 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
|||
// test equal voting power, different age
|
||||
validators[3].Tokens = sdk.NewDec(200)
|
||||
ctx = ctx.WithBlockHeight(10)
|
||||
testingUpdateValidator(keeper, ctx, validators[3])
|
||||
TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
|
@ -339,7 +339,7 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
|||
|
||||
// no change in voting power - no change in sort
|
||||
ctx = ctx.WithBlockHeight(20)
|
||||
testingUpdateValidator(keeper, ctx, validators[4])
|
||||
TestingUpdateValidator(keeper, ctx, validators[4])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
|
@ -348,11 +348,11 @@ func GetValidatorSortingUnmixed(t *testing.T) {
|
|||
// change in voting power of both validators, both still in v-set, no age change
|
||||
validators[3].Tokens = sdk.NewDec(300)
|
||||
validators[4].Tokens = sdk.NewDec(300)
|
||||
testingUpdateValidator(keeper, ctx, validators[3])
|
||||
TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n)
|
||||
ctx = ctx.WithBlockHeight(30)
|
||||
testingUpdateValidator(keeper, ctx, validators[4])
|
||||
TestingUpdateValidator(keeper, ctx, validators[4])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, len(resValidators), n, "%v", resValidators)
|
||||
assert.True(ValEq(t, validators[3], resValidators[0]))
|
||||
|
@ -390,7 +390,7 @@ func GetValidatorSortingMixed(t *testing.T) {
|
|||
validators[4].Tokens = sdk.NewDec(amts[4])
|
||||
|
||||
for i := range amts {
|
||||
testingUpdateValidator(keeper, ctx, validators[i])
|
||||
TestingUpdateValidator(keeper, ctx, validators[i])
|
||||
}
|
||||
val0, found := keeper.GetValidator(ctx, sdk.ValAddress(Addrs[0]))
|
||||
require.True(t, found)
|
||||
|
@ -444,7 +444,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
|||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||
validators[i].BondIntraTxCounter = int16(i)
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[i] = testingUpdateValidator(keeper, ctx, validators[i])
|
||||
validators[i] = TestingUpdateValidator(keeper, ctx, validators[i])
|
||||
}
|
||||
|
||||
for i := range amts {
|
||||
|
@ -460,7 +460,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
|||
keeper.DeleteValidatorByPowerIndex(ctx, validators[0], pool)
|
||||
validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(500))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, nMax, uint16(len(resValidators)))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
|
@ -478,7 +478,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
|||
keeper.DeleteValidatorByPowerIndex(ctx, validators[3], pool)
|
||||
validators[3], pool, _ = validators[3].AddTokensFromDel(pool, sdk.NewInt(1))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[3] = testingUpdateValidator(keeper, ctx, validators[3])
|
||||
validators[3] = TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, nMax, uint16(len(resValidators)))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
|
@ -488,7 +488,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
|||
keeper.DeleteValidatorByPowerIndex(ctx, validators[3], pool)
|
||||
validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewDec(201))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[3] = testingUpdateValidator(keeper, ctx, validators[3])
|
||||
validators[3] = TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, nMax, uint16(len(resValidators)))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
|
@ -498,7 +498,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
|
|||
keeper.DeleteValidatorByPowerIndex(ctx, validators[3], pool)
|
||||
validators[3], pool, _ = validators[3].AddTokensFromDel(pool, sdk.NewInt(200))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[3] = testingUpdateValidator(keeper, ctx, validators[3])
|
||||
validators[3] = TestingUpdateValidator(keeper, ctx, validators[3])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, nMax, uint16(len(resValidators)))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
|
@ -531,13 +531,13 @@ func TestValidatorBondHeight(t *testing.T) {
|
|||
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(100))
|
||||
keeper.SetPool(ctx, pool)
|
||||
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
|
||||
////////////////////////////////////////
|
||||
// If two validators both increase to the same voting power in the same block,
|
||||
// the one with the first transaction should become bonded
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[2] = testingUpdateValidator(keeper, ctx, validators[2])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[2] = TestingUpdateValidator(keeper, ctx, validators[2])
|
||||
|
||||
pool = keeper.GetPool(ctx)
|
||||
|
||||
|
@ -551,10 +551,10 @@ func TestValidatorBondHeight(t *testing.T) {
|
|||
validators[1], pool, _ = validators[1].AddTokensFromDel(pool, sdk.NewInt(50))
|
||||
validators[2], pool, _ = validators[2].AddTokensFromDel(pool, sdk.NewInt(50))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[2] = testingUpdateValidator(keeper, ctx, validators[2])
|
||||
validators[2] = TestingUpdateValidator(keeper, ctx, validators[2])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
require.Equal(t, params.MaxValidators, uint16(len(resValidators)))
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
assert.True(ValEq(t, validators[2], resValidators[1]))
|
||||
}
|
||||
|
@ -575,7 +575,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) {
|
|||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||
validators[i].BondIntraTxCounter = int16(i)
|
||||
keeper.SetPool(ctx, pool)
|
||||
testingUpdateValidator(keeper, ctx, validators[i])
|
||||
TestingUpdateValidator(keeper, ctx, validators[i])
|
||||
}
|
||||
for i := range amts {
|
||||
var found bool
|
||||
|
@ -596,7 +596,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) {
|
|||
pool := keeper.GetPool(ctx)
|
||||
validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(600))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
resValidators = keeper.GetBondedValidatorsByPower(ctx)
|
||||
assert.Equal(t, max, len(resValidators))
|
||||
assert.True(ValEq(t, validators[0], resValidators[0]))
|
||||
|
@ -647,14 +647,14 @@ func TestApplyAndReturnValidatorSetUpdatesIdentical(t *testing.T) {
|
|||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||
keeper.SetPool(ctx, pool)
|
||||
}
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
require.Equal(t, 0, len(keeper.ApplyAndReturnValidatorSetUpdates(ctx)))
|
||||
|
||||
// test identical,
|
||||
// tendermintUpdate set: {} -> {}
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
require.Equal(t, 0, len(keeper.ApplyAndReturnValidatorSetUpdates(ctx)))
|
||||
}
|
||||
|
||||
|
@ -669,15 +669,15 @@ func TestApplyAndReturnValidatorSetUpdatesSingleValueChange(t *testing.T) {
|
|||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||
keeper.SetPool(ctx, pool)
|
||||
}
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
require.Equal(t, 0, len(keeper.ApplyAndReturnValidatorSetUpdates(ctx)))
|
||||
|
||||
// test single value change
|
||||
// tendermintUpdate set: {} -> {c1'}
|
||||
validators[0].Status = sdk.Bonded
|
||||
validators[0].Tokens = sdk.NewDec(600)
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
|
||||
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
|
||||
|
@ -696,8 +696,8 @@ func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) {
|
|||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||
keeper.SetPool(ctx, pool)
|
||||
}
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
require.Equal(t, 0, len(keeper.ApplyAndReturnValidatorSetUpdates(ctx)))
|
||||
|
||||
// test multiple value change
|
||||
|
@ -706,8 +706,8 @@ func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) {
|
|||
validators[0], pool, _ = validators[0].AddTokensFromDel(pool, sdk.NewInt(190))
|
||||
validators[1], pool, _ = validators[1].AddTokensFromDel(pool, sdk.NewInt(80))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
|
||||
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
require.Equal(t, 2, len(updates))
|
||||
|
@ -726,8 +726,8 @@ func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) {
|
|||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||
keeper.SetPool(ctx, pool)
|
||||
}
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
require.Equal(t, 0, len(keeper.ApplyAndReturnValidatorSetUpdates(ctx)))
|
||||
|
||||
// test validtor added at the beginning
|
||||
|
@ -775,13 +775,13 @@ func TestApplyAndReturnValidatorSetUpdatesWithCliffValidator(t *testing.T) {
|
|||
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||
keeper.SetPool(ctx, pool)
|
||||
}
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
require.Equal(t, 0, len(keeper.ApplyAndReturnValidatorSetUpdates(ctx)))
|
||||
|
||||
// test validator added at the end but not inserted in the valset
|
||||
// tendermintUpdate set: {} -> {}
|
||||
testingUpdateValidator(keeper, ctx, validators[2])
|
||||
TestingUpdateValidator(keeper, ctx, validators[2])
|
||||
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
require.Equal(t, 0, len(updates))
|
||||
|
||||
|
@ -813,8 +813,8 @@ func TestApplyAndReturnValidatorSetUpdatesPowerDecrease(t *testing.T) {
|
|||
validators[i].BondIntraTxCounter = int16(i)
|
||||
keeper.SetPool(ctx, pool)
|
||||
}
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
require.Equal(t, 0, len(keeper.ApplyAndReturnValidatorSetUpdates(ctx)))
|
||||
|
||||
// check initial power
|
||||
|
@ -827,8 +827,8 @@ func TestApplyAndReturnValidatorSetUpdatesPowerDecrease(t *testing.T) {
|
|||
validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewDec(20))
|
||||
validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewDec(30))
|
||||
keeper.SetPool(ctx, pool)
|
||||
validators[0] = testingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = testingUpdateValidator(keeper, ctx, validators[1])
|
||||
validators[0] = TestingUpdateValidator(keeper, ctx, validators[0])
|
||||
validators[1] = TestingUpdateValidator(keeper, ctx, validators[1])
|
||||
|
||||
// power has changed
|
||||
require.Equal(t, sdk.NewDec(80).RoundInt64(), validators[0].GetPower().RoundInt64())
|
||||
|
|
|
@ -16,7 +16,9 @@ import (
|
|||
// SimulateMsgCreateValidator
|
||||
func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.Operation {
|
||||
handler := stake.NewHandler(k)
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||
accs []simulation.Account, event func(string)) (
|
||||
action string, fOp []simulation.FutureOperation, err error) {
|
||||
|
||||
denom := k.GetParams(ctx).BondDenom
|
||||
description := stake.Description{
|
||||
|
@ -71,7 +73,9 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation
|
|||
// SimulateMsgEditValidator
|
||||
func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation {
|
||||
handler := stake.NewHandler(k)
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||
accs []simulation.Account, event func(string)) (
|
||||
action string, fOp []simulation.FutureOperation, err error) {
|
||||
|
||||
description := stake.Description{
|
||||
Moniker: simulation.RandStringOfLength(r, 10),
|
||||
|
@ -109,7 +113,9 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation {
|
|||
// SimulateMsgDelegate
|
||||
func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation {
|
||||
handler := stake.NewHandler(k)
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||
accs []simulation.Account, event func(string)) (
|
||||
action string, fOp []simulation.FutureOperation, err error) {
|
||||
|
||||
denom := k.GetParams(ctx).BondDenom
|
||||
validatorAcc := simulation.RandomAcc(r, accs)
|
||||
|
@ -145,7 +151,9 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat
|
|||
// SimulateMsgBeginUnbonding
|
||||
func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.Operation {
|
||||
handler := stake.NewHandler(k)
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||
accs []simulation.Account, event func(string)) (
|
||||
action string, fOp []simulation.FutureOperation, err error) {
|
||||
|
||||
denom := k.GetParams(ctx).BondDenom
|
||||
validatorAcc := simulation.RandomAcc(r, accs)
|
||||
|
@ -181,7 +189,9 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.
|
|||
// SimulateMsgBeginRedelegate
|
||||
func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation {
|
||||
handler := stake.NewHandler(k)
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simulation.Account, event func(string)) (action string, fOp []simulation.FutureOperation, err error) {
|
||||
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||
accs []simulation.Account, event func(string)) (
|
||||
action string, fOp []simulation.FutureOperation, err error) {
|
||||
|
||||
denom := k.GetParams(ctx).BondDenom
|
||||
sourceValidatorAcc := simulation.RandomAcc(r, accs)
|
||||
|
|
|
@ -56,6 +56,7 @@ var (
|
|||
GetREDsFromValSrcIndexKey = keeper.GetREDsFromValSrcIndexKey
|
||||
GetREDsToValDstIndexKey = keeper.GetREDsToValDstIndexKey
|
||||
GetREDsByDelToValDstIndexKey = keeper.GetREDsByDelToValDstIndexKey
|
||||
TestingUpdateValidator = keeper.TestingUpdateValidator
|
||||
|
||||
DefaultParamspace = keeper.DefaultParamspace
|
||||
KeyInflationRateChange = types.KeyInflationRateChange
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package stake
|
||||
|
||||
import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
)
|
||||
|
||||
var (
|
||||
priv1 = ed25519.GenPrivKey()
|
||||
addr1 = sdk.AccAddress(priv1.PubKey().Address())
|
||||
priv2 = ed25519.GenPrivKey()
|
||||
addr2 = sdk.AccAddress(priv2.PubKey().Address())
|
||||
addr3 = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address())
|
||||
priv4 = ed25519.GenPrivKey()
|
||||
addr4 = sdk.AccAddress(priv4.PubKey().Address())
|
||||
coins = sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(10))}
|
||||
fee = auth.NewStdFee(
|
||||
100000,
|
||||
sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(0))}...,
|
||||
)
|
||||
|
||||
commissionMsg = NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())
|
||||
)
|
||||
|
||||
func NewTestMsgCreateValidator(address sdk.ValAddress, pubKey crypto.PubKey, amt int64) MsgCreateValidator {
|
||||
return types.NewMsgCreateValidator(
|
||||
address, pubKey, sdk.NewCoin("steak", sdk.NewInt(amt)), Description{}, commissionMsg,
|
||||
)
|
||||
}
|
||||
|
||||
func NewTestMsgCreateValidatorWithCommission(address sdk.ValAddress, pubKey crypto.PubKey,
|
||||
amt int64, commissionRate sdk.Dec) MsgCreateValidator {
|
||||
|
||||
commission := NewCommissionMsg(commissionRate, sdk.OneDec(), sdk.ZeroDec())
|
||||
|
||||
return types.NewMsgCreateValidator(
|
||||
address, pubKey, sdk.NewCoin("steak", sdk.NewInt(amt)), Description{}, commission,
|
||||
)
|
||||
}
|
||||
|
||||
func NewTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt int64) MsgDelegate {
|
||||
return MsgDelegate{
|
||||
DelegatorAddr: delAddr,
|
||||
ValidatorAddr: valAddr,
|
||||
Delegation: sdk.NewCoin("steak", sdk.NewInt(amt)),
|
||||
}
|
||||
}
|
||||
|
||||
func NewTestMsgCreateValidatorOnBehalfOf(delAddr sdk.AccAddress, valAddr sdk.ValAddress, valPubKey crypto.PubKey, amt int64) MsgCreateValidator {
|
||||
return MsgCreateValidator{
|
||||
Description: Description{},
|
||||
Commission: commissionMsg,
|
||||
DelegatorAddr: delAddr,
|
||||
ValidatorAddr: valAddr,
|
||||
PubKey: valPubKey,
|
||||
Delegation: sdk.NewCoin("steak", sdk.NewInt(amt)),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue